selection_acquire: Also emit release when X11 selection is lost
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
e4199dd6b5
commit
869b1b0dff
4
event.c
4
event.c
|
@ -25,6 +25,7 @@
|
|||
#include "objects/tag.h"
|
||||
#include "objects/selection_getter.h"
|
||||
#include "objects/drawin.h"
|
||||
#include "objects/selection_acquire.h"
|
||||
#include "objects/selection_watcher.h"
|
||||
#include "xwindow.h"
|
||||
#include "ewmh.h"
|
||||
|
@ -1013,7 +1014,8 @@ event_handle_selectionclear(xcb_selection_clear_event_t *ev)
|
|||
{
|
||||
warn("Lost WM_Sn selection, exiting...");
|
||||
g_main_loop_quit(globalconf.loop);
|
||||
}
|
||||
} else
|
||||
selection_handle_selectionclear(ev);
|
||||
}
|
||||
|
||||
/** \brief awesome xerror function.
|
||||
|
|
|
@ -28,17 +28,85 @@
|
|||
typedef struct selection_acquire_t
|
||||
{
|
||||
LUA_OBJECT_HEADER
|
||||
/** The selection that is being owned. */
|
||||
xcb_atom_t selection;
|
||||
/** Window used for owning the selection. */
|
||||
xcb_window_t window;
|
||||
/** Timestamp used for acquiring the selection. */
|
||||
xcb_timestamp_t timestamp;
|
||||
/** Reference in the special table to this object. */
|
||||
int ref;
|
||||
} selection_acquire_t;
|
||||
|
||||
static lua_class_t selection_acquire_class;
|
||||
LUA_OBJECT_FUNCS(selection_acquire_class, selection_acquire_t, selection_acquire)
|
||||
|
||||
static void
|
||||
luaA_pushatom(lua_State *L, xcb_atom_t atom)
|
||||
{
|
||||
lua_pushnumber(L, atom);
|
||||
}
|
||||
|
||||
static int
|
||||
selection_acquire_find_by_window(lua_State *L, xcb_window_t window)
|
||||
{
|
||||
/* Iterate over all active selection acquire objects */
|
||||
lua_pushliteral(L, REGISTRY_ACQUIRE_TABLE_INDEX);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
if (lua_type(L, -1) == LUA_TUSERDATA) {
|
||||
selection_acquire_t *selection = lua_touserdata(L, -1);
|
||||
if (selection->window == window)
|
||||
{
|
||||
/* Remove table and key */
|
||||
lua_remove(L, -2);
|
||||
lua_remove(L, -2);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* Remove the value, leaving only the key */
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
/* Remove the table */
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
selection_release(lua_State *L, int ud)
|
||||
{
|
||||
selection_acquire_t *selection = luaA_checkudata(L, ud, &selection_acquire_class);
|
||||
|
||||
luaA_object_emit_signal(L, ud, "release", 0);
|
||||
|
||||
/* Destroy the window, this also releases the selection in X11 */
|
||||
xcb_destroy_window(globalconf.connection, selection->window);
|
||||
selection->window = XCB_NONE;
|
||||
|
||||
/* Unreference the object, it's now dead */
|
||||
lua_pushliteral(L, REGISTRY_ACQUIRE_TABLE_INDEX);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
luaA_pushatom(L, selection->selection);
|
||||
lua_pushnil(L);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
selection->selection = XCB_NONE;
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void
|
||||
selection_handle_selectionclear(xcb_selection_clear_event_t *ev)
|
||||
{
|
||||
lua_State *L = globalconf_get_lua_State();
|
||||
|
||||
if (selection_acquire_find_by_window(L, ev->owner) == 0)
|
||||
return;
|
||||
|
||||
selection_release(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
luaA_selection_acquire_new(lua_State *L)
|
||||
{
|
||||
|
@ -51,13 +119,6 @@ luaA_selection_acquire_new(lua_State *L)
|
|||
|
||||
name = luaL_checklstring(L, 2, &name_length);
|
||||
|
||||
/* Create a selection object */
|
||||
selection = (void *) selection_acquire_class.allocator(L);
|
||||
selection->window = xcb_generate_id(globalconf.connection);
|
||||
xcb_create_window(globalconf.connection, globalconf.screen->root_depth,
|
||||
selection->window, globalconf.screen->root, -1, -1, 1, 1, 0,
|
||||
XCB_COPY_FROM_PARENT, globalconf.screen->root_visual, 0, NULL);
|
||||
|
||||
/* Get the atom identifying the selection */
|
||||
reply = xcb_intern_atom_reply(globalconf.connection,
|
||||
xcb_intern_atom_unchecked(globalconf.connection, false, name_length, name),
|
||||
|
@ -65,8 +126,16 @@ luaA_selection_acquire_new(lua_State *L)
|
|||
name_atom = reply ? reply->atom : XCB_NONE;
|
||||
p_delete(&reply);
|
||||
|
||||
/* Try to acquire the selection */
|
||||
/* Create a selection object */
|
||||
selection = (void *) selection_acquire_class.allocator(L);
|
||||
selection->selection = name_atom;
|
||||
selection->timestamp = globalconf.timestamp;
|
||||
selection->window = xcb_generate_id(globalconf.connection);
|
||||
xcb_create_window(globalconf.connection, globalconf.screen->root_depth,
|
||||
selection->window, globalconf.screen->root, -1, -1, 1, 1, 0,
|
||||
XCB_COPY_FROM_PARENT, globalconf.screen->root_visual, 0, NULL);
|
||||
|
||||
/* Try to acquire the selection */
|
||||
xcb_set_selection_owner(globalconf.connection, selection->window, name_atom, selection->timestamp);
|
||||
selection_reply = xcb_get_selection_owner_reply(globalconf.connection,
|
||||
xcb_get_selection_owner(globalconf.connection, name_atom),
|
||||
|
@ -80,12 +149,24 @@ luaA_selection_acquire_new(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Everything worked, register the object in table */
|
||||
/* Everything worked, register the object in the table */
|
||||
lua_pushliteral(L, REGISTRY_ACQUIRE_TABLE_INDEX);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(L, -2);
|
||||
selection->ref = luaL_ref(L, -2);
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaA_pushatom(L, name_atom);
|
||||
lua_rawget(L, -2);
|
||||
if (!lua_isnil(L, -1)) {
|
||||
/* There is already another selection_acquire object for this selection,
|
||||
* release it now. X11 does not send us SelectionClear events for our
|
||||
* own changes to the selection.
|
||||
*/
|
||||
selection_release(L, -1);
|
||||
}
|
||||
|
||||
luaA_pushatom(L, name_atom);
|
||||
lua_pushvalue(L, -4);
|
||||
lua_rawset(L, -4);
|
||||
lua_pop(L, 2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -93,18 +174,8 @@ luaA_selection_acquire_new(lua_State *L)
|
|||
static int
|
||||
luaA_selection_acquire_release(lua_State *L)
|
||||
{
|
||||
selection_acquire_t *selection = luaA_checkudata(L, 1, &selection_acquire_class);
|
||||
|
||||
xcb_destroy_window(globalconf.connection, selection->window);
|
||||
selection->window = XCB_NONE;
|
||||
|
||||
/* Unreference the object, it's now dead */
|
||||
lua_pushliteral(L, REGISTRY_ACQUIRE_TABLE_INDEX);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
luaL_unref(L, -1, selection->ref);
|
||||
lua_pop(L, 1);
|
||||
|
||||
selection->ref = LUA_NOREF;
|
||||
luaA_checkudata(L, 1, &selection_acquire_class);
|
||||
selection_release(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -112,7 +183,7 @@ luaA_selection_acquire_release(lua_State *L)
|
|||
static bool
|
||||
selection_acquire_checker(selection_acquire_t *selection)
|
||||
{
|
||||
return selection->window != XCB_NONE;
|
||||
return selection->selection != XCB_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
#define AWESOME_OBJECTS_SELECTION_ACQUIRE_H
|
||||
|
||||
#include <lua.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
void selection_acquire_class_setup(lua_State*);
|
||||
void selection_handle_selectionclear(xcb_selection_clear_event_t*);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue