1 /*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2019 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21
22 #include "xwidget.h"
23 #include "xwidget_private.h"
24
25
key_mapping(Display * dpy,XKeyEvent * xkey)26 int key_mapping(Display *dpy, XKeyEvent *xkey) {
27 if (xkey->keycode == XKeysymToKeycode(dpy,XK_Tab))
28 return (xkey->state == ShiftMask) ? 1 : 2;
29 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_Up))
30 return 3;
31 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_Right))
32 return 4;
33 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_Down))
34 return 5;
35 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_Left))
36 return 6;
37 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_Home))
38 return 7;
39 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_Insert))
40 return 8;
41 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_End))
42 return 9;
43 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_Return))
44 return 10;
45 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_BackSpace))
46 return 11;
47 // keypad
48 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Subtract))
49 return 1;
50 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Add))
51 return 2;
52 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Up))
53 return 3;
54 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Right))
55 return 4;
56 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Down))
57 return 5;
58 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Left))
59 return 6;
60 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Home))
61 return 7;
62 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Insert))
63 return 8;
64 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_End))
65 return 9;
66 else if (xkey->keycode == XKeysymToKeycode(dpy,XK_KP_Enter))
67 return 10;
68 else return 0;
69 }
70
destroy_widget(Widget_t * w,Xputty * main)71 void destroy_widget(Widget_t * w, Xputty *main) {
72 int count = childlist_find_child(main->childlist, w);
73 if (count == 0 && main->run == true) {
74 quit(w);
75 } else if(childlist_find_child(main->childlist, w)>=0) {
76 if(w->flags & REUSE_IMAGE) {
77 w->image = NULL;
78 }
79 if(w->flags & HAS_MEM) {
80 w->func.mem_free_callback(w, NULL);
81 }
82 childlist_remove_child(main->childlist, w);
83 int ch = childlist_has_child(w->childlist);
84 if (ch) {
85 int i = ch;
86 for(;i>0;i--) {
87 destroy_widget(w->childlist->childs[i-1],main);
88 }
89 destroy_widget(w,main);
90 }
91 if(w->flags & IS_WIDGET) {
92 Widget_t *p = (Widget_t *) w->parent;
93 childlist_remove_child(p->childlist, w);
94 }
95 delete_adjustment(w->adj_x);
96 delete_adjustment(w->adj_y);
97 childlist_destroy(w->childlist);
98 cairo_surface_destroy(w->image);
99 cairo_destroy(w->crb);
100 cairo_surface_destroy(w->buffer);
101 cairo_destroy(w->cr);
102 cairo_surface_destroy(w->surface);
103
104 if (w->xic) XDestroyIC(w->xic);
105 if (w->xim) XCloseIM(w->xim);
106 XUnmapWindow(w->app->dpy, w->widget);
107 XDestroyWindow(w->app->dpy, w->widget);
108 free(w->childlist);
109 free(w);
110 w = NULL;
111 }
112 }
113
configure_event(void * w_,void * user_data)114 void configure_event(void *w_, void* user_data) {
115 Widget_t *wid = (Widget_t*)w_;
116 XWindowAttributes attrs;
117 XGetWindowAttributes(wid->app->dpy, (Window)wid->widget, &attrs);
118 if (wid->width != attrs.width || wid->height != attrs.height) {
119 wid->scale.scale_x = (float)wid->scale.init_width - attrs.width;
120 wid->scale.scale_y = (float)wid->scale.init_height - attrs.height;
121 wid->scale.cscale_x = (float)((float)wid->scale.init_width/(float)attrs.width);
122 wid->scale.cscale_y = (float)((float)wid->scale.init_height/(float)attrs.height);
123 wid->scale.rcscale_x = (float)((float)attrs.width/(float)wid->scale.init_width);
124 wid->scale.rcscale_y = (float)((float)attrs.height/(float)wid->scale.init_height);
125 wid->scale.ascale = wid->scale.cscale_x < wid->scale.cscale_y ?
126 wid->scale.cscale_y : wid->scale.cscale_x;
127
128 _resize_surface(wid, attrs.width, attrs.height);
129
130 debug_print("Widget_t configure callback width %i height %i\n", attrs.width, attrs.height);
131
132 _resize_childs(wid);
133 }
134 }
135
widget_reset_scale(Widget_t * w)136 void widget_reset_scale(Widget_t *w) {
137 cairo_scale(w->crb, w->scale.cscale_x,w->scale.cscale_y);
138 }
139
widget_set_scale(Widget_t * w)140 void widget_set_scale(Widget_t *w) {
141 cairo_scale(w->crb, w->scale.rcscale_x,w->scale.rcscale_y);
142 }
143
create_window(Xputty * app,Window win,int x,int y,int width,int height)144 Widget_t *create_window(Xputty *app, Window win,
145 int x, int y, int width, int height) {
146
147 Widget_t *w = (Widget_t*)malloc(sizeof(Widget_t));
148 assert(w != NULL);
149 debug_print("assert(w)\n");
150 XSetWindowAttributes attributes;
151 attributes.save_under = True;
152 attributes.override_redirect = 0;
153
154 long event_mask = StructureNotifyMask|ExposureMask|KeyPressMask
155 |EnterWindowMask|LeaveWindowMask|ButtonReleaseMask
156 |ButtonPressMask|Button1MotionMask;
157
158
159
160 w->widget = XCreateWindow(app->dpy, win , x, y, width, height, 0,
161 CopyFromParent, InputOutput, CopyFromParent,
162 CopyFromParent, &attributes);
163 debug_print("XCreateWindow\n");
164
165 XSetLocaleModifiers("");
166 w->xim = XOpenIM(app->dpy, 0, 0, 0);
167 if(!w->xim){
168 XSetLocaleModifiers("@im=none");
169 w->xim = XOpenIM(app->dpy, 0, 0, 0);
170 }
171
172 w->xic = XCreateIC(w->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
173 XNClientWindow, w->widget, XNFocusWindow, w->widget, NULL);
174
175 XSetICFocus(w->xic);
176
177 XSelectInput(app->dpy, w->widget, event_mask);
178
179 XSizeHints* win_size_hints;
180 win_size_hints = XAllocSizeHints();
181 win_size_hints->flags = PMinSize|PBaseSize|PWinGravity;
182 win_size_hints->min_width = width/2;
183 win_size_hints->min_height = height/2;
184 win_size_hints->base_width = width;
185 win_size_hints->base_height = height;
186 win_size_hints->win_gravity = CenterGravity;
187 XSetWMNormalHints(app->dpy, w->widget, win_size_hints);
188 XFree(win_size_hints);
189
190 w->surface = cairo_xlib_surface_create (app->dpy, w->widget,
191 DefaultVisual(app->dpy, DefaultScreen(app->dpy)), width, height);
192
193 assert(cairo_surface_status(w->surface) == CAIRO_STATUS_SUCCESS);
194 w->cr = cairo_create(w->surface);
195 cairo_select_font_face (w->cr, "Roboto", CAIRO_FONT_SLANT_NORMAL,
196 CAIRO_FONT_WEIGHT_NORMAL);
197
198 w->buffer = cairo_surface_create_similar (w->surface,
199 CAIRO_CONTENT_COLOR_ALPHA, width, height);
200 assert(cairo_surface_status(w->buffer) == CAIRO_STATUS_SUCCESS);
201 w->crb = cairo_create (w->buffer);
202 cairo_select_font_face (w->crb, "Roboto", CAIRO_FONT_SLANT_NORMAL,
203 CAIRO_FONT_WEIGHT_NORMAL);
204
205 w->image = NULL;
206
207 w->flags = IS_WINDOW;
208 w->flags &= ~NO_AUTOREPEAT;
209 w->flags &= ~FAST_REDRAW;
210 w->flags &= ~HIDE_ON_DELETE;
211 w->flags &= ~REUSE_IMAGE;
212 w->app = app;
213 w->parent = &win;
214 w->parent_struct = NULL;
215 w->label = NULL;
216 memset(w->input_label, 0, 32 * (sizeof w->input_label[0]));
217 w->state = 0;
218 w->data = 0;
219 w->x = x;
220 w->y = y;
221 w->width = width;
222 w->height = height;
223 w->scale.init_x = x;
224 w->scale.init_y = y;
225 w->scale.init_width = width;
226 w->scale.init_height = height;
227 w->scale.scale_x = 0.0;
228 w->scale.scale_y = 0.0;
229 w->scale.cscale_x = 1.0;
230 w->scale.cscale_y = 1.0;
231 w->scale.rcscale_x = 1.0;
232 w->scale.rcscale_y = 1.0;
233 w->scale.ascale = 1.0;
234 w->scale.gravity = CENTER;
235 w->adj_x = NULL;
236 w->adj_y = NULL;
237 w->adj = NULL;
238 w->childlist = (Childlist_t*)malloc(sizeof(Childlist_t));
239 assert(w->childlist != NULL);
240 childlist_init(w->childlist);
241 w->event_callback = widget_event_loop;
242 w->func.expose_callback = _dummy_callback;
243 w->func.configure_callback = configure_event;
244 w->func.button_press_callback = _dummy1_callback;
245 w->func.button_release_callback = _dummy1_callback;
246 w->func.motion_callback = _dummy1_callback;
247 w->func.adj_callback = transparent_draw;
248 w->func.value_changed_callback = _dummy_callback;
249 w->func.key_press_callback = _dummy1_callback;
250 w->func.key_release_callback = _dummy1_callback;
251 w->func.enter_callback = _dummy_callback;
252 w->func.leave_callback = _dummy_callback;
253 w->func.user_callback = _dummy_callback;
254 w->func.mem_free_callback = _dummy_callback;
255 w->func.configure_notify_callback = _dummy_callback;
256 w->func.map_notify_callback = _dummy_callback;
257 w->func.unmap_notify_callback = _dummy_callback;
258 w->func.dialog_callback = _dummy_callback;
259
260 childlist_add_child(app->childlist,w);
261 //XMapWindow(app->dpy, w->widget);
262 debug_print("size of Func_t = %lu\n", sizeof(w->func)/sizeof(void*));
263 return w;
264 }
265
create_widget(Xputty * app,Widget_t * parent,int x,int y,int width,int height)266 Widget_t *create_widget(Xputty *app, Widget_t *parent,
267 int x, int y, int width, int height) {
268
269 Widget_t *w = (Widget_t*)malloc(sizeof(Widget_t));
270 assert(w != NULL);
271 debug_print("assert(w)\n");
272 XSetWindowAttributes attributes;
273 attributes.save_under = True;
274 attributes.override_redirect = True;
275
276 long event_mask = StructureNotifyMask|ExposureMask|KeyPressMask
277 |EnterWindowMask|LeaveWindowMask|ButtonReleaseMask
278 |ButtonPressMask|Button1MotionMask;
279
280
281
282 w->widget = XCreateWindow(app->dpy, parent->widget , x, y, width, height, 0,
283 CopyFromParent, InputOutput, CopyFromParent,
284 CopyFromParent|CWOverrideRedirect, &attributes);
285 debug_print("XCreateWindow\n");
286
287 XSetLocaleModifiers("");
288 w->xim = XOpenIM(app->dpy, 0, 0, 0);
289 if(!w->xim){
290 XSetLocaleModifiers("@im=none");
291 w->xim = XOpenIM(app->dpy, 0, 0, 0);
292 }
293
294 w->xic = XCreateIC(w->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
295 XNClientWindow, w->widget, XNFocusWindow, w->widget, NULL);
296
297 XSetICFocus(w->xic);
298
299 XSelectInput(app->dpy, w->widget, event_mask);
300
301 w->surface = cairo_xlib_surface_create (app->dpy, w->widget,
302 DefaultVisual(app->dpy, DefaultScreen(app->dpy)), width, height);
303 assert(cairo_surface_status(w->surface) == CAIRO_STATUS_SUCCESS);
304 w->cr = cairo_create(w->surface);
305 cairo_select_font_face (w->cr, "Roboto", CAIRO_FONT_SLANT_NORMAL,
306 CAIRO_FONT_WEIGHT_NORMAL);
307
308 w->buffer = cairo_surface_create_similar (w->surface,
309 CAIRO_CONTENT_COLOR_ALPHA, width, height);
310 assert(cairo_surface_status(w->buffer) == CAIRO_STATUS_SUCCESS);
311 w->crb = cairo_create (w->buffer);
312 cairo_select_font_face (w->crb, "Roboto", CAIRO_FONT_SLANT_NORMAL,
313 CAIRO_FONT_WEIGHT_NORMAL);
314
315 w->image = NULL;
316
317 w->flags = IS_WIDGET | USE_TRANSPARENCY;
318 w->flags &= ~NO_AUTOREPEAT;
319 w->flags &= ~FAST_REDRAW;
320 w->flags &= ~HIDE_ON_DELETE;
321 w->flags &= ~REUSE_IMAGE;
322 w->app = app;
323 w->parent = parent;
324 w->parent_struct = NULL;
325 w->label = NULL;
326 memset(w->input_label, 0, 32 * (sizeof w->input_label[0]));
327 w->state = 0;
328 w->data = 0;
329 w->x = x;
330 w->y = y;
331 w->width = width;
332 w->height = height;
333 w->scale.gravity = CENTER;
334 w->scale.init_width = width;
335 w->scale.init_height = height;
336 w->scale.init_x = x;
337 w->scale.init_y = y;
338 w->scale.scale_x = 0.0;
339 w->scale.scale_y = 0.0;
340 w->scale.cscale_x = 1.0;
341 w->scale.cscale_y = 1.0;
342 w->scale.rcscale_x = 1.0;
343 w->scale.rcscale_y = 1.0;
344 w->scale.ascale = 1.0;
345 w->adj_x = NULL;
346 w->adj_y = NULL;
347 w->adj = NULL;
348 w->childlist = (Childlist_t*)malloc(sizeof(Childlist_t));
349 assert(w->childlist != NULL);
350 childlist_init(w->childlist);
351 childlist_add_child(parent->childlist, w);
352 w->event_callback = widget_event_loop;
353 w->func.expose_callback = _dummy_callback;
354 w->func.configure_callback = configure_event;
355 w->func.button_press_callback = _dummy1_callback;
356 w->func.button_release_callback = _dummy1_callback;
357 w->func.motion_callback = _dummy1_callback;
358 w->func.adj_callback = transparent_draw;
359 w->func.value_changed_callback = _dummy_callback;
360 w->func.key_press_callback = _dummy1_callback;
361 w->func.key_release_callback = _dummy1_callback;
362 w->func.enter_callback = _dummy_callback;
363 w->func.leave_callback = _dummy_callback;
364 w->func.user_callback = _dummy_callback;
365 w->func.mem_free_callback = _dummy_callback;
366 w->func.configure_notify_callback = _dummy_callback;
367 w->func.map_notify_callback = _dummy_callback;
368 w->func.unmap_notify_callback = _dummy_callback;
369 w->func.dialog_callback = _dummy_callback;
370
371 childlist_add_child(app->childlist,w);
372 //XMapWindow(app->dpy, w->widget);
373 debug_print("size of Widget_t = %ld\n", sizeof(struct Widget_t));
374 return w;
375 }
376
connect_func(void (** event)(),void (* handler)())377 void connect_func(void (**event)(), void (*handler)()) {
378 debug_print("address of a is: %p\n", (void*)event);
379 debug_print("address of b is: %p\n", (void*)handler);
380 *event = handler;
381 debug_print("address of a is: %p\n", (void*)(*event));
382 }
383
widget_set_title(Widget_t * w,const char * title)384 void widget_set_title(Widget_t *w, const char *title) {
385 XStoreName(w->app->dpy, w->widget, title);
386 }
387
widget_show(Widget_t * w)388 void widget_show(Widget_t *w) {
389 w->func.map_notify_callback(w, NULL);
390 XMapWindow(w->app->dpy, w->widget);
391 }
392
widget_hide(Widget_t * w)393 void widget_hide(Widget_t *w) {
394 int i=0;
395 for(;i<w->childlist->elem;i++) {
396 widget_hide(w->childlist->childs[i]);
397 }
398 w->func.unmap_notify_callback(w, NULL);
399 XUnmapWindow(w->app->dpy, w->widget);
400 }
401
widget_show_all(Widget_t * w)402 void widget_show_all(Widget_t *w) {
403 if (w->flags & IS_POPUP || w->flags & IS_TOOLTIP) {
404 return;
405 } else {
406 w->func.map_notify_callback(w, NULL);
407 XMapWindow(w->app->dpy, w->widget);
408 int i=0;
409 for(;i<w->childlist->elem;i++) {
410 widget_show_all(w->childlist->childs[i]);
411 }
412 }
413 }
414
pop_widget_show_all(Widget_t * w)415 void pop_widget_show_all(Widget_t *w) {
416 w->func.map_notify_callback(w, NULL);
417 XMapWindow(w->app->dpy, w->widget);
418 int i=0;
419 for(;i<w->childlist->elem;i++) {
420 pop_widget_show_all(w->childlist->childs[i]);
421 }
422 }
423
show_tooltip(Widget_t * wid)424 void show_tooltip(Widget_t *wid) {
425 int i = 0;
426 for(;i<wid->childlist->elem;i++) {
427 Widget_t *w = wid->childlist->childs[i];
428 if (w->flags & IS_TOOLTIP) {
429 unsigned int mask;
430 int x, y, rx, ry;
431 Window child, root;
432 XQueryPointer(wid->app->dpy, wid->widget, &root, &child, &rx, &ry, &x, &y, &mask);
433 int x1, y1;
434 XTranslateCoordinates( wid->app->dpy, wid->widget, DefaultRootWindow(wid->app->dpy),
435 x, y, &x1, &y1, &child );
436 XMoveWindow(w->app->dpy,w->widget,x1+10, y1-10);
437 widget_show(w);
438 break;
439 }
440 }
441 }
442
hide_tooltip(Widget_t * wid)443 void hide_tooltip(Widget_t *wid) {
444 int i = 0;
445 for(;i<wid->childlist->elem;i++) {
446 Widget_t *w = wid->childlist->childs[i];
447 if (w->flags & IS_TOOLTIP) {
448 widget_hide(w);
449 break;
450 }
451 }
452 }
453
get_toplevel_widget(Xputty * main)454 Widget_t *get_toplevel_widget(Xputty *main) {
455 return main->childlist->childs[0];
456 }
457
expose_widget(Widget_t * w)458 void expose_widget(Widget_t *w) {
459 XEvent exp;
460 memset(&exp, 0, sizeof(exp));
461 exp.type = Expose;
462 exp.xexpose.window = w->widget;
463 XSendEvent(w->app->dpy, w->widget, False, ExposureMask, (XEvent *)&exp);
464 }
465
transparent_draw(void * w_,void * user_data)466 void transparent_draw(void * w_, void* user_data) {
467 Widget_t *wid = (Widget_t*)w_;
468
469 cairo_push_group (wid->cr);
470
471 if (wid->flags & USE_TRANSPARENCY) {
472 Widget_t *parent = (Widget_t*)wid->parent;
473 XWindowAttributes attrs;
474 XGetWindowAttributes(wid->app->dpy, wid->widget, &attrs);
475
476 debug_print("Widget_t _transparency \n");
477 cairo_set_source_surface (wid->crb, parent->buffer, -attrs.x, -attrs.y);
478 cairo_paint (wid->crb);
479 }
480
481 cairo_push_group (wid->crb);
482 wid->func.expose_callback(wid, user_data);
483 cairo_pop_group_to_source (wid->crb);
484 cairo_paint (wid->crb);
485
486 cairo_set_source_surface (wid->cr, wid->buffer,0,0);
487 cairo_paint (wid->cr);
488
489 cairo_pop_group_to_source (wid->cr);
490 cairo_paint (wid->cr);
491 _propagate_child_expose(wid);
492 }
493
widget_event_loop(void * w_,void * event,Xputty * main,void * user_data)494 void widget_event_loop(void *w_, void* event, Xputty *main, void* user_data) {
495 Widget_t *wid = (Widget_t*)w_;
496 XEvent *xev = (XEvent*)event;
497 if (XFilterEvent(xev, wid->widget))
498 return;
499
500 switch(xev->type) {
501 case ConfigureNotify:
502 wid->func.configure_callback(w_, user_data);
503 debug_print("Widget_t ConfigureNotify \n");
504 break;
505
506 case Expose:
507 if (xev->xexpose.count == 0) {
508 transparent_draw(w_, user_data);
509 debug_print("Widget_t Expose \n");
510 }
511 break;
512
513 case ButtonPress:
514 if (wid->state == 4) break;
515 if (wid->flags & HAS_TOOLTIP) hide_tooltip(wid);
516 _button_press(wid, &xev->xbutton, user_data);
517 debug_print("Widget_t ButtonPress %i\n", xev->xbutton.button);
518 break;
519
520 case ButtonRelease:
521 _check_grab(wid, &xev->xbutton, main);
522 if (wid->state == 4) break;
523 _has_pointer(wid, &xev->xbutton);
524 if(wid->flags & HAS_POINTER) wid->state = 1;
525 else wid->state = 0;
526 _check_enum(wid, &xev->xbutton);
527 wid->func.button_release_callback(w_, &xev->xbutton, user_data);
528 debug_print("Widget_t ButtonRelease %i\n", xev->xbutton.button);
529 break;
530
531 case KeyPress:
532 if (wid->state == 4) break;
533 _check_keymap(wid, xev->xkey);
534 wid->func.key_press_callback(w_, &xev->xkey, user_data);
535 debug_print("Widget_t KeyPress %u\n", xev->xkey.keycode);
536 break;
537
538 case KeyRelease:
539 if (wid->state == 4) break;
540 {
541 unsigned short is_retriggered = 0;
542 if(wid->flags & NO_AUTOREPEAT) {
543 if (XEventsQueued(main->dpy, QueuedAlready)) {
544 XEvent nev;
545 XPeekEvent(main->dpy, &nev);
546 if (nev.type == KeyPress && nev.xkey.time == xev->xkey.time &&
547 nev.xkey.keycode == xev->xkey.keycode &&
548 (nev.xkey.keycode > 119 || nev.xkey.keycode < 110)) {
549 XNextEvent (main->dpy, xev);
550 is_retriggered = 1;
551 }
552 }
553 }
554 if (!is_retriggered) {
555 wid->func.key_release_callback(w_, &xev->xkey, user_data);
556 debug_print("Widget_t KeyRelease %u\n", xev->xkey.keycode);
557 }
558 }
559 break;
560
561 case LeaveNotify:
562 wid->flags &= ~HAS_FOCUS;
563 if (wid->state == 4) break;
564 if(!(xev->xcrossing.state & Button1Mask)) {
565 wid->state = 0;
566 wid->func.leave_callback(w_, user_data);
567 }
568 if (wid->flags & HAS_TOOLTIP) hide_tooltip(wid);
569 debug_print("Widget_t LeaveNotify \n");
570 break;
571
572 case EnterNotify:
573 wid->flags |= HAS_FOCUS;
574 if (wid->state == 4) break;
575 if(!(xev->xcrossing.state & Button1Mask)) {
576 wid->state = 1;
577 wid->func.enter_callback(w_, user_data);
578 if (wid->flags & HAS_TOOLTIP) show_tooltip(wid);
579 else _hide_all_tooltips(wid);
580 }
581 debug_print("Widget_t EnterNotify \n");
582 break;
583
584 case MotionNotify:
585 if (wid->state == 4) break;
586 adj_set_motion_state(wid, xev->xmotion.x, xev->xmotion.y);
587 wid->func.motion_callback(w_,&xev->xmotion, user_data);
588 debug_print("Widget_t MotionNotify x = %i Y = %i \n",xev->xmotion.x,xev->xmotion.y );
589 break;
590
591 case ClientMessage:
592 if (xev->xclient.message_type == XInternAtom(wid->app->dpy, "WIDGET_DESTROY", 1)) {
593 int ch = childlist_has_child(wid->childlist);
594 if (ch) {
595 int i = ch;
596 for(;i>0;i--) {
597 quit_widget(wid->childlist->childs[i-1]);
598 }
599 quit_widget(wid);
600 } else {
601 destroy_widget(wid,main);
602 }
603 }
604
605 default:
606 break;
607 }
608 if (main->queue_event) {
609 main->queue_event = false;
610 transparent_draw(w_, user_data);
611 }
612 }
613
send_configure_event(Widget_t * w,int x,int y,int width,int height)614 void send_configure_event(Widget_t *w,int x, int y, int width, int height) {
615 XConfigureEvent notify;
616 memset(¬ify, 0, sizeof(notify));
617 notify.type = ConfigureNotify;
618 notify.display = w->app->dpy;
619 notify.send_event = True;
620 notify.event = w->widget;
621 notify.window = w->widget;
622 notify.x = x;
623 notify.y = y;
624 notify.width = width;
625 notify.height = height;
626 notify.border_width = 0;
627 notify.above = None;
628 notify.override_redirect = 1;
629 XSendEvent( w->app->dpy, w->widget, true, StructureNotifyMask, (XEvent*)¬ify );
630 }
631
send_button_press_event(Widget_t * w)632 void send_button_press_event(Widget_t *w) {
633 XEvent event;
634 memset(&event, 0, sizeof(XEvent));
635 XWindowAttributes attr;
636 XGetWindowAttributes(w->app->dpy, w->widget, &attr);
637 event.type = ButtonPress;
638 event.xbutton.same_screen = true;
639 event.xbutton.root = None;
640 event.xbutton.window = w->widget;
641 event.xbutton.subwindow = None;
642 event.xbutton.x = 1;
643 event.xbutton.y = 1;
644 event.xbutton.x_root = attr.x;
645 event.xbutton.y_root = attr.y;
646 event.xbutton.state = 0;
647 event.xbutton.button = Button1;
648 XSendEvent(w->app->dpy, PointerWindow, True, ButtonPressMask, &event);
649 }
650
send_button_release_event(Widget_t * w)651 void send_button_release_event(Widget_t *w) {
652 XEvent event;
653 memset(&event, 0, sizeof(XEvent));
654 XWindowAttributes attr;
655 XGetWindowAttributes(w->app->dpy, w->widget, &attr);
656 event.type = ButtonRelease;
657 event.xbutton.same_screen = true;
658 event.xbutton.root = None;
659 event.xbutton.window = w->widget;
660 event.xbutton.subwindow = None;
661 event.xbutton.x = 1;
662 event.xbutton.y = 1;
663 event.xbutton.x_root = attr.x;
664 event.xbutton.y_root = attr.y;
665 event.xbutton.state = 0;
666 event.xbutton.button = Button1;
667 XSendEvent(w->app->dpy, PointerWindow, True, ButtonReleaseMask, &event);
668 }
669
send_systray_message(Widget_t * w)670 void send_systray_message(Widget_t *w) {
671 XEvent event;
672 Screen *xscreen;
673 char buf[256];
674 buf[0]=0;
675
676 xscreen=DefaultScreenOfDisplay(w->app->dpy);
677 sprintf(buf,"_NET_SYSTEM_TRAY_S%d",XScreenNumberOfScreen (xscreen));
678 Atom selection_atom = XInternAtom (w->app->dpy,buf,0);
679
680 Window tray = XGetSelectionOwner (w->app->dpy,selection_atom);
681 Atom visualatom = XInternAtom(w->app->dpy, "_NET_SYSTEM_TRAY_VISUAL", False);
682 VisualID value = XVisualIDFromVisual(DefaultVisual(w->app->dpy, DefaultScreen(w->app->dpy)));
683 XChangeProperty(w->app->dpy, w->widget, visualatom, XA_VISUALID, 32,
684 PropModeReplace, (unsigned char*)&value, 1);
685
686 if ( tray != None)
687 XSelectInput (w->app->dpy,tray,StructureNotifyMask);
688
689 memset(&event, 0, sizeof(event));
690 event.xclient.type = ClientMessage;
691 event.xclient.window = tray;
692 event.xclient.message_type = XInternAtom (w->app->dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
693 event.xclient.format = 32;
694 event.xclient.data.l[0] = CurrentTime;
695 event.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
696 event.xclient.data.l[2] = w->widget;
697 event.xclient.data.l[3] = 0;
698 event.xclient.data.l[4] = 0;
699
700 XSendEvent(w->app->dpy, tray, False, NoEventMask, &event);
701 }
702
quit(Widget_t * w)703 void quit(Widget_t *w) {
704 Atom WM_DELETE_WINDOW = XInternAtom(w->app->dpy, "WM_DELETE_WINDOW", True);
705 XClientMessageEvent xevent;
706 xevent.type = ClientMessage;
707 xevent.message_type = WM_DELETE_WINDOW;
708 xevent.display = w->app->dpy;
709 xevent.window = get_toplevel_widget(w->app)->widget;
710 xevent.format = 16;
711 xevent.data.l[0] = WM_DELETE_WINDOW;
712 XSendEvent(w->app->dpy, w->widget, 0, 0, (XEvent *)&xevent);
713 }
714
quit_widget(Widget_t * w)715 void quit_widget(Widget_t *w) {
716 Atom QUIT_WIDGET = XInternAtom(w->app->dpy, "WIDGET_DESTROY", False);
717 XClientMessageEvent xevent;
718 xevent.type = ClientMessage;
719 xevent.message_type = QUIT_WIDGET;
720 xevent.display = w->app->dpy;
721 xevent.window = w->widget;
722 xevent.format = 16;
723 xevent.data.l[0] = 1;
724 XSendEvent(w->app->dpy, w->widget, 0, 0, (XEvent *)&xevent);
725 }
726
727