0 /*

1 * button.c - window buttons

2 */

3

4 /*

5 * Copyright 2006 Johan Veenhuizen

6 *

7 * Permission is hereby granted, free of charge, to any person obtaining a

8 * copy of this software and associated documentation files (the "Software"),

9 * to deal in the Software without restriction, including without limitation

10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,

11 * and/or sell copies of the Software, and to permit persons to whom the

12 * Software is furnished to do so, subject to the following conditions:

13 *

14 * The above copyright notice and this permission notice shall be included

15 * in all copies or substantial portions of the Software.

16 *

17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL

20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING

22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

23 * DEALINGS IN THE SOFTWARE.

24 */

25

26 #include <X11/Xlib.h>

27 #include <X11/Xutil.h>

28

29 #include "button.h"

30 #include "global.h"

31 #include "lib.h"

32 #include "menu.h"

33 #include "window.h"

34

35 static void setcolors(struct button *bp)

36 {

37 bp->fg = window_family_is_active(bp->window) ?

38 &color_title_active_fg : &color_title_inactive_fg;

39 bp->bg = window_family_is_active(bp->window) ?

40 &color_title_active_bg : &color_title_inactive_bg;

41 }

42

43 static unsigned long getbgpixel(struct button *bp)

44 {

45 setcolors(bp);

46 if (bp->hover && !bp->depressed)

47 return bp->bg->bright1;

48 else

49 return bp->bg->normal;

50

51 }

52

53 static void prepare_repaint(struct widget *widget)

54 {

55 struct button *bp = (struct button *)widget;

56

57 XSetWindowBackground(display, WIDGET_XWINDOW(bp), getbgpixel(bp));

58 }

59

60 static void repaint(struct widget *widget)

61 {

62 struct button *bp = (struct button *)widget;

63 unsigned long bgpixel;

64

65 setcolors(bp);

66 bgpixel = getbgpixel(bp);

67

68 /* clear */

69 XSetForeground(display, bp->gc, bgpixel);

70 XFillRectangle(display, bp->pixmap, bp->gc,

71 0, 0, WIDGET_WIDTH(bp), WIDGET_HEIGHT(bp));

72

73 /* draw */

74 XSetForeground(display, bp->gc, bp->fg->normal);

75 XSetBackground(display, bp->gc, bgpixel);

76 if (bp->image != NULL) {

77 int x, y;

78

79 x = WIDGET_WIDTH(bp) / 2 - bp->image->width / 2;

80 y = WIDGET_HEIGHT(bp) / 2 - bp->image->height / 2;

81 if (bp->depressed) {

82 x++;

83 y++;

84 }

85 putimage(display, bp->pixmap, bp->gc, bp->image, x, y);

86 }

87

88 if (bp->depressed)

89 drawdepressed(bp->pixmap, bp->gc, bp->bg,

90 0, 0, WIDGET_WIDTH(bp), WIDGET_HEIGHT(bp));

91 else

92 drawraised(bp->pixmap, bp->gc, bp->bg,

93 0, 0, WIDGET_WIDTH(bp), WIDGET_HEIGHT(bp));

94

95 /* display */

96 if (WIDGET_MAPPED(bp))

97 XCopyArea(display,

98 bp->pixmap, WIDGET_XWINDOW(bp), bp->gc,

99 0, 0, WIDGET_WIDTH(bp), WIDGET_HEIGHT(bp), 0, 0);

100 }

101

102 static void buttonevent(struct widget *widget, XEvent *ep)

103 {

104 struct button *bp = (struct button *)widget;

105 int docall;

106

107 switch (ep->type) {

108 case ButtonPress:

109 if (ep->xbutton.button != Button1) {

110 bp->acting = 0;

111 bp->depressed = 0;

112 if (ep->xbutton.button == Button3)

113 show_menu(winmenu,

114 ep->xbutton.x_root, ep->xbutton.y_root,

115 ep->xbutton.button);

116 } else {

117 bp->acting = 1;

118 bp->depressed = 1;

119 }

120 REPAINT(bp);

121 break;

122 case ButtonRelease:

123 docall = (bp->acting && bp->depressed

124 && ep->xbutton.button == Button1

125 && bp->handler != NULL);

126 bp->depressed = 0;

127 bp->acting = 0;

128 REPAINT(bp);

129 /* must call handler as the last thing, it might destroy us */

130 if (docall)

131 bp->handler(bp->window);

132 break;

133 case Expose:

134 XCopyArea(display, bp->pixmap, WIDGET_XWINDOW(bp),

135 bp->gc, ep->xexpose.x, ep->xexpose.y,

136 ep->xexpose.width, ep->xexpose.height,

137 ep->xexpose.x, ep->xexpose.y);

138 break;

139 case EnterNotify:

140 if (bp->acting)

141 bp->depressed = 1;

142 bp->hover = 1;

143 REPAINT(bp);

144 break;

145 case LeaveNotify:

146 if (bp->acting)

147 bp->depressed = 0;

148 bp->hover = 0;

149 REPAINT(bp);

150 break;

151 }

152 }

153

154 struct button *create_button(struct window *window, int x, int y,

155 int width, int height)

156 {

157 XGCValues gcval;

158 struct button *bp;

159

160 bp = MALLOC(sizeof (struct button));

161 create_widget(&bp->widget, WIDGET_BUTTON, WIDGET_XWINDOW(window),

162 InputOutput, x, y, width, height);

163

164 bp->pixmap = XCreatePixmap(display, WIDGET_XWINDOW(bp),

165 WIDGET_WIDTH(bp), WIDGET_HEIGHT(bp),

166 DefaultDepth(display, screen));

167 gcval.graphics_exposures = False;

168 bp->gc = XCreateGC(display, WIDGET_XWINDOW(bp),

169 GCGraphicsExposures, &gcval);

170 bp->image = NULL;

171

172 bp->window = window;

173 bp->acting = 0;

174 bp->depressed = 0;

175 bp->hover = 0;

176 bp->handler = NULL;

177 bp->widget.event = buttonevent;

178 XSelectInput(display, WIDGET_XWINDOW(bp),

179 ButtonPressMask | ButtonReleaseMask |

180 ExposureMask | EnterWindowMask | LeaveWindowMask);

181 bp->widget.prepare_repaint = prepare_repaint;

182 bp->widget.repaint = repaint;

183 REPAINT(bp);

184

185 map_widget(&bp->widget);

186 return bp;

187 }

188

189 void move_button(struct button *bp, int x, int y)

190 {

191 move_widget(&bp->widget, x, y);

192 }

193

194 void destroy_button(struct button *bp)

195 {

196 XFreePixmap(display, bp->pixmap);

197 XFreeGC(display, bp->gc);

198 destroy_widget(&bp->widget);

199 FREE(bp);

200 }

201

202 void set_button_handler(struct button *bp, void (*handler)(struct window *))

203 {

204 bp->handler = handler;

205 }

206

207 void set_button_image(struct button *bp, IMAGE *image)

208 {

209 if (!bp||!image) return;

210 bp->image = image;

211 REPAINT(bp);

212 }

213