]> git.sur5r.net Git - i3/i3/blob - src/ewmh.c
ipc/parser: commands can now return custom JSON replies
[i3/i3] / src / ewmh.c
1 /*
2  * vim:ts=8:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  *
6  * © 2009 Michael Stapelberg and contributors
7  *
8  * See file LICENSE for license information.
9  *
10  * ewmh.c: Functions to get/set certain EWMH properties easily.
11  *
12  */
13 #include <stdint.h>
14 #include <string.h>
15 #include <stdlib.h>
16
17 #include "data.h"
18 #include "table.h"
19 #include "i3.h"
20 #include "xcb.h"
21 #include "util.h"
22 #include "log.h"
23
24 /*
25  * Updates _NET_CURRENT_DESKTOP with the current desktop number.
26  *
27  * EWMH: The index of the current desktop. This is always an integer between 0
28  * and _NET_NUMBER_OF_DESKTOPS - 1.
29  *
30  */
31 void ewmh_update_current_desktop() {
32         uint32_t current_desktop = c_ws->num;
33         xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root,
34                             atoms[_NET_CURRENT_DESKTOP], CARDINAL, 32, 1,
35                             &current_desktop);
36 }
37
38 /*
39  * Updates _NET_ACTIVE_WINDOW with the currently focused window.
40  *
41  * EWMH: The window ID of the currently active window or None if no window has
42  * the focus.
43  *
44  */
45 void ewmh_update_active_window(xcb_window_t window) {
46         xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root,
47                             atoms[_NET_ACTIVE_WINDOW], WINDOW, 32, 1, &window);
48 }
49
50 /*
51  * Updates the workarea for each desktop.
52  *
53  * EWMH: Contains a geometry for each desktop. These geometries specify an area
54  * that is completely contained within the viewport. Work area SHOULD be used by
55  * desktop applications to place desktop icons appropriately.
56  *
57  */
58 void ewmh_update_workarea() {
59         Workspace *ws;
60         int num_workspaces = 0, count = 0;
61         Rect last_rect = {0, 0, 0, 0};
62
63         /* Get the number of workspaces */
64         TAILQ_FOREACH(ws, workspaces, workspaces) {
65                 /* Check if we need to initialize last_rect. The case that the
66                  * first workspace is all-zero may happen when the user
67                  * assigned workspace 2 for his first screen, for example. Thus
68                  * we need an initialized last_rect in the very first run of
69                  * the following loop. */
70                 if (last_rect.width == 0 && last_rect.height == 0 &&
71                     ws->rect.width != 0 && ws->rect.height != 0) {
72                         memcpy(&last_rect, &(ws->rect), sizeof(Rect));
73                 }
74                 num_workspaces++;
75         }
76
77         DLOG("Got %d workspaces\n", num_workspaces);
78         uint8_t *workarea = smalloc(sizeof(Rect) * num_workspaces);
79         TAILQ_FOREACH(ws, workspaces, workspaces) {
80                 DLOG("storing %d: %dx%d with %d x %d\n", count, ws->rect.x,
81                      ws->rect.y, ws->rect.width, ws->rect.height);
82                 /* If a workspace is not yet initialized and thus its
83                  * dimensions are zero, we will instead put the dimensions
84                  * of the last workspace in the list. For example firefox
85                  * intersects all workspaces and does not cope so well with
86                  * an all-zero workspace. */
87                 if (ws->rect.width == 0 || ws->rect.height == 0) {
88                         DLOG("re-using last_rect (%dx%d, %d, %d)\n",
89                              last_rect.x, last_rect.y, last_rect.width,
90                              last_rect.height);
91                         memcpy(workarea + (sizeof(Rect) * count++), &last_rect, sizeof(Rect));
92                         continue;
93                 }
94                 memcpy(workarea + (sizeof(Rect) * count++), &(ws->rect), sizeof(Rect));
95                 memcpy(&last_rect, &(ws->rect), sizeof(Rect));
96         }
97         xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root,
98                             atoms[_NET_WORKAREA], CARDINAL, 32,
99                             num_workspaces * (sizeof(Rect) / sizeof(uint32_t)),
100                             workarea);
101         free(workarea);
102         xcb_flush(global_conn);
103 }