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'
* relatively to the first matching in the list.
*/
static void
void
client_stack(void)
{
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);
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 *);

View File

@ -21,6 +21,7 @@
#include <xcb/xcb.h>
#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;
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);
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.

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

View File

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