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 "lua.h"
#include "mouse.h" #include "mouse.h"
#include "systray.h" #include "systray.h"
#include "statusbar.h"
#include "layouts/floating.h" #include "layouts/floating.h"
#include "common/markup.h" #include "common/markup.h"
#include "common/atoms.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 */ /* update window title */
client_updatetitle(c); client_updatetitle(c);
/* update strut */
ewmh_client_strut_update(c);
ewmh_update_net_client_list(c->phys_screen); ewmh_update_net_client_list(c->phys_screen);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); 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); xcb_unmap_window(globalconf.connection, c->titlebar->sw->window);
c->titlebar->position = Off; c->titlebar->position = Off;
} }
geometry = screen_area_get(&globalconf.screens[c->screen].geometry, geometry = screen_area_get(c->screen, NULL, &globalconf.screens[c->screen].padding, false);
NULL,
&globalconf.screens[c->screen].padding);
c->m_geometry = c->geometry; c->m_geometry = c->geometry;
c->oldborder = c->border; c->oldborder = c->border;
client_setborder(c, 0); 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_TAGS);
xcb_delete_property(globalconf.connection, c->win, _AWESOME_FLOATING); 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 */ /* set client as invalid */
c->invalid = true; c->invalid = true;

View File

@ -100,5 +100,26 @@ client_isfloating(client_t *c)
|| client_isfixed(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 #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // 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_SUPPORTING_WM_CHECK
_NET_CLOSE_WINDOW _NET_CLOSE_WINDOW
_NET_WM_NAME _NET_WM_NAME
_NET_WM_STRUT_PARTIAL
_NET_WM_VISIBLE_NAME _NET_WM_VISIBLE_NAME
_NET_WM_DESKTOP _NET_WM_DESKTOP
_NET_WM_ICON_NAME _NET_WM_ICON_NAME

View File

@ -217,6 +217,11 @@ event_handle_configurerequest(void *data __attribute__ ((unused)),
{ {
client_resize(c, geometry, false); client_resize(c, geometry, false);
titlebar_draw(c); 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 else
{ {
@ -658,6 +663,8 @@ event_handle_propertynotify(void *data __attribute__ ((unused)),
client_updatewmhints(c); client_updatewmhints(c);
else if(ev->atom == WM_NAME || ev->atom == _NET_WM_NAME) else if(ev->atom == WM_NAME || ev->atom == _NET_WM_NAME)
client_updatetitle(c); client_updatetitle(c);
else if(ev->atom == _NET_WM_STRUT_PARTIAL)
ewmh_client_strut_update(c);
else if(ev->atom == _NET_WM_ICON) else if(ev->atom == _NET_WM_ICON)
{ {
xcb_get_property_cookie_t icon_q = ewmh_window_icon_get_unchecked(c->win); 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 "widget.h"
#include "cnode.h" #include "cnode.h"
#include "titlebar.h" #include "titlebar.h"
#include "statusbar.h"
#include "common/atoms.h" #include "common/atoms.h"
extern awesome_t globalconf; extern awesome_t globalconf;
@ -58,6 +59,7 @@ ewmh_init(int phys_screen)
_NET_WORKAREA, _NET_WORKAREA,
_NET_CLOSE_WINDOW, _NET_CLOSE_WINDOW,
_NET_WM_NAME, _NET_WM_NAME,
_NET_WM_STRUT_PARTIAL,
_NET_WM_ICON_NAME, _NET_WM_ICON_NAME,
_NET_WM_VISIBLE_ICON_NAME, _NET_WM_VISIBLE_ICON_NAME,
_NET_WM_DESKTOP, _NET_WM_DESKTOP,
@ -213,9 +215,10 @@ ewmh_update_workarea(int phys_screen)
{ {
tag_array_t *tags = &globalconf.screens[phys_screen].tags; tag_array_t *tags = &globalconf.screens[phys_screen].tags;
uint32_t *area = p_alloca(uint32_t, tags->len * 4); 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].statusbar,
&globalconf.screens[phys_screen].padding); &globalconf.screens[phys_screen].padding,
true);
for(int i = 0; i < tags->len; i++) for(int i = 0; i < tags->len; i++)
@ -435,6 +438,64 @@ ewmh_check_client_hints(client_t *c)
p_delete(&reply); 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) /** Send request to get NET_WM_ICON (EWMH)
* \param w The window. * \param w The window.
* \return The cookie associated with the request. * \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_update_net_client_list_stacking(int);
void ewmh_check_client_hints(client_t *); void ewmh_check_client_hints(client_t *);
void ewmh_update_workarea(int); 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); 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); 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; client_t *c;
area_t geometry, area; area_t geometry, area;
area = screen_area_get(&globalconf.screens[screen].geometry, area = screen_area_get(screen,
globalconf.screens[screen].statusbar, globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding); &globalconf.screens[screen].padding,
true);
for(c = globalconf.clients ; c; c = c->next) for(c = globalconf.clients ; c; c = c->next)
if(IS_TILED(c, screen)) if(IS_TILED(c, screen))

View File

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

View File

@ -34,9 +34,10 @@ layout_magnifier(int screen)
int n = 0; int n = 0;
client_t *c, *focus; client_t *c, *focus;
tag_t **curtags = tags_get_current(screen); 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].statusbar,
&globalconf.screens[screen].padding); &globalconf.screens[screen].padding,
true);
focus = globalconf.screens[screen].client_focus; focus = globalconf.screens[screen].client_focus;

View File

@ -30,9 +30,10 @@ void
layout_max(int screen) layout_max(int screen)
{ {
client_t *c; 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].statusbar,
&globalconf.screens[screen].padding); &globalconf.screens[screen].padding,
true);
for(c = globalconf.clients; c; c = c->next) for(c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen)) if(IS_TILED(c, screen))

View File

@ -42,9 +42,10 @@ _tile(int screen, const position_t position)
client_t *c; client_t *c;
tag_t **curtags = tags_get_current(screen); 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].statusbar,
&globalconf.screens[screen].padding); &globalconf.screens[screen].padding,
true);
for(n = 0, c = globalconf.clients; c; c = c->next) for(n = 0, c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen)) 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; client_t *snapper;
area_t snapper_geometry; area_t snapper_geometry;
area_t screen_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].statusbar,
&globalconf.screens[c->screen].padding); &globalconf.screens[c->screen].padding,
false);
area_t screen_geometry_barless = area_t screen_geometry_barless =
screen_area_get(&globalconf.screens[c->screen].geometry, screen_area_get(c->screen,
NULL, NULL,
&globalconf.screens[c->screen].padding); &globalconf.screens[c->screen].padding,
false);
geometry = titlebar_geometry_add(c->titlebar, c->border, geometry); 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]; tag = tags_get_current(c->screen)[0];
layout = tag->layout; 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].statusbar,
&globalconf.screens[tag->screen].padding); &globalconf.screens[tag->screen].padding,
true);
mouse_query_pointer(screen->root, &mouse_x, &mouse_y, NULL); 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; 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].statusbar,
&globalconf.screens[tag->screen].padding); &globalconf.screens[tag->screen].padding,
true);
center_x = area.x + (round(area.width / 2.)); center_x = area.x + (round(area.width / 2.));
center_y = area.y + (round(area.height / 2.)); center_y = area.y + (round(area.height / 2.));

View File

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

View File

@ -26,7 +26,7 @@
#define SCREEN_UNDEF (-1) #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 *); area_t display_area_get(int, statusbar_t *, padding_t *);
int screen_virttophys(int); int screen_virttophys(int);
void screen_client_moveto(client_t *, int, bool); void screen_client_moveto(client_t *, int, bool);

View File

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

View File

@ -261,6 +261,16 @@ typedef struct
unsigned char *image; unsigned char *image;
} netwm_icon_t; } 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 */ /** client_t type */
struct client_t struct client_t
{ {
@ -280,6 +290,8 @@ struct client_t
int basew, baseh, incw, inch, maxw, maxh, minw, minh; int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int minax, maxax, minay, maxay; int minax, maxax, minay, maxay;
bool hassizehints; bool hassizehints;
/** Strut */
strut_t strut;
/** Respect resize hints */ /** Respect resize hints */
bool honorsizehints; bool honorsizehints;
int border, oldborder; int border, oldborder;