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.

-- 
    Gregor Best
From e3b42d73f647b4799109013723c0bc785f1c3058 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    |  134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 selection.h    |   40 +++++++++++++++++
 4 files changed, 180 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..3938ac2
--- /dev/null
+++ b/selection.c
@@ -0,0 +1,134 @@
+/*
+ * 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_map_window(globalconf.connection, window);
+    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

Attachment: signature.asc
Description: PGP signature

Reply via email to