From 46aab61bf6a6d7509367a5c016a5e9baab9646b3 Mon Sep 17 00:00:00 2001 From: o9000 Date: Thu, 16 Jul 2015 22:25:18 +0200 Subject: [PATCH] Revert "systray: Process XEmbed events according to spec" This reverts commit 227dc8e48ab70685129fcc6359bb4c0d2162e49f. --- src/systray/systraybar.c | 238 ++++++++++++++++++++++----------------- src/systray/systraybar.h | 7 +- src/tint.c | 21 +--- 3 files changed, 137 insertions(+), 129 deletions(-) diff --git a/src/systray/systraybar.c b/src/systray/systraybar.c index 48dd3db..51b0867 100644 --- a/src/systray/systraybar.c +++ b/src/systray/systraybar.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "systraybar.h" @@ -610,14 +609,12 @@ gboolean reparent_icon(TrayWindow *traywin) if (traywin->reparented) return TRUE; - Panel* panel = systray.area.panel; - // Watch for the icon trying to resize itself / closing again XSync(server.dsp, False); error = FALSE; XErrorHandler old = XSetErrorHandler(window_error_handler); if (systray_profile) - fprintf(stderr, "XSelectInput(server.dsp, traywin->win, StructureNotifyMask | PropertyChangeMask)\n"); + fprintf(stderr, "XSelectInput(server.dsp, traywin->win, StructureNotifyMask)\n"); XSelectInput(server.dsp, traywin->win, StructureNotifyMask | PropertyChangeMask); XSync(server.dsp, False); XSetErrorHandler(old); @@ -633,19 +630,138 @@ gboolean reparent_icon(TrayWindow *traywin) XSync(server.dsp, False); error = FALSE; old = XSetErrorHandler(window_error_handler); - if (systray_profile) - fprintf(stderr, "XWithdrawWindow(server.dsp, traywin->win, server.screen)\n"); - XWithdrawWindow(server.dsp, traywin->win, server.screen); if (systray_profile) fprintf(stderr, "XReparentWindow(server.dsp, traywin->win, traywin->parent, 0, 0)\n"); + XWithdrawWindow(server.dsp, traywin->win, server.screen); XReparentWindow(server.dsp, traywin->win, traywin->parent, 0, 0); - if (systray_profile) - fprintf(stderr, "XMoveResizeWindow(server.dsp, traywin->parent = %ld, traywin->x = %d, traywin->y = %d, traywin->width = %d, traywin->height = %d)\n", traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height); - XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height); if (systray_profile) 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); + XSync(server.dsp, False); + XSetErrorHandler(old); + if (error != FALSE) { + fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid); + remove_icon(traywin); + return FALSE; + } + + traywin->reparented = 1; + + if (systray_profile) + fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); + + return TRUE; +} + +gboolean embed_icon(TrayWindow *traywin) +{ + if (systray_profile) + fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); + if (traywin->embedded) + return TRUE; + + Panel* panel = systray.area.panel; + + // Watch for the icon trying to resize itself / closing again + XSync(server.dsp, False); + error = FALSE; + XErrorHandler old = XSetErrorHandler(window_error_handler); + if (systray_profile) + fprintf(stderr, "XSelectInput(server.dsp, traywin->win, StructureNotifyMask)\n"); + XSelectInput(server.dsp, traywin->win, StructureNotifyMask | PropertyChangeMask); + XSync(server.dsp, False); + XSetErrorHandler(old); + if (error != FALSE) { + fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid); + remove_icon(traywin); + return FALSE; + } + + // Reparent + if (systray_profile) + fprintf(stderr, "XSync(server.dsp, False)\n"); + XSync(server.dsp, False); + error = FALSE; + old = XSetErrorHandler(window_error_handler); + if (systray_profile) + fprintf(stderr, "XReparentWindow(server.dsp, traywin->win, traywin->parent, 0, 0)\n"); + XWithdrawWindow(server.dsp, traywin->win, server.screen); + XReparentWindow(server.dsp, traywin->win, traywin->parent, 0, 0); + if (systray_profile) + 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); + + XSync(server.dsp, False); + XSetErrorHandler(old); + if (error != FALSE) { + fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid); + remove_icon(traywin); + return FALSE; + } + + // 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; + XSync(server.dsp, False); + error = FALSE; + XErrorHandler old = XSetErrorHandler(window_error_handler); + if (systray_profile) + fprintf(stderr, "XSendEvent(server.dsp, traywin->win, False, 0xFFFFFF, &e)\n"); + XSendEvent(server.dsp, traywin->win, False, 0xFFFFFF, &e); + XSync(server.dsp, False); + XSetErrorHandler(old); + if (error != FALSE) { + fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->pid); + remove_icon(traywin); + return FALSE; + } + } + + { + 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) @@ -669,103 +785,15 @@ gboolean reparent_icon(TrayWindow *traywin) } XSync(server.dsp, False); + if (systray_profile) + fprintf(stderr, "XMoveResizeWindow(server.dsp, traywin->parent = %ld, traywin->x = %d, traywin->y = %d, traywin->width = %d, traywin->height = %d)\n", traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height); + XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height); + + if (systray_profile) + fprintf(stderr, "XSync(server.dsp, False)\n"); XSync(server.dsp, False); - XSetErrorHandler(old); - if (error != FALSE) { - fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid); - remove_icon(traywin); - return FALSE; - } - traywin->reparented = 1; - - if (systray_profile) - fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); - - return TRUE; -} - -gboolean start_embedding_icon(TrayWindow *traywin) -{ - if (systray_profile) - fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); - if (traywin->embedding_started) - return TRUE; - - // 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; - XSync(server.dsp, False); - error = FALSE; - XErrorHandler old = XSetErrorHandler(window_error_handler); - 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) { - fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->pid); - remove_icon(traywin); - return FALSE; - } - - traywin->embedding_started = 1; - - if (systray_profile) - fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); - - return TRUE; -} - -gboolean icon_embedded(TrayWindow *traywin) -{ - 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); - gboolean hide = False; - if (ret == Success) { - if (data) { - if (nbitem >= 2) { - hide = ((data[1] & XEMBED_MAPPED) == 0); - } - XFree(data); - } - } else { - fprintf(stderr, RED "tint2 : xembed error\n" RESET); - hide = TRUE; - } - return !hide; -} - -gboolean finalize_embedding_icon(TrayWindow *traywin) -{ - if (systray_profile) - fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); - if (traywin->embedding_finalized) - return TRUE; - - if (!icon_embedded(traywin)) { - remove_icon(traywin); - return FALSE; - } - - traywin->embedding_finalized = 1; + traywin->embedded = 1; if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); diff --git a/src/systray/systraybar.h b/src/systray/systraybar.h index 43c7f8d..11b7d0c 100644 --- a/src/systray/systraybar.h +++ b/src/systray/systraybar.h @@ -50,8 +50,7 @@ typedef struct struct timespec time_last_render; int num_fast_renders; int reparented; - int embedding_started; - int embedding_finalized; + int embedded; char *name; } TrayWindow; @@ -88,9 +87,7 @@ void net_message(XClientMessageEvent *e); gboolean add_icon(Window id); gboolean reparent_icon(TrayWindow *traywin); -gboolean start_embedding_icon(TrayWindow *traywin); -gboolean finalize_embedding_icon(TrayWindow *traywin); -gboolean icon_embedded(TrayWindow *traywin); +gboolean embed_icon(TrayWindow *traywin); void remove_icon(TrayWindow *traywin); void refresh_systray_icons(); diff --git a/src/tint.c b/src/tint.c index 74531ec..64b4467 100644 --- a/src/tint.c +++ b/src/tint.c @@ -1280,22 +1280,6 @@ start: case PropertyNotify: event_property_notify(&e); - if (e.xproperty.atom == server.atom._XEMBED_INFO) { - if (systray_profile) - fprintf(stderr, "XEMBED event\n"); - for (it = systray.list_icons; it; it = g_slist_next(it)) { - TrayWindow *traywin = (TrayWindow*)it->data; - if (traywin->win == e.xany.window) { - if (!traywin->embedding_finalized) { - finalize_embedding_icon(traywin); - } else { - if (!icon_embedded(traywin)) - remove_icon(traywin); - } - break; - } - } - } break; case ConfigureNotify: @@ -1303,6 +1287,7 @@ start: break; case ReparentNotify: + fprintf(stderr, "ReparentNotify\n"); if (!systray_enabled) break; panel = (Panel*)systray.area.panel; @@ -1311,10 +1296,8 @@ start: for (it = systray.list_icons; it; it = g_slist_next(it)) { TrayWindow *traywin = (TrayWindow*)it->data; if (traywin->win == e.xreparent.window) { - if (systray_profile) - fprintf(stderr, "ReparentNotify\n"); if (traywin->parent == e.xreparent.parent) { - start_embedding_icon(traywin); + embed_icon(traywin); } else { remove_icon(traywin); }