Merge branch 'role-criterion' into next
This commit is contained in:
commit
14dd830270
|
@ -754,6 +754,8 @@ class::
|
||||||
Compares the window class (the second part of WM_CLASS)
|
Compares the window class (the second part of WM_CLASS)
|
||||||
instance::
|
instance::
|
||||||
Compares the window instance (the first part of WM_CLASS)
|
Compares the window instance (the first part of WM_CLASS)
|
||||||
|
window_role::
|
||||||
|
Compares the window role (WM_WINDOW_ROLE).
|
||||||
id::
|
id::
|
||||||
Compares the X11 window ID, which you can get via +xwininfo+ for example.
|
Compares the X11 window ID, which you can get via +xwininfo+ for example.
|
||||||
title::
|
title::
|
||||||
|
@ -764,9 +766,9 @@ con_id::
|
||||||
Compares the i3-internal container ID, which you can get via the IPC
|
Compares the i3-internal container ID, which you can get via the IPC
|
||||||
interface. Handy for scripting.
|
interface. Handy for scripting.
|
||||||
|
|
||||||
The criteria +class+, +instance+, +title+ and +mark+ are actually regular
|
The criteria +class+, +instance+, +role+, +title+ and +mark+ are actually
|
||||||
expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for information on
|
regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for
|
||||||
how to use them.
|
information on how to use them.
|
||||||
|
|
||||||
=== Splitting containers
|
=== Splitting containers
|
||||||
|
|
||||||
|
|
|
@ -21,5 +21,6 @@ xmacro(UTF8_STRING)
|
||||||
xmacro(WM_STATE)
|
xmacro(WM_STATE)
|
||||||
xmacro(WM_CLIENT_LEADER)
|
xmacro(WM_CLIENT_LEADER)
|
||||||
xmacro(WM_TAKE_FOCUS)
|
xmacro(WM_TAKE_FOCUS)
|
||||||
|
xmacro(WM_WINDOW_ROLE)
|
||||||
xmacro(I3_SOCKET_PATH)
|
xmacro(I3_SOCKET_PATH)
|
||||||
xmacro(I3_CONFIG_PATH)
|
xmacro(I3_CONFIG_PATH)
|
||||||
|
|
|
@ -264,6 +264,11 @@ struct Window {
|
||||||
* application supports _NET_WM_NAME, in COMPOUND_TEXT otherwise). */
|
* application supports _NET_WM_NAME, in COMPOUND_TEXT otherwise). */
|
||||||
char *name_x;
|
char *name_x;
|
||||||
|
|
||||||
|
/** The WM_WINDOW_ROLE of this window (for example, the pidgin buddy window
|
||||||
|
* sets "buddy list"). Useful to match specific windows in assignments or
|
||||||
|
* for_window. */
|
||||||
|
char *role;
|
||||||
|
|
||||||
/** Flag to force re-rendering the decoration upon changes */
|
/** Flag to force re-rendering the decoration upon changes */
|
||||||
bool name_x_changed;
|
bool name_x_changed;
|
||||||
|
|
||||||
|
@ -298,6 +303,7 @@ struct Match {
|
||||||
struct regex *class;
|
struct regex *class;
|
||||||
struct regex *instance;
|
struct regex *instance;
|
||||||
struct regex *mark;
|
struct regex *mark;
|
||||||
|
struct regex *role;
|
||||||
enum {
|
enum {
|
||||||
M_DONTCHECK = -1,
|
M_DONTCHECK = -1,
|
||||||
M_NODOCK = 0,
|
M_NODOCK = 0,
|
||||||
|
|
|
@ -42,4 +42,10 @@ void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop);
|
||||||
*/
|
*/
|
||||||
void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop);
|
void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the WM_WINDOW_ROLE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -170,6 +170,7 @@ shift { return TOKSHIFT; }
|
||||||
|
|
||||||
class { yy_push_state(WANT_QSTRING); return TOK_CLASS; }
|
class { yy_push_state(WANT_QSTRING); return TOK_CLASS; }
|
||||||
instance { yy_push_state(WANT_QSTRING); return TOK_INSTANCE; }
|
instance { yy_push_state(WANT_QSTRING); return TOK_INSTANCE; }
|
||||||
|
window_role { yy_push_state(WANT_QSTRING); return TOK_WINDOW_ROLE; }
|
||||||
id { yy_push_state(WANT_QSTRING); return TOK_ID; }
|
id { yy_push_state(WANT_QSTRING); return TOK_ID; }
|
||||||
con_id { yy_push_state(WANT_QSTRING); return TOK_CON_ID; }
|
con_id { yy_push_state(WANT_QSTRING); return TOK_CON_ID; }
|
||||||
con_mark { yy_push_state(WANT_QSTRING); return TOK_MARK; }
|
con_mark { yy_push_state(WANT_QSTRING); return TOK_MARK; }
|
||||||
|
|
|
@ -632,6 +632,7 @@ void parse_file(const char *f) {
|
||||||
%token TOK_MARK "mark"
|
%token TOK_MARK "mark"
|
||||||
%token TOK_CLASS "class"
|
%token TOK_CLASS "class"
|
||||||
%token TOK_INSTANCE "instance"
|
%token TOK_INSTANCE "instance"
|
||||||
|
%token TOK_WINDOW_ROLE "window_role"
|
||||||
%token TOK_ID "id"
|
%token TOK_ID "id"
|
||||||
%token TOK_CON_ID "con_id"
|
%token TOK_CON_ID "con_id"
|
||||||
%token TOK_TITLE "title"
|
%token TOK_TITLE "title"
|
||||||
|
@ -792,6 +793,12 @@ criterion:
|
||||||
current_match.instance = regex_new($3);
|
current_match.instance = regex_new($3);
|
||||||
free($3);
|
free($3);
|
||||||
}
|
}
|
||||||
|
| TOK_WINDOW_ROLE '=' STR
|
||||||
|
{
|
||||||
|
printf("criteria: window_role = %s\n", $3);
|
||||||
|
current_match.role = regex_new($3);
|
||||||
|
free($3);
|
||||||
|
}
|
||||||
| TOK_CON_ID '=' STR
|
| TOK_CON_ID '=' STR
|
||||||
{
|
{
|
||||||
printf("criteria: id = %s\n", $3);
|
printf("criteria: id = %s\n", $3);
|
||||||
|
|
|
@ -155,6 +155,7 @@ no { return TOK_DISABLE; }
|
||||||
|
|
||||||
class { BEGIN(WANT_QSTRING); return TOK_CLASS; }
|
class { BEGIN(WANT_QSTRING); return TOK_CLASS; }
|
||||||
instance { BEGIN(WANT_QSTRING); return TOK_INSTANCE; }
|
instance { BEGIN(WANT_QSTRING); return TOK_INSTANCE; }
|
||||||
|
window_role { BEGIN(WANT_QSTRING); return TOK_WINDOW_ROLE; }
|
||||||
id { BEGIN(WANT_QSTRING); return TOK_ID; }
|
id { BEGIN(WANT_QSTRING); return TOK_ID; }
|
||||||
con_id { BEGIN(WANT_QSTRING); return TOK_CON_ID; }
|
con_id { BEGIN(WANT_QSTRING); return TOK_CON_ID; }
|
||||||
con_mark { BEGIN(WANT_QSTRING); return TOK_MARK; }
|
con_mark { BEGIN(WANT_QSTRING); return TOK_MARK; }
|
||||||
|
|
|
@ -177,6 +177,7 @@ bool definitelyGreaterThan(float a, float b, float epsilon) {
|
||||||
|
|
||||||
%token TOK_CLASS "class"
|
%token TOK_CLASS "class"
|
||||||
%token TOK_INSTANCE "instance"
|
%token TOK_INSTANCE "instance"
|
||||||
|
%token TOK_WINDOW_ROLE "window_role"
|
||||||
%token TOK_ID "id"
|
%token TOK_ID "id"
|
||||||
%token TOK_CON_ID "con_id"
|
%token TOK_CON_ID "con_id"
|
||||||
%token TOK_TITLE "title"
|
%token TOK_TITLE "title"
|
||||||
|
@ -308,6 +309,12 @@ criterion:
|
||||||
current_match.instance = regex_new($3);
|
current_match.instance = regex_new($3);
|
||||||
free($3);
|
free($3);
|
||||||
}
|
}
|
||||||
|
| TOK_WINDOW_ROLE '=' STR
|
||||||
|
{
|
||||||
|
printf("criteria: window_role = %s\n", $3);
|
||||||
|
current_match.role = regex_new($3);
|
||||||
|
free($3);
|
||||||
|
}
|
||||||
| TOK_CON_ID '=' STR
|
| TOK_CON_ID '=' STR
|
||||||
{
|
{
|
||||||
printf("criteria: id = %s\n", $3);
|
printf("criteria: id = %s\n", $3);
|
||||||
|
|
|
@ -557,6 +557,21 @@ static bool handle_windowname_change_legacy(void *data, xcb_connection_t *conn,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when a window changes its WM_WINDOW_ROLE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool handle_windowrole_change(void *data, xcb_connection_t *conn, uint8_t state,
|
||||||
|
xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
|
||||||
|
Con *con;
|
||||||
|
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
window_update_role(con->window, prop, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* Updates the client’s WM_CLASS property
|
* Updates the client’s WM_CLASS property
|
||||||
|
@ -933,7 +948,8 @@ static struct property_handler_t property_handlers[] = {
|
||||||
{ 0, 128, handle_windowname_change_legacy },
|
{ 0, 128, handle_windowname_change_legacy },
|
||||||
{ 0, UINT_MAX, handle_normal_hints },
|
{ 0, UINT_MAX, handle_normal_hints },
|
||||||
{ 0, UINT_MAX, handle_clientleader_change },
|
{ 0, UINT_MAX, handle_clientleader_change },
|
||||||
{ 0, UINT_MAX, handle_transient_for }
|
{ 0, UINT_MAX, handle_transient_for },
|
||||||
|
{ 0, 128, handle_windowrole_change }
|
||||||
};
|
};
|
||||||
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
|
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
|
||||||
|
|
||||||
|
@ -949,6 +965,7 @@ void property_handlers_init() {
|
||||||
property_handlers[3].atom = XCB_ATOM_WM_NORMAL_HINTS;
|
property_handlers[3].atom = XCB_ATOM_WM_NORMAL_HINTS;
|
||||||
property_handlers[4].atom = A_WM_CLIENT_LEADER;
|
property_handlers[4].atom = A_WM_CLIENT_LEADER;
|
||||||
property_handlers[5].atom = XCB_ATOM_WM_TRANSIENT_FOR;
|
property_handlers[5].atom = XCB_ATOM_WM_TRANSIENT_FOR;
|
||||||
|
property_handlers[6].atom = A_WM_WINDOW_ROLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
|
static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
|
||||||
|
|
|
@ -83,7 +83,8 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
||||||
|
|
||||||
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
|
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
|
||||||
utf8_title_cookie, title_cookie,
|
utf8_title_cookie, title_cookie,
|
||||||
class_cookie, leader_cookie, transient_cookie;
|
class_cookie, leader_cookie, transient_cookie,
|
||||||
|
role_cookie;
|
||||||
|
|
||||||
|
|
||||||
geomc = xcb_get_geometry(conn, d);
|
geomc = xcb_get_geometry(conn, d);
|
||||||
|
@ -145,6 +146,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
||||||
transient_cookie = GET_PROPERTY(XCB_ATOM_WM_TRANSIENT_FOR, UINT32_MAX);
|
transient_cookie = GET_PROPERTY(XCB_ATOM_WM_TRANSIENT_FOR, UINT32_MAX);
|
||||||
title_cookie = GET_PROPERTY(XCB_ATOM_WM_NAME, 128);
|
title_cookie = GET_PROPERTY(XCB_ATOM_WM_NAME, 128);
|
||||||
class_cookie = GET_PROPERTY(XCB_ATOM_WM_CLASS, 128);
|
class_cookie = GET_PROPERTY(XCB_ATOM_WM_CLASS, 128);
|
||||||
|
role_cookie = GET_PROPERTY(A_WM_WINDOW_ROLE, 128);
|
||||||
/* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */
|
/* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */
|
||||||
|
|
||||||
DLOG("reparenting!\n");
|
DLOG("reparenting!\n");
|
||||||
|
@ -171,6 +173,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
||||||
window_update_leader(cwindow, xcb_get_property_reply(conn, leader_cookie, NULL));
|
window_update_leader(cwindow, xcb_get_property_reply(conn, leader_cookie, NULL));
|
||||||
window_update_transient_for(cwindow, xcb_get_property_reply(conn, transient_cookie, NULL));
|
window_update_transient_for(cwindow, xcb_get_property_reply(conn, transient_cookie, NULL));
|
||||||
window_update_strut_partial(cwindow, xcb_get_property_reply(conn, strut_cookie, NULL));
|
window_update_strut_partial(cwindow, xcb_get_property_reply(conn, strut_cookie, NULL));
|
||||||
|
window_update_role(cwindow, xcb_get_property_reply(conn, role_cookie, NULL), true);
|
||||||
|
|
||||||
/* check if the window needs WM_TAKE_FOCUS */
|
/* check if the window needs WM_TAKE_FOCUS */
|
||||||
cwindow->needs_take_focus = window_supports_protocol(cwindow->id, A_WM_TAKE_FOCUS);
|
cwindow->needs_take_focus = window_supports_protocol(cwindow->id, A_WM_TAKE_FOCUS);
|
||||||
|
|
14
src/match.c
14
src/match.c
|
@ -39,6 +39,7 @@ bool match_is_empty(Match *match) {
|
||||||
match->application == NULL &&
|
match->application == NULL &&
|
||||||
match->class == NULL &&
|
match->class == NULL &&
|
||||||
match->instance == NULL &&
|
match->instance == NULL &&
|
||||||
|
match->role == NULL &&
|
||||||
match->id == XCB_NONE &&
|
match->id == XCB_NONE &&
|
||||||
match->con_id == NULL &&
|
match->con_id == NULL &&
|
||||||
match->dock == -1 &&
|
match->dock == -1 &&
|
||||||
|
@ -65,6 +66,7 @@ void match_copy(Match *dest, Match *src) {
|
||||||
DUPLICATE_REGEX(application);
|
DUPLICATE_REGEX(application);
|
||||||
DUPLICATE_REGEX(class);
|
DUPLICATE_REGEX(class);
|
||||||
DUPLICATE_REGEX(instance);
|
DUPLICATE_REGEX(instance);
|
||||||
|
DUPLICATE_REGEX(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -113,6 +115,16 @@ bool match_matches_window(Match *match, i3Window *window) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (match->role != NULL) {
|
||||||
|
if (window->role != NULL &&
|
||||||
|
regex_matches(match->role, window->role)) {
|
||||||
|
LOG("window_role matches (%s)\n", window->role);
|
||||||
|
} else {
|
||||||
|
LOG("window_role does not match\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (match->dock != -1) {
|
if (match->dock != -1) {
|
||||||
LOG("match->dock = %d, window->dock = %d\n", match->dock, window->dock);
|
LOG("match->dock = %d, window->dock = %d\n", match->dock, window->dock);
|
||||||
if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
|
if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
|
||||||
|
@ -148,6 +160,7 @@ void match_free(Match *match) {
|
||||||
regex_free(match->class);
|
regex_free(match->class);
|
||||||
regex_free(match->instance);
|
regex_free(match->instance);
|
||||||
regex_free(match->mark);
|
regex_free(match->mark);
|
||||||
|
regex_free(match->role);
|
||||||
|
|
||||||
/* Second step: free the regex helper struct itself */
|
/* Second step: free the regex helper struct itself */
|
||||||
FREE(match->title);
|
FREE(match->title);
|
||||||
|
@ -155,4 +168,5 @@ void match_free(Match *match) {
|
||||||
FREE(match->class);
|
FREE(match->class);
|
||||||
FREE(match->instance);
|
FREE(match->instance);
|
||||||
FREE(match->mark);
|
FREE(match->mark);
|
||||||
|
FREE(match->role);
|
||||||
}
|
}
|
||||||
|
|
33
src/window.c
33
src/window.c
|
@ -215,3 +215,36 @@ void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop)
|
||||||
|
|
||||||
free(prop);
|
free(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Updates the WM_WINDOW_ROLE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) {
|
||||||
|
if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
|
||||||
|
DLOG("prop == NULL\n");
|
||||||
|
FREE(prop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *new_role;
|
||||||
|
if (asprintf(&new_role, "%.*s", xcb_get_property_value_length(prop),
|
||||||
|
(char*)xcb_get_property_value(prop)) == -1) {
|
||||||
|
perror("asprintf()");
|
||||||
|
DLOG("Could not get WM_WINDOW_ROLE\n");
|
||||||
|
free(prop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FREE(win->role);
|
||||||
|
win->role = new_role;
|
||||||
|
LOG("WM_WINDOW_ROLE changed to \"%s\"\n", win->role);
|
||||||
|
|
||||||
|
if (before_mgmt) {
|
||||||
|
free(prop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
run_assignments(win);
|
||||||
|
|
||||||
|
free(prop);
|
||||||
|
}
|
||||||
|
|
|
@ -242,7 +242,7 @@ sub take_job {
|
||||||
|
|
||||||
my $output;
|
my $output;
|
||||||
my $parser = TAP::Parser->new({
|
my $parser = TAP::Parser->new({
|
||||||
exec => [ 'sh', '-c', "DISPLAY=$display /usr/bin/perl -It/lib $test" ],
|
exec => [ 'sh', '-c', qq|DISPLAY=$display LOGPATH="$logpath" /usr/bin/perl -It/lib $test| ],
|
||||||
spool => IO::Scalar->new(\$output),
|
spool => IO::Scalar->new(\$output),
|
||||||
merge => 1,
|
merge => 1,
|
||||||
});
|
});
|
||||||
|
|
|
@ -349,5 +349,108 @@ is($content[0]->{border}, 'normal', 'normal border');
|
||||||
|
|
||||||
exit_gracefully($process->pid);
|
exit_gracefully($process->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 = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
|
for_window [window_role="i3test"] border none
|
||||||
|
EOT
|
||||||
|
|
||||||
|
$process = launch_with_config($config);
|
||||||
|
|
||||||
|
$tmp = fresh_workspace;
|
||||||
|
|
||||||
|
$window = $x->root->create_child(
|
||||||
|
class => WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
rect => [ 0, 0, 30, 30 ],
|
||||||
|
background_color => '#00ff00',
|
||||||
|
);
|
||||||
|
|
||||||
|
$window->_create;
|
||||||
|
|
||||||
|
my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
|
||||||
|
my $atomtype = $x->atom(name => 'STRING');
|
||||||
|
$x->change_property(
|
||||||
|
PROP_MODE_REPLACE,
|
||||||
|
$window->id,
|
||||||
|
$atomname->id,
|
||||||
|
$atomtype->id,
|
||||||
|
8,
|
||||||
|
length("i3test") + 1,
|
||||||
|
"i3test\x00"
|
||||||
|
);
|
||||||
|
|
||||||
|
$window->name('usethis');
|
||||||
|
$window->map;
|
||||||
|
sleep 0.25;
|
||||||
|
|
||||||
|
@content = @{get_ws_content($tmp)};
|
||||||
|
cmp_ok(@content, '==', 1, 'one node on this workspace now');
|
||||||
|
is($content[0]->{border}, 'none', 'no border (window_role)');
|
||||||
|
|
||||||
|
exit_gracefully($process->pid);
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
# 9: another test for the window_role, but this time it changes
|
||||||
|
# *after* the window has been mapped
|
||||||
|
##############################################################
|
||||||
|
|
||||||
|
# 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 = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
|
for_window [window_role="i3test"] border none
|
||||||
|
EOT
|
||||||
|
|
||||||
|
$process = launch_with_config($config);
|
||||||
|
|
||||||
|
$tmp = fresh_workspace;
|
||||||
|
|
||||||
|
$window = $x->root->create_child(
|
||||||
|
class => WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
rect => [ 0, 0, 30, 30 ],
|
||||||
|
background_color => '#00ff00',
|
||||||
|
);
|
||||||
|
|
||||||
|
$window->_create;
|
||||||
|
|
||||||
|
$window->name('usethis');
|
||||||
|
$window->map;
|
||||||
|
sleep 0.25;
|
||||||
|
|
||||||
|
@content = @{get_ws_content($tmp)};
|
||||||
|
cmp_ok(@content, '==', 1, 'one node on this workspace now');
|
||||||
|
is($content[0]->{border}, 'normal', 'normal border (window_role 2)');
|
||||||
|
|
||||||
|
$atomname = $x->atom(name => 'WM_WINDOW_ROLE');
|
||||||
|
$atomtype = $x->atom(name => 'STRING');
|
||||||
|
$x->change_property(
|
||||||
|
PROP_MODE_REPLACE,
|
||||||
|
$window->id,
|
||||||
|
$atomname->id,
|
||||||
|
$atomtype->id,
|
||||||
|
8,
|
||||||
|
length("i3test") + 1,
|
||||||
|
"i3test\x00"
|
||||||
|
);
|
||||||
|
|
||||||
|
$x->flush;
|
||||||
|
|
||||||
|
sleep 0.25;
|
||||||
|
|
||||||
|
@content = @{get_ws_content($tmp)};
|
||||||
|
cmp_ok(@content, '==', 1, 'one node on this workspace now');
|
||||||
|
is($content[0]->{border}, 'none', 'no border (window_role 2)');
|
||||||
|
|
||||||
|
exit_gracefully($process->pid);
|
||||||
|
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
|
|
@ -259,7 +259,10 @@ sub launch_with_config {
|
||||||
say $fh "ipc-socket $tmp_socket_path";
|
say $fh "ipc-socket $tmp_socket_path";
|
||||||
close($fh);
|
close($fh);
|
||||||
|
|
||||||
my $i3cmd = "exec " . abs_path("../i3") . " -V -d all --disable-signalhandler -c $tmpfile >/dev/null 2>/dev/null";
|
# Use $ENV{LOGPATH}, gets set in complete-run.pl. We append instead of
|
||||||
|
# overwrite because there might be multiple instances of i3 running during
|
||||||
|
# one test case.
|
||||||
|
my $i3cmd = "exec " . abs_path("../i3") . " -V -d all --disable-signalhandler -c $tmpfile >>$ENV{LOGPATH} 2>&1";
|
||||||
my $process = Proc::Background->new($i3cmd);
|
my $process = Proc::Background->new($i3cmd);
|
||||||
sleep 1;
|
sleep 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue