ewmh: add support for _NET_WM_STRUT_PARTIAL

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-09-03 22:15:14 +02:00
parent 6b901356e2
commit fcde8d229b
16 changed files with 205 additions and 38 deletions

View File

@ -34,6 +34,7 @@
#include "lua.h"
#include "mouse.h"
#include "systray.h"
#include "statusbar.h"
#include "layouts/floating.h"
#include "common/markup.h"
#include "common/atoms.h"
@ -457,6 +458,9 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen)
/* update window title */
client_updatetitle(c);
/* update strut */
ewmh_client_strut_update(c);
ewmh_update_net_client_list(c->phys_screen);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
@ -668,9 +672,7 @@ client_setfullscreen(client_t *c, bool s)
xcb_unmap_window(globalconf.connection, c->titlebar->sw->window);
c->titlebar->position = Off;
}
geometry = screen_area_get(&globalconf.screens[c->screen].geometry,
NULL,
&globalconf.screens[c->screen].padding);
geometry = screen_area_get(c->screen, NULL, &globalconf.screens[c->screen].padding, false);
c->m_geometry = c->geometry;
c->oldborder = c->border;
client_setborder(c, 0);
@ -826,6 +828,12 @@ client_unmanage(client_t *c)
xcb_delete_property(globalconf.connection, c->win, _AWESOME_TAGS);
xcb_delete_property(globalconf.connection, c->win, _AWESOME_FLOATING);
if(client_hasstrut(c))
/* All the statusbars (may) need to be repositioned */
for(int screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(statusbar_t *s = globalconf.screens[screen].statusbar; s; s = s->next)
statusbar_position_update(s);
/* set client as invalid */
c->invalid = true;

View File

@ -100,5 +100,26 @@ client_isfloating(client_t *c)
|| client_isfixed(c));
}
/** Check if a client has strut information.
* \param c A client.
* \return A boolean value, true if the client has strut information.
*/
static inline bool
client_hasstrut(client_t *c)
{
return (c->strut.left
|| c->strut.right
|| c->strut.top
|| c->strut.bottom
|| c->strut.left_start_y
|| c->strut.left_end_y
|| c->strut.right_start_y
|| c->strut.right_end_y
|| c->strut.top_start_x
|| c->strut.top_end_x
|| c->strut.bottom_start_x
|| c->strut.bottom_end_x);
}
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -9,6 +9,7 @@ _NET_WORKAREA
_NET_SUPPORTING_WM_CHECK
_NET_CLOSE_WINDOW
_NET_WM_NAME
_NET_WM_STRUT_PARTIAL
_NET_WM_VISIBLE_NAME
_NET_WM_DESKTOP
_NET_WM_ICON_NAME

View File

@ -217,6 +217,11 @@ event_handle_configurerequest(void *data __attribute__ ((unused)),
{
client_resize(c, geometry, false);
titlebar_draw(c);
if(client_hasstrut(c))
/* All the statusbars (may) need to be repositioned */
for(int screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(statusbar_t *s = globalconf.screens[screen].statusbar; s; s = s->next)
statusbar_position_update(s);
}
else
{
@ -658,6 +663,8 @@ event_handle_propertynotify(void *data __attribute__ ((unused)),
client_updatewmhints(c);
else if(ev->atom == WM_NAME || ev->atom == _NET_WM_NAME)
client_updatetitle(c);
else if(ev->atom == _NET_WM_STRUT_PARTIAL)
ewmh_client_strut_update(c);
else if(ev->atom == _NET_WM_ICON)
{
xcb_get_property_cookie_t icon_q = ewmh_window_icon_get_unchecked(c->win);

65
ewmh.c
View File

@ -32,6 +32,7 @@
#include "widget.h"
#include "cnode.h"
#include "titlebar.h"
#include "statusbar.h"
#include "common/atoms.h"
extern awesome_t globalconf;
@ -58,6 +59,7 @@ ewmh_init(int phys_screen)
_NET_WORKAREA,
_NET_CLOSE_WINDOW,
_NET_WM_NAME,
_NET_WM_STRUT_PARTIAL,
_NET_WM_ICON_NAME,
_NET_WM_VISIBLE_ICON_NAME,
_NET_WM_DESKTOP,
@ -213,9 +215,10 @@ ewmh_update_workarea(int phys_screen)
{
tag_array_t *tags = &globalconf.screens[phys_screen].tags;
uint32_t *area = p_alloca(uint32_t, tags->len * 4);
area_t geom = screen_area_get(&globalconf.screens[phys_screen].geometry,
area_t geom = screen_area_get(phys_screen,
globalconf.screens[phys_screen].statusbar,
&globalconf.screens[phys_screen].padding);
&globalconf.screens[phys_screen].padding,
true);
for(int i = 0; i < tags->len; i++)
@ -435,6 +438,64 @@ ewmh_check_client_hints(client_t *c)
p_delete(&reply);
}
/** Update the WM strut of a client.
* \param c The client.
*/
void
ewmh_client_strut_update(client_t *c)
{
void *data;
xcb_get_property_cookie_t strut_q;
xcb_get_property_reply_t *strut_r;
strut_q = xcb_get_property_unchecked(globalconf.connection, false, c->win,
_NET_WM_STRUT_PARTIAL, CARDINAL, 0, 12);
strut_r = xcb_get_property_reply(globalconf.connection, strut_q, NULL);
if(strut_r
&& strut_r->value_len
&& (data = xcb_get_property_value(strut_r)))
{
uint32_t *strut = data;
if(c->strut.left != strut[0]
|| c->strut.right != strut[1]
|| c->strut.top != strut[2]
|| c->strut.bottom != strut[3]
|| c->strut.left_start_y != strut[4]
|| c->strut.left_end_y != strut[5]
|| c->strut.right_start_y != strut[6]
|| c->strut.right_end_y != strut[7]
|| c->strut.top_start_x != strut[8]
|| c->strut.top_end_x != strut[9]
|| c->strut.bottom_start_x != strut[10]
|| c->strut.bottom_end_x != strut[11])
{
c->strut.left = strut[0];
c->strut.right = strut[1];
c->strut.top = strut[2];
c->strut.bottom = strut[3];
c->strut.left_start_y = strut[4];
c->strut.left_end_y = strut[5];
c->strut.right_start_y = strut[6];
c->strut.right_end_y = strut[7];
c->strut.top_start_x = strut[8];
c->strut.top_end_x = strut[9];
c->strut.bottom_start_x = strut[10];
c->strut.bottom_end_x = strut[11];
client_need_arrange(c);
/* All the statusbars (may) need to be repositioned */
for(int screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(statusbar_t *s = globalconf.screens[screen].statusbar; s; s = s->next)
statusbar_position_update(s);
}
}
p_delete(&strut_r);
}
/** Send request to get NET_WM_ICON (EWMH)
* \param w The window.
* \return The cookie associated with the request.

1
ewmh.h
View File

@ -44,6 +44,7 @@ int ewmh_process_client_message(xcb_client_message_event_t *);
void ewmh_update_net_client_list_stacking(int);
void ewmh_check_client_hints(client_t *);
void ewmh_update_workarea(int);
void ewmh_client_strut_update(client_t *);
xcb_get_property_cookie_t ewmh_window_icon_get_unchecked(xcb_window_t);
netwm_icon_t *ewmh_window_icon_get_reply(xcb_get_property_cookie_t);

View File

@ -41,9 +41,10 @@ layout_fair(int screen, const orientation_t orientation)
client_t *c;
area_t geometry, area;
area = screen_area_get(&globalconf.screens[screen].geometry,
area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
&globalconf.screens[screen].padding,
true);
for(c = globalconf.clients ; c; c = c->next)
if(IS_TILED(c, screen))

View File

@ -32,9 +32,10 @@ layout_fibonacci(int screen, int shape)
int n = 0, i = 0;
client_t *c;
area_t geometry, area;
geometry = area = screen_area_get(&globalconf.screens[screen].geometry,
geometry = area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
&globalconf.screens[screen].padding,
true);
for(c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))

View File

@ -34,9 +34,10 @@ layout_magnifier(int screen)
int n = 0;
client_t *c, *focus;
tag_t **curtags = tags_get_current(screen);
area_t geometry, area = screen_area_get(&globalconf.screens[screen].geometry,
area_t geometry, area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
&globalconf.screens[screen].padding,
true);
focus = globalconf.screens[screen].client_focus;

View File

@ -30,9 +30,10 @@ void
layout_max(int screen)
{
client_t *c;
area_t area = screen_area_get(&globalconf.screens[screen].geometry,
area_t area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
&globalconf.screens[screen].padding,
true);
for(c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))

View File

@ -42,9 +42,10 @@ _tile(int screen, const position_t position)
client_t *c;
tag_t **curtags = tags_get_current(screen);
area = screen_area_get(&globalconf.screens[screen].geometry,
area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
&globalconf.screens[screen].padding,
true);
for(n = 0, c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))

20
mouse.c
View File

@ -130,14 +130,16 @@ mouse_snapclient(client_t *c, area_t geometry, int snap)
client_t *snapper;
area_t snapper_geometry;
area_t screen_geometry =
screen_area_get(&globalconf.screens[c->screen].geometry,
screen_area_get(c->screen,
globalconf.screens[c->screen].statusbar,
&globalconf.screens[c->screen].padding);
&globalconf.screens[c->screen].padding,
false);
area_t screen_geometry_barless =
screen_area_get(&globalconf.screens[c->screen].geometry,
screen_area_get(c->screen,
NULL,
&globalconf.screens[c->screen].padding);
&globalconf.screens[c->screen].padding,
false);
geometry = titlebar_geometry_add(c->titlebar, c->border, geometry);
@ -745,9 +747,10 @@ mouse_client_resize_tiled(client_t *c)
tag = tags_get_current(c->screen)[0];
layout = tag->layout;
area = screen_area_get(&globalconf.screens[tag->screen].geometry,
area = screen_area_get(tag->screen,
globalconf.screens[tag->screen].statusbar,
&globalconf.screens[tag->screen].padding);
&globalconf.screens[tag->screen].padding,
true);
mouse_query_pointer(screen->root, &mouse_x, &mouse_y, NULL);
@ -848,9 +851,10 @@ mouse_client_resize_magnified(client_t *c, bool infobox)
root = xutil_screen_get(globalconf.connection, c->phys_screen)->root;
area = screen_area_get(&globalconf.screens[tag->screen].geometry,
area = screen_area_get(tag->screen,
globalconf.screens[tag->screen].statusbar,
&globalconf.screens[tag->screen].padding);
&globalconf.screens[tag->screen].padding,
true);
center_x = area.x + (round(area.width / 2.));
center_y = area.y + (round(area.height / 2.));

View File

@ -36,13 +36,16 @@ extern awesome_t globalconf;
* \param screen Screen number.
* \param statusbar Statusbar list to remove.
* \param padding Padding.
* \param strut Honor windows strut.
* \return The screen area.
*/
area_t
screen_area_get(area_t *geometry, statusbar_t *statusbar, padding_t *padding)
screen_area_get(int screen, statusbar_t *statusbar,
padding_t *padding, bool strut)
{
area_t area = *geometry;
area_t area = globalconf.screens[screen].geometry;
statusbar_t *sb;
uint16_t top = 0, bottom = 0, left = 0, right = 0;
/* make padding corrections */
if(padding)
@ -53,23 +56,68 @@ screen_area_get(area_t *geometry, statusbar_t *statusbar, padding_t *padding)
area.height -= padding->top + padding->bottom;
}
if(strut)
{
client_t *c;
for(c = globalconf.clients; c; c = c->next)
if(client_isvisible(c, screen))
{
if(c->strut.top_start_x || c->strut.top_end_x)
{
if(c->strut.top)
top = MAX(top, c->strut.top);
else
top = MAX(top, (c->geometry.y - area.y) + c->geometry.height);
}
if(c->strut.bottom_start_x || c->strut.bottom_end_x)
{
if(c->strut.bottom)
bottom = MAX(bottom, c->strut.bottom);
else
bottom = MAX(bottom, (area.y + area.height) - c->geometry.y);
}
if(c->strut.left_start_y || c->strut.left_end_y)
{
if(c->strut.left)
left = MAX(left, c->strut.left);
else
left = MAX(left, (c->geometry.x - area.x) + c->geometry.width);
}
if(c->strut.right_start_y || c->strut.right_end_y)
{
if(c->strut.right)
right = MAX(right, c->strut.right);
else
right = MAX(right, (area.x + area.width) - c->geometry.x);
}
}
}
for(sb = statusbar; sb; sb = sb->next)
switch(sb->position)
{
case Top:
area.y += sb->height;
top = MAX(top, (uint16_t) (sb->sw->geometry.y - area.y) + sb->sw->geometry.height);
break;
case Bottom:
area.height -= sb->height;
bottom = MAX(bottom, (uint16_t) (area.y + area.height) - sb->sw->geometry.y);
break;
case Left:
area.x += sb->height;
left = MAX(left, (uint16_t) (sb->sw->geometry.x - area.x) + sb->sw->geometry.width);
break;
case Right:
area.width -= sb->height;
right = MAX(right, (uint16_t) (area.x + area.width) - sb->sw->geometry.x);
break;
default:
break;
}
area.x += left;
area.y += top;
area.width -= left + right;
area.height -= top + bottom;
return area;
}
@ -151,10 +199,10 @@ screen_client_moveto(client_t *c, int new_screen, bool doresize)
area_t new_geometry, new_f_geometry;
new_f_geometry = c->f_geometry;
to = screen_area_get(&globalconf.screens[c->screen].geometry,
NULL, NULL);
from = screen_area_get(&globalconf.screens[old_screen].geometry,
NULL, NULL);
to = screen_area_get(c->screen,
NULL, NULL, false);
from = screen_area_get(old_screen,
NULL, NULL, false);
/* compute new coords in new screen */
new_f_geometry.x = (c->f_geometry.x - from.x) + to.x;
@ -331,7 +379,7 @@ luaA_screen_index(lua_State *L)
lua_setfield(L, -2, "height");
break;
case A_TK_WORKAREA:
g = screen_area_get(&s->geometry, s->statusbar, &s->padding);
g = screen_area_get(s->index, s->statusbar, &s->padding, true);
lua_newtable(L);
lua_pushnumber(L, g.x);
lua_setfield(L, -2, "x");

View File

@ -26,7 +26,7 @@
#define SCREEN_UNDEF (-1)
area_t screen_area_get(area_t *, statusbar_t *, padding_t *);
area_t screen_area_get(int, statusbar_t *, padding_t *, bool);
area_t display_area_get(int, statusbar_t *, padding_t *);
int screen_virttophys(int);
void screen_client_moveto(client_t *, int, bool);

View File

@ -283,9 +283,8 @@ statusbar_position_update(statusbar_t *statusbar)
if(statusbar->position == Off)
return;
area = screen_area_get(&globalconf.screens[statusbar->screen].geometry,
NULL,
&globalconf.screens[statusbar->screen].padding);
area = screen_area_get(statusbar->screen, NULL,
&globalconf.screens[statusbar->screen].padding, true);
/* Top and Bottom statusbar_t have prio */
for(sb = globalconf.screens[statusbar->screen].statusbar; sb; sb = sb->next)

View File

@ -261,6 +261,16 @@ typedef struct
unsigned char *image;
} netwm_icon_t;
/* Strut */
typedef struct
{
uint16_t left, right, top, bottom;
uint16_t left_start_y, left_end_y;
uint16_t right_start_y, right_end_y;
uint16_t top_start_x, top_end_x;
uint16_t bottom_start_x, bottom_end_x;
} strut_t;
/** client_t type */
struct client_t
{
@ -280,6 +290,8 @@ struct client_t
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int minax, maxax, minay, maxay;
bool hassizehints;
/** Strut */
strut_t strut;
/** Respect resize hints */
bool honorsizehints;
int border, oldborder;