systray: reparent windows

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-09-01 17:54:53 +02:00
parent 2c0febaedc
commit 7b00a2baf0
5 changed files with 76 additions and 41 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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;