1 /*
2  * Copyright (C) 2000-2019 the xine project
3  *
4  * This file is part of xine, a unix video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdio.h>
26 
27 #include "_xitk.h"
28 
29 /*
30  *
31  */
notify_destroy(xitk_widget_t * w)32 static void notify_destroy(xitk_widget_t *w) {
33   button_private_data_t *private_data;
34 
35   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
36     private_data = (button_private_data_t *) w->private_data;
37 
38     if(!private_data->skin_element_name)
39       xitk_image_free_image(private_data->imlibdata, &(private_data->skin));
40 
41     XITK_FREE(private_data->skin_element_name);
42     XITK_FREE(private_data);
43   }
44 }
45 
46 /*
47  *
48  */
get_skin(xitk_widget_t * w,int sk)49 static xitk_image_t *get_skin(xitk_widget_t *w, int sk) {
50   button_private_data_t *private_data;
51 
52   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
53     private_data = (button_private_data_t *) w->private_data;
54 
55     if(sk == FOREGROUND_SKIN && private_data->skin) {
56       return private_data->skin;
57     }
58   }
59 
60   return NULL;
61 }
62 
63 /*
64  *
65  */
notify_inside(xitk_widget_t * w,int x,int y)66 static int notify_inside(xitk_widget_t *w, int x, int y) {
67   button_private_data_t *private_data;
68 
69   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
70     private_data = (button_private_data_t *) w->private_data;
71 
72     if(w->visible == 1) {
73       xitk_image_t *skin = private_data->skin;
74 
75       if(skin->mask)
76 	return xitk_is_cursor_out_mask(private_data->imlibdata->x.disp, w, skin->mask->pixmap, x, y);
77     }
78     else
79       return 0;
80   }
81 
82   return 1;
83 }
84 
85 /**
86  *
87  */
paint_button(xitk_widget_t * w)88 static void paint_button (xitk_widget_t *w) {
89   button_private_data_t *private_data;
90   GC                     lgc;
91   int                    button_width;
92   xitk_image_t          *skin;
93 
94   if(w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON) && w->visible == 1)) {
95 
96     private_data = (button_private_data_t *) w->private_data;
97     skin         = private_data->skin;
98     button_width = skin->width / 3;
99 
100     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
101     lgc = XCreateGC(private_data->imlibdata->x.disp, w->wl->win, None, None);
102     XCopyGC(private_data->imlibdata->x.disp, w->wl->gc, (1 << GCLastBit) - 1, lgc);
103     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
104 
105     if (skin->mask) {
106       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
107       XSetClipOrigin(private_data->imlibdata->x.disp, lgc, w->x, w->y);
108       XSetClipMask(private_data->imlibdata->x.disp, lgc, skin->mask->pixmap);
109       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
110     }
111 
112     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
113     if ((private_data->focus == FOCUS_RECEIVED) || (private_data->focus == FOCUS_MOUSE_IN)) {
114       if(private_data->bClicked) {
115 	XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
116 		   w->wl->win, lgc, 2*button_width, 0,
117 		   button_width, skin->height, w->x, w->y);
118       }
119       else {
120 	XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
121 		   w->wl->win, lgc, button_width, 0,
122 		   button_width, skin->height, w->x, w->y);
123       }
124     }
125     else {
126       XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
127 		 w->wl->win, lgc, 0, 0,
128 		 button_width, skin->height, w->x, w->y);
129     }
130     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
131 
132     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
133     XFreeGC(private_data->imlibdata->x.disp, lgc);
134     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
135   }
136 
137 }
138 
139 /*
140  *
141  */
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)142 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
143   button_private_data_t *private_data;
144 
145   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
146     private_data = (button_private_data_t *) w->private_data;
147 
148     if(private_data->skin_element_name) {
149       xitk_skin_lock(skonfig);
150       private_data->skin              = xitk_skin_get_image(skonfig,
151 							    (xitk_skin_get_skin_filename(skonfig, private_data->skin_element_name)));
152       w->x                            = xitk_skin_get_coord_x(skonfig, private_data->skin_element_name);
153       w->y                            = xitk_skin_get_coord_y(skonfig, private_data->skin_element_name);
154       w->width                        = private_data->skin->width/3;
155       w->height                       = private_data->skin->height;
156 
157       w->visible                      = (xitk_skin_get_visibility(skonfig, private_data->skin_element_name)) ? 1 : -1;
158       w->enable                       = xitk_skin_get_enability(skonfig, private_data->skin_element_name);
159 
160       xitk_skin_unlock(skonfig);
161       xitk_set_widget_pos(w, w->x, w->y);
162     }
163   }
164 }
165 
166 /*
167  *
168  */
notify_click_button(xitk_widget_t * w,int button,int bUp,int x,int y)169 static int notify_click_button (xitk_widget_t *w, int button, int bUp, int x, int y) {
170   button_private_data_t *private_data;
171   int                    ret = 0;
172 
173   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
174     if(button == Button1) {
175       private_data = (button_private_data_t *) w->private_data;
176       private_data->bClicked = !bUp;
177 
178       paint_button(w);
179 
180       if (bUp && (private_data->focus == FOCUS_RECEIVED)) {
181 	if(private_data->callback) {
182 	  private_data->callback(private_data->bWidget,
183 				 private_data->userdata);
184 	}
185       }
186       ret = 1;
187     }
188   }
189 
190   return ret;
191 }
192 
193 /*
194  *
195  */
notify_focus_button(xitk_widget_t * w,int focus)196 static int notify_focus_button (xitk_widget_t *w, int focus) {
197   button_private_data_t *private_data;
198 
199   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
200     private_data = (button_private_data_t *) w->private_data;
201     private_data->focus = focus;
202   }
203 
204   return 1;
205 }
206 
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)207 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
208   int retval = 0;
209 
210   switch(event->type) {
211   case WIDGET_EVENT_PAINT:
212     paint_button(w);
213     break;
214   case WIDGET_EVENT_CLICK:
215     result->value = notify_click_button(w, event->button,
216 					event->button_pressed, event->x, event->y);
217     retval = 1;
218     break;
219   case WIDGET_EVENT_FOCUS:
220     notify_focus_button(w, event->focus);
221     break;
222   case WIDGET_EVENT_INSIDE:
223     result->value = notify_inside(w, event->x, event->y);
224     retval = 1;
225     break;
226   case WIDGET_EVENT_CHANGE_SKIN:
227     notify_change_skin(w, event->skonfig);
228     break;
229   case WIDGET_EVENT_DESTROY:
230     notify_destroy(w);
231     break;
232   case WIDGET_EVENT_GET_SKIN:
233     if(result) {
234       result->image = get_skin(w, event->skin_layer);
235       retval = 1;
236     }
237     break;
238   }
239 
240   return retval;
241 }
242 
243 /*
244  *
245  */
_xitk_button_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_button_widget_t * b,int x,int y,const char * skin_element_name,xitk_image_t * skin,int visible,int enable)246 static xitk_widget_t *_xitk_button_create (xitk_widget_list_t *wl,
247 					   xitk_skin_config_t *skonfig, xitk_button_widget_t *b,
248 					   int x, int y,
249                                            const char *skin_element_name, xitk_image_t *skin,
250 					   int visible, int enable) {
251   xitk_widget_t          *mywidget;
252   button_private_data_t  *private_data;
253 
254   mywidget = (xitk_widget_t *) xitk_xmalloc (sizeof(xitk_widget_t));
255 
256   private_data = (button_private_data_t *) xitk_xmalloc(sizeof(button_private_data_t));
257 
258   private_data->imlibdata         = b->imlibdata;
259 
260   private_data->bWidget           = mywidget;
261   private_data->bClicked          = 0;
262   private_data->focus             = FOCUS_LOST;
263 
264   private_data->skin_element_name = (skin_element_name == NULL) ? NULL : strdup(b->skin_element_name);
265   private_data->skin              = skin;
266 
267   private_data->callback          = b->callback;
268   private_data->userdata          = b->userdata;
269 
270   mywidget->private_data          = private_data;
271 
272   mywidget->wl                    = wl;
273 
274   mywidget->enable                = enable;
275   mywidget->running               = 1;
276   mywidget->visible               = visible;
277   mywidget->have_focus            = FOCUS_LOST;
278   mywidget->imlibdata             = private_data->imlibdata;
279   mywidget->x                     = x;
280   mywidget->y                     = y;
281   mywidget->width                 = private_data->skin->width/3;
282   mywidget->height                = private_data->skin->height;
283   mywidget->type                  = WIDGET_TYPE_BUTTON | WIDGET_CLICKABLE | WIDGET_FOCUSABLE | WIDGET_KEYABLE;
284   mywidget->event                 = notify_event;
285   mywidget->tips_timeout          = 0;
286   mywidget->tips_string           = NULL;
287 
288   return mywidget;
289 }
290 
291 /*
292  *
293  */
xitk_button_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_button_widget_t * b)294 xitk_widget_t *xitk_button_create (xitk_widget_list_t *wl,
295 				   xitk_skin_config_t *skonfig, xitk_button_widget_t *b) {
296 
297   XITK_CHECK_CONSTITENCY(b);
298 
299   return _xitk_button_create(wl, skonfig, b,
300 			     (xitk_skin_get_coord_x(skonfig, b->skin_element_name)),
301 			     (xitk_skin_get_coord_y(skonfig, b->skin_element_name)),
302 			     b->skin_element_name,
303 			     xitk_skin_get_image(skonfig,
304 						 (xitk_skin_get_skin_filename(skonfig, b->skin_element_name))),
305 			     (xitk_skin_get_visibility(skonfig, b->skin_element_name)) ? 1 : -1,
306 			     xitk_skin_get_enability(skonfig, b->skin_element_name));
307 }
308 
309 /*
310  *
311  */
xitk_noskin_button_create(xitk_widget_list_t * wl,xitk_button_widget_t * b,int x,int y,int width,int height)312 xitk_widget_t *xitk_noskin_button_create (xitk_widget_list_t *wl,
313 					  xitk_button_widget_t *b,
314 					  int x, int y, int width, int height) {
315   xitk_image_t *i;
316 
317   XITK_CHECK_CONSTITENCY(b);
318 
319   i = xitk_image_create_image(b->imlibdata, width * 3, height);
320   draw_bevel_three_state(b->imlibdata, i);
321 
322   return _xitk_button_create(wl, NULL, b, x, y, NULL, i, 0, 0);
323 }
324