Turn this into a reparenting WM

Each window is now reparented under a window created by awesome. This window is
NOT visible, this commit should not cause any visible differences. Instead, this
is done to work around problems with X11.

The only alternative would be to ban windows by moving them offscreen which is
ugly in itself and breaks pagers. Doing it like this seems to be the better
solution.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2010-07-30 20:54:20 +02:00
parent 5d0a81c8bf
commit 102063dbbd
6 changed files with 67 additions and 18 deletions

View File

@ -737,8 +737,8 @@ event_handle_mappingnotify(xcb_mapping_notify_event_t *ev)
foreach(_c, globalconf.clients)
{
client_t *c = *_c;
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY);
xwindow_grabkeys(c->window, &c->keys);
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->frame_window, XCB_BUTTON_MASK_ANY);
xwindow_grabkeys(c->frame_window, &c->keys);
}
}
}
@ -747,6 +747,8 @@ static void
event_handle_reparentnotify(xcb_reparent_notify_event_t *ev)
{
client_t *c;
#warning ugly, gotta do this properly
return 0;
if((c = client_getbywin(ev->window)))
client_unmanage(c);

View File

@ -227,7 +227,7 @@ client_t *
client_getbywin(xcb_window_t w)
{
foreach(c, globalconf.clients)
if((*c)->window == w)
if((*c)->window == w || (*c)->frame_window == w)
return *c;
return NULL;
@ -313,7 +313,7 @@ client_ban(client_t *c)
{
if(!c->isbanned)
{
xcb_unmap_window(globalconf.connection, c->window);
xcb_unmap_window(globalconf.connection, c->frame_window);
c->isbanned = true;
@ -328,20 +328,32 @@ void
client_ignore_enterleave_events(void)
{
foreach(c, globalconf.clients)
{
xcb_change_window_attributes(globalconf.connection,
(*c)->window,
XCB_CW_EVENT_MASK,
(const uint32_t []) { CLIENT_SELECT_INPUT_EVENT_MASK & ~(XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW) });
xcb_change_window_attributes(globalconf.connection,
(*c)->frame_window,
XCB_CW_EVENT_MASK,
(const uint32_t []) { FRAME_SELECT_INPUT_EVENT_MASK & ~(XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW) });
}
}
void
client_restore_enterleave_events(void)
{
foreach(c, globalconf.clients)
{
xcb_change_window_attributes(globalconf.connection,
(*c)->window,
XCB_CW_EVENT_MASK,
(const uint32_t []) { CLIENT_SELECT_INPUT_EVENT_MASK });
xcb_change_window_attributes(globalconf.connection,
(*c)->frame_window,
XCB_CW_EVENT_MASK,
(const uint32_t []) { FRAME_SELECT_INPUT_EVENT_MASK });
}
}
/** Record that a client got focus.
@ -439,6 +451,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen,
(uint32_t[]) { XCB_STACK_MODE_BELOW});
client_t *c = client_new(globalconf.L);
xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
/* This cannot change, ever. */
c->phys_screen = phys_screen;
@ -446,6 +459,23 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen,
c->isbanned = true;
/* Store window */
c->window = w;
c->frame_window = xcb_generate_id(globalconf.connection);
xcb_create_window(globalconf.connection, s->root_depth, c->frame_window, s->root,
wgeom->x, wgeom->y, wgeom->width, wgeom->height,
wgeom->border_width, XCB_COPY_FROM_PARENT, s->root_visual,
XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY
| XCB_CW_WIN_GRAVITY | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
(const uint32_t [])
{
globalconf.colors.bg.pixel,
globalconf.colors.bg.pixel,
XCB_GRAVITY_NORTH_WEST,
XCB_GRAVITY_NORTH_WEST,
1,
FRAME_SELECT_INPUT_EVENT_MASK
});
xcb_reparent_window(globalconf.connection, w, c->frame_window, 0, 0);
xcb_map_window(globalconf.connection, w);
luaA_object_emit_signal(globalconf.L, -1, "property::window", 0);
/* Duplicate client and push it in client list */
@ -693,8 +723,10 @@ client_resize(client_t *c, area_t geometry, bool hints)
client_ignore_enterleave_events();
xcb_configure_window(globalconf.connection, c->window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
| XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
(uint32_t[]) { geometry.width, geometry.height });
xcb_configure_window(globalconf.connection, c->frame_window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
(uint32_t[]) { geometry.x, geometry.y, geometry.width, geometry.height });
client_restore_enterleave_events();
@ -934,7 +966,7 @@ client_unban(client_t *c)
{
if(c->isbanned)
{
xcb_map_window(globalconf.connection, c->window);
xcb_map_window(globalconf.connection, c->frame_window);
c->isbanned = false;
}
@ -989,6 +1021,8 @@ client_unmanage(client_t *c)
* after a restart anymore. */
xcb_change_save_set(globalconf.connection, XCB_SET_MODE_DELETE, c->window);
xcb_destroy_window(globalconf.connection, c->frame_window);
/* set client as invalid */
c->invalid = true;
@ -1651,8 +1685,8 @@ luaA_client_keys(lua_State *L)
{
luaA_key_array_set(L, 1, 2, keys);
luaA_object_emit_signal(L, 1, "property::keys", 0);
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY);
xwindow_grabkeys(c->window, keys);
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->frame_window, XCB_BUTTON_MASK_ANY);
xwindow_grabkeys(c->frame_window, keys);
}
return luaA_key_array_get(L, 1, keys);

View File

@ -31,9 +31,12 @@
#define CLIENT_SELECT_INPUT_EVENT_MASK (XCB_EVENT_MASK_STRUCTURE_NOTIFY \
| XCB_EVENT_MASK_PROPERTY_CHANGE \
| XCB_EVENT_MASK_FOCUS_CHANGE)
#define FRAME_SELECT_INPUT_EVENT_MASK (XCB_EVENT_MASK_STRUCTURE_NOTIFY \
| XCB_EVENT_MASK_ENTER_WINDOW \
| XCB_EVENT_MASK_LEAVE_WINDOW \
| XCB_EVENT_MASK_FOCUS_CHANGE)
| XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT)
/** Windows type */
typedef enum

View File

@ -28,6 +28,14 @@
LUA_CLASS_FUNCS(window, window_class)
static xcb_window_t
window_get(window_t *window)
{
if (window->frame_window != XCB_NONE)
return window->frame_window;
return window->window;
}
static void
window_wipe(window_t *window)
{
@ -47,7 +55,7 @@ luaA_window_buttons(lua_State *L)
{
luaA_button_array_set(L, 1, 2, &window->buttons);
luaA_object_emit_signal(L, 1, "property::buttons", 0);
xwindow_buttons_grab(window->window, &window->buttons);
xwindow_buttons_grab(window_get(window), &window->buttons);
}
return luaA_button_array_get(L, 1, &window->buttons);
@ -87,7 +95,7 @@ window_set_opacity(lua_State *L, int idx, double opacity)
if(window->opacity != opacity)
{
window->opacity = opacity;
xwindow_set_opacity(window->window, opacity);
xwindow_set_opacity(window_get(window), opacity);
luaA_object_emit_signal(L, idx, "property::opacity", 0);
}
}
@ -141,7 +149,7 @@ luaA_window_set_border_color(lua_State *L, window_t *window)
if(color_name &&
xcolor_init_reply(xcolor_init_unchecked(&window->border_color, color_name, len)))
{
xwindow_set_border_color(window->window, &window->border_color);
xwindow_set_border_color(window_get(window), &window->border_color);
luaA_object_emit_signal(L, -3, "property::border_color", 0);
}
@ -162,7 +170,7 @@ window_set_border_width(lua_State *L, int idx, int width)
return;
if(window->window)
xcb_configure_window(globalconf.connection, window->window,
xcb_configure_window(globalconf.connection, window_get(window),
XCB_CONFIG_WINDOW_BORDER_WIDTH,
(uint32_t[]) { width });

View File

@ -30,6 +30,8 @@
LUA_OBJECT_HEADER \
/** The X window number */ \
xcb_window_t window; \
/** The frame window, might be XCB_NONE */ \
xcb_window_t frame_window; \
/** Opacity */ \
double opacity; \
/** Strut */ \

View File

@ -96,9 +96,9 @@ stack_window_above(xcb_window_t w, xcb_window_t previous)
static xcb_window_t
stack_client_above(client_t *c, xcb_window_t previous)
{
stack_window_above(c->window, previous);
stack_window_above(c->frame_window, previous);
previous = c->window;
previous = c->frame_window;
/* stack transient window on top of their parents */
foreach(node, globalconf.stack)