Merge pull request #513 from psychon/WM_Sn_selection

Various selection stuff that ICCCM requires us to do.

Fixes https://awesome.naquadah.org/bugs/index.php?do=details&task_id=782.
Fixes https://github.com/awesomeWM/awesome/issues/292.
Closes https://github.com/awesomeWM/awesome/pull/513.
This commit is contained in:
Daniel Hahler 2015-10-11 13:26:38 +02:00
commit 0478b946fb
9 changed files with 109 additions and 2 deletions

View File

@ -47,6 +47,7 @@
#include <xcb/bigreq.h> #include <xcb/bigreq.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <xcb/xcb_atom.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h> #include <xcb/xcb_event.h>
#include <xcb/xinerama.h> #include <xcb/xinerama.h>
@ -221,6 +222,76 @@ scan(xcb_query_tree_cookie_t tree_c)
restore_client_order(prop_cookie); 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 static void
a_xcb_check(void) a_xcb_check(void)
{ {
@ -365,6 +436,7 @@ main(int argc, char **argv)
xdgHandle xdg; xdgHandle xdg;
bool no_argb = false; bool no_argb = false;
bool run_test = false; bool run_test = false;
bool replace_wm = false;
xcb_query_tree_cookie_t tree_c; xcb_query_tree_cookie_t tree_c;
static struct option long_options[] = static struct option long_options[] =
{ {
@ -373,6 +445,7 @@ main(int argc, char **argv)
{ "config", 1, NULL, 'c' }, { "config", 1, NULL, 'c' },
{ "check", 0, NULL, 'k' }, { "check", 0, NULL, 'k' },
{ "no-argb", 0, NULL, 'a' }, { "no-argb", 0, NULL, 'a' },
{ "replace", 0, NULL, 'r' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
@ -409,7 +482,7 @@ main(int argc, char **argv)
luaA_init(&xdg); luaA_init(&xdg);
/* check args */ /* check args */
while((opt = getopt_long(argc, argv, "vhkc:a", while((opt = getopt_long(argc, argv, "vhkc:ar",
long_options, NULL)) != -1) long_options, NULL)) != -1)
switch(opt) switch(opt)
{ {
@ -431,6 +504,9 @@ main(int argc, char **argv)
case 'a': case 'a':
no_argb = true; no_argb = true;
break; break;
case 'r':
replace_wm = true;
break;
} }
if (run_test) if (run_test)
@ -506,6 +582,9 @@ main(int argc, char **argv)
/* Did we get some usable data from the above X11 setup? */ /* Did we get some usable data from the above X11 setup? */
draw_test_cairo_xcb(); draw_test_cairo_xcb();
/* Acquire the WM_Sn selection */
acquire_WM_Sn(replace_wm);
/* initialize dbus */ /* initialize dbus */
a_dbus_init(); a_dbus_init();
@ -527,7 +606,7 @@ main(int argc, char **argv)
globalconf.screen->root, globalconf.screen->root,
XCB_CW_EVENT_MASK, &select_input_val); XCB_CW_EVENT_MASK, &select_input_val);
if (xcb_request_check(globalconf.connection, cookie)) 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 */ /* Prefetch the maximum request length */

11
event.c
View File

@ -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. /** \brief awesome xerror function.
* There's no way to check accesses to destroyed windows, thus those cases are * There's no way to check accesses to destroyed windows, thus those cases are
* ignored (especially on UnmapNotify's). * 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_PROPERTY_NOTIFY, property_handle_propertynotify);
EVENT(XCB_REPARENT_NOTIFY, event_handle_reparentnotify); EVENT(XCB_REPARENT_NOTIFY, event_handle_reparentnotify);
EVENT(XCB_UNMAP_NOTIFY, event_handle_unmapnotify); EVENT(XCB_UNMAP_NOTIFY, event_handle_unmapnotify);
EVENT(XCB_SELECTION_CLEAR, event_handle_selectionclear);
#undef EVENT #undef EVENT
} }

View File

@ -84,6 +84,10 @@ typedef struct
key_array_t keys; key_array_t keys;
/** Root window mouse bindings */ /** Root window mouse bindings */
button_array_t buttons; 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 */ /** Modifiers masks */
uint16_t numlockmask, shiftlockmask, capslockmask, modeswitchmask; uint16_t numlockmask, shiftlockmask, capslockmask, modeswitchmask;
/** Check for XTest extension */ /** Check for XTest extension */

View File

@ -35,6 +35,8 @@ OPTIONEN
Überprüft die Konfigurationsdatei auf Syntaxfehler. Überprüft die Konfigurationsdatei auf Syntaxfehler.
*-a*, *--no-argb*:: *-a*, *--no-argb*::
Verwende keine ARGB-Visuals Verwende keine ARGB-Visuals
*-r*, *--replace*::
Existierenden Fenstermanager ersetzen.
TASTENBELEGUNG FÜR MAUSZEIGER TASTENBELEGUNG FÜR MAUSZEIGER
----------------------------- -----------------------------

View File

@ -52,6 +52,8 @@ OPCIONES
Verifica la sintaxis del archivo de configuración. Verifica la sintaxis del archivo de configuración.
*-a*, *--no-argb*:: *-a*, *--no-argb*::
No utilice colores ARGB. No utilice colores ARGB.
*-r*, *--replace*::
Replace an existing window manager.
ATAJOS DE RAtÓN POR OMISIÓN ATAJOS DE RAtÓN POR OMISIÓN
--------------------------- ---------------------------

View File

@ -45,6 +45,9 @@ OPTIONS
Vérifie la syntaxe du fichier de configuration. Vérifie la syntaxe du fichier de configuration.
*-a*, *--no-argb*:: *-a*, *--no-argb*::
N'utilise pas le codage ARGB. N'utilise pas le codage ARGB.
*-r*, *--replace*::
Remplace le gestionnaire de fenêtres existant.
ASSOCIATIONS AVEC LA SOURIS (PAR DÉFAUT) ASSOCIATIONS AVEC LA SOURIS (PAR DÉFAUT)
---------------------------------------- ----------------------------------------

View File

@ -52,6 +52,8 @@ OPZIONI
Verifica la sintassi del file di configurazione. Verifica la sintassi del file di configurazione.
*-a*, *--no-argb*:: *-a*, *--no-argb*::
Non usare visuali ARGB. Non usare visuali ARGB.
*-r*, *--replace*::
Replace an existing window manager.
DEFAULT SCORCIATOIE CON IL MOUSE DEFAULT SCORCIATOIE CON IL MOUSE
-------------------------------- --------------------------------

View File

@ -47,6 +47,8 @@ awesome - потрясающий оконный менеджер
Проверить синтаксис конфигурационного файла. Проверить синтаксис конфигурационного файла.
*-a*, *--no-argb*:: *-a*, *--no-argb*::
Не использовать ARGB. Не использовать ARGB.
*-r*, *--replace*::
Replace an existing window manager.
НАСТРОЙКИ МЫШИ ПО-УМОЛЧАНИЮ НАСТРОЙКИ МЫШИ ПО-УМОЛЧАНИЮ
--------------------------- ---------------------------

View File

@ -44,6 +44,8 @@ OPTIONS
Check configuration file syntax. Check configuration file syntax.
*-a*, *--no-argb*:: *-a*, *--no-argb*::
Don't use ARGB visuals. Don't use ARGB visuals.
*-r*, *--replace*::
Replace an existing window manager.
DEFAULT MOUSE BINDINGS DEFAULT MOUSE BINDINGS
----------------------- -----------------------