From 78bc3304484e978ef2aff7a419fb4b1401ee8f43 Mon Sep 17 00:00:00 2001 From: o9000 Date: Thu, 30 Jul 2015 23:54:46 +0200 Subject: [PATCH] systray: Break embedding into 2 steps --- src/systray/systraybar.c | 113 +++++++++++++++++++++------------------ src/systray/systraybar.h | 3 ++ src/tint.c | 24 ++++++++- 3 files changed, 86 insertions(+), 54 deletions(-) diff --git a/src/systray/systraybar.c b/src/systray/systraybar.c index 971e9ed..7ebd528 100644 --- a/src/systray/systraybar.c +++ b/src/systray/systraybar.c @@ -632,7 +632,7 @@ gboolean reparent_icon(TrayWindow *traywin) XErrorHandler old = XSetErrorHandler(window_error_handler); if (systray_profile) fprintf(stderr, "XSelectInput(server.dsp, traywin->win, StructureNotifyMask)\n"); - XSelectInput(server.dsp, traywin->win, SubstructureNotifyMask | StructureNotifyMask | PropertyChangeMask); + XSelectInput(server.dsp, traywin->win, SubstructureNotifyMask | StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); XWithdrawWindow(server.dsp, traywin->win, server.screen); XReparentWindow(server.dsp, traywin->win, traywin->parent, 0, 0); @@ -640,25 +640,6 @@ gboolean reparent_icon(TrayWindow *traywin) fprintf(stderr, "XMoveResizeWindow(server.dsp, traywin->win = %ld, 0, 0, traywin->width = %d, traywin->height = %d)\n", traywin->win, traywin->width, traywin->height); XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height); - // Embed into parent - { - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.serial = 0; - e.xclient.send_event = True; - e.xclient.message_type = server.atom._XEMBED; - e.xclient.window = traywin->win; - e.xclient.format = 32; - e.xclient.data.l[0] = CurrentTime; - e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; - e.xclient.data.l[2] = 0; - e.xclient.data.l[3] = traywin->parent; - e.xclient.data.l[4] = 0; - if (systray_profile) - fprintf(stderr, "XSendEvent(server.dsp, traywin->win, False, 0xFFFFFF, &e)\n"); - XSendEvent(server.dsp, traywin->win, False, NoEventMask, &e); - } - XSync(server.dsp, False); XSetErrorHandler(old); if (error != FALSE) { @@ -675,6 +656,63 @@ gboolean reparent_icon(TrayWindow *traywin) return TRUE; } +gboolean is_embedded(TrayWindow *traywin) +{ + Atom acttype; + int actfmt; + unsigned long nbitem, bytes; + unsigned long *data = 0; + int ret; + + if (systray_profile) + fprintf(stderr, "XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data)\n"); + ret = XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, (unsigned char**)&data); + if (ret == Success) { + if (data) { + if (nbitem >= 2) { + int hide = ((data[1] & XEMBED_MAPPED) == 0); + if (hide) { + XFree(data); + return FALSE; + } else { + XFree(data); + return TRUE; + } + } + XFree(data); + } + } + return FALSE; +} + +gboolean request_embed_icon(TrayWindow *traywin) +{ + if (traywin->embed_requested) + return TRUE; + + { + XEvent e; + e.xclient.type = ClientMessage; + e.xclient.serial = 0; + e.xclient.send_event = True; + e.xclient.message_type = server.atom._XEMBED; + e.xclient.window = traywin->win; + e.xclient.format = 32; + e.xclient.data.l[0] = CurrentTime; + e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; + e.xclient.data.l[2] = 0; + e.xclient.data.l[3] = traywin->parent; + e.xclient.data.l[4] = 0; + if (systray_profile) + fprintf(stderr, "XSendEvent(server.dsp, traywin->win, False, 0xFFFFFF, &e)\n"); + XSendEvent(server.dsp, traywin->win, False, NoEventMask, &e); + XSync(server.dsp, False); + } + + traywin->embed_requested = 1; + return TRUE; +} + gboolean embed_icon(TrayWindow *traywin) { fprintf(stderr, "embedding tray icon\n"); @@ -682,6 +720,8 @@ gboolean embed_icon(TrayWindow *traywin) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); if (traywin->embedded) return TRUE; + if (!is_embedded(traywin)) + return FALSE; Panel* panel = systray.area.panel; @@ -689,39 +729,6 @@ gboolean embed_icon(TrayWindow *traywin) error = FALSE; XErrorHandler old = XSetErrorHandler(window_error_handler); - if (0) { - Atom acttype; - int actfmt; - unsigned long nbitem, bytes; - unsigned char *data = 0; - int ret; - - if (systray_profile) - fprintf(stderr, "XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data)\n"); - ret = XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data); - if (ret == Success) { - if (data) { - if (nbitem >= 2) { - int hide = ((data[1] & XEMBED_MAPPED) == 0); - if (hide) { - // In theory we have to check the embedding with this and remove icons that refuse embedding. - // In practice we have no idea when the other application processes the event and accepts the embed so we cannot check without a race. - // Race can be triggered with PyGtk(2) apps. - //fprintf(stderr, RED "tint2: window refused embedding\n" RESET); - //remove_icon(traywin); - //XFree(data); - //return FALSE; - } - } - XFree(data); - } - } else { - fprintf(stderr, RED "tint2 : xembed error\n" RESET); - remove_icon(traywin); - return FALSE; - } - } - // Redirect rendering when using compositing if (systray_composited) { if (systray_profile) diff --git a/src/systray/systraybar.h b/src/systray/systraybar.h index 79e6f5e..19cca2f 100644 --- a/src/systray/systraybar.h +++ b/src/systray/systraybar.h @@ -50,6 +50,7 @@ typedef struct struct timespec time_last_render; int num_fast_renders; int reparented; + int embed_requested; int embedded; int bad_size_counter; timeout* resize_timeout; @@ -91,11 +92,13 @@ void net_message(XClientMessageEvent *e); gboolean add_icon(Window id); gboolean reparent_icon(TrayWindow *traywin); +gboolean is_embedded(TrayWindow *traywin); gboolean embed_icon(TrayWindow *traywin); void remove_icon(TrayWindow *traywin); void refresh_systray_icons(); void systray_render_icon(void *t); +gboolean request_embed_icon(TrayWindow *traywin); void systray_reconfigure_event(TrayWindow *traywin, XEvent *e); void systray_destroy_event(TrayWindow *traywin); void kde_update_icons(); diff --git a/src/tint.c b/src/tint.c index 9550f56..6f90c3e 100644 --- a/src/tint.c +++ b/src/tint.c @@ -1279,10 +1279,28 @@ start: break; case PropertyNotify: + for (it = systray.list_icons; it ; it = g_slist_next(it)) { + TrayWindow *traywin = (TrayWindow*)it->data; + if (traywin->win == e.xany.window && e.xproperty.atom == server.atom._XEMBED_INFO) { + fprintf(stderr, "PropertyNotify\n"); + if (is_embedded(traywin)) + embed_icon(traywin); + break; + } + } event_property_notify(&e); break; case ConfigureNotify: + for (it = systray.list_icons; it ; it = g_slist_next(it)) { + TrayWindow *traywin = (TrayWindow*)it->data; + if (traywin->win == e.xany.window) { + fprintf(stderr, "ConfigureNotify\n"); + if (is_embedded(traywin)) + embed_icon(traywin); + break; + } + } event_configure_notify(&e); break; @@ -1291,6 +1309,7 @@ start: for (it = systray.list_icons; it ; it = g_slist_next(it)) { TrayWindow *traywin = (TrayWindow*)it->data; if (traywin->win == e.xany.window) { + fprintf(stderr, "ConfigureRequest\n"); systray_reconfigure_event(traywin, &e); break; } @@ -1306,8 +1325,11 @@ start: for (it = systray.list_icons; it; it = g_slist_next(it)) { TrayWindow *traywin = (TrayWindow*)it->data; if (traywin->win == e.xreparent.window) { + fprintf(stderr, "ReparentNotify\n"); if (traywin->parent == e.xreparent.parent) { - embed_icon(traywin); + request_embed_icon(traywin); + if (is_embedded(traywin)) + embed_icon(traywin); } else { remove_icon(traywin); }