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/atoms.h"
/* I should really include the correct header instead... */
void luaA_systray_invalidate(void);
/** Send an XEMBED message to a window.
* \param connection Connection to the X server.
* \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_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)
{
client_t *c;
xembed_window_t *em;
xcb_get_window_attributes_cookie_t wa_c;
xcb_get_window_attributes_reply_t *wa_r;
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)
goto bailout;
if(xembed_getbywin(&globalconf.embedded, ev->window))
if((em = xembed_getbywin(&globalconf.embedded, ev->window)))
{
xcb_map_window(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)))
{
@ -770,14 +778,6 @@ event_handle_unmapnotify(xcb_unmap_notify_event_t *ev)
if((c = client_getbywin(ev->window)))
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.
@ -918,6 +918,16 @@ event_handle_reparentnotify(xcb_reparent_notify_event_t *ev)
if (ev->parent != globalconf.screen->root)
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

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))
{
systray_request_handle(w, NULL);
systray_request_handle(w);
return;
}

View File

@ -124,11 +124,10 @@ systray_cleanup(void)
/** Handle a systray request.
* \param embed_win The window to embed.
* \param info The embedding info
* \return 0 on no error.
*/
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;
xcb_get_property_cookie_t em_cookie;
@ -145,8 +144,7 @@ systray_request_handle(xcb_window_t embed_win, xembed_info_t *info)
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,
select_input_val);
@ -161,10 +159,11 @@ systray_request_handle(xcb_window_t embed_win, xembed_info_t *info)
em.win = embed_win;
if(info)
em.info = *info;
else
xembed_info_get_reply(globalconf.connection, em_cookie, &em.info);
if (!xembed_info_get_reply(globalconf.connection, em_cookie, &em.info)) {
/* Set some sane defaults */
em.info.version = XEMBED_VERSION;
em.info.flags = XEMBED_MAPPED;
}
xembed_embedded_notify(globalconf.connection, em.win,
globalconf.systray.window,
@ -196,7 +195,7 @@ systray_process_client_message(xcb_client_message_event_t *ev)
return -1;
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);
break;
@ -248,6 +247,16 @@ xembed_process_client_message(xcb_client_message_event_t *ev)
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.
*/
void
@ -257,7 +266,7 @@ luaA_systray_invalidate(void)
signal_object_emit(L, &global_signals, "systray::update", 0);
/* 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);
}
@ -268,11 +277,12 @@ systray_update(int base_size, bool horizontal, bool reverse, int spacing, bool f
return;
/* 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 };
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
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,
globalconf.systray.window,
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
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_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
config_vals);
@ -363,7 +379,7 @@ luaA_systray(lua_State *L)
globalconf.systray.parent = w;
if(globalconf.embedded.len != 0)
if(systray_num_visible_entries() != 0)
{
systray_update(base_size, horiz, revers, spacing, force_redraw);
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);
return 2;
}

View File

@ -28,7 +28,7 @@
void systray_init(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);
int systray_process_client_message(xcb_client_message_event_t *);
int xembed_process_client_message(xcb_client_message_event_t *);