-#include <stdio.h>
+/* Copyright (c) 2012, Bastien Dejean
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
#include <string.h>
-#include <xcb/xcb_ewmh.h>
-#include "types.h"
+#include <unistd.h>
#include "bspwm.h"
#include "settings.h"
#include "tree.h"
void ewmh_init(void)
{
- ewmh = malloc(sizeof(xcb_ewmh_connection_t));
- if (xcb_ewmh_init_atoms_replies(ewmh, xcb_ewmh_init_atoms(dpy, ewmh), NULL) == 0)
- err("Can't initialize EWMH atoms.\n");
-}
-
-void ewmh_update_wm_name(void)
-{
- if (wm_name != NULL)
- xcb_ewmh_set_wm_name(ewmh, root, strlen(wm_name), wm_name);
+ ewmh = malloc(sizeof(xcb_ewmh_connection_t));
+ if (xcb_ewmh_init_atoms_replies(ewmh, xcb_ewmh_init_atoms(dpy, ewmh), NULL) == 0) {
+ err("Can't initialize EWMH atoms.\n");
+ }
}
void ewmh_update_active_window(void)
{
- xcb_window_t win = (mon->desk->focus == NULL ? XCB_NONE : mon->desk->focus->client->window);
- xcb_ewmh_set_active_window(ewmh, default_screen, win);
+ xcb_window_t win = ((mon->desk->focus == NULL || mon->desk->focus->client == NULL) ? XCB_NONE : mon->desk->focus->id);
+ xcb_ewmh_set_active_window(ewmh, default_screen, win);
}
void ewmh_update_number_of_desktops(void)
{
- xcb_ewmh_set_number_of_desktops(ewmh, default_screen, num_desktops);
+ uint32_t desktops_count = 0;
+
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ desktops_count++;
+ }
+ }
+
+ xcb_ewmh_set_number_of_desktops(ewmh, default_screen, desktops_count);
}
uint32_t ewmh_get_desktop_index(desktop_t *d)
{
- uint32_t i = 0;
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next, i++)
- if (d == cd)
- return i;
-
- return 0;
+ uint32_t i = 0;
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next, i++) {
+ if (d == cd) {
+ return i;
+ }
+ }
+ }
+ return 0;
}
-bool ewmh_locate_desktop(uint32_t i, desktop_location_t *loc)
+bool ewmh_locate_desktop(uint32_t i, coordinates_t *loc)
{
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- for (desktop_t *d = m->desk_head; d != NULL; d = d->next, i--)
- if (i == 0) {
- loc->monitor = m;
- loc->desktop = d;
- return true;
- }
-
- return false;
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next, i--) {
+ if (i == 0) {
+ loc->monitor = m;
+ loc->desktop = d;
+ loc->node = NULL;
+ return true;
+ }
+ }
+ }
+ return false;
}
void ewmh_update_current_desktop(void)
{
- uint32_t i = ewmh_get_desktop_index(mon->desk);
- xcb_ewmh_set_current_desktop(ewmh, default_screen, i);
+ if (mon == NULL) {
+ return;
+ }
+ uint32_t i = ewmh_get_desktop_index(mon->desk);
+ xcb_ewmh_set_current_desktop(ewmh, default_screen, i);
}
void ewmh_set_wm_desktop(node_t *n, desktop_t *d)
{
- uint32_t i = ewmh_get_desktop_index(d);
- xcb_ewmh_set_wm_desktop(ewmh, n->client->window, i);
+ uint32_t i = ewmh_get_desktop_index(d);
+ for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) {
+ if (f->client == NULL) {
+ continue;
+ }
+ xcb_ewmh_set_wm_desktop(ewmh, f->id, i);
+ }
}
-void ewmh_update_desktop_names(void)
+void ewmh_update_wm_desktops(void)
{
- char names[MAXLEN];
- monitor_t *m = mon_head;
- unsigned int pos, i;
- pos = i = 0;
-
- while (m != NULL) {
- desktop_t *d = m->desk_head;
-
- while (d != NULL && i < num_desktops) {
- for (unsigned int j = 0; j < strlen(d->name); j++)
- names[pos + j] = d->name[j];
- pos += strlen(d->name);
- names[pos] = '\0';
- pos++;
- d = d->next;
- i++;
- }
-
- m = m->next;
- }
-
- if (i != num_desktops)
- return;
-
- pos--;
-
- xcb_ewmh_set_desktop_names(ewmh, default_screen, pos, names);
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ uint32_t i = ewmh_get_desktop_index(d);
+ for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
+ if (n->client == NULL) {
+ continue;
+ }
+ xcb_ewmh_set_wm_desktop(ewmh, n->id, i);
+ }
+ }
+ }
}
-void ewmh_update_client_list(void)
+void ewmh_update_desktop_names(void)
{
- if (num_clients == 0) {
- xcb_ewmh_set_client_list(ewmh, default_screen, 0, NULL);
- return;
- }
-
- xcb_window_t wins[num_clients];
- unsigned int i = 0;
+ char names[MAXLEN];
+ unsigned int i, j;
+ uint32_t names_len;
+ i = 0;
+
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ for (j = 0; d->name[j] != '\0' && (i + j) < sizeof(names); j++) {
+ names[i + j] = d->name[j];
+ }
+ i += j;
+ if (i < sizeof(names)) {
+ names[i++] = '\0';
+ }
+ }
+ }
+
+ if (i < 1) {
+ xcb_ewmh_set_desktop_names(ewmh, default_screen, 0, NULL);
+ return;
+ }
+
+ names_len = i - 1;
+ xcb_ewmh_set_desktop_names(ewmh, default_screen, names_len, names);
+}
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
- for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n))
- wins[i++] = n->client->window;
+void ewmh_update_client_list(bool stacking)
+{
+ if (clients_count == 0) {
+ xcb_ewmh_set_client_list(ewmh, default_screen, 0, NULL);
+ xcb_ewmh_set_client_list_stacking(ewmh, default_screen, 0, NULL);
+ return;
+ }
+
+ xcb_window_t wins[clients_count];
+ unsigned int i = 0;
+
+ if (stacking) {
+ for (stacking_list_t *s = stack_head; s != NULL; s = s->next) {
+ wins[i++] = s->node->id;
+ }
+ xcb_ewmh_set_client_list_stacking(ewmh, default_screen, clients_count, wins);
+ } else {
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
+ if (n->client == NULL) {
+ continue;
+ }
+ wins[i++] = n->id;
+ }
+ }
+ }
+ xcb_ewmh_set_client_list(ewmh, default_screen, clients_count, wins);
+ }
+}
- if (i != num_clients)
- return;
+void ewmh_wm_state_update(node_t *n)
+{
+ client_t *c = n->client;
+ size_t count = 0;
+ uint32_t values[12];
+#define HANDLE_WM_STATE(s) \
+ if (WM_FLAG_##s & c->wm_flags) { \
+ values[count++] = ewmh->_NET_WM_STATE_##s; \
+ }
+ HANDLE_WM_STATE(MODAL)
+ HANDLE_WM_STATE(STICKY)
+ HANDLE_WM_STATE(MAXIMIZED_VERT)
+ HANDLE_WM_STATE(MAXIMIZED_HORZ)
+ HANDLE_WM_STATE(SHADED)
+ HANDLE_WM_STATE(SKIP_TASKBAR)
+ HANDLE_WM_STATE(SKIP_PAGER)
+ HANDLE_WM_STATE(HIDDEN)
+ HANDLE_WM_STATE(FULLSCREEN)
+ HANDLE_WM_STATE(ABOVE)
+ HANDLE_WM_STATE(BELOW)
+ HANDLE_WM_STATE(DEMANDS_ATTENTION)
+#undef HANDLE_WM_STATE
+ xcb_ewmh_set_wm_state(ewmh, n->id, count, values);
+}
- xcb_ewmh_set_client_list(ewmh, default_screen, num_clients, wins);
- xcb_ewmh_set_client_list_stacking(ewmh, default_screen, num_clients, wins);
+void ewmh_set_supporting(xcb_window_t win)
+{
+ pid_t wm_pid = getpid();
+ xcb_ewmh_set_supporting_wm_check(ewmh, root, win);
+ xcb_ewmh_set_supporting_wm_check(ewmh, win, win);
+ xcb_ewmh_set_wm_name(ewmh, win, strlen(WM_NAME), WM_NAME);
+ xcb_ewmh_set_wm_pid(ewmh, win, wm_pid);
}