diff --git a/awesome.c b/awesome.c index 08d136ad..b4b50637 100644 --- a/awesome.c +++ b/awesome.c @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -221,6 +222,76 @@ scan(xcb_query_tree_cookie_t tree_c) restore_client_order(prop_cookie); } +static 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 */ + 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"); + + 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; use --replace)"); + + /* 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); + 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 a_xcb_check(void) { @@ -365,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[] = { @@ -373,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 } }; @@ -409,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) { @@ -431,6 +504,9 @@ main(int argc, char **argv) case 'a': no_argb = true; break; + case 'r': + replace_wm = true; + break; } if (run_test) @@ -506,6 +582,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(replace_wm); + /* initialize dbus */ a_dbus_init(); @@ -527,7 +606,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 */ 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 0f1b8484..344cfe5f 100644 --- a/globalconf.h +++ b/globalconf.h @@ -84,6 +84,10 @@ 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 */ uint16_t numlockmask, shiftlockmask, capslockmask, modeswitchmask; /** Check for XTest extension */ diff --git a/manpages/awesome.1.de.txt b/manpages/awesome.1.de.txt index 8f325a6b..4b740465 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..37c11694 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..00da895c 100644 --- a/manpages/awesome.1.fr.txt +++ b/manpages/awesome.1.fr.txt @@ -45,6 +45,9 @@ OPTIONS Vérifie la syntaxe du fichier de configuration. *-a*, *--no-argb*:: N'utilise pas le codage ARGB. +*-r*, *--replace*:: + Remplace le gestionnaire de fenêtres existant. + ASSOCIATIONS AVEC LA SOURIS (PAR DÉFAUT) ---------------------------------------- diff --git a/manpages/awesome.1.it.txt b/manpages/awesome.1.it.txt index 411839dc..631fe058 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..5048b96f 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..17f52bfa 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 -----------------------