At Fri, 2 Jan 2009 20:17:09 +0100 Gregor Best wrote: > Hi people, > > with some help by Julien, i have worked on implementing a function for getting > the current primary X selection from Lua. The attached patch adds the global > function selection() which returns the content of the current selection. > > This patch does not yet allow setting the current selection, though that > should be relatively easy to implement. >
I just noticed a small leftover xcb_map_window which I had in for development
which lead to the small 1x1 window used for getting the selection being there
even after the selection() function has been run. The attached patch doesn't
have this.
--
Gregor Best
From f7d40a016cfa90f5e05711d610db87858c302281 Mon Sep 17 00:00:00 2001 From: Gregor Best <[email protected]> Date: Fri, 2 Jan 2009 20:11:21 +0100 Subject: [PATCH] awesome: add selection() for getting the primary X selection Signed-off-by: Gregor Best <[email protected]> --- CMakeLists.txt | 1 + luaa.c | 5 ++ selection.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ selection.h | 40 +++++++++++++++++ 4 files changed, 179 insertions(+), 0 deletions(-) create mode 100644 selection.c create mode 100644 selection.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cb09cc4..a605492 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ set(AWE_SRCS ${SOURCE_DIR}/mouse.c ${SOURCE_DIR}/screen.c ${SOURCE_DIR}/stack.c + ${SOURCE_DIR}/selection.c ${SOURCE_DIR}/wibox.c ${SOURCE_DIR}/systray.c ${SOURCE_DIR}/tag.c diff --git a/luaa.c b/luaa.c index 6e6a379..f478805 100644 --- a/luaa.c +++ b/luaa.c @@ -76,6 +76,8 @@ extern const struct luaL_reg awesome_wibox_meta[]; extern const struct luaL_reg awesome_key_methods[]; extern const struct luaL_reg awesome_key_meta[]; extern const struct luaL_reg awesome_keybinding_methods[]; +extern const struct luaL_reg awesome_selection_methods[]; +extern const struct luaL_reg awesome_selection_meta[]; static struct sockaddr_un *addr; static ev_io csio = { .fd = -1 }; @@ -840,6 +842,9 @@ luaA_init(void) luaA_openlib(L, "key", awesome_key_methods, awesome_key_meta); luaA_openlib(L, "keybinding", awesome_keybinding_methods, awesome_key_meta); + /* Export selection */ + luaA_openlib(L, "selection", awesome_selection_methods, awesome_selection_meta); + lua_pushliteral(L, "AWESOME_VERSION"); lua_pushstring(L, AWESOME_VERSION); lua_settable(L, LUA_GLOBALSINDEX); diff --git a/selection.c b/selection.c new file mode 100644 index 0000000..da68714 --- /dev/null +++ b/selection.c @@ -0,0 +1,133 @@ +/* + * selection.c - Selection handling + * + * Copyright © 2009 Gregor Best <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "selection.h" + +extern awesome_t globalconf; + +xcb_window_t window; +xcb_atom_t null_atom; +xcb_atom_t utf8_atom; + +char *wait_selection (xcb_atom_t selection) +{ xcb_generic_event_t *event; + xcb_selection_notify_event_t *event_notify; + xcb_get_property_cookie_t cookie; + + while (1) + { event = xcb_wait_for_event(globalconf.connection); + + if (!event) + return NULL; + + if (XCB_EVENT_RESPONSE_TYPE(event) != XCB_SELECTION_NOTIFY) + { xcb_event_handle(&globalconf.evenths, event); + continue; + } + + event_notify = (xcb_selection_notify_event_t *) event; + + if(event_notify->selection == selection) + { if ((event_notify->property != XCB_NONE) && + (event_notify->property != null_atom)) + { cookie = xcb_get_text_property(globalconf.connection, event_notify->requestor, event_notify->property); + xcb_get_text_property_reply_t prop; + xcb_get_text_property_reply(globalconf.connection, cookie, &prop, NULL); + xcb_get_text_property_reply_wipe(&prop); + xcb_delete_property(globalconf.connection, + event_notify->requestor, + event_notify->property); + free(event_notify); + return prop.name; + }else + break; + } + } + free(event_notify); + return NULL; +} + +char *get_selection (xcb_atom_t selection, xcb_atom_t request_target) +{ xcb_atom_t prop; + xcb_atom_fast_cookie_t prop_cookie; + char *retval; + + prop_cookie = xcb_atom_get_fast(globalconf.connection, 0, 9, "XSEL_DATA"); + prop = xcb_atom_get_fast_reply(globalconf.connection, prop_cookie, 0); + xcb_convert_selection(globalconf.connection, window, selection, request_target, prop, XCB_CURRENT_TIME); + xcb_flush(globalconf.connection); + + retval = wait_selection(selection); + + return retval; +} + +static int luaA_selection_get(lua_State *L) +{ + xcb_screen_t *screen = xutil_screen_get(globalconf.connection, globalconf.default_screen); + xcb_atom_t selection = PRIMARY; + + window = xcb_generate_id(globalconf.connection); + uint32_t mask = 0; + uint32_t values[3]; + mask |= XCB_CW_BACK_PIXEL; + values[0] = screen->black_pixel; + + mask |= XCB_CW_OVERRIDE_REDIRECT; + values[1] = 1; + + mask |= XCB_CW_EVENT_MASK; + values[2] = XCB_EVENT_MASK_PROPERTY_CHANGE; + + xcb_create_window(globalconf.connection, screen->root_depth, window, screen->root, + 0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT, screen->root_visual, + mask, values); + xcb_flush(globalconf.connection); + + xcb_atom_fast_cookie_t utf8_atom_cookie = xcb_atom_get_fast(globalconf.connection, 0, 11, "UTF8_STRING"); + utf8_atom = xcb_atom_get_fast_reply(globalconf.connection, utf8_atom_cookie, 0); + if(utf8_atom == XCB_NONE) + { utf8_atom = STRING; + printf("UTF8 atom not found\n"); + } + + xcb_atom_fast_cookie_t null_atom_cookie = xcb_atom_get_fast(globalconf.connection, 0, 4, "NULL"); + null_atom = xcb_atom_get_fast_reply(globalconf.connection, null_atom_cookie, 0); + + const char *sel = get_selection(selection, utf8_atom); + if (!sel) + { lua_pushnil(L); + return 0; + } + lua_pushstring(L, sel); + return 1; +} + +const struct luaL_reg awesome_selection_methods[] = +{ + { "__call", luaA_selection_get }, + { NULL, NULL } +}; + +const struct luaL_reg awesome_selection_meta[] = +{ + { NULL, NULL } +}; diff --git a/selection.h b/selection.h new file mode 100644 index 0000000..bcc8ec7 --- /dev/null +++ b/selection.h @@ -0,0 +1,40 @@ +/* + * selection.h - Selection handling header + * + * Copyright © 2009 Gregor Best <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef AWESOME_SELECTION_H +#define AWESOME_SELECTION_H + +#include <xcb/xcb.h> +#include <xcb/xcb_event.h> +#include <xcb/xcb_atom.h> +#include <xcb/xcb_icccm.h> + +#include <string.h> + +#include "luaa.h" +#include "structs.h" +#include "awesome.h" + +char *wait_selection (xcb_atom_t); +char *get_selection (xcb_atom_t, xcb_atom_t); +static int luaA_selection_get(lua_State *); + +#endif -- 1.6.0.6
signature.asc
Description: PGP signature
