Get the _NET_STARTUP_ID in manage_window, get the corresponding workspace
This commit is contained in:
parent
7750382b89
commit
4204b8e2b0
|
@ -15,6 +15,7 @@ xmacro(_NET_CLIENT_LIST_STACKING)
|
||||||
xmacro(_NET_CURRENT_DESKTOP)
|
xmacro(_NET_CURRENT_DESKTOP)
|
||||||
xmacro(_NET_ACTIVE_WINDOW)
|
xmacro(_NET_ACTIVE_WINDOW)
|
||||||
xmacro(_NET_WORKAREA)
|
xmacro(_NET_WORKAREA)
|
||||||
|
xmacro(_NET_STARTUP_ID)
|
||||||
xmacro(WM_PROTOCOLS)
|
xmacro(WM_PROTOCOLS)
|
||||||
xmacro(WM_DELETE_WINDOW)
|
xmacro(WM_DELETE_WINDOW)
|
||||||
xmacro(UTF8_STRING)
|
xmacro(UTF8_STRING)
|
||||||
|
|
|
@ -32,4 +32,15 @@ void start_application(const char *command);
|
||||||
*/
|
*/
|
||||||
void startup_monitor_event(SnMonitorEvent *event, void *userdata);
|
void startup_monitor_event(SnMonitorEvent *event, void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given window belongs to a startup notification by checking if
|
||||||
|
* the _NET_STARTUP_ID property is set on the window (or on its leader, if it’s
|
||||||
|
* unset).
|
||||||
|
*
|
||||||
|
* If so, returns the workspace on which the startup was initiated.
|
||||||
|
* Returns NULL otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *startup_workspace_for_window(i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
17
src/manage.c
17
src/manage.c
|
@ -84,7 +84,7 @@ 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;
|
role_cookie, startup_id_cookie;
|
||||||
|
|
||||||
|
|
||||||
geomc = xcb_get_geometry(conn, d);
|
geomc = xcb_get_geometry(conn, d);
|
||||||
|
@ -147,6 +147,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
||||||
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);
|
role_cookie = GET_PROPERTY(A_WM_WINDOW_ROLE, 128);
|
||||||
|
startup_id_cookie = GET_PROPERTY(A__NET_STARTUP_ID, 512);
|
||||||
/* 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");
|
||||||
|
@ -175,6 +176,11 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
||||||
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);
|
window_update_role(cwindow, xcb_get_property_reply(conn, role_cookie, NULL), true);
|
||||||
|
|
||||||
|
xcb_get_property_reply_t *startup_id_reply;
|
||||||
|
startup_id_reply = xcb_get_property_reply(conn, startup_id_cookie, NULL);
|
||||||
|
char *startup_ws = startup_workspace_for_window(cwindow, startup_id_reply);
|
||||||
|
DLOG("startup workspace = %s\n", startup_ws);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
|
@ -233,6 +239,15 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
||||||
else nc = tree_open_con(nc->parent, cwindow);
|
else nc = tree_open_con(nc->parent, cwindow);
|
||||||
}
|
}
|
||||||
/* TODO: handle assignments with type == A_TO_OUTPUT */
|
/* TODO: handle assignments with type == A_TO_OUTPUT */
|
||||||
|
} else if (startup_ws) {
|
||||||
|
/* If it’s not assigned, but was started on a specific workspace,
|
||||||
|
* we want to open it there */
|
||||||
|
DLOG("Using workspace on which this application was started (%s)\n", startup_ws);
|
||||||
|
nc = con_descend_tiling_focused(workspace_get(startup_ws, NULL));
|
||||||
|
DLOG("focused on ws %s: %p / %s\n", startup_ws, nc, nc->name);
|
||||||
|
if (nc->type == CT_WORKSPACE)
|
||||||
|
nc = tree_open_con(nc, cwindow);
|
||||||
|
else nc = tree_open_con(nc->parent, cwindow);
|
||||||
} else {
|
} else {
|
||||||
/* If not, insert it at the currently focused position */
|
/* If not, insert it at the currently focused position */
|
||||||
if (focused->type == CT_CON && con_accepts_window(focused)) {
|
if (focused->type == CT_CON && con_accepts_window(focused)) {
|
||||||
|
|
|
@ -115,3 +115,51 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks if the given window belongs to a startup notification by checking if
|
||||||
|
* the _NET_STARTUP_ID property is set on the window (or on its leader, if it’s
|
||||||
|
* unset).
|
||||||
|
*
|
||||||
|
* If so, returns the workspace on which the startup was initiated.
|
||||||
|
* Returns NULL otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *startup_workspace_for_window(i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply) {
|
||||||
|
/* The _NET_STARTUP_ID is only needed during this function, so we get it
|
||||||
|
* here and don’t save it in the 'cwindow'. */
|
||||||
|
if (startup_id_reply == NULL || xcb_get_property_value_length(startup_id_reply) == 0) {
|
||||||
|
DLOG("No _NET_STARTUP_ID set on this window\n");
|
||||||
|
/* TODO: check the leader, if any */
|
||||||
|
FREE(startup_id_reply);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *startup_id;
|
||||||
|
if (asprintf(&startup_id, "%.*s", xcb_get_property_value_length(startup_id_reply),
|
||||||
|
(char*)xcb_get_property_value(startup_id_reply)) == -1) {
|
||||||
|
perror("asprintf()");
|
||||||
|
DLOG("Could not get _NET_STARTUP_ID\n");
|
||||||
|
free(startup_id_reply);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Startup_Sequence *current, *sequence = NULL;
|
||||||
|
TAILQ_FOREACH(current, &startup_sequences, sequences) {
|
||||||
|
if (strcmp(current->id, startup_id) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sequence = current;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(startup_id);
|
||||||
|
free(startup_id_reply);
|
||||||
|
|
||||||
|
if (!sequence) {
|
||||||
|
DLOG("WARNING: This sequence (ID %s) was not found\n", startup_id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequence->workspace;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue