From 5a17b3978c7aafa720197f670c961aa8cd794dd6 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 10 Oct 2015 21:51:04 +0200 Subject: [PATCH 1/5] Acquire the WM_Sn selection during startup Signed-off-by: Uli Schlachter --- awesome.c | 40 ++++++++++++++++++++++++++++++++++++++++ globalconf.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/awesome.c b/awesome.c index 952b1939..0a19a792 100644 --- a/awesome.c +++ b/awesome.c @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -221,6 +222,42 @@ scan(xcb_query_tree_cookie_t tree_c) restore_client_order(prop_cookie); } +static void +acquire_WM_Sn(void) +{ + xcb_intern_atom_cookie_t atom_q; + xcb_intern_atom_reply_t *atom_r; + xcb_atom_t atom; + char *atom_name; + + /* Get the WM_Sn atom */ + globalconf.selection_owner_window = xcb_generate_id(globalconf.connection); + xcb_create_window(globalconf.connection, globalconf.screen->root_depth, + globalconf.selection_owner_window, globalconf.screen->root, + -1, -1, 1, 1, 0, + XCB_COPY_FROM_PARENT, globalconf.screen->root_visual, + 0, NULL); + + atom_name = xcb_atom_name_by_screen("WM_S", globalconf.default_screen); + if(!atom_name) + fatal("error getting WM_Sn atom name"); + + atom_q = xcb_intern_atom_unchecked(globalconf.connection, false, + a_strlen(atom_name), atom_name); + + p_delete(&atom_name); + + atom_r = xcb_intern_atom_reply(globalconf.connection, atom_q, NULL); + if(!atom_r) + fatal("error getting WM_Sn atom"); + + atom = atom_r->atom; + p_delete(&atom_r); + + /* Acquire the selection */ + xcb_set_selection_owner(globalconf.connection, globalconf.selection_owner_window, atom, XCB_CURRENT_TIME); +} + static void a_xcb_check(void) { @@ -506,6 +543,9 @@ main(int argc, char **argv) /* Did we get some usable data from the above X11 setup? */ draw_test_cairo_xcb(); + /* Acquire the WM_Sn selection */ + acquire_WM_Sn(); + /* initialize dbus */ a_dbus_init(); diff --git a/globalconf.h b/globalconf.h index 0f1b8484..2299a502 100644 --- a/globalconf.h +++ b/globalconf.h @@ -84,6 +84,8 @@ typedef struct key_array_t keys; /** Root window mouse bindings */ button_array_t buttons; + /** Window owning the WM_Sn selection */ + xcb_window_t selection_owner_window; /** Modifiers masks */ uint16_t numlockmask, shiftlockmask, capslockmask, modeswitchmask; /** Check for XTest extension */ From e824f8f30d3f797374f6597baf4fb70f48f51b25 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 10 Oct 2015 21:59:12 +0200 Subject: [PATCH 2/5] Exit when we loose the WM_Sn selection Signed-off-by: Uli Schlachter --- awesome.c | 6 +++--- event.c | 11 +++++++++++ globalconf.h | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/awesome.c b/awesome.c index 0a19a792..5953f811 100644 --- a/awesome.c +++ b/awesome.c @@ -227,7 +227,6 @@ acquire_WM_Sn(void) { xcb_intern_atom_cookie_t atom_q; xcb_intern_atom_reply_t *atom_r; - xcb_atom_t atom; char *atom_name; /* Get the WM_Sn atom */ @@ -251,11 +250,12 @@ acquire_WM_Sn(void) if(!atom_r) fatal("error getting WM_Sn atom"); - atom = atom_r->atom; + globalconf.selection_atom = atom_r->atom; p_delete(&atom_r); /* Acquire the selection */ - xcb_set_selection_owner(globalconf.connection, globalconf.selection_owner_window, atom, XCB_CURRENT_TIME); + xcb_set_selection_owner(globalconf.connection, globalconf.selection_owner_window, + globalconf.selection_atom, XCB_CURRENT_TIME); } static void diff --git a/event.c b/event.c index 1246772d..44139ccf 100644 --- a/event.c +++ b/event.c @@ -862,6 +862,16 @@ event_handle_reparentnotify(xcb_reparent_notify_event_t *ev) } } +static void +event_handle_selectionclear(xcb_selection_clear_event_t *ev) +{ + if(ev->selection == globalconf.selection_atom) + { + warn("Lost WM_Sn selection, exiting..."); + g_main_loop_quit(globalconf.loop); + } +} + /** \brief awesome xerror function. * There's no way to check accesses to destroyed windows, thus those cases are * ignored (especially on UnmapNotify's). @@ -921,6 +931,7 @@ void event_handle(xcb_generic_event_t *event) EVENT(XCB_PROPERTY_NOTIFY, property_handle_propertynotify); EVENT(XCB_REPARENT_NOTIFY, event_handle_reparentnotify); EVENT(XCB_UNMAP_NOTIFY, event_handle_unmapnotify); + EVENT(XCB_SELECTION_CLEAR, event_handle_selectionclear); #undef EVENT } diff --git a/globalconf.h b/globalconf.h index 2299a502..344cfe5f 100644 --- a/globalconf.h +++ b/globalconf.h @@ -84,6 +84,8 @@ typedef struct key_array_t keys; /** Root window mouse bindings */ button_array_t buttons; + /** Atom for WM_Sn */ + xcb_atom_t selection_atom; /** Window owning the WM_Sn selection */ xcb_window_t selection_owner_window; /** Modifiers masks */ From 86313e0afdd19880a3a4c05b52f1a696c7b305bf Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 10 Oct 2015 22:06:41 +0200 Subject: [PATCH 3/5] Send an event after we acquired the WM_Sn selection Signed-off-by: Uli Schlachter --- awesome.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/awesome.c b/awesome.c index 5953f811..9ee5a0df 100644 --- a/awesome.c +++ b/awesome.c @@ -228,6 +228,7 @@ acquire_WM_Sn(void) xcb_intern_atom_cookie_t atom_q; xcb_intern_atom_reply_t *atom_r; char *atom_name; + xcb_client_message_event_t ev; /* Get the WM_Sn atom */ globalconf.selection_owner_window = xcb_generate_id(globalconf.connection); @@ -256,6 +257,19 @@ acquire_WM_Sn(void) /* Acquire the selection */ xcb_set_selection_owner(globalconf.connection, globalconf.selection_owner_window, globalconf.selection_atom, XCB_CURRENT_TIME); + + /* Announce that we are the new owner */ + p_clear(&ev, 1); + ev.response_type = XCB_CLIENT_MESSAGE; + ev.window = globalconf.screen->root; + ev.format = 32; + ev.type = MANAGER; + ev.data.data32[0] = XCB_CURRENT_TIME; + ev.data.data32[1] = globalconf.selection_atom; + ev.data.data32[2] = globalconf.selection_owner_window; + ev.data.data32[3] = ev.data.data32[4] = 0; + + xcb_send_event(globalconf.connection, false, globalconf.screen->root, 0xFFFFFF, (char *) &ev); } static void From 19111121ce51e555ba92d1f10e4735d9c217f7ad Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 10 Oct 2015 22:12:25 +0200 Subject: [PATCH 4/5] Check if WM_Sn is already owned before acquiring it Signed-off-by: Uli Schlachter --- awesome.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/awesome.c b/awesome.c index 9ee5a0df..f387fdc2 100644 --- a/awesome.c +++ b/awesome.c @@ -223,11 +223,12 @@ scan(xcb_query_tree_cookie_t tree_c) } static void -acquire_WM_Sn(void) +acquire_WM_Sn(bool replace) { xcb_intern_atom_cookie_t atom_q; xcb_intern_atom_reply_t *atom_r; char *atom_name; + xcb_get_selection_owner_reply_t *get_sel_reply; xcb_client_message_event_t ev; /* Get the WM_Sn atom */ @@ -254,9 +255,28 @@ acquire_WM_Sn(void) globalconf.selection_atom = atom_r->atom; p_delete(&atom_r); + /* Is the selection already owned? */ + get_sel_reply = xcb_get_selection_owner_reply(globalconf.connection, + xcb_get_selection_owner(globalconf.connection, globalconf.selection_atom), + NULL); + if (!replace && get_sel_reply->owner != XCB_NONE) + fatal("another window manager is already running (selection owned)"); + /* Acquire the selection */ xcb_set_selection_owner(globalconf.connection, globalconf.selection_owner_window, globalconf.selection_atom, XCB_CURRENT_TIME); + if (get_sel_reply->owner != XCB_NONE) + { + /* Wait for the old owner to go away */ + xcb_get_geometry_reply_t *geom_reply = NULL; + do { + p_delete(&geom_reply); + geom_reply = xcb_get_geometry_reply(globalconf.connection, + xcb_get_geometry(globalconf.connection, get_sel_reply->owner), + NULL); + } while (geom_reply != NULL); + } + p_delete(&get_sel_reply); /* Announce that we are the new owner */ p_clear(&ev, 1); @@ -558,7 +578,7 @@ main(int argc, char **argv) draw_test_cairo_xcb(); /* Acquire the WM_Sn selection */ - acquire_WM_Sn(); + acquire_WM_Sn(true); /* initialize dbus */ a_dbus_init(); @@ -581,7 +601,7 @@ main(int argc, char **argv) globalconf.screen->root, XCB_CW_EVENT_MASK, &select_input_val); if (xcb_request_check(globalconf.connection, cookie)) - fatal("another window manager is already running"); + fatal("another window manager is already running (can't select SubstructureRedirect)"); } /* Prefetch the maximum request length */ From f6e633eee4e8c4f6390ad6bf484a11c9ed520ac2 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 10 Oct 2015 22:19:22 +0200 Subject: [PATCH 5/5] Add a --replace argument Signed-off-by: Uli Schlachter --- awesome.c | 11 ++++++++--- manpages/awesome.1.de.txt | 2 ++ manpages/awesome.1.es.txt | 2 ++ manpages/awesome.1.fr.txt | 2 ++ manpages/awesome.1.it.txt | 2 ++ manpages/awesome.1.ru.txt | 2 ++ manpages/awesome.1.txt | 2 ++ 7 files changed, 20 insertions(+), 3 deletions(-) diff --git a/awesome.c b/awesome.c index f387fdc2..6154ec3c 100644 --- a/awesome.c +++ b/awesome.c @@ -260,7 +260,7 @@ acquire_WM_Sn(bool replace) xcb_get_selection_owner(globalconf.connection, globalconf.selection_atom), NULL); if (!replace && get_sel_reply->owner != XCB_NONE) - fatal("another window manager is already running (selection owned)"); + fatal("another window manager is already running (selection owned; use --replace)"); /* Acquire the selection */ xcb_set_selection_owner(globalconf.connection, globalconf.selection_owner_window, @@ -436,6 +436,7 @@ main(int argc, char **argv) xdgHandle xdg; bool no_argb = false; bool run_test = false; + bool replace_wm = false; xcb_query_tree_cookie_t tree_c; static struct option long_options[] = { @@ -444,6 +445,7 @@ main(int argc, char **argv) { "config", 1, NULL, 'c' }, { "check", 0, NULL, 'k' }, { "no-argb", 0, NULL, 'a' }, + { "replace", 0, NULL, 'r' }, { NULL, 0, NULL, 0 } }; @@ -480,7 +482,7 @@ main(int argc, char **argv) luaA_init(&xdg); /* check args */ - while((opt = getopt_long(argc, argv, "vhkc:a", + while((opt = getopt_long(argc, argv, "vhkc:ar", long_options, NULL)) != -1) switch(opt) { @@ -502,6 +504,9 @@ main(int argc, char **argv) case 'a': no_argb = true; break; + case 'r': + replace_wm = true; + break; } if (run_test) @@ -578,7 +583,7 @@ main(int argc, char **argv) draw_test_cairo_xcb(); /* Acquire the WM_Sn selection */ - acquire_WM_Sn(true); + acquire_WM_Sn(replace_wm); /* initialize dbus */ a_dbus_init(); diff --git a/manpages/awesome.1.de.txt b/manpages/awesome.1.de.txt index 8f325a6b..d08e95d0 100644 --- a/manpages/awesome.1.de.txt +++ b/manpages/awesome.1.de.txt @@ -35,6 +35,8 @@ OPTIONEN Überprüft die Konfigurationsdatei auf Syntaxfehler. *-a*, *--no-argb*:: Verwende keine ARGB-Visuals +*-r*, *--replace*:: + Existierenden Fenstermanager ersetzen TASTENBELEGUNG FÜR MAUSZEIGER ----------------------------- diff --git a/manpages/awesome.1.es.txt b/manpages/awesome.1.es.txt index 23788971..e3fd619c 100644 --- a/manpages/awesome.1.es.txt +++ b/manpages/awesome.1.es.txt @@ -52,6 +52,8 @@ OPCIONES Verifica la sintaxis del archivo de configuración. *-a*, *--no-argb*:: No utilice colores ARGB. +*-r*, *--replace*:: + Replace an existing window manager ATAJOS DE RAtÓN POR OMISIÓN --------------------------- diff --git a/manpages/awesome.1.fr.txt b/manpages/awesome.1.fr.txt index 83779d72..ac68ea52 100644 --- a/manpages/awesome.1.fr.txt +++ b/manpages/awesome.1.fr.txt @@ -45,6 +45,8 @@ OPTIONS Vérifie la syntaxe du fichier de configuration. *-a*, *--no-argb*:: N'utilise pas le codage ARGB. +*-r*, *--replace*:: + Replace an existing window manager ASSOCIATIONS AVEC LA SOURIS (PAR DÉFAUT) ---------------------------------------- diff --git a/manpages/awesome.1.it.txt b/manpages/awesome.1.it.txt index 411839dc..098e1948 100644 --- a/manpages/awesome.1.it.txt +++ b/manpages/awesome.1.it.txt @@ -52,6 +52,8 @@ OPZIONI Verifica la sintassi del file di configurazione. *-a*, *--no-argb*:: Non usare visuali ARGB. +*-r*, *--replace*:: + Replace an existing window manager DEFAULT SCORCIATOIE CON IL MOUSE -------------------------------- diff --git a/manpages/awesome.1.ru.txt b/manpages/awesome.1.ru.txt index d0b82871..63cfa262 100644 --- a/manpages/awesome.1.ru.txt +++ b/manpages/awesome.1.ru.txt @@ -47,6 +47,8 @@ awesome - потрясающий оконный менеджер Проверить синтаксис конфигурационного файла. *-a*, *--no-argb*:: Не использовать ARGB. +*-r*, *--replace*:: + Replace an existing window manager НАСТРОЙКИ МЫШИ ПО-УМОЛЧАНИЮ --------------------------- diff --git a/manpages/awesome.1.txt b/manpages/awesome.1.txt index a7f066e1..5d9efb87 100644 --- a/manpages/awesome.1.txt +++ b/manpages/awesome.1.txt @@ -44,6 +44,8 @@ OPTIONS Check configuration file syntax. *-a*, *--no-argb*:: Don't use ARGB visuals. +*-r*, *--replace*:: + Replace an existing window manager DEFAULT MOUSE BINDINGS -----------------------