systray: Break embedding into 2 steps
This commit is contained in:
parent
3805adc9f3
commit
78bc330448
3 changed files with 86 additions and 54 deletions
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
24
src/tint.c
24
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue