From 254a39b6d3322392d8cb74179ffd1e0d8a2db39d Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 5 Aug 2008 16:59:54 +0200 Subject: [PATCH] statusbar: handle systray invisibility Signed-off-by: Julien Danjou --- client.c | 2 +- client.h | 1 + statusbar.c | 142 +++++++++++++++++++++++++++++++++++++++++++--- widget.c | 10 +--- widgets/systray.c | 102 +++------------------------------ 5 files changed, 147 insertions(+), 110 deletions(-) diff --git a/client.c b/client.c index 107d85d1..5fb73f70 100644 --- a/client.c +++ b/client.c @@ -264,7 +264,7 @@ client_focus(client_t *c, int screen) * \todo It might be worth stopping to restack everyone and only stack `c' * relatively to the first matching in the list. */ -static void +void client_stack(void) { uint32_t config_win_vals[2]; diff --git a/client.h b/client.h index 7ee34595..40b64e5c 100644 --- a/client.h +++ b/client.h @@ -30,6 +30,7 @@ bool client_isvisible(client_t *, int); client_t * client_getbywin(xcb_window_t); void client_focus(client_t *, int); void client_setlayer(client_t *, layer_t); +void client_stack(void); void client_raise(client_t *); void client_ban(client_t *); void client_unban(client_t *); diff --git a/statusbar.c b/statusbar.c index 63cc0895..ccc70801 100644 --- a/statusbar.c +++ b/statusbar.c @@ -21,6 +21,7 @@ #include +#include "client.h" #include "statusbar.h" #include "screen.h" #include "widget.h" @@ -38,19 +39,142 @@ DO_LUA_EQ(statusbar_t, statusbar, "statusbar") static void statusbar_draw(statusbar_t *statusbar) { + widget_node_t *systray; + statusbar->need_update = false; - if(!statusbar->position) - return; + /* found the systray if any */ + for(systray = statusbar->widgets; systray; systray = systray->next) + if(systray->widget->type == systray_new) + break; - widget_render(statusbar->widgets, statusbar->ctx, statusbar->sw->gc, - statusbar->sw->pixmap, - statusbar->screen, statusbar->position, - statusbar->sw->geometry.x, statusbar->sw->geometry.y, - statusbar, AWESOME_TYPE_STATUSBAR); + if(statusbar->position) + { + widget_render(statusbar->widgets, statusbar->ctx, statusbar->sw->gc, + statusbar->sw->pixmap, + statusbar->screen, statusbar->position, + statusbar->sw->geometry.x, statusbar->sw->geometry.y, + statusbar, AWESOME_TYPE_STATUSBAR); + simplewindow_refresh_pixmap(statusbar->sw); + } - simplewindow_refresh_pixmap(statusbar->sw); - xcb_aux_sync(globalconf.connection); + if(systray) + { + uint32_t config_win_vals[4]; + uint32_t config_win_vals_off[4] = { -1, -1, 1, 1 }; + xembed_window_t *em; + position_t pos; + + if(statusbar->position && systray->widget->isvisible) + { + pos = statusbar->position; + /* width */ + config_win_vals[2] = systray->area.height; + /* height */ + config_win_vals[3] = systray->area.height; + } + else + /* hide */ + pos = Off; + + 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]; + for(em = globalconf.embedded; em; em = em->next) + if(em->phys_screen == statusbar->phys_screen) + { + if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) statusbar->sw->geometry.y) + { + xcb_map_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, + config_win_vals); + config_win_vals[1] -= config_win_vals[3]; + } + else + xcb_configure_window(globalconf.connection, em->win, + XCB_CONFIG_WINDOW_X + | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH + | XCB_CONFIG_WINDOW_HEIGHT, + 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; + for(em = globalconf.embedded; em; em = em->next) + if(em->phys_screen == statusbar->phys_screen) + { + if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) statusbar->sw->geometry.y + statusbar->ctx->width) + { + xcb_map_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, + config_win_vals); + config_win_vals[1] += config_win_vals[3]; + } + else + xcb_configure_window(globalconf.connection, em->win, + XCB_CONFIG_WINDOW_X + | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH + | XCB_CONFIG_WINDOW_HEIGHT, + 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; + for(em = globalconf.embedded; em; em = em->next) + if(em->phys_screen == statusbar->phys_screen) + { + /* if(x + width < systray.x + systray.width) */ + if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->area) + statusbar->sw->geometry.x) + { + xcb_map_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, + config_win_vals); + config_win_vals[0] += config_win_vals[2]; + } + else + xcb_configure_window(globalconf.connection, em->win, + XCB_CONFIG_WINDOW_X + | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH + | XCB_CONFIG_WINDOW_HEIGHT, + config_win_vals_off); + } + client_stack(); + break; + default: + for(em = globalconf.embedded; em; em = em->next) + if(em->phys_screen == statusbar->phys_screen) + xcb_configure_window(globalconf.connection, em->win, + XCB_CONFIG_WINDOW_X + | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH + | XCB_CONFIG_WINDOW_HEIGHT, + config_win_vals_off); + break; + } + } } /** Statusbar refresh function. diff --git a/widget.c b/widget.c index d177bee8..4ce13faf 100644 --- a/widget.c +++ b/widget.c @@ -154,20 +154,16 @@ widget_render(widget_node_t *wnode, draw_context_t *ctx, xcb_gcontext_t gc, xcb_ draw_rectangle(ctx, rectangle, 1.0, true, &ctx->bg); for(w = wnode; w; w = w->next) - if(w->widget->align == AlignLeft) - /* special case: systray need to be called even if it's not visible */ - if(w->widget->isvisible || w->widget->type == systray_new) + if(w->widget->align == AlignLeft && w->widget->isvisible) left += w->widget->draw(ctx, screen, w, left, (left + right), object, type); /* renders right widget from last to first */ for(w = *widget_node_list_last(&wnode); w; w = w->prev) - if(w->widget->align == AlignRight) - if(w->widget->isvisible || w->widget->type == systray_new) + if(w->widget->align == AlignRight && w->widget->isvisible) right += w->widget->draw(ctx, screen, w, right, (left + right), object, type); for(w = wnode; w; w = w->next) - if(w->widget->align == AlignFlex) - if(w->widget->isvisible || w->widget->type == systray_new) + if(w->widget->align == AlignFlex && w->widget->isvisible) left += w->widget->draw(ctx, screen, w, left, (left + right), object, type); switch(position) diff --git a/widgets/systray.c b/widgets/systray.c index 2e7eca4e..994f5402 100644 --- a/widgets/systray.c +++ b/widgets/systray.c @@ -40,35 +40,21 @@ systray_draw(draw_context_t *ctx, void *p, awesome_type_t type) { - int phys_screen; - xembed_window_t *em; - uint32_t orient, config_win_vals[4]; + uint32_t orient; /* p is always a statusbar, titlebars are forbidden */ statusbar_t *sb = (statusbar_t *) p; /* we are on a statusbar */ assert(type == AWESOME_TYPE_STATUSBAR); - phys_screen = screen_virttophys(screen); - w->area.height = ctx->height; - /* width */ - config_win_vals[2] = w->area.height; - /* height */ - config_win_vals[3] = w->area.height; - - if(!w->widget->isvisible) - { - w->area.width = 0; - config_win_vals[0] = - config_win_vals[2]; - config_win_vals[1] = - config_win_vals[3]; - } - else if(ctx->width - used > 0) + if(ctx->width - used > 0) { int i = 0; + xembed_window_t *em; for(em = globalconf.embedded; em; em = em->next) - if(em->phys_screen == phys_screen) + if(em->phys_screen == sb->phys_screen) i++; w->area.width = MIN(i * ctx->height, ctx->width - used); } @@ -81,94 +67,24 @@ systray_draw(draw_context_t *ctx, w->widget->align); w->area.y = 0; + /* inform that there's a widget */ + globalconf.screens[sb->phys_screen].systray.has_systray_widget = true; + switch(sb->position) { - case Left: - if(w->widget->isvisible) - { - config_win_vals[0] = sb->sw->geometry.x + w->area.y; - config_win_vals[1] = sb->sw->geometry.y + sb->sw->geometry.height - - w->area.x - config_win_vals[3]; - } - orient = _NET_SYSTEM_TRAY_ORIENTATION_VERT; - for(em = globalconf.embedded; em; em = em->next) - if(em->phys_screen == phys_screen) - { - if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) sb->sw->geometry.y) - { - xcb_map_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, - config_win_vals); - config_win_vals[1] -= config_win_vals[3]; - } - else - xcb_unmap_window(globalconf.connection, em->win); - } - break; case Right: - if(w->widget->isvisible) - { - config_win_vals[0] = sb->sw->geometry.x - w->area.y; - config_win_vals[1] = sb->sw->geometry.y + w->area.x; - } + case Left: orient = _NET_SYSTEM_TRAY_ORIENTATION_VERT; - for(em = globalconf.embedded; em; em = em->next) - if(em->phys_screen == phys_screen) - { - if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) sb->sw->geometry.y + ctx->width) - { - xcb_map_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, - config_win_vals); - config_win_vals[1] += config_win_vals[3]; - } - else - xcb_unmap_window(globalconf.connection, em->win); - } break; default: - if(w->widget->isvisible) - { - config_win_vals[0] = sb->sw->geometry.x + w->area.x; - config_win_vals[1] = sb->sw->geometry.y + w->area.y; - } orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; - for(em = globalconf.embedded; em; em = em->next) - if(em->phys_screen == phys_screen) - { - /* if(x + width < systray.x + systray.width) */ - if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(w->area) + sb->sw->geometry.x) - { - xcb_map_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, - config_win_vals); - config_win_vals[0] += config_win_vals[2]; - } - else - xcb_unmap_window(globalconf.connection, em->win); - } break; } - /* inform that there's a widget */ - globalconf.screens[phys_screen].systray.has_systray_widget = true; - /* set statusbar orientation */ /** \todo stop setting that property on each redraw */ xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, - globalconf.screens[phys_screen].systray.window, + globalconf.screens[sb->phys_screen].systray.window, _NET_SYSTEM_TRAY_ORIENTATION, CARDINAL, 32, 1, &orient); return w->area.width;