Merge pull request #904 from psychon/xembed-fixes

Some Xembed fixes
This commit is contained in:
Daniel Hahler 2016-06-01 00:14:47 +02:00
commit 12f42fc9cc
5 changed files with 55 additions and 25 deletions

View File

@ -24,6 +24,9 @@
#include "common/util.h" #include "common/util.h"
#include "common/atoms.h" #include "common/atoms.h"
/* I should really include the correct header instead... */
void luaA_systray_invalidate(void);
/** Send an XEMBED message to a window. /** Send an XEMBED message to a window.
* \param connection Connection to the X server. * \param connection Connection to the X server.
* \param towin Destination window * \param towin Destination window
@ -141,6 +144,7 @@ xembed_property_update(xcb_connection_t *connection, xembed_window_t *emwin,
xembed_window_deactivate(connection, emwin->win); xembed_window_deactivate(connection, emwin->win);
xembed_focus_out(connection, emwin->win); xembed_focus_out(connection, emwin->win);
} }
luaA_systray_invalidate();
} }
} }

28
event.c
View File

@ -711,6 +711,7 @@ static void
event_handle_maprequest(xcb_map_request_event_t *ev) event_handle_maprequest(xcb_map_request_event_t *ev)
{ {
client_t *c; client_t *c;
xembed_window_t *em;
xcb_get_window_attributes_cookie_t wa_c; xcb_get_window_attributes_cookie_t wa_c;
xcb_get_window_attributes_reply_t *wa_r; xcb_get_window_attributes_reply_t *wa_r;
xcb_get_geometry_cookie_t geom_c; xcb_get_geometry_cookie_t geom_c;
@ -724,10 +725,17 @@ event_handle_maprequest(xcb_map_request_event_t *ev)
if(wa_r->override_redirect) if(wa_r->override_redirect)
goto bailout; goto bailout;
if(xembed_getbywin(&globalconf.embedded, ev->window)) if((em = xembed_getbywin(&globalconf.embedded, ev->window)))
{ {
xcb_map_window(globalconf.connection, ev->window); xcb_map_window(globalconf.connection, ev->window);
xembed_window_activate(globalconf.connection, ev->window); xembed_window_activate(globalconf.connection, ev->window);
/* The correct way to set this is via the _XEMBED_INFO property. Neither
* of the XEMBED not the systray spec talk about mapping windows.
* Apparently, Qt doesn't care and does not set an _XEMBED_INFO
* property. Let's simulate the XEMBED_MAPPED bit.
*/
em->info.flags |= XEMBED_MAPPED;
luaA_systray_invalidate();
} }
else if((c = client_getbywin(ev->window))) else if((c = client_getbywin(ev->window)))
{ {
@ -770,14 +778,6 @@ event_handle_unmapnotify(xcb_unmap_notify_event_t *ev)
if((c = client_getbywin(ev->window))) if((c = client_getbywin(ev->window)))
client_unmanage(c, true); client_unmanage(c, true);
else
for(int i = 0; i < globalconf.embedded.len; i++)
if(globalconf.embedded.tab[i].win == ev->window)
{
xembed_window_array_take(&globalconf.embedded, i);
xcb_change_save_set(globalconf.connection, XCB_SET_MODE_DELETE, ev->window);
luaA_systray_invalidate();
}
} }
/** The randr screen change notify event handler. /** The randr screen change notify event handler.
@ -918,6 +918,16 @@ event_handle_reparentnotify(xcb_reparent_notify_event_t *ev)
if (ev->parent != globalconf.screen->root) if (ev->parent != globalconf.screen->root)
client_unmanage(c, true); client_unmanage(c, true);
} }
else if (ev->parent != globalconf.systray.window) {
/* Embedded window moved elsewhere, end of embedding */
for(int i = 0; i < globalconf.embedded.len; i++)
if(globalconf.embedded.tab[i].win == ev->window)
{
xembed_window_array_take(&globalconf.embedded, i);
xcb_change_save_set(globalconf.connection, XCB_SET_MODE_DELETE, ev->window);
luaA_systray_invalidate();
}
}
} }
static void static void

View File

@ -1113,7 +1113,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at
if(systray_iskdedockapp(w)) if(systray_iskdedockapp(w))
{ {
systray_request_handle(w, NULL); systray_request_handle(w);
return; return;
} }

View File

@ -124,11 +124,10 @@ systray_cleanup(void)
/** Handle a systray request. /** Handle a systray request.
* \param embed_win The window to embed. * \param embed_win The window to embed.
* \param info The embedding info
* \return 0 on no error. * \return 0 on no error.
*/ */
int int
systray_request_handle(xcb_window_t embed_win, xembed_info_t *info) systray_request_handle(xcb_window_t embed_win)
{ {
xembed_window_t em; xembed_window_t em;
xcb_get_property_cookie_t em_cookie; xcb_get_property_cookie_t em_cookie;
@ -145,7 +144,6 @@ systray_request_handle(xcb_window_t embed_win, xembed_info_t *info)
p_clear(&em_cookie, 1); p_clear(&em_cookie, 1);
if(!info)
em_cookie = xembed_info_get_unchecked(globalconf.connection, embed_win); em_cookie = xembed_info_get_unchecked(globalconf.connection, embed_win);
xcb_change_window_attributes(globalconf.connection, embed_win, XCB_CW_EVENT_MASK, xcb_change_window_attributes(globalconf.connection, embed_win, XCB_CW_EVENT_MASK,
@ -161,10 +159,11 @@ systray_request_handle(xcb_window_t embed_win, xembed_info_t *info)
em.win = embed_win; em.win = embed_win;
if(info) if (!xembed_info_get_reply(globalconf.connection, em_cookie, &em.info)) {
em.info = *info; /* Set some sane defaults */
else em.info.version = XEMBED_VERSION;
xembed_info_get_reply(globalconf.connection, em_cookie, &em.info); em.info.flags = XEMBED_MAPPED;
}
xembed_embedded_notify(globalconf.connection, em.win, xembed_embedded_notify(globalconf.connection, em.win,
globalconf.systray.window, globalconf.systray.window,
@ -196,7 +195,7 @@ systray_process_client_message(xcb_client_message_event_t *ev)
return -1; return -1;
if(globalconf.screen->root == geom_r->root) if(globalconf.screen->root == geom_r->root)
ret = systray_request_handle(ev->data.data32[2], NULL); ret = systray_request_handle(ev->data.data32[2]);
p_delete(&geom_r); p_delete(&geom_r);
break; break;
@ -248,6 +247,16 @@ xembed_process_client_message(xcb_client_message_event_t *ev)
return 0; return 0;
} }
static int
systray_num_visible_entries(void)
{
int result = 0;
foreach(em, globalconf.embedded)
if (em->info.flags & XEMBED_MAPPED)
result++;
return result;
}
/** Inform lua that the systray needs to be updated. /** Inform lua that the systray needs to be updated.
*/ */
void void
@ -257,7 +266,7 @@ luaA_systray_invalidate(void)
signal_object_emit(L, &global_signals, "systray::update", 0); signal_object_emit(L, &global_signals, "systray::update", 0);
/* Unmap now if the systray became empty */ /* Unmap now if the systray became empty */
if(globalconf.embedded.len == 0) if(systray_num_visible_entries() == 0)
xcb_unmap_window(globalconf.connection, globalconf.systray.window); xcb_unmap_window(globalconf.connection, globalconf.systray.window);
} }
@ -268,11 +277,12 @@ systray_update(int base_size, bool horizontal, bool reverse, int spacing, bool f
return; return;
/* Give the systray window the correct size */ /* Give the systray window the correct size */
int num_entries = systray_num_visible_entries();
uint32_t config_vals[4] = { base_size, base_size, 0, 0 }; uint32_t config_vals[4] = { base_size, base_size, 0, 0 };
if(horizontal) if(horizontal)
config_vals[0] = base_size * globalconf.embedded.len + spacing * (globalconf.embedded.len - 1); config_vals[0] = base_size * num_entries + spacing * (num_entries - 1);
else else
config_vals[1] = base_size * globalconf.embedded.len + spacing * (globalconf.embedded.len - 1); config_vals[1] = base_size * num_entries + spacing * (num_entries - 1);
xcb_configure_window(globalconf.connection, xcb_configure_window(globalconf.connection,
globalconf.systray.window, globalconf.systray.window,
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
@ -290,6 +300,12 @@ systray_update(int base_size, bool horizontal, bool reverse, int spacing, bool f
else else
em = &globalconf.embedded.tab[i]; em = &globalconf.embedded.tab[i];
if (!(em->info.flags & XEMBED_MAPPED))
{
xcb_unmap_window(globalconf.connection, em->win);
continue;
}
xcb_configure_window(globalconf.connection, em->win, xcb_configure_window(globalconf.connection, em->win,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
config_vals); config_vals);
@ -363,7 +379,7 @@ luaA_systray(lua_State *L)
globalconf.systray.parent = w; globalconf.systray.parent = w;
if(globalconf.embedded.len != 0) if(systray_num_visible_entries() != 0)
{ {
systray_update(base_size, horiz, revers, spacing, force_redraw); systray_update(base_size, horiz, revers, spacing, force_redraw);
xcb_map_window(globalconf.connection, xcb_map_window(globalconf.connection,
@ -371,7 +387,7 @@ luaA_systray(lua_State *L)
} }
} }
lua_pushinteger(L, globalconf.embedded.len); lua_pushinteger(L, systray_num_visible_entries());
luaA_object_push(L, globalconf.systray.parent); luaA_object_push(L, globalconf.systray.parent);
return 2; return 2;
} }

View File

@ -28,7 +28,7 @@
void systray_init(void); void systray_init(void);
void systray_cleanup(void); void systray_cleanup(void);
int systray_request_handle(xcb_window_t, xembed_info_t *); int systray_request_handle(xcb_window_t);
bool systray_iskdedockapp(xcb_window_t); bool systray_iskdedockapp(xcb_window_t);
int systray_process_client_message(xcb_client_message_event_t *); int systray_process_client_message(xcb_client_message_event_t *);
int xembed_process_client_message(xcb_client_message_event_t *); int xembed_process_client_message(xcb_client_message_event_t *);