55 return XOpenDisplay(display_name);
63 if (w->
xic) XDestroyIC(w->
xic);
64 if (w->
xim) XCloseIM(w->
xim);
70 return DefaultRootWindow(main->
dpy);
74 int from_x,
int from_y,
int *to_x,
int *to_y) {
76 XTranslateCoordinates(w->
app->
dpy, from_window, to_window,
77 from_x, from_y, to_x, to_y, &child);
82 XWindowAttributes attrs;
86 metrics->
width = attrs.width;
87 metrics->
height = attrs.height;
88 metrics->
visible = (attrs.map_state == IsViewable);
92 int base_width,
int base_height) {
93 XSizeHints* win_size_hints;
94 win_size_hints = XAllocSizeHints();
95 win_size_hints->flags = PMinSize|PBaseSize|PWinGravity;
96 win_size_hints->min_width = min_width;
97 win_size_hints->min_height = min_height;
98 win_size_hints->base_width = base_width;
99 win_size_hints->base_height = base_height;
100 win_size_hints->win_gravity = CenterGravity;
101 XSetWMNormalHints(w->
app->
dpy, w->
widget, win_size_hints);
102 XFree(win_size_hints);
106 XMoveWindow(dpy,w->
widget, x, y);
110 XResizeWindow(dpy, w->
widget, x, y);
114 *width = cairo_xlib_surface_get_width(surface);
115 *height = cairo_xlib_surface_get_height(surface);
119 cairo_xlib_surface_set_size(w->
surface, width, height);
123 int x,
int y,
int width,
int height) {
124 XSetWindowAttributes attributes;
125 attributes.save_under = True;
126 attributes.override_redirect = 0;
128 long event_mask = StructureNotifyMask|ExposureMask|KeyPressMask
129 |EnterWindowMask|LeaveWindowMask|ButtonReleaseMask
130 |ButtonPressMask|Button1MotionMask;
134 w->
widget = XCreateWindow(app->
dpy, win , x, y, width, height, 0,
135 CopyFromParent, InputOutput, CopyFromParent,
136 CopyFromParent, &attributes);
137 debug_print(
"XCreateWindow\n");
139 XSetLocaleModifiers(
"");
140 w->
xim = XOpenIM(app->
dpy, 0, 0, 0);
142 XSetLocaleModifiers(
"@im=none");
143 w->
xim = XOpenIM(app->
dpy, 0, 0, 0);
146 w->
xic = XCreateIC(w->
xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
147 XNClientWindow, w->
widget, XNFocusWindow, w->
widget, NULL);
151 XSelectInput(app->
dpy, w->
widget, event_mask);
156 DefaultVisual(app->
dpy, DefaultScreen(app->
dpy)), width, height);
160 int x,
int y,
int width,
int height) {
161 XSetWindowAttributes attributes;
162 attributes.save_under = True;
163 attributes.override_redirect = True;
165 long event_mask = StructureNotifyMask|ExposureMask|KeyPressMask
166 |EnterWindowMask|LeaveWindowMask|ButtonReleaseMask
167 |ButtonPressMask|Button1MotionMask;
171 w->
widget = XCreateWindow(app->
dpy, parent->
widget , x, y, width, height, 0,
172 CopyFromParent, InputOutput, CopyFromParent,
173 CopyFromParent|CWOverrideRedirect, &attributes);
174 debug_print(
"XCreateWindow\n");
176 XSetLocaleModifiers(
"");
177 w->
xim = XOpenIM(app->
dpy, 0, 0, 0);
179 XSetLocaleModifiers(
"@im=none");
180 w->
xim = XOpenIM(app->
dpy, 0, 0, 0);
183 w->
xic = XCreateIC(w->
xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
184 XNClientWindow, w->
widget, XNFocusWindow, w->
widget, NULL);
188 XSelectInput(app->
dpy, w->
widget, event_mask);
191 DefaultVisual(app->
dpy, DefaultScreen(app->
dpy)), width, height);
197 XInternAtom(w->
app->
dpy,
"_NET_WM_NAME", False),
198 XInternAtom(w->
app->
dpy,
"UTF8_STRING", False),
199 8, PropModeReplace, (
unsigned char *) title,
215 XQueryPointer(wid->
app->
dpy, wid->
widget, &root, &child, &rx, &ry, &x, &y, &mask);
224 memset(&exp, 0,
sizeof(exp));
235 case ConfigureNotify:
238 debug_print(
"Widget_t ConfigureNotify \n");
241 case VisibilityNotify:
243 debug_print(
"Widget_t VisibilityNotify \n");
247 if (xev->xexpose.count == 0) {
250 while (XCheckTypedWindowEvent(main->
dpy, wid->
widget, Expose, &ev)) {}
253 debug_print(
"Widget_t Expose \n");
258 if (wid->
state == 4)
break;
261 debug_print(
"Widget_t ButtonPress %i\n", xev->xbutton.
button);
269 if (wid->
state == 4)
break;
270 if (xbutton->
button == Button1) {
284 debug_print(
"Widget_t ButtonRelease %i\n", xev->xbutton.
button);
289 if (wid->
state == 4)
break;
292 debug_print(
"Widget_t KeyPress %u\n", xev->xkey.
keycode);
297 if (wid->
state == 4)
break;
298 unsigned short is_retriggered = 0;
301 XQueryKeymap(main->
dpy, keys);
303 if((keys[xev->xkey.
keycode>>3] & (0x1 << (xev->xkey.
keycode % 8))) &&
308 if (!is_retriggered) {
310 debug_print(
"Widget_t KeyRelease %u\n", xev->xkey.
keycode);
316 wid->
flags &= ~HAS_FOCUS;
317 if (wid->
state == 4)
break;
318 if(!(xev->xcrossing.
state & Button1Mask) &&
319 !(xev->xcrossing.
state & Button2Mask) &&
320 !(xev->xcrossing.
state & Button3Mask)) {
325 debug_print(
"Widget_t LeaveNotify \n");
330 if (wid->
state == 4)
break;
331 if(!(xev->xcrossing.
state & Button1Mask) &&
332 !(xev->xcrossing.
state & Button2Mask) &&
333 !(xev->xcrossing.
state & Button3Mask)) {
339 debug_print(
"Widget_t EnterNotify \n");
343 if (wid->
state == 4)
break;
344 if (xev->xmotion.
state) {
348 debug_print(
"Widget_t MotionNotify x = %i Y = %i \n",xev->xmotion.
x,xev->xmotion.
y );
351 case SelectionRequest:
352 if (xev->xselectionrequest.selection != main->
selection)
break;
357 case SelectionNotify:
358 if (xev->xselection.property == None) {
362 if (xev->xselection.selection == main->
selection) {
366 debug_print(
"Widget_t SelectionNotify\n");
372 debug_print(
"XdndPosition\n");
374 }
else if (xev->xclient.message_type == main->
XdndEnter) {
375 debug_print(
"XdndEnter\n");
377 }
else if (xev->xclient.message_type == main->
XdndLeave) {
378 debug_print(
"XdndLeave\n");
382 }
else if (xev->xclient.message_type == main->
XdndDrop) {
391 }
else if (xev->xclient.message_type == XInternAtom(wid->
app->
dpy,
"WIDGET_DESTROY", 1)) {
410 Atom dnd_version = 5;
412 32, PropModeReplace, (
unsigned char*)&dnd_version, 1);
421 if ((q = r = strstr(str, sub)) != NULL) {
422 size_t len = strlen(sub);
423 while ((r = strstr(p = r + len, sub)) != NULL) {
427 while ((*q++ = *p++) !=
'\0')
432void strdecode(
char *target,
const char *needle,
const char *replacement) {
433 char buffer[1024] = { 0 };
434 char *insert_point = &buffer[0];
435 const char *tmp = target;
436 size_t needle_len = strlen(needle);
437 size_t repl_len = strlen(replacement);
440 const char *p = strstr(tmp, needle);
442 strcpy(insert_point, tmp);
445 memcpy(insert_point, tmp, p - tmp);
446 insert_point += p - tmp;
447 memcpy(insert_point, replacement, repl_len);
448 insert_point += repl_len;
449 tmp = p + needle_len;
451 strcpy(target, buffer);
460 unsigned long count = 0, remaining;
461 unsigned char* data = 0;
463 XGetWindowProperty(w->
app->
dpy,w->
widget, event->xselection.property,
465 &count, &remaining, &data);
469 if (!data || count == 0) {
472 char* dndfile = (
char*)data;
484 if (DND_STATUS_ACCEPT(event)) {
489 unsigned long count, remaining;
490 unsigned char *data = 0;
493 0, 0x8000000L, False, XA_ATOM, &type, &format, &count, &remaining, &data);
494 if (!data || type != XA_ATOM || format != 32) {
501 for (
unsigned long l = 1; l < count; l++) {
513 for (
int i = 2; i < 5; ++i) {
517 main->
dnd_type =
event->xclient.data.l[i];
526 memset (&xev, 0,
sizeof (
XEvent));
527 xev.xany.type = ClientMessage;
528 xev.xany.display = w->
app->
dpy;
531 xev.xclient.format = 32;
532 xev.xclient.data.l[0] =
event->xany.
window;
533 xev.xclient.data.l[1] = (w->
app->
dnd_type != None) ? 1 : 0;
534 xev.xclient.data.l[2] = DND_DROP_TIME(event);
535 xev.xclient.data.l[3] = 0;
545 memset (&xev, 0,
sizeof (
XEvent));
546 xev.xany.type = ClientMessage;
547 xev.xany.display = w->
app->
dpy;
550 xev.xclient.format = 32;
551 xev.xclient.data.l[0] =
event->xany.
window;
552 xev.xclient.data.l[1] = 1;
562 Atom XSEL_DATA = XInternAtom(w->
app->
dpy,
"XSEL_DATA", 0);
567 if(event->xselection.property) {
571 unsigned long N, size;
572 XGetWindowProperty(event->xselection.display, event->xselection.requestor,
573 event->xselection.property, 0L,(~0L), 0, AnyPropertyType, &target,
574 &format, &size, &N,(
unsigned char**)&data);
575 if(target == w->
app->
UTF8 || target == XA_STRING) {
578 w->
app->
ctext = (
unsigned char*)strndup(data, size);
581 XDeleteProperty(event->xselection.display, event->xselection.requestor, event->xselection.property);
591 w->
app->
ctext = (
unsigned char*)strndup(text, size);
596 XSelectionRequestEvent * xsr = &
event->xselectionrequest;
598 memset (&xev, 0,
sizeof (XSelectionEvent));
600 xev.type = SelectionNotify;
601 xev.display = xsr->display;
602 xev.requestor = xsr->requestor;
603 xev.selection = xsr->selection;
604 xev.time = xsr->time;
605 xev.target = xsr->target;
606 xev.property = xsr->property;
608 R = XChangeProperty (xev.display, xev.requestor, xev.property, XA_ATOM, 32,
609 PropModeReplace, (
unsigned char*)&w->
app->
UTF8, 1);
610 }
else if (xev.target == XA_STRING || xev.target == w->
app->
text_atom) {
611 R = XChangeProperty(xev.display, xev.requestor, xev.property, XA_STRING, 8,
613 }
else if (xev.target == w->
app->
UTF8) {
614 R = XChangeProperty(xev.display, xev.requestor, xev.property, w->
app->
UTF8, 8,
619 if ((R & 2) == 0) XSendEvent (w->
app->
dpy, xev.requestor, 0, 0, (
XEvent *)&xev);
620 debug_print(
"send to clipboard %s\n", w->
app->
ctext);
624 XConfigureEvent notify;
625 memset(¬ify, 0,
sizeof(notify));
626 notify.type = ConfigureNotify;
627 notify.display = w->
app->
dpy;
628 notify.send_event = True;
630 notify.window = w->
widget;
633 notify.width = width;
634 notify.height = height;
635 notify.border_width = 0;
637 notify.override_redirect = 1;
643 memset(&event, 0,
sizeof(
XEvent));
644 XWindowAttributes attr;
646 event.type = ButtonPress;
647 event.xbutton.same_screen =
true;
648 event.xbutton.root = None;
649 event.xbutton.window = w->
widget;
650 event.xbutton.subwindow = None;
653 event.xbutton.x_root = attr.x;
654 event.xbutton.y_root = attr.y;
655 event.xbutton.state = 0;
656 event.xbutton.button = Button1;
657 XSendEvent(w->
app->
dpy, PointerWindow, True, ButtonPressMask, &event);
662 memset(&event, 0,
sizeof(
XEvent));
663 XWindowAttributes attr;
665 event.type = ButtonRelease;
666 event.xbutton.same_screen =
true;
667 event.xbutton.root = None;
668 event.xbutton.window = w->
widget;
669 event.xbutton.subwindow = None;
672 event.xbutton.x_root = attr.x;
673 event.xbutton.y_root = attr.y;
674 event.xbutton.state = 0;
675 event.xbutton.button = Button1;
676 XSendEvent(w->
app->
dpy, PointerWindow, True, ButtonReleaseMask, &event);
685 xscreen=DefaultScreenOfDisplay(w->
app->
dpy);
686 sprintf(buf,
"_NET_SYSTEM_TRAY_S%d",XScreenNumberOfScreen (xscreen));
687 Atom selection_atom = XInternAtom (w->
app->
dpy,buf,0);
689 Window tray = XGetSelectionOwner (w->
app->
dpy,selection_atom);
690 Atom visualatom = XInternAtom(w->
app->
dpy,
"_NET_SYSTEM_TRAY_VISUAL", False);
691 VisualID value = XVisualIDFromVisual(DefaultVisual(w->
app->
dpy, DefaultScreen(w->
app->
dpy)));
692 XChangeProperty(w->
app->
dpy, w->
widget, visualatom, XA_VISUALID, 32,
693 PropModeReplace, (
unsigned char*)&value, 1);
696 XSelectInput (w->
app->
dpy,tray,StructureNotifyMask);
699 XWindowAttributes attrs;
700 XGetWindowAttributes(w->
app->
dpy, DefaultRootWindow(w->
app->
dpy), &attrs);
702 XImage *image = NULL;
704 image = XGetImage(w->
app->
dpy, DefaultRootWindow(w->
app->
dpy),
705 attrs.width -2, attrs.height -2, 1, 1, AllPlanes, XYPixmap);
708 c.pixel = XGetPixel(image, 0, 0);
709 XQueryColor (w->
app->
dpy, DefaultColormap(w->
app->
dpy, DefaultScreen (w->
app->
dpy)), &c);
710 double r = (double)c.red/65535.0;
711 double g = (double)c.green/65535.0;
712 double b = (double)c.blue/65535.0;
714 XDestroyImage(image);
718 memset(&event, 0,
sizeof(event));
719 event.xclient.type = ClientMessage;
720 event.xclient.window = tray;
721 event.xclient.message_type = XInternAtom (w->
app->
dpy,
"_NET_SYSTEM_TRAY_OPCODE", False );
722 event.xclient.format = 32;
723 event.xclient.data.l[0] = CurrentTime;
724 event.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
725 event.xclient.data.l[2] = w->
widget;
726 event.xclient.data.l[3] = 0;
727 event.xclient.data.l[4] = 0;
729 XSendEvent(w->
app->
dpy, tray, False, NoEventMask, &event);
743 return XGrabPointer(w->
app->
dpy, DefaultRootWindow(w->
app->
dpy), True,
744 ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
745 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
750 XSelectInput(w->
app->
dpy, w->
widget,StructureNotifyMask|ExposureMask|KeyPressMask
751 |EnterWindowMask|LeaveWindowMask|ButtonReleaseMask
752 |ButtonPressMask|Button1MotionMask|PointerMotionMask);
756 XSetWindowAttributes attributes;
757 attributes.override_redirect = True;
758 XChangeWindowAttributes(w->
app->
dpy, w->
widget, CWOverrideRedirect, &attributes);
760 Atom window_type = XInternAtom(w->
app->
dpy,
"_NET_WM_WINDOW_TYPE", False);
761 Atom window_type_popup = XInternAtom(w->
app->
dpy,
"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False);
763 XA_ATOM, 32, PropModeReplace, (
unsigned char *) &window_type_popup,1 );
765 Atom window_state = XInternAtom(w->
app->
dpy,
"_NET_WM_STATE", False);
766 Atom window_state_modal = XInternAtom(w->
app->
dpy,
"_NET_WM_STATE_MODAL", False);
768 XA_ATOM, 32, PropModeReplace, (
unsigned char *) &window_state_modal, 1);
777 int snum = DefaultScreen(w->
app->
dpy);
778 return DisplayHeight(w->
app->
dpy, snum);
782 int snum = DefaultScreen(w->
app->
dpy);
783 return DisplayWidth(w->
app->
dpy, snum);
788 return (stat(filename, &sb) == 0 && S_ISDIR(sb.st_mode));
793 asprintf(&pPath,
"%s", getenv(
"HOME"));
794 assert(pPath != NULL);
801 Xutf8LookupString(w->
xic, key, buf, bufsize - 1, &keysym, &status);
802 return (status == XLookupChars || status == XLookupBoth);
806 XFreePixmap(w->
app->
dpy, pixmap);
812 XClientMessageEvent xevent;
813 xevent.type = ClientMessage;
814 xevent.message_type = WM_DELETE_WINDOW;
815 xevent.display = w->
app->
dpy;
818 xevent.data.l[0] = WM_DELETE_WINDOW;
824 XClientMessageEvent xevent;
825 xevent.type = ClientMessage;
826 xevent.message_type = QUIT_WIDGET;
827 xevent.display = w->
app->
dpy;
828 xevent.window = w->
widget;
830 xevent.data.l[0] = 1;
835 Atom WM_DELETE_WINDOW;
836 WM_DELETE_WINDOW = XInternAtom(wid->
app->
dpy,
"WM_DELETE_WINDOW", True);
837 XSetWMProtocols(wid->
app->
dpy, wid->
widget, &WM_DELETE_WINDOW, 1);
838 return WM_DELETE_WINDOW;
842 return XInternAtom(wid->
app->
dpy,
"WIDGET_DESTROY", False);
847 Atom WM_DELETE_WINDOW;
848 WM_DELETE_WINDOW = XInternAtom(main->
dpy,
"WM_DELETE_WINDOW", True);
849 XSetWMProtocols(main->
dpy, wid->
widget, &WM_DELETE_WINDOW, 1);
855 while (main->
run && (XNextEvent(main->
dpy, &xev)>=0)) {
856 if (XFilterEvent(&xev, None))
continue;
866 bool is_item = False;
899 if (xev.xbutton.
window == view_port->
widget) is_item = True;
902 XUngrabPointer(main->
dpy,CurrentTime);
934 if (xev.xclient.data.l[0] == (
long int)WM_DELETE_WINDOW &&
937 }
else if (xev.xclient.data.l[0] == (
long int)WM_DELETE_WINDOW) {
955 while (XPending(main->
dpy) > 0) {
956 XNextEvent(main->
dpy, &xev);
957 if (xev.type == ClientMessage || xev.type == SelectionNotify) {
969 bool is_item = False;
1002 if (xev.xbutton.
window == view_port->
widget) is_item = True;
1005 XUngrabPointer(main->
dpy,CurrentTime);
1036 if (xev.xclient.data.l[0] == (
long int)XInternAtom(main->
dpy,
"WM_DELETE_WINDOW", True) ) {
1051 main->
XdndAware = XInternAtom (main->
dpy,
"XdndAware", False);
1054 main->
XdndStatus = XInternAtom (main->
dpy,
"XdndStatus", False);
1055 main->
XdndEnter = XInternAtom (main->
dpy,
"XdndEnter", False);
1057 main->
XdndLeave = XInternAtom (main->
dpy,
"XdndLeave", False);
1058 main->
XdndDrop = XInternAtom (main->
dpy,
"XdndDrop", False);
1066 main->
selection = XInternAtom(main->
dpy,
"CLIPBOARD", 0);
1069 main->
UTF8 = XInternAtom(main->
dpy,
"UTF8_STRING", 1);
1070 if (main->
UTF8 == None) main->
UTF8 = XA_STRING;
evfunc button_release_callback
xevfunc configure_callback
evfunc key_release_callback
evfunc key_press_callback
xevfunc visibiliy_change_callback
evfunc double_click_callback
xevfunc dnd_notify_callback
evfunc button_press_callback
Metrics_t - struct to receive window size, position & visibility Pass this struct to os_get_window_...
Xputty - the main struct. It should be declared before any other call to a Xputty function....
void adj_set_motion_state(void *w, float x, float y)
adj_set_motion_state - internal use to set value and state of the Adjustment_t on mouse pointer movme...
Multiplatform implementation of asprintf() from: https://stackoverflow.com/questions/40159892/using-a...
int asprintf(char *strp[], const char *fmt,...)
int childlist_find_widget(Childlist_t *childlist, Window child_window)
childlist_find_widget - find a child Widget_t in a the childlist by given the Window id
int childlist_has_child(Childlist_t *childlist)
childlist_has_child - check if a Widget_t Childlist_t contain a child
void set_systray_color(Xputty *main, double r, double g, double b, double a)
set_systray_color - set the systray background color