return;
}
+/*
+ * Handles the WM_CLASS property for assignments and criteria selection.
+ *
+ */
+static bool handle_class_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
+ xcb_atom_t name, xcb_get_property_reply_t *prop) {
+ Con *con;
+ if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
+ return false;
+
+ if (prop == NULL) {
+ prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
+ false, window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, 32),
+ NULL);
+
+ if (prop == NULL)
+ return false;
+ }
+
+ window_update_class(con->window, prop, false);
+
+ return true;
+}
+
/* Returns false if the event could not be processed (e.g. the window could not
* be found), true otherwise */
typedef bool (*cb_property_handler_t)(void *data, xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property);
{0, UINT_MAX, handle_normal_hints},
{0, UINT_MAX, handle_clientleader_change},
{0, UINT_MAX, handle_transient_for},
- {0, 128, handle_windowrole_change}};
+ {0, 128, handle_windowrole_change},
+ {0, 128, handle_class_change}};
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
/*
property_handlers[4].atom = A_WM_CLIENT_LEADER;
property_handlers[5].atom = XCB_ATOM_WM_TRANSIENT_FOR;
property_handlers[6].atom = A_WM_WINDOW_ROLE;
+ property_handlers[7].atom = XCB_ATOM_WM_CLASS;
}
static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Test that changes to WM_CLASS are internally processed by i3 by updating the
+# cached property and running assignments. This allows the property to be used
+# in criteria selection
+# Ticket: #1052
+# Bug still in: 4.8-73-g6bf7f8e
+use i3test i3_autostart => 0;
+use X11::XCB qw(PROP_MODE_REPLACE);
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [class="Special"] mark special_class_mark
+EOT
+
+my $pid = launch_with_config($config);
+
+sub change_window_class {
+ my ($window, $class) = @_;
+ my $atomname = $x->atom(name => 'WM_CLASS');
+ my $atomtype = $x->atom(name => 'STRING');
+ $x->change_property(
+ PROP_MODE_REPLACE,
+ $window->id,
+ $atomname->id,
+ $atomtype->id,
+ 8,
+ length($class) + 1,
+ $class
+ );
+ sync_with_i3;
+}
+
+my $ws = fresh_workspace;
+
+my $win = open_window;
+
+change_window_class($win, "special\0Special");
+
+my $con = @{get_ws_content($ws)}[0];
+
+is($con->{window_properties}->{class}, 'Special',
+ 'The container class should be updated when a window changes class');
+
+is($con->{window_properties}->{instance}, 'special',
+ 'The container instance should be updated when a window changes instance');
+
+# The mark `special_class_mark` is added in a `for_window` assignment in the
+# config for testing purposes
+is($con->{mark}, 'special_class_mark',
+ 'A `for_window` assignment should run for a match when the window changes class');
+
+exit_gracefully($pid);
+
+done_testing;