Improved detection of windows that want floating
Patch status: merged
Patch by Kernc
Long description:
Windows that match the following criteria are floated by default: - dialog, utility, toolbar, or splash windows, - modal windows, or - windows that have specified equal minimum and maximum size. This closes #1182.
To apply this patch, use:
curl http://cr.i3wm.org/patch/443/raw.patch | git am
b/include/atoms.xmacro
21 |
@@ -3,6 +3,7 @@ xmacro(_NET_SUPPORTING_WM_CHECK) |
22 |
xmacro(_NET_WM_NAME) |
23 |
xmacro(_NET_WM_STATE_FULLSCREEN) |
24 |
xmacro(_NET_WM_STATE_DEMANDS_ATTENTION) |
25 |
+xmacro(_NET_WM_STATE_MODAL) |
26 |
xmacro(_NET_WM_STATE) |
27 |
xmacro(_NET_WM_WINDOW_TYPE) |
28 |
xmacro(_NET_WM_WINDOW_TYPE_DOCK) |
b/include/xcb_compat.h
33 |
@@ -19,9 +19,12 @@ |
34 |
#define XCB_ICCCM_WM_STATE_NORMAL XCB_WM_STATE_NORMAL |
35 |
#define XCB_ICCCM_WM_STATE_WITHDRAWN XCB_WM_STATE_WITHDRAWN |
36 |
#define xcb_icccm_get_wm_size_hints_from_reply xcb_get_wm_size_hints_from_reply |
37 |
+#define xcb_icccm_get_wm_size_hints_reply xcb_get_wm_size_hints_reply |
38 |
+#define xcb_icccm_get_wm_normal_hints xcb_get_wm_normal_hints |
39 |
#define xcb_icccm_get_wm_normal_hints_reply xcb_get_wm_normal_hints_reply |
40 |
#define xcb_icccm_get_wm_normal_hints_unchecked xcb_get_wm_normal_hints_unchecked |
41 |
#define XCB_ICCCM_SIZE_HINT_P_MIN_SIZE XCB_SIZE_HINT_P_MIN_SIZE |
42 |
+#define XCB_ICCCM_SIZE_HINT_P_MAX_SIZE XCB_SIZE_HINT_P_MAX_SIZE |
43 |
#define XCB_ICCCM_SIZE_HINT_P_RESIZE_INC XCB_SIZE_HINT_P_RESIZE_INC |
44 |
#define XCB_ICCCM_SIZE_HINT_BASE_SIZE XCB_SIZE_HINT_BASE_SIZE |
45 |
#define XCB_ICCCM_SIZE_HINT_P_ASPECT XCB_SIZE_HINT_P_ASPECT |
b/src/manage.c
50 |
@@ -90,7 +90,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki |
51 |
utf8_title_cookie, title_cookie, |
52 |
class_cookie, leader_cookie, transient_cookie, |
53 |
role_cookie, startup_id_cookie, wm_hints_cookie, |
54 |
- motif_wm_hints_cookie; |
55 |
+ wm_normal_hints_cookie, motif_wm_hints_cookie; |
56 |
|
57 |
|
58 |
geomc = xcb_get_geometry(conn, d); |
59 |
@@ -160,8 +160,8 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki |
60 |
role_cookie = GET_PROPERTY(A_WM_WINDOW_ROLE, 128); |
61 |
startup_id_cookie = GET_PROPERTY(A__NET_STARTUP_ID, 512); |
62 |
wm_hints_cookie = xcb_icccm_get_wm_hints(conn, window); |
63 |
+ wm_normal_hints_cookie = xcb_icccm_get_wm_normal_hints(conn, window); |
64 |
motif_wm_hints_cookie = GET_PROPERTY(A__MOTIF_WM_HINTS, 5 * sizeof(uint64_t)); |
65 |
- /* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */ |
66 |
|
67 |
DLOG("Managing window 0x%08x\n", window); |
68 |
|
69 |
@@ -197,6 +197,10 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki |
70 |
window_update_hints(cwindow, xcb_get_property_reply(conn, wm_hints_cookie, NULL), &urgency_hint); |
71 |
border_style_t motif_border_style = BS_NORMAL; |
72 |
window_update_motif_hints(cwindow, xcb_get_property_reply(conn, motif_wm_hints_cookie, NULL), &motif_border_style); |
73 |
+ xcb_size_hints_t wm_size_hints; |
74 |
+ xcb_icccm_get_wm_size_hints_reply(conn, wm_normal_hints_cookie, &wm_size_hints, NULL); |
75 |
+ xcb_get_property_reply_t *type_reply = xcb_get_property_reply(conn, wm_type_cookie, NULL); |
76 |
+ xcb_get_property_reply_t *state_reply = xcb_get_property_reply(conn, state_cookie, NULL); |
77 |
|
78 |
xcb_get_property_reply_t *startup_id_reply; |
79 |
startup_id_reply = xcb_get_property_reply(conn, startup_id_cookie, NULL); |
80 |
@@ -209,8 +213,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki |
81 |
/* Where to start searching for a container that swallows the new one? */ |
82 |
Con *search_at = croot; |
83 |
|
84 |
- xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, wm_type_cookie, NULL); |
85 |
- if (xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_DOCK)) { |
86 |
+ if (xcb_reply_contains_atom(type_reply, A__NET_WM_WINDOW_TYPE_DOCK)) { |
87 |
LOG("This window is of type dock\n"); |
88 |
Output *output = get_output_containing(geom->x, geom->y); |
89 |
if (output != NULL) { |
90 |
@@ -323,14 +326,11 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki |
91 |
if (fs == NULL) |
92 |
fs = con_get_fullscreen_con(croot, CF_GLOBAL); |
93 |
|
94 |
- xcb_get_property_reply_t *state_reply = xcb_get_property_reply(conn, state_cookie, NULL); |
95 |
if (xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_FULLSCREEN)) { |
96 |
fs = NULL; |
97 |
con_toggle_fullscreen(nc, CF_OUTPUT); |
98 |
} |
99 |
|
100 |
- FREE(state_reply); |
101 |
- |
102 |
bool set_focus = false; |
103 |
|
104 |
if (fs == NULL) { |
105 |
@@ -365,15 +365,21 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki |
106 |
|
107 |
/* set floating if necessary */ |
108 |
bool want_floating = false; |
109 |
- if (xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_DIALOG) || |
110 |
- xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_UTILITY) || |
111 |
- xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_TOOLBAR) || |
112 |
- xcb_reply_contains_atom(reply, A__NET_WM_WINDOW_TYPE_SPLASH)) { |
113 |
+ if (xcb_reply_contains_atom(type_reply, A__NET_WM_WINDOW_TYPE_DIALOG) || |
114 |
+ xcb_reply_contains_atom(type_reply, A__NET_WM_WINDOW_TYPE_UTILITY) || |
115 |
+ xcb_reply_contains_atom(type_reply, A__NET_WM_WINDOW_TYPE_TOOLBAR) || |
116 |
+ xcb_reply_contains_atom(type_reply, A__NET_WM_WINDOW_TYPE_SPLASH) || |
117 |
+ xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_MODAL) || |
118 |
+ (wm_size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE && |
119 |
+ wm_size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE && |
120 |
+ wm_size_hints.min_height == wm_size_hints.max_height && |
121 |
+ wm_size_hints.min_width == wm_size_hints.max_width)) { |
122 |
LOG("This window is a dialog window, setting floating\n"); |
123 |
want_floating = true; |
124 |
} |
125 |
|
126 |
- FREE(reply); |
127 |
+ FREE(state_reply); |
128 |
+ FREE(type_reply); |
129 |
|
130 |
if (cwindow->transient_for != XCB_NONE || |
131 |
(cwindow->leader != XCB_NONE && |