From 7e424b2d71e4c3dbdb314aad03479fc8ee5480ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 18 Apr 2015 22:02:03 +0200 Subject: [PATCH 1/7] Added testcase for criterion 'window_type'. --- testcases/t/165-for_window.t | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/testcases/t/165-for_window.t b/testcases/t/165-for_window.t index ada7c5c5..036fc9d6 100644 --- a/testcases/t/165-for_window.t +++ b/testcases/t/165-for_window.t @@ -370,5 +370,44 @@ is($content[0]->{border}, 'none', 'no border (window_role 2)'); exit_gracefully($pid); +############################################################## +# 10: check that the criterion 'window_type' works +############################################################## + +# test all window types +my %window_types = ( + 'normal' => '_NET_WM_WINDOW_TYPE_NORMAL', + 'dialog' => '_NET_WM_WINDOW_TYPE_DIALOG', + 'utility' => '_NET_WM_WINDOW_TYPE_UTILITY', + 'toolbar' => '_NET_WM_WINDOW_TYPE_TOOLBAR', + 'splash' => '_NET_WM_WINDOW_TYPE_SPLASH', + 'menu' => '_NET_WM_WINDOW_TYPE_MENU', + 'dropdown_menu' => '_NET_WM_WINDOW_TYPE_DROPDOWN_MENU', + 'popup_menu' => '_NET_WM_WINDOW_TYPE_POPUP_MENU', + 'tooltip' => '_NET_WM_WINDOW_TYPE_TOOLTIP' +); + +while (my ($window_type, $atom) = each %window_types) { + + $config = <<"EOT"; +# i3 config file (v4) +font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +for_window [window_type="$window_type"] floating enable, mark branded +EOT + + $pid = launch_with_config($config); + $tmp = fresh_workspace; + + $window = open_window(window_type => $x->atom(name => $atom)); + + my @nodes = @{get_ws($tmp)->{floating_nodes}}; + cmp_ok(@nodes, '==', 1, 'one floating container on this workspace'); + is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)"); + + exit_gracefully($pid); + +} + +############################################################## done_testing; From 550c0ec31867f780b4bbd1a14f1496e7919a2766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 18 Apr 2015 21:09:03 +0200 Subject: [PATCH 2/7] Implement new criterion 'window_type = normal|dialog|utility|toolbar|splash|menu|dropdown_menu|popup_menu|tooltip' fixes #1658 --- docs/userguide | 4 ++++ include/atoms.xmacro | 5 +++++ include/data.h | 4 ++++ include/xcb.h | 10 ++++++++++ parser-specs/commands.spec | 1 + parser-specs/config.spec | 1 + src/commands.c | 25 ++++++++++++++++++++++++ src/config_directives.c | 25 ++++++++++++++++++++++++ src/ewmh.c | 4 ++-- src/main.c | 40 +++++++++++++++++++------------------- src/manage.c | 3 +++ src/match.c | 15 ++++++++++++-- src/xcb.c | 29 +++++++++++++++++++++++++++ 13 files changed, 142 insertions(+), 24 deletions(-) diff --git a/docs/userguide b/docs/userguide index 687dff10..965f839e 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1508,6 +1508,10 @@ instance:: Compares the window instance (the first part of WM_CLASS) window_role:: Compares the window role (WM_WINDOW_ROLE). +window_type:: + Compare the window type (_NET_WM_WINDOW_TYPE). Possible values are + +normal+, +dialog+, +utility+, +toolbar+, +splash+, +menu+, +dropdown_menu+, + +popup_menu+ and +toolti+. id:: Compares the X11 window ID, which you can get via +xwininfo+ for example. title:: diff --git a/include/atoms.xmacro b/include/atoms.xmacro index 59dab6ed..b9ee4eb7 100644 --- a/include/atoms.xmacro +++ b/include/atoms.xmacro @@ -7,11 +7,16 @@ xmacro(_NET_WM_STATE_DEMANDS_ATTENTION) xmacro(_NET_WM_STATE_MODAL) xmacro(_NET_WM_STATE) xmacro(_NET_WM_WINDOW_TYPE) +xmacro(_NET_WM_WINDOW_TYPE_NORMAL) xmacro(_NET_WM_WINDOW_TYPE_DOCK) xmacro(_NET_WM_WINDOW_TYPE_DIALOG) xmacro(_NET_WM_WINDOW_TYPE_UTILITY) xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR) xmacro(_NET_WM_WINDOW_TYPE_SPLASH) +xmacro(_NET_WM_WINDOW_TYPE_MENU) +xmacro(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) +xmacro(_NET_WM_WINDOW_TYPE_POPUP_MENU) +xmacro(_NET_WM_WINDOW_TYPE_TOOLTIP) xmacro(_NET_WM_DESKTOP) xmacro(_NET_WM_STRUT_PARTIAL) xmacro(_NET_CLIENT_LIST) diff --git a/include/data.h b/include/data.h index 50e1f180..5fb9a074 100644 --- a/include/data.h +++ b/include/data.h @@ -378,6 +378,9 @@ struct Window { * default will be 'accepts focus'. */ bool doesnt_accept_focus; + /** The _NET_WM_WINDOW_TYPE for this window. */ + xcb_atom_t window_type; + /** Whether the window says it is a dock window */ enum { W_NODOCK = 0, W_DOCK_TOP = 1, @@ -408,6 +411,7 @@ struct Match { struct regex *instance; struct regex *mark; struct regex *window_role; + xcb_atom_t window_type; enum { U_DONTCHECK = -1, U_LATEST = 0, diff --git a/include/xcb.h b/include/xcb.h index 9f4ea91f..69d5af2c 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -108,6 +108,16 @@ void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window); */ void xcb_set_window_rect(xcb_connection_t *conn, xcb_window_t window, Rect r); +/** + * Returns the first supported _NET_WM_WINDOW_TYPE atom. + * + */ +xcb_atom_t xcb_get_preferred_window_type(xcb_get_property_reply_t *reply); + +/** + * Returns true if the given reply contains the given data. + * + */ bool xcb_reply_contains_atom(xcb_get_property_reply_t *prop, xcb_atom_t atom); /** diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index 87db6cf0..e6217b19 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -49,6 +49,7 @@ state CRITERIA: ctype = 'con_mark' -> CRITERION ctype = 'title' -> CRITERION ctype = 'urgent' -> CRITERION + ctype = 'window_type' -> CRITERION ']' -> call cmd_criteria_match_windows(); INITIAL state CRITERION: diff --git a/parser-specs/config.spec b/parser-specs/config.spec index d27e0792..c5c8ad25 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -167,6 +167,7 @@ state CRITERIA: ctype = 'window_role' -> CRITERION ctype = 'con_id' -> CRITERION ctype = 'id' -> CRITERION + ctype = 'window_type' -> CRITERION ctype = 'con_mark' -> CRITERION ctype = 'title' -> CRITERION ctype = 'urgent' -> CRITERION diff --git a/src/commands.c b/src/commands.c index 79071d6b..6b720251 100644 --- a/src/commands.c +++ b/src/commands.c @@ -363,6 +363,31 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) { return; } + if (strcmp(ctype, "window_type") == 0) { + if (strcasecmp(cvalue, "normal") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_NORMAL; + else if (strcasecmp(cvalue, "dialog") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_DIALOG; + else if (strcasecmp(cvalue, "utility") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_UTILITY; + else if (strcasecmp(cvalue, "toolbar") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLBAR; + else if (strcasecmp(cvalue, "splash") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_SPLASH; + else if (strcasecmp(cvalue, "menu") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_MENU; + else if (strcasecmp(cvalue, "dropdown_menu") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU; + else if (strcasecmp(cvalue, "popup_menu") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_POPUP_MENU; + else if (strcasecmp(cvalue, "tooltip") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLTIP; + else + ELOG("unknown window_type value \"%s\"\n", cvalue); + + return; + } + if (strcmp(ctype, "con_mark") == 0) { current_match->mark = regex_new(cvalue); return; diff --git a/src/config_directives.c b/src/config_directives.c index 398e53bb..49e8d91d 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -89,6 +89,31 @@ CFGFUN(criteria_add, const char *ctype, const char *cvalue) { return; } + if (strcmp(ctype, "window_type") == 0) { + if (strcasecmp(cvalue, "normal") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_NORMAL; + else if (strcasecmp(cvalue, "dialog") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_DIALOG; + else if (strcasecmp(cvalue, "utility") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_UTILITY; + else if (strcasecmp(cvalue, "toolbar") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLBAR; + else if (strcasecmp(cvalue, "splash") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_SPLASH; + else if (strcasecmp(cvalue, "menu") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_MENU; + else if (strcasecmp(cvalue, "dropdown_menu") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU; + else if (strcasecmp(cvalue, "popup_menu") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_POPUP_MENU; + else if (strcasecmp(cvalue, "tooltip") == 0) + current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLTIP; + else + ELOG("unknown window_type value \"%s\"\n", cvalue); + + return; + } + if (strcmp(ctype, "con_mark") == 0) { current_match->mark = regex_new(cvalue); return; diff --git a/src/ewmh.c b/src/ewmh.c index 844a0db9..883b929e 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -234,6 +234,6 @@ void ewmh_setup_hints(void) { /* I’m not entirely sure if we need to keep _NET_WM_NAME on root. */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3"); - /* only send the first 24 atoms (last one is _NET_CLOSE_WINDOW) increment that number when adding supported atoms */ - xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 24, supported_atoms); + /* only send the first 29 atoms (last one is _NET_CLOSE_WINDOW) increment that number when adding supported atoms */ + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 29, supported_atoms); } diff --git a/src/main.c b/src/main.c index ac40e7a3..3c534431 100644 --- a/src/main.c +++ b/src/main.c @@ -474,6 +474,12 @@ int main(int argc, char *argv[]) { root_screen = xcb_aux_get_screen(conn, conn_screen); root = root_screen->root; +/* Place requests for the atoms we need as soon as possible */ +#define xmacro(atom) \ + xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom); +#include "atoms.xmacro" +#undef xmacro + /* By default, we use the same depth and visual as the root window, which * usually is TrueColor (24 bit depth) and the corresponding visual. * However, we also check if a 32 bit depth and visual are available (for @@ -491,6 +497,20 @@ int main(int argc, char *argv[]) { xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root); xcb_query_pointer_cookie_t pointercookie = xcb_query_pointer(conn, root); +/* Setup NetWM atoms */ +#define xmacro(name) \ + do { \ + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \ + if (!reply) { \ + ELOG("Could not get atom " #name "\n"); \ + exit(-1); \ + } \ + A_##name = reply->atom; \ + free(reply); \ + } while (0); +#include "atoms.xmacro" +#undef xmacro + load_configuration(conn, override_configpath, false); if (config.ipc_socket_path == NULL) { @@ -512,12 +532,6 @@ int main(int argc, char *argv[]) { } DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height); -/* Place requests for the atoms we need as soon as possible */ -#define xmacro(atom) \ - xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom); -#include "atoms.xmacro" -#undef xmacro - xcursor_load_cursors(); /* Set a cursor for the root window (otherwise the root window will show no @@ -547,20 +561,6 @@ int main(int argc, char *argv[]) { restore_connect(); -/* Setup NetWM atoms */ -#define xmacro(name) \ - do { \ - xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \ - if (!reply) { \ - ELOG("Could not get atom " #name "\n"); \ - exit(-1); \ - } \ - A_##name = reply->atom; \ - free(reply); \ - } while (0); -#include "atoms.xmacro" -#undef xmacro - property_handlers_init(); ewmh_setup_hints(); diff --git a/src/manage.c b/src/manage.c index 3499963b..bc9c9bff 100644 --- a/src/manage.c +++ b/src/manage.c @@ -210,6 +210,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki /* check if the window needs WM_TAKE_FOCUS */ cwindow->needs_take_focus = window_supports_protocol(cwindow->id, A_WM_TAKE_FOCUS); + /* read the preferred _NET_WM_WINDOW_TYPE atom */ + cwindow->window_type = xcb_get_preferred_window_type(type_reply); + /* Where to start searching for a container that swallows the new one? */ Con *search_at = croot; diff --git a/src/match.c b/src/match.c index dc4d422f..21778ed1 100644 --- a/src/match.c +++ b/src/match.c @@ -27,8 +27,10 @@ */ void match_init(Match *match) { memset(match, 0, sizeof(Match)); - match->dock = -1; + match->dock = M_DONTCHECK; match->urgent = U_DONTCHECK; + /* we use this as the placeholder value for "not set". */ + match->window_type = UINT32_MAX; } /* @@ -48,6 +50,7 @@ bool match_is_empty(Match *match) { match->window_role == NULL && match->urgent == U_DONTCHECK && match->id == XCB_NONE && + match->window_type == UINT32_MAX && match->con_id == NULL && match->dock == -1 && match->floating == M_ANY); @@ -129,6 +132,14 @@ bool match_matches_window(Match *match, i3Window *window) { } } + if (match->window_type != UINT32_MAX) { + if (window->window_type == match->window_type) { + LOG("window_type matches (%i)\n", match->window_type); + } else { + return false; + } + } + Con *con = NULL; if (match->urgent == U_LATEST) { /* if the window isn't urgent, no sense in searching */ @@ -161,7 +172,7 @@ bool match_matches_window(Match *match, i3Window *window) { LOG("urgent matches oldest\n"); } - if (match->dock != -1) { + if (match->dock != M_DONTCHECK) { if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) || (window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) || ((window->dock == W_DOCK_TOP || window->dock == W_DOCK_BOTTOM) && diff --git a/src/xcb.c b/src/xcb.c index 5dda5cce..d081d54d 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -154,6 +154,35 @@ void xcb_set_window_rect(xcb_connection_t *conn, xcb_window_t window, Rect r) { add_ignore_event(cookie.sequence, -1); } +/* + * Returns the first supported _NET_WM_WINDOW_TYPE atom. + * + */ +xcb_atom_t xcb_get_preferred_window_type(xcb_get_property_reply_t *reply) { + if (reply == NULL || xcb_get_property_value_length(reply) == 0) + return XCB_NONE; + + xcb_atom_t *atoms; + if ((atoms = xcb_get_property_value(reply)) == NULL) + return XCB_NONE; + + for (int i = 0; i < xcb_get_property_value_length(reply) / (reply->format / 8); i++) { + if (atoms[i] == A__NET_WM_WINDOW_TYPE_NORMAL || + atoms[i] == A__NET_WM_WINDOW_TYPE_DIALOG || + atoms[i] == A__NET_WM_WINDOW_TYPE_UTILITY || + atoms[i] == A__NET_WM_WINDOW_TYPE_TOOLBAR || + atoms[i] == A__NET_WM_WINDOW_TYPE_SPLASH || + atoms[i] == A__NET_WM_WINDOW_TYPE_MENU || + atoms[i] == A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU || + atoms[i] == A__NET_WM_WINDOW_TYPE_POPUP_MENU || + atoms[i] == A__NET_WM_WINDOW_TYPE_TOOLTIP) { + return atoms[i]; + } + } + + return XCB_NONE; +} + /* * Returns true if the given reply contains the given atom. * From 1f472b454cdb7d7e5d6d064e273bf927d193be42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 19 Apr 2015 00:29:31 +0200 Subject: [PATCH 3/7] Handle changes to _NET_WM_WINDOW_TYPE after the window has been managed. --- include/window.h | 6 ++++++ src/handlers.c | 20 +++++++++++--------- src/window.c | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/include/window.h b/include/window.h index 480cee18..d5b07cb1 100644 --- a/include/window.h +++ b/include/window.h @@ -56,6 +56,12 @@ void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop); */ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt); +/** + * Updates the _NET_WM_WINDOW_TYPE property. + * + */ +void window_update_type(i3Window *window, xcb_get_property_reply_t *reply); + /** * Updates the WM_HINTS (we only care about the input focus handling part). * diff --git a/src/handlers.c b/src/handlers.c index c80c279e..0d536e44 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -892,15 +892,15 @@ static void handle_client_message(xcb_client_message_event_t *event) { } } -#if 0 -int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, - xcb_atom_t atom, xcb_get_property_reply_t *property) { - /* TODO: Implement this one. To do this, implement a little test program which sleep(1)s - before changing this property. */ - ELOG("_NET_WM_WINDOW_TYPE changed, this is not yet implemented.\n"); - return 0; +bool handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, + xcb_atom_t atom, xcb_get_property_reply_t *reply) { + Con *con; + if ((con = con_by_window_id(window)) == NULL || con->window == NULL) + return false; + + window_update_type(con->window, reply); + return true; } -#endif /* * Handles the size hints set by a window, but currently only the part necessary for displaying @@ -1264,7 +1264,8 @@ static struct property_handler_t property_handlers[] = { {0, UINT_MAX, handle_transient_for}, {0, 128, handle_windowrole_change}, {0, 128, handle_class_change}, - {0, UINT_MAX, handle_strut_partial_change}}; + {0, UINT_MAX, handle_strut_partial_change}, + {0, UINT_MAX, handle_window_type}}; #define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t)) /* @@ -1284,6 +1285,7 @@ void property_handlers_init(void) { property_handlers[6].atom = A_WM_WINDOW_ROLE; property_handlers[7].atom = XCB_ATOM_WM_CLASS; property_handlers[8].atom = A__NET_WM_STRUT_PARTIAL; + property_handlers[9].atom = A__NET_WM_WINDOW_TYPE; } static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) { diff --git a/src/window.c b/src/window.c index 5485bcc3..b87c1db5 100644 --- a/src/window.c +++ b/src/window.c @@ -232,6 +232,23 @@ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool befo free(prop); } +/* + * Updates the _NET_WM_WINDOW_TYPE property. + * + */ +void window_update_type(i3Window *window, xcb_get_property_reply_t *reply) { + xcb_atom_t new_type = xcb_get_preferred_window_type(reply); + if (new_type == XCB_NONE) { + DLOG("cannot read _NET_WM_WINDOW_TYPE from window.\n"); + return; + } + + window->window_type = new_type; + LOG("_NET_WM_WINDOW_TYPE changed to %i", window->window_type); + + run_assignments(window); +} + /* * Updates the WM_HINTS (we only care about the input focus handling part). * From 18c45a7f098a05549c2ab3dd12d42c77771d1064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 19 Apr 2015 00:30:01 +0200 Subject: [PATCH 4/7] Added testcase for changing _NET_WM_WINDOW_TYPE after the window is already managed. --- testcases/t/165-for_window.t | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/testcases/t/165-for_window.t b/testcases/t/165-for_window.t index 036fc9d6..a7629d63 100644 --- a/testcases/t/165-for_window.t +++ b/testcases/t/165-for_window.t @@ -408,6 +408,39 @@ EOT } +############################################################## +# 11: check that the criterion 'window_type' works if the +# _NET_WM_WINDOW_TYPE is changed after managing. +############################################################## + +while (my ($window_type, $atom) = each %window_types) { + + $config = <<"EOT"; +# i3 config file (v4) +font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +for_window [window_type="$window_type"] floating enable, mark branded +EOT + + $pid = launch_with_config($config); + $tmp = fresh_workspace; + + $window = open_window(); + + my $atomname = $x->atom(name => '_NET_WM_WINDOW_TYPE'); + my $atomtype = $x->atom(name => 'ATOM'); + $x->change_property(PROP_MODE_REPLACE, $window->id, $atomname->id, $atomtype->id, + 32, 1, pack('L1', $x->atom(name => $atom)->id)); + $x->flush; + sync_with_i3; + + my @nodes = @{get_ws($tmp)->{floating_nodes}}; + cmp_ok(@nodes, '==', 1, 'one floating container on this workspace'); + is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)"); + + exit_gracefully($pid); + +} + ############################################################## done_testing; From 761a8713df7c768e939eeae1c922b8d7d1194d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 19 Apr 2015 00:37:10 +0200 Subject: [PATCH 5/7] Added testcase for 'window_type' criterion when used as a command. --- testcases/t/232-cmd-move-criteria.t | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/testcases/t/232-cmd-move-criteria.t b/testcases/t/232-cmd-move-criteria.t index 22a2eb4e..48a51d56 100644 --- a/testcases/t/232-cmd-move-criteria.t +++ b/testcases/t/232-cmd-move-criteria.t @@ -18,6 +18,10 @@ # Bug still in: 4.8-16-g6888a1f use i3test; +############################################################################### +# Tets moving with 'id' criterion. +############################################################################### + my $ws = fresh_workspace; my $win1 = open_window; @@ -34,4 +38,39 @@ my $ws_con = get_ws($ws); is($ws_con->{nodes}[0]->{window}, $win2->{id}, 'the `move [direction]` command should work with criteria'); is($x->input_focus, $win3->{id}, 'it should not disturb focus'); +############################################################################### +# Tets moving with 'window_type' criterion. +############################################################################### + +# test all window types +my %window_types = ( + 'normal' => '_NET_WM_WINDOW_TYPE_NORMAL', + 'dialog' => '_NET_WM_WINDOW_TYPE_DIALOG', + 'utility' => '_NET_WM_WINDOW_TYPE_UTILITY', + 'toolbar' => '_NET_WM_WINDOW_TYPE_TOOLBAR', + 'splash' => '_NET_WM_WINDOW_TYPE_SPLASH', + 'menu' => '_NET_WM_WINDOW_TYPE_MENU', + 'dropdown_menu' => '_NET_WM_WINDOW_TYPE_DROPDOWN_MENU', + 'popup_menu' => '_NET_WM_WINDOW_TYPE_POPUP_MENU', + 'tooltip' => '_NET_WM_WINDOW_TYPE_TOOLTIP' +); + +while (my ($window_type, $atom) = each %window_types) { + + $ws = fresh_workspace; + + $win1 = open_window(window_type => $x->atom(name => $atom)); + $win2 = open_window; + $win3 = open_window; + + cmd '[window_type="' . $window_type . '"] move right'; + + $ws_con = get_ws($ws); + is($ws_con->{nodes}[0]->{window}, $win2->{id}, 'the `move [direction]` command should work with window_type = ' . $window_type); + is($x->input_focus, $win3->{id}, 'it should not disturb focus'); + +} + +############################################################################### + done_testing; From 09d1deda7f471c737d38665c4f6a212429ee5b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 19 Apr 2015 10:47:09 +0200 Subject: [PATCH 6/7] Small cleanups: * Implement criterion specs just like it is done in the spec for the config * Declare variables in test case early so the 'my' keyword can be dropped in the actual test cases --- parser-specs/commands.spec | 14 +++++++------- testcases/t/232-cmd-move-criteria.t | 12 +++++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index e6217b19..d8f81d3e 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -41,15 +41,15 @@ state INITIAL: 'bar' -> BAR state CRITERIA: - ctype = 'class' -> CRITERION - ctype = 'instance' -> CRITERION + ctype = 'class' -> CRITERION + ctype = 'instance' -> CRITERION ctype = 'window_role' -> CRITERION - ctype = 'con_id' -> CRITERION - ctype = 'id' -> CRITERION - ctype = 'con_mark' -> CRITERION - ctype = 'title' -> CRITERION - ctype = 'urgent' -> CRITERION + ctype = 'con_id' -> CRITERION + ctype = 'id' -> CRITERION ctype = 'window_type' -> CRITERION + ctype = 'con_mark' -> CRITERION + ctype = 'title' -> CRITERION + ctype = 'urgent' -> CRITERION ']' -> call cmd_criteria_match_windows(); INITIAL state CRITERION: diff --git a/testcases/t/232-cmd-move-criteria.t b/testcases/t/232-cmd-move-criteria.t index 48a51d56..c023bca4 100644 --- a/testcases/t/232-cmd-move-criteria.t +++ b/testcases/t/232-cmd-move-criteria.t @@ -18,21 +18,23 @@ # Bug still in: 4.8-16-g6888a1f use i3test; +my ($ws, $win1, $win2, $win3, $ws_con); + ############################################################################### # Tets moving with 'id' criterion. ############################################################################### -my $ws = fresh_workspace; +$ws = fresh_workspace; -my $win1 = open_window; -my $win2 = open_window; -my $win3 = open_window; +$win1 = open_window; +$win2 = open_window; +$win3 = open_window; # move win1 from the left to the right cmd '[id="' . $win1->{id} . '"] move right'; # now they should be switched, with win2 still being focused -my $ws_con = get_ws($ws); +$ws_con = get_ws($ws); # win2 should be on the left is($ws_con->{nodes}[0]->{window}, $win2->{id}, 'the `move [direction]` command should work with criteria'); From e4a86d4aefa0b992fe4e1472d78fc58a352dcea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 19 Apr 2015 10:47:33 +0200 Subject: [PATCH 7/7] Cleanup: delete comments that were accidentally copy-pasted and are incorrect for these test cases --- testcases/t/165-for_window.t | 6 ------ 1 file changed, 6 deletions(-) diff --git a/testcases/t/165-for_window.t b/testcases/t/165-for_window.t index a7629d63..b684d41f 100644 --- a/testcases/t/165-for_window.t +++ b/testcases/t/165-for_window.t @@ -287,9 +287,6 @@ exit_gracefully($pid); # 8: check that the role criterion works properly ############################################################## -# this configuration is broken because "asdf" is not a valid integer -# the for_window should therefore recognize this error and don’t add the -# assignment $config = <