statusbar: handle systray invisibility

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-08-05 16:59:54 +02:00
parent d98c28ef86
commit 254a39b6d3
5 changed files with 147 additions and 110 deletions

View File

@ -264,7 +264,7 @@ client_focus(client_t *c, int screen)
* \todo It might be worth stopping to restack everyone and only stack `c' * \todo It might be worth stopping to restack everyone and only stack `c'
* relatively to the first matching in the list. * relatively to the first matching in the list.
*/ */
static void void
client_stack(void) client_stack(void)
{ {
uint32_t config_win_vals[2]; uint32_t config_win_vals[2];

View File

@ -30,6 +30,7 @@ bool client_isvisible(client_t *, int);
client_t * client_getbywin(xcb_window_t); client_t * client_getbywin(xcb_window_t);
void client_focus(client_t *, int); void client_focus(client_t *, int);
void client_setlayer(client_t *, layer_t); void client_setlayer(client_t *, layer_t);
void client_stack(void);
void client_raise(client_t *); void client_raise(client_t *);
void client_ban(client_t *); void client_ban(client_t *);
void client_unban(client_t *); void client_unban(client_t *);

View File

@ -21,6 +21,7 @@
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include "client.h"
#include "statusbar.h" #include "statusbar.h"
#include "screen.h" #include "screen.h"
#include "widget.h" #include "widget.h"
@ -38,19 +39,142 @@ DO_LUA_EQ(statusbar_t, statusbar, "statusbar")
static void static void
statusbar_draw(statusbar_t *statusbar) statusbar_draw(statusbar_t *statusbar)
{ {
widget_node_t *systray;
statusbar->need_update = false; statusbar->need_update = false;
if(!statusbar->position) /* found the systray if any */
return; for(systray = statusbar->widgets; systray; systray = systray->next)
if(systray->widget->type == systray_new)
break;
widget_render(statusbar->widgets, statusbar->ctx, statusbar->sw->gc, if(statusbar->position)
statusbar->sw->pixmap, {
statusbar->screen, statusbar->position, widget_render(statusbar->widgets, statusbar->ctx, statusbar->sw->gc,
statusbar->sw->geometry.x, statusbar->sw->geometry.y, statusbar->sw->pixmap,
statusbar, AWESOME_TYPE_STATUSBAR); 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); if(systray)
xcb_aux_sync(globalconf.connection); {
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. /** Statusbar refresh function.

View File

@ -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); draw_rectangle(ctx, rectangle, 1.0, true, &ctx->bg);
for(w = wnode; w; w = w->next) for(w = wnode; w; w = w->next)
if(w->widget->align == AlignLeft) if(w->widget->align == AlignLeft && w->widget->isvisible)
/* special case: systray need to be called even if it's not visible */
if(w->widget->isvisible || w->widget->type == systray_new)
left += w->widget->draw(ctx, screen, w, left, (left + right), object, type); left += w->widget->draw(ctx, screen, w, left, (left + right), object, type);
/* renders right widget from last to first */ /* renders right widget from last to first */
for(w = *widget_node_list_last(&wnode); w; w = w->prev) for(w = *widget_node_list_last(&wnode); w; w = w->prev)
if(w->widget->align == AlignRight) if(w->widget->align == AlignRight && w->widget->isvisible)
if(w->widget->isvisible || w->widget->type == systray_new)
right += w->widget->draw(ctx, screen, w, right, (left + right), object, type); right += w->widget->draw(ctx, screen, w, right, (left + right), object, type);
for(w = wnode; w; w = w->next) for(w = wnode; w; w = w->next)
if(w->widget->align == AlignFlex) if(w->widget->align == AlignFlex && w->widget->isvisible)
if(w->widget->isvisible || w->widget->type == systray_new)
left += w->widget->draw(ctx, screen, w, left, (left + right), object, type); left += w->widget->draw(ctx, screen, w, left, (left + right), object, type);
switch(position) switch(position)

View File

@ -40,35 +40,21 @@ systray_draw(draw_context_t *ctx,
void *p, void *p,
awesome_type_t type) awesome_type_t type)
{ {
int phys_screen; uint32_t orient;
xembed_window_t *em;
uint32_t orient, config_win_vals[4];
/* p is always a statusbar, titlebars are forbidden */ /* p is always a statusbar, titlebars are forbidden */
statusbar_t *sb = (statusbar_t *) p; statusbar_t *sb = (statusbar_t *) p;
/* we are on a statusbar */ /* we are on a statusbar */
assert(type == AWESOME_TYPE_STATUSBAR); assert(type == AWESOME_TYPE_STATUSBAR);
phys_screen = screen_virttophys(screen);
w->area.height = ctx->height; w->area.height = ctx->height;
/* width */ if(ctx->width - used > 0)
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)
{ {
int i = 0; int i = 0;
xembed_window_t *em;
for(em = globalconf.embedded; em; em = em->next) for(em = globalconf.embedded; em; em = em->next)
if(em->phys_screen == phys_screen) if(em->phys_screen == sb->phys_screen)
i++; i++;
w->area.width = MIN(i * ctx->height, ctx->width - used); w->area.width = MIN(i * ctx->height, ctx->width - used);
} }
@ -81,94 +67,24 @@ systray_draw(draw_context_t *ctx,
w->widget->align); w->widget->align);
w->area.y = 0; w->area.y = 0;
/* inform that there's a widget */
globalconf.screens[sb->phys_screen].systray.has_systray_widget = true;
switch(sb->position) 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: case Right:
if(w->widget->isvisible) case Left:
{
config_win_vals[0] = sb->sw->geometry.x - w->area.y;
config_win_vals[1] = sb->sw->geometry.y + w->area.x;
}
orient = _NET_SYSTEM_TRAY_ORIENTATION_VERT; 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; break;
default: 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; 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; break;
} }
/* inform that there's a widget */
globalconf.screens[phys_screen].systray.has_systray_widget = true;
/* set statusbar orientation */ /* set statusbar orientation */
/** \todo stop setting that property on each redraw */ /** \todo stop setting that property on each redraw */
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, 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); _NET_SYSTEM_TRAY_ORIENTATION, CARDINAL, 32, 1, &orient);
return w->area.width; return w->area.width;