selection_getter: Implement simple data transfers

This commit adds support for simple selection transfers. INCR support is
still missing. The API is that a selection getter object emit the "data"
signal when some data becomes available and "data_end" when all data was
received.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2019-02-07 16:20:02 +01:00
parent 010c51aa83
commit 8ad29950f5
4 changed files with 67 additions and 2 deletions

View File

@ -63,5 +63,6 @@ WM_CLIENT_LEADER
XSEL_DATA
WM_TAKE_FOCUS
AWESOME_CLIENT_ORDER
AWESOME_SELECTION_ATOM
_XKB_RULES_NAMES
_MOTIF_WM_HINTS

View File

@ -23,6 +23,7 @@
#include "awesome.h"
#include "property.h"
#include "objects/tag.h"
#include "objects/selection_getter.h"
#include "objects/drawin.h"
#include "xwindow.h"
#include "ewmh.h"
@ -1105,6 +1106,7 @@ void event_handle(xcb_generic_event_t *event)
EVENT(XCB_REPARENT_NOTIFY, event_handle_reparentnotify);
EVENT(XCB_UNMAP_NOTIFY, event_handle_unmapnotify);
EVENT(XCB_SELECTION_CLEAR, event_handle_selectionclear);
EVENT(XCB_SELECTION_NOTIFY, event_handle_selectionnotify);
#undef EVENT
}

View File

@ -21,6 +21,7 @@
#include "objects/selection_getter.h"
#include "common/luaobject.h"
#include "common/atoms.h"
#include "globalconf.h"
#define REGISTRY_GETTER_TABLE_INDEX "awesome_selection_getters"
@ -82,12 +83,71 @@ luaA_selection_getter_new(lua_State *L)
target_atom = reply ? reply->atom : XCB_NONE;
p_delete(&reply);
(void) name_atom;
(void) target_atom;
xcb_convert_selection(globalconf.connection, selection->window, name_atom,
target_atom, AWESOME_SELECTION_ATOM, globalconf.timestamp);
return 1;
}
static void
selection_handle_selectionnotify(lua_State *L, int ud, xcb_atom_t property)
{
selection_getter_t *selection;
ud = luaA_absindex(L, ud);
selection = lua_touserdata(L, ud);
if (property != XCB_NONE)
{
xcb_get_property_reply_t *property_r = xcb_get_property_reply(globalconf.connection,
xcb_get_property(globalconf.connection, true, selection->window, AWESOME_SELECTION_ATOM,
XCB_GET_PROPERTY_TYPE_ANY, 0, 0xffffffff), NULL);
if (property_r)
{
lua_pushlstring(L, xcb_get_property_value(property_r), xcb_get_property_value_length(property_r));
luaA_object_emit_signal(L, ud, "data", 1);
p_delete(&property_r);
}
}
luaA_object_emit_signal(L, ud, "data_end", 0);
/* Now unreference the selection object; it's dead */
lua_pushliteral(L, REGISTRY_GETTER_TABLE_INDEX);
lua_rawget(L, LUA_REGISTRYINDEX);
luaL_unref(L, -1, selection->ref);
lua_pop(L, 1);
selection->ref = LUA_NOREF;
}
void
event_handle_selectionnotify(xcb_selection_notify_event_t *ev)
{
lua_State *L = globalconf_get_lua_State();
/* Iterate over all active selection getters */
lua_pushliteral(L, REGISTRY_GETTER_TABLE_INDEX);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_type(L, -1) == LUA_TUSERDATA) {
selection_getter_t *selection = lua_touserdata(L, -1);
if (ev->requestor == selection->window) {
/* Found the right selection */
selection_handle_selectionnotify(L, -1, ev->property);
lua_pop(L, 2);
break;
}
}
/* Remove the value, leaving only the key */
lua_pop(L, 1);
}
/* Remove the getter table */
lua_pop(L, 1);
}
void
selection_getter_class_setup(lua_State *L)
{

View File

@ -23,8 +23,10 @@
#define AWESOME_OBJECTS_SELECTION_GETTER_H
#include <lua.h>
#include <xcb/xcb.h>
void selection_getter_class_setup(lua_State*);
void event_handle_selectionnotify(xcb_selection_notify_event_t*);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80