aboutsummaryrefslogtreecommitdiff
path: root/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'manager.c')
-rw-r--r--manager.c151
1 files changed, 59 insertions, 92 deletions
diff --git a/manager.c b/manager.c
index 63f7e58..78836bc 100644
--- a/manager.c
+++ b/manager.c
@@ -37,6 +37,58 @@ static Atom WM_DELETE_WINDOW;
37static Atom WM_TAKE_FOCUS; 37static Atom WM_TAKE_FOCUS;
38static Atom _NET_SUPPORTED; 38static Atom _NET_SUPPORTED;
39 39
40static void update_window_border(Window window, int active) {
41 if (window == None) return;
42 if (!window_exists(window)) return;
43
44 Atom actual_type;
45 int actual_format;
46 unsigned long nitems, bytes_after;
47 unsigned char *prop = NULL;
48 int has_decorations = 1;
49
50 // Check _MOTIF_WM_HINTS to see if the window requested no decorations
51 XErrorHandler old = XSetErrorHandler(ignore_x_error);
52 int status = XGetWindowProperty(wm.dpy, window, _MOTIF_WM_HINTS, 0, 5, False, AnyPropertyType,
53 &actual_type, &actual_format, &nitems, &bytes_after, &prop);
54 XSync(wm.dpy, False);
55 XSetErrorHandler(old);
56
57 if (status == Success) {
58 if (prop && nitems >= 3) {
59 unsigned long flags = ((unsigned long *)prop)[0];
60 unsigned long decorations = ((unsigned long *)prop)[2];
61 // If flags bit 1 is set (MWM_HINTS_DECORATIONS) and decorations bit 0 is cleared (MWM_DECOR_ALL/BORDER), then no border.
62 // Simplification: if decorations is 0, assume no border.
63 if ((flags & 2) && (decorations & 1) == 0) {
64 has_decorations = 0;
65 }
66 }
67 if (prop) XFree(prop);
68 }
69
70 unsigned int bw = has_decorations ? border_size : 0;
71 XSetWindowBorderWidth(wm.dpy, window, bw);
72
73 if (active) {
74 if (is_always_on_top(window)) {
75 XSetWindowBorder(wm.dpy, window, wm.borders.on_top_active);
76 } else if (is_sticky(window)) {
77 XSetWindowBorder(wm.dpy, window, wm.borders.sticky_active);
78 } else {
79 XSetWindowBorder(wm.dpy, window, wm.borders.normal_active);
80 }
81 } else {
82 if (is_always_on_top(window)) {
83 XSetWindowBorder(wm.dpy, window, wm.borders.on_top_inactive);
84 } else if (is_sticky(window)) {
85 XSetWindowBorder(wm.dpy, window, wm.borders.sticky_inactive);
86 } else {
87 XSetWindowBorder(wm.dpy, window, wm.borders.normal_inactive);
88 }
89 }
90}
91
40static void update_wm_state(Window w, Atom state_atom, int add); 92static void update_wm_state(Window w, Atom state_atom, int add);
41static int has_wm_state(Window w, Atom state_atom); 93static int has_wm_state(Window w, Atom state_atom);
42static void check_and_clear_maximized_state(Window w, int horizontal, int vertical); 94static void check_and_clear_maximized_state(Window w, int horizontal, int vertical);
@@ -140,15 +192,7 @@ static void scan_windows(void) {
140 add_client(wins[i]); 192 add_client(wins[i]);
141 XSelectInput(wm.dpy, wins[i], EnterWindowMask | LeaveWindowMask); 193 XSelectInput(wm.dpy, wins[i], EnterWindowMask | LeaveWindowMask);
142 grab_buttons(wins[i]); 194 grab_buttons(wins[i]);
143 195 update_window_border(wins[i], 0);
144 XSetWindowBorderWidth(wm.dpy, wins[i], border_size);
145 if (is_sticky(wins[i])) {
146 XSetWindowBorder(wm.dpy, wins[i], wm.borders.sticky_inactive);
147 } else if (is_always_on_top(wins[i])) {
148 XSetWindowBorder(wm.dpy, wins[i], wm.borders.on_top_inactive);
149 } else {
150 XSetWindowBorder(wm.dpy, wins[i], wm.borders.normal_inactive);
151 }
152 } 196 }
153 } 197 }
154 if (wins) XFree(wins); 198 if (wins) XFree(wins);
@@ -339,8 +383,6 @@ void init_window_manager(void) {
339 383
340 wm.running = 1; 384 wm.running = 1;
341 385
342 scan_windows();
343
344 // Grab keys for keybinds. 386 // Grab keys for keybinds.
345 for (unsigned int i = 0; i < LENGTH(keybinds); i++) { 387 for (unsigned int i = 0; i < LENGTH(keybinds); i++) {
346 KeyCode keycode = XKeysymToKeycode(wm.dpy, keybinds[i].keysym); 388 KeyCode keycode = XKeysymToKeycode(wm.dpy, keybinds[i].keysym);
@@ -399,24 +441,10 @@ void init_window_manager(void) {
399 wm.borders.on_top_inactive = on_top_inactive.pixel; 441 wm.borders.on_top_inactive = on_top_inactive.pixel;
400 } 442 }
401 443
402 // Scan for existing windows. 444 // Scan for existing windows and apply initial layout.
403 unsigned int nchildren; 445 scan_windows();
404 Window root_return, parent_return, *children; 446 apply_tiling_layout();
405 XWindowAttributes wa;
406 447
407 if (XQueryTree(wm.dpy, wm.root, &root_return, &parent_return, &children, &nchildren)) {
408 for (unsigned int i = 0; i < nchildren; i++) {
409 if (!XGetWindowAttributes(wm.dpy, children[i], &wa) || wa.override_redirect)
410 continue;
411 if (wa.map_state == IsViewable) {
412 grab_buttons(children[i]);
413 XSelectInput(wm.dpy, children[i], EnterWindowMask | LeaveWindowMask);
414 add_client(children[i]);
415 log_message(stdout, LOG_DEBUG, "Grabbed existing window 0x%lx", children[i]);
416 }
417 }
418 if (children) XFree(children);
419 }
420 redraw_widgets(); 448 redraw_widgets();
421 update_client_list(); 449 update_client_list();
422 init_audio(); 450 init_audio();
@@ -1115,75 +1143,14 @@ void set_active_border(Window window) {
1115 if (window == None) return; 1143 if (window == None) return;
1116 if (!window_exists(window)) return; 1144 if (!window_exists(window)) return;
1117 1145
1118 Atom actual_type;
1119 int actual_format;
1120 unsigned long nitems, bytes_after;
1121 unsigned char *prop = NULL;
1122 int has_decorations = 1;
1123
1124 // Check _MOTIF_WM_HINTS to see if the window requested no decorations
1125 XErrorHandler old = XSetErrorHandler(ignore_x_error);
1126 int status = XGetWindowProperty(wm.dpy, window, _MOTIF_WM_HINTS, 0, 5, False, AnyPropertyType,
1127 &actual_type, &actual_format, &nitems, &bytes_after, &prop);
1128 XSync(wm.dpy, False);
1129 XSetErrorHandler(old);
1130
1131 if (status == Success) {
1132 if (prop && nitems >= 3) {
1133 unsigned long flags = ((unsigned long *)prop)[0];
1134 unsigned long decorations = ((unsigned long *)prop)[2];
1135 // If flags bit 1 is set (MWM_HINTS_DECORATIONS) and decorations bit 0 is cleared (MWM_DECOR_ALL/BORDER), then no border.
1136 // Simplification: if decorations is 0, assume no border.
1137 if ((flags & 2) && (decorations & 1) == 0) {
1138 has_decorations = 0;
1139 }
1140 }
1141 if (prop) XFree(prop);
1142 }
1143
1144 unsigned int bw = has_decorations ? border_size : 0;
1145
1146 // Setting current active window to inactive. 1146 // Setting current active window to inactive.
1147 if (wm.active != None) { 1147 if (wm.active != None && wm.active != window) {
1148 // For safety/speed, let's re-check hints for the old active window too. 1148 update_window_border(wm.active, 0);
1149 int old_has_decorations = 1;
1150
1151 old = XSetErrorHandler(ignore_x_error);
1152 status = XGetWindowProperty(wm.dpy, wm.active, _MOTIF_WM_HINTS, 0, 5, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
1153 XSync(wm.dpy, False);
1154 XSetErrorHandler(old);
1155
1156 if (status == Success) {
1157 if (prop && nitems >= 3) {
1158 unsigned long flags = ((unsigned long *)prop)[0];
1159 unsigned long decorations = ((unsigned long *)prop)[2];
1160 if ((flags & 2) && (decorations & 1) == 0) {
1161 old_has_decorations = 0;
1162 }
1163 }
1164 if (prop) XFree(prop);
1165 }
1166
1167 XSetWindowBorderWidth(wm.dpy, wm.active, old_has_decorations ? border_size : 0);
1168 if (is_always_on_top(wm.active)) {
1169 XSetWindowBorder(wm.dpy, wm.active, wm.borders.on_top_inactive);
1170 } else if (is_sticky(wm.active)) {
1171 XSetWindowBorder(wm.dpy, wm.active, wm.borders.sticky_inactive);
1172 } else {
1173 XSetWindowBorder(wm.dpy, wm.active, wm.borders.normal_inactive);
1174 }
1175 log_message(stdout, LOG_DEBUG, "Active window 0x%lx border set to inactive", wm.active); 1149 log_message(stdout, LOG_DEBUG, "Active window 0x%lx border set to inactive", wm.active);
1176 } 1150 }
1177 1151
1178 // Setting desired window to active. 1152 // Setting desired window to active.
1179 XSetWindowBorderWidth(wm.dpy, window, bw); 1153 update_window_border(window, 1);
1180 if (is_always_on_top(window)) {
1181 XSetWindowBorder(wm.dpy, window, wm.borders.on_top_active);
1182 } else if (is_sticky(window)) {
1183 XSetWindowBorder(wm.dpy, window, wm.borders.sticky_active);
1184 } else {
1185 XSetWindowBorder(wm.dpy, window, wm.borders.normal_active);
1186 }
1187 XFlush(wm.dpy); 1154 XFlush(wm.dpy);
1188 1155
1189 log_message(stdout, LOG_DEBUG, "Desired window 0x%lx border set to active", window); 1156 log_message(stdout, LOG_DEBUG, "Desired window 0x%lx border set to active", window);