i3
src/ewmh.c
Go to the documentation of this file.
00001 /*
00002  * vim:ts=4:sw=4:expandtab
00003  *
00004  * i3 - an improved dynamic tiling window manager
00005  *
00006  * © 2009-2011 Michael Stapelberg and contributors
00007  *
00008  * See file LICENSE for license information.
00009  *
00010  * ewmh.c: Functions to get/set certain EWMH properties easily.
00011  *
00012  */
00013 
00014 #include "all.h"
00015 
00016 /*
00017  * Updates _NET_CURRENT_DESKTOP with the current desktop number.
00018  *
00019  * EWMH: The index of the current desktop. This is always an integer between 0
00020  * and _NET_NUMBER_OF_DESKTOPS - 1.
00021  *
00022  */
00023 void ewmh_update_current_desktop() {
00024     Con *focused_ws = con_get_workspace(focused);
00025     Con *output;
00026     uint32_t idx = 0;
00027     /* We count to get the index of this workspace because named workspaces
00028      * don’t have the ->num property */
00029     TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
00030         Con *ws;
00031         TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
00032             if (ws == focused_ws) {
00033                 xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
00034                         A__NET_CURRENT_DESKTOP, A_CARDINAL, 32, 1, &idx);
00035                 return;
00036             }
00037             ++idx;
00038         }
00039     }
00040 }
00041 
00042 /*
00043  * Updates _NET_ACTIVE_WINDOW with the currently focused window.
00044  *
00045  * EWMH: The window ID of the currently active window or None if no window has
00046  * the focus.
00047  *
00048  */
00049 void ewmh_update_active_window(xcb_window_t window) {
00050     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
00051             A__NET_ACTIVE_WINDOW, A_WINDOW, 32, 1, &window);
00052 }
00053 
00054 /*
00055  * Updates the workarea for each desktop.
00056  *
00057  * EWMH: Contains a geometry for each desktop. These geometries specify an area
00058  * that is completely contained within the viewport. Work area SHOULD be used by
00059  * desktop applications to place desktop icons appropriately.
00060  *
00061  */
00062 void ewmh_update_workarea() {
00063     int num_workspaces = 0, count = 0;
00064     Rect last_rect = {0, 0, 0, 0};
00065     Con *output;
00066 
00067     TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
00068         Con *ws;
00069         TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
00070             /* Check if we need to initialize last_rect. The case that the
00071              * first workspace is all-zero may happen when the user
00072              * assigned workspace 2 for his first screen, for example. Thus
00073              * we need an initialized last_rect in the very first run of
00074              * the following loop. */
00075             if (last_rect.width == 0 && last_rect.height == 0 &&
00076                     ws->rect.width != 0 && ws->rect.height != 0) {
00077                 memcpy(&last_rect, &(ws->rect), sizeof(Rect));
00078             }
00079             num_workspaces++;
00080         }
00081     }
00082 
00083     DLOG("Got %d workspaces\n", num_workspaces);
00084     uint8_t *workarea = smalloc(sizeof(Rect) * num_workspaces);
00085     TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
00086         Con *ws;
00087         TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
00088             DLOG("storing %d: %dx%d with %d x %d\n", count, ws->rect.x,
00089                  ws->rect.y, ws->rect.width, ws->rect.height);
00090             /* If a workspace is not yet initialized and thus its
00091              * dimensions are zero, we will instead put the dimensions
00092              * of the last workspace in the list. For example firefox
00093              * intersects all workspaces and does not cope so well with
00094              * an all-zero workspace. */
00095             if (ws->rect.width == 0 || ws->rect.height == 0) {
00096                 DLOG("re-using last_rect (%dx%d, %d, %d)\n",
00097                      last_rect.x, last_rect.y, last_rect.width,
00098                      last_rect.height);
00099                 memcpy(workarea + (sizeof(Rect) * count++), &last_rect, sizeof(Rect));
00100                 continue;
00101             }
00102             memcpy(workarea + (sizeof(Rect) * count++), &(ws->rect), sizeof(Rect));
00103             memcpy(&last_rect, &(ws->rect), sizeof(Rect));
00104         }
00105     }
00106     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
00107             A__NET_WORKAREA, A_CARDINAL, 32,
00108             num_workspaces * (sizeof(Rect) / sizeof(uint32_t)),
00109             workarea);
00110     free(workarea);
00111     xcb_flush(conn);
00112 }