i3
|
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 }