|
diff --git a/manager.c b/manager.c
|
| ... |
| 37 |
static Atom WM_TAKE_FOCUS; |
37 |
static Atom WM_TAKE_FOCUS; |
| 38 |
static Atom _NET_SUPPORTED; |
38 |
static Atom _NET_SUPPORTED; |
| 39 |
|
39 |
|
|
|
40 |
static 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 |
|
| 40 |
static void update_wm_state(Window w, Atom state_atom, int add); |
92 |
static void update_wm_state(Window w, Atom state_atom, int add); |
| 41 |
static int has_wm_state(Window w, Atom state_atom); |
93 |
static int has_wm_state(Window w, Atom state_atom); |
| 42 |
static void check_and_clear_maximized_state(Window w, int horizontal, int vertical); |
94 |
static void check_and_clear_maximized_state(Window w, int horizontal, int vertical); |
| ... |
| 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 |
|
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 |
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 |
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); |
| ... |