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 && |