i3
|
00001 /* 00002 * vim:ts=8:expandtab 00003 * 00004 * i3 - an improved dynamic tiling window manager 00005 * 00006 * © 2009 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 #include <stdint.h> 00014 #include <string.h> 00015 #include <stdlib.h> 00016 00017 #include "data.h" 00018 #include "table.h" 00019 #include "i3.h" 00020 #include "xcb.h" 00021 #include "util.h" 00022 #include "log.h" 00023 00024 /* 00025 * Updates _NET_CURRENT_DESKTOP with the current desktop number. 00026 * 00027 * EWMH: The index of the current desktop. This is always an integer between 0 00028 * and _NET_NUMBER_OF_DESKTOPS - 1. 00029 * 00030 */ 00031 void ewmh_update_current_desktop() { 00032 uint32_t current_desktop = c_ws->num; 00033 xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, 00034 atoms[_NET_CURRENT_DESKTOP], CARDINAL, 32, 1, 00035 ¤t_desktop); 00036 } 00037 00038 /* 00039 * Updates _NET_ACTIVE_WINDOW with the currently focused window. 00040 * 00041 * EWMH: The window ID of the currently active window or None if no window has 00042 * the focus. 00043 * 00044 */ 00045 void ewmh_update_active_window(xcb_window_t window) { 00046 xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, 00047 atoms[_NET_ACTIVE_WINDOW], WINDOW, 32, 1, &window); 00048 } 00049 00050 /* 00051 * Updates the workarea for each desktop. 00052 * 00053 * EWMH: Contains a geometry for each desktop. These geometries specify an area 00054 * that is completely contained within the viewport. Work area SHOULD be used by 00055 * desktop applications to place desktop icons appropriately. 00056 * 00057 */ 00058 void ewmh_update_workarea() { 00059 Workspace *ws; 00060 int num_workspaces = 0, count = 0; 00061 Rect last_rect = {0, 0, 0, 0}; 00062 00063 /* Get the number of workspaces */ 00064 TAILQ_FOREACH(ws, workspaces, workspaces) { 00065 /* Check if we need to initialize last_rect. The case that the 00066 * first workspace is all-zero may happen when the user 00067 * assigned workspace 2 for his first screen, for example. Thus 00068 * we need an initialized last_rect in the very first run of 00069 * the following loop. */ 00070 if (last_rect.width == 0 && last_rect.height == 0 && 00071 ws->rect.width != 0 && ws->rect.height != 0) { 00072 memcpy(&last_rect, &(ws->rect), sizeof(Rect)); 00073 } 00074 num_workspaces++; 00075 } 00076 00077 DLOG("Got %d workspaces\n", num_workspaces); 00078 uint8_t *workarea = smalloc(sizeof(Rect) * num_workspaces); 00079 TAILQ_FOREACH(ws, workspaces, workspaces) { 00080 DLOG("storing %d: %dx%d with %d x %d\n", count, ws->rect.x, 00081 ws->rect.y, ws->rect.width, ws->rect.height); 00082 /* If a workspace is not yet initialized and thus its 00083 * dimensions are zero, we will instead put the dimensions 00084 * of the last workspace in the list. For example firefox 00085 * intersects all workspaces and does not cope so well with 00086 * an all-zero workspace. */ 00087 if (ws->rect.width == 0 || ws->rect.height == 0) { 00088 DLOG("re-using last_rect (%dx%d, %d, %d)\n", 00089 last_rect.x, last_rect.y, last_rect.width, 00090 last_rect.height); 00091 memcpy(workarea + (sizeof(Rect) * count++), &last_rect, sizeof(Rect)); 00092 continue; 00093 } 00094 memcpy(workarea + (sizeof(Rect) * count++), &(ws->rect), sizeof(Rect)); 00095 memcpy(&last_rect, &(ws->rect), sizeof(Rect)); 00096 } 00097 xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, 00098 atoms[_NET_WORKAREA], CARDINAL, 32, 00099 num_workspaces * (sizeof(Rect) / sizeof(uint32_t)), 00100 workarea); 00101 free(workarea); 00102 xcb_flush(global_conn); 00103 }