diff --git a/awesomerc.lua.in b/awesomerc.lua.in index ff2d959f..142a0fe0 100644 --- a/awesomerc.lua.in +++ b/awesomerc.lua.in @@ -136,7 +136,7 @@ end mystatusbar = {} for s = 1, screen.count() do mystatusbar[s] = statusbar({ position = "top", name = "mystatusbar" .. s, - fg = beautiful.fg_normal, bg = beautiful.bg_normal }) + fg = beautiful.fg_normal, bg = beautiful.bg_normal }) -- Add widgets to the statusbar - order matters mystatusbar[s]:widgets({ mytaglist, @@ -145,7 +145,7 @@ for s = 1, screen.count() do mypromptbox, mytextbox, mylayoutbox[s], - s == screen.count() and mysystray or nil + s == 1 and mysystray or nil }) mystatusbar[s].screen = s end diff --git a/client.c b/client.c index 2d1991c9..23b8d48e 100644 --- a/client.c +++ b/client.c @@ -274,7 +274,6 @@ client_stack(void) layer_t layer; statusbar_t *sb; int screen; - xembed_window_t *emwin; config_win_vals[0] = XCB_NONE; config_win_vals[1] = XCB_STACK_MODE_BELOW; @@ -300,16 +299,6 @@ client_stack(void) config_win_vals[0] = node->client->win; } - /* then stack systray windows */ - for(emwin = globalconf.embedded; emwin; emwin = emwin->next) - { - xcb_configure_window(globalconf.connection, - emwin->win, - XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, - config_win_vals); - config_win_vals[0] = emwin->win; - } - /* then stack statusbar window */ for(screen = 0; screen < globalconf.screens_info->nscreen; screen++) for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next) diff --git a/statusbar.c b/statusbar.c index 58935070..8218ba0b 100644 --- a/statusbar.c +++ b/statusbar.c @@ -39,15 +39,13 @@ DO_LUA_EQ(statusbar_t, statusbar, "statusbar") static void statusbar_systray_kickout(int phys_screen) { - xembed_window_t *em; - uint32_t config_win_vals_off[2] = { -512, -512 }; + xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen); - for(em = globalconf.embedded; em; em = em->next) - if(em->phys_screen == phys_screen) - xcb_configure_window(globalconf.connection, em->win, - XCB_CONFIG_WINDOW_X - | XCB_CONFIG_WINDOW_Y, - config_win_vals_off); + xcb_reparent_window(globalconf.connection, + globalconf.screens[phys_screen].systray.window, + s->root, -512, -512); + + globalconf.screens[phys_screen].systray.parent = s->root; } static void @@ -61,35 +59,77 @@ statusbar_systray_refresh(statusbar_t *statusbar) for(systray = statusbar->widgets; systray; systray = systray->next) if(systray->widget->type == systray_new) { - uint32_t config_back[] = { globalconf.colors.bg.pixel }; + uint32_t config_back[] = { statusbar->colors.bg.pixel }; uint32_t config_win_vals[4]; uint32_t config_win_vals_off[2] = { -512, -512 }; xembed_window_t *em; position_t pos; if(statusbar->position - && systray->widget->isvisible) + && systray->widget->isvisible + && systray->area.width) { pos = statusbar->position; - /* width */ - config_win_vals[2] = systray->area.height; - /* height */ - config_win_vals[3] = systray->area.height; + + /* Set background of the systray window. */ + xcb_change_window_attributes(globalconf.connection, + globalconf.screens[statusbar->phys_screen].systray.window, + XCB_CW_BACK_PIXEL, config_back); + /* Map it. */ + xcb_map_window(globalconf.connection, globalconf.screens[statusbar->phys_screen].systray.window); + /* Move it. */ + switch(statusbar->position) + { + case Left: + config_win_vals[0] = systray->area.y; + config_win_vals[1] = statusbar->sw->geometry.height - systray->area.x - systray->area.width; + config_win_vals[2] = systray->area.height; + config_win_vals[3] = systray->area.width; + break; + case Right: + config_win_vals[0] = systray->area.y; + config_win_vals[1] = systray->area.x; + config_win_vals[2] = systray->area.height; + config_win_vals[3] = systray->area.width; + break; + default: + config_win_vals[0] = systray->area.x; + config_win_vals[1] = systray->area.y; + config_win_vals[2] = systray->area.width; + config_win_vals[3] = systray->area.height; + break; + } + /* reparent */ + if(globalconf.screens[statusbar->phys_screen].systray.parent != statusbar->sw->window) + { + xcb_reparent_window(globalconf.connection, + globalconf.screens[statusbar->phys_screen].systray.window, + statusbar->sw->window, + config_win_vals[0], config_win_vals[1]); + globalconf.screens[statusbar->phys_screen].systray.parent = statusbar->sw->window; + } + xcb_configure_window(globalconf.connection, + globalconf.screens[statusbar->phys_screen].systray.window, + XCB_CONFIG_WINDOW_X + | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH + | XCB_CONFIG_WINDOW_HEIGHT, + config_win_vals); + /* width = height = systray height */ + config_win_vals[2] = config_win_vals[3] = systray->area.height; + config_win_vals[0] = 0; } else + { + xcb_unmap_window(globalconf.connection, globalconf.screens[statusbar->phys_screen].systray.window); /* hide */ pos = Off; - - for(em = globalconf.embedded; em; em = em->next) - if(em->phys_screen == statusbar->phys_screen) - xcb_change_window_attributes(globalconf.connection, em->win, XCB_CW_BACK_PIXEL, config_back); + } switch(pos) { case Left: - config_win_vals[0] = statusbar->sw->geometry.x + systray->area.y; - config_win_vals[1] = statusbar->sw->geometry.y + statusbar->sw->geometry.height - - systray->area.x - config_win_vals[3]; + config_win_vals[1] = systray->area.width - config_win_vals[3]; for(em = globalconf.embedded; em; em = em->next) if(em->phys_screen == statusbar->phys_screen) { @@ -110,11 +150,9 @@ statusbar_systray_refresh(statusbar_t *statusbar) | XCB_CONFIG_WINDOW_Y, config_win_vals_off); } - client_stack(); break; case Right: - config_win_vals[0] = statusbar->sw->geometry.x - systray->area.y; - config_win_vals[1] = statusbar->sw->geometry.y + systray->area.x; + config_win_vals[1] = 0; for(em = globalconf.embedded; em; em = em->next) if(em->phys_screen == statusbar->phys_screen) { @@ -135,12 +173,10 @@ statusbar_systray_refresh(statusbar_t *statusbar) | XCB_CONFIG_WINDOW_Y, config_win_vals_off); } - client_stack(); break; case Top: case Bottom: - config_win_vals[0] = statusbar->sw->geometry.x + systray->area.x; - config_win_vals[1] = statusbar->sw->geometry.y + systray->area.y; + config_win_vals[1] = 0; for(em = globalconf.embedded; em; em = em->next) if(em->phys_screen == statusbar->phys_screen) { @@ -162,7 +198,6 @@ statusbar_systray_refresh(statusbar_t *statusbar) | XCB_CONFIG_WINDOW_Y, config_win_vals_off); } - client_stack(); break; default: statusbar_systray_kickout(statusbar->phys_screen); @@ -222,6 +257,11 @@ statusbar_position_update(statusbar_t *statusbar) globalconf.screens[statusbar->screen].need_arrange = true; + /* Who! Check that we're not deleting a statusbar with a systray, because it + * may be its parent. If so, we reparent to root before, otherwise it will + * hurt very much. */ + statusbar_systray_kickout(statusbar->phys_screen); + simplewindow_delete(&statusbar->sw); draw_context_delete(&statusbar->ctx); diff --git a/structs.h b/structs.h index e53b36d3..5c76911a 100644 --- a/structs.h +++ b/structs.h @@ -384,6 +384,8 @@ typedef struct struct { xcb_window_t window; + /** Systray window parent */ + xcb_window_t parent; } systray; /** Focused client */ client_t *client_focus; diff --git a/systray.c b/systray.c index 0918263f..652e6029 100644 --- a/systray.c +++ b/systray.c @@ -111,6 +111,10 @@ systray_request_handle(xcb_window_t embed_win, int phys_screen, xembed_info_t *i select_input_val); window_state_set(embed_win, XCB_WM_WITHDRAWN_STATE); + xcb_reparent_window(globalconf.connection, embed_win, + globalconf.screens[phys_screen].systray.window, + 0, 0); + em = p_new(xembed_window_t, 1); em->win = embed_win; em->phys_screen = phys_screen;