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:
commit
0478b946fb
83
awesome.c
83
awesome.c
|
@ -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
11
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.
|
/** \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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
|
@ -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
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
|
@ -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)
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
|
@ -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
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
|
@ -47,6 +47,8 @@ awesome - потрясающий оконный менеджер
|
||||||
Проверить синтаксис конфигурационного файла.
|
Проверить синтаксис конфигурационного файла.
|
||||||
*-a*, *--no-argb*::
|
*-a*, *--no-argb*::
|
||||||
Не использовать ARGB.
|
Не использовать ARGB.
|
||||||
|
*-r*, *--replace*::
|
||||||
|
Replace an existing window manager.
|
||||||
|
|
||||||
НАСТРОЙКИ МЫШИ ПО-УМОЛЧАНИЮ
|
НАСТРОЙКИ МЫШИ ПО-УМОЛЧАНИЮ
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
|
@ -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
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
Loading…
Reference in New Issue