X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fewmh.c;h=7b2cc3e458fe03d754acae891d0ca48a61a72a20;hb=36583ec6ee7ada36764a492fdaae158a5cdd04c3;hp=2e6e121bcd840bca195d4af9ddd29aea0822cb9d;hpb=e7e9e8e49d3df01c3f534a17e810242b9621058c;p=i3%2Fi3 diff --git a/src/ewmh.c b/src/ewmh.c index 2e6e121b..7b2cc3e4 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -1,21 +1,17 @@ /* - * vim:ts=8:expandtab + * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager * - * © 2009 Michael Stapelberg and contributors + * © 2009-2011 Michael Stapelberg and contributors * * See file LICENSE for license information. * * ewmh.c: Functions to get/set certain EWMH properties easily. * */ -#include -#include "data.h" -#include "table.h" -#include "i3.h" -#include "xcb.h" +#include "all.h" /* * Updates _NET_CURRENT_DESKTOP with the current desktop number. @@ -25,10 +21,22 @@ * */ void ewmh_update_current_desktop() { - uint32_t current_desktop = c_ws->num; - xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, - atoms[_NET_CURRENT_DESKTOP], CARDINAL, 32, 1, - ¤t_desktop); + Con *focused_ws = con_get_workspace(focused); + Con *output; + uint32_t idx = 0; + /* We count to get the index of this workspace because named workspaces + * don’t have the ->num property */ + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + if (ws == focused_ws) { + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, + A__NET_CURRENT_DESKTOP, A_CARDINAL, 32, 1, &idx); + return; + } + ++idx; + } + } } /* @@ -39,6 +47,66 @@ void ewmh_update_current_desktop() { * */ void ewmh_update_active_window(xcb_window_t window) { - xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, - atoms[_NET_ACTIVE_WINDOW], WINDOW, 32, 1, &window); + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, + A__NET_ACTIVE_WINDOW, A_WINDOW, 32, 1, &window); +} + +/* + * Updates the workarea for each desktop. + * + * EWMH: Contains a geometry for each desktop. These geometries specify an area + * that is completely contained within the viewport. Work area SHOULD be used by + * desktop applications to place desktop icons appropriately. + * + */ +void ewmh_update_workarea() { + int num_workspaces = 0, count = 0; + Rect last_rect = {0, 0, 0, 0}; + Con *output; + + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + /* Check if we need to initialize last_rect. The case that the + * first workspace is all-zero may happen when the user + * assigned workspace 2 for his first screen, for example. Thus + * we need an initialized last_rect in the very first run of + * the following loop. */ + if (last_rect.width == 0 && last_rect.height == 0 && + ws->rect.width != 0 && ws->rect.height != 0) { + memcpy(&last_rect, &(ws->rect), sizeof(Rect)); + } + num_workspaces++; + } + } + + DLOG("Got %d workspaces\n", num_workspaces); + uint8_t *workarea = smalloc(sizeof(Rect) * num_workspaces); + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + DLOG("storing %d: %dx%d with %d x %d\n", count, ws->rect.x, + ws->rect.y, ws->rect.width, ws->rect.height); + /* If a workspace is not yet initialized and thus its + * dimensions are zero, we will instead put the dimensions + * of the last workspace in the list. For example firefox + * intersects all workspaces and does not cope so well with + * an all-zero workspace. */ + if (ws->rect.width == 0 || ws->rect.height == 0) { + DLOG("re-using last_rect (%dx%d, %d, %d)\n", + last_rect.x, last_rect.y, last_rect.width, + last_rect.height); + memcpy(workarea + (sizeof(Rect) * count++), &last_rect, sizeof(Rect)); + continue; + } + memcpy(workarea + (sizeof(Rect) * count++), &(ws->rect), sizeof(Rect)); + memcpy(&last_rect, &(ws->rect), sizeof(Rect)); + } + } + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, + A__NET_WORKAREA, A_CARDINAL, 32, + num_workspaces * (sizeof(Rect) / sizeof(uint32_t)), + workarea); + free(workarea); + xcb_flush(conn); }