Browse Source

Implement INCR transfers

Incremental transfers are required to be supported. This commit adds
that necessary support to awesomeWM.

Signed-off-by: Uli Schlachter <psychon@znc.in>
Uli Schlachter 11 months ago
parent
commit
0d2c6fc5d1
4 changed files with 94 additions and 18 deletions
  1. 1
    0
      common/atoms.list
  2. 88
    18
      objects/selection_getter.c
  3. 1
    0
      objects/selection_getter.h
  4. 4
    0
      property.c

+ 1
- 0
common/atoms.list View File

@@ -64,5 +64,6 @@ XSEL_DATA
64 64
 WM_TAKE_FOCUS
65 65
 AWESOME_CLIENT_ORDER
66 66
 AWESOME_SELECTION_ATOM
67
+INCR
67 68
 _XKB_RULES_NAMES
68 69
 _MOTIF_WM_HINTS

+ 88
- 18
objects/selection_getter.c View File

@@ -89,6 +89,22 @@ luaA_selection_getter_new(lua_State *L)
89 89
     return 1;
90 90
 }
91 91
 
92
+static void
93
+selection_transfer_finished(lua_State *L, int ud)
94
+{
95
+    selection_getter_t *selection = lua_touserdata(L, ud);
96
+
97
+    /* Unreference the selection object; it's dead */
98
+    lua_pushliteral(L, REGISTRY_GETTER_TABLE_INDEX);
99
+    lua_rawget(L, LUA_REGISTRYINDEX);
100
+    luaL_unref(L, -1, selection->ref);
101
+    lua_pop(L, 1);
102
+
103
+    selection->ref = LUA_NOREF;
104
+
105
+    luaA_object_emit_signal(L, ud, "data_end", 0);
106
+}
107
+
92 108
 static void
93 109
 selection_handle_selectionnotify(lua_State *L, int ud, xcb_atom_t property)
94 110
 {
@@ -99,34 +115,37 @@ selection_handle_selectionnotify(lua_State *L, int ud, xcb_atom_t property)
99 115
 
100 116
     if (property != XCB_NONE)
101 117
     {
118
+        xcb_change_window_attributes(globalconf.connection, selection->window,
119
+            XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_PROPERTY_CHANGE });
120
+
102 121
         xcb_get_property_reply_t *property_r = xcb_get_property_reply(globalconf.connection,
103 122
                 xcb_get_property(globalconf.connection, true, selection->window, AWESOME_SELECTION_ATOM,
104 123
                     XCB_GET_PROPERTY_TYPE_ANY, 0, 0xffffffff), NULL);
105 124
 
106 125
         if (property_r)
107 126
         {
127
+            if (property_r->type == INCR)
128
+            {
129
+                /* This is an incremental transfer. The above GetProperty had
130
+                 * delete=true. This indicates to the other end that the
131
+                 * transfer should start now. Right now we only get an estimate
132
+                 * of the size of the data to be transferred, which we ignore.
133
+                 */
134
+                p_delete(&property_r);
135
+                return;
136
+            }
108 137
             lua_pushlstring(L, xcb_get_property_value(property_r), xcb_get_property_value_length(property_r));
109 138
             luaA_object_emit_signal(L, ud, "data", 1);
110 139
             p_delete(&property_r);
111 140
         }
112 141
     }
113 142
 
114
-    luaA_object_emit_signal(L, ud, "data_end", 0);
115
-
116
-    /* Now unreference the selection object; it's dead */
117
-    lua_pushliteral(L, REGISTRY_GETTER_TABLE_INDEX);
118
-    lua_rawget(L, LUA_REGISTRYINDEX);
119
-    luaL_unref(L, -1, selection->ref);
120
-    lua_pop(L, 1);
121
-
122
-    selection->ref = LUA_NOREF;
143
+    selection_transfer_finished(L, ud);
123 144
 }
124 145
 
125
-void
126
-event_handle_selectionnotify(xcb_selection_notify_event_t *ev)
146
+static int
147
+selection_getter_find_by_window(lua_State *L, xcb_window_t window)
127 148
 {
128
-    lua_State *L = globalconf_get_lua_State();
129
-
130 149
     /* Iterate over all active selection getters */
131 150
     lua_pushliteral(L, REGISTRY_GETTER_TABLE_INDEX);
132 151
     lua_rawget(L, LUA_REGISTRYINDEX);
@@ -134,11 +153,11 @@ event_handle_selectionnotify(xcb_selection_notify_event_t *ev)
134 153
     while (lua_next(L, -2) != 0) {
135 154
         if (lua_type(L, -1) == LUA_TUSERDATA) {
136 155
             selection_getter_t *selection = lua_touserdata(L, -1);
137
-            if (ev->requestor == selection->window) {
138
-                /* Found the right selection */
139
-                selection_handle_selectionnotify(L, -1, ev->property);
140
-                lua_pop(L, 2);
141
-                break;
156
+            if (selection->window == window) {
157
+                /* Found the right selection, remove table and key */
158
+                lua_remove(L, -2);
159
+                lua_remove(L, -2);
160
+                return 1;
142 161
             }
143 162
         }
144 163
         /* Remove the value, leaving only the key */
@@ -146,6 +165,57 @@ event_handle_selectionnotify(xcb_selection_notify_event_t *ev)
146 165
     }
147 166
     /* Remove the getter table */
148 167
     lua_pop(L, 1);
168
+
169
+    return 0;
170
+}
171
+
172
+int
173
+property_handle_awesome_selection_atom(uint8_t state, xcb_window_t window)
174
+{
175
+    lua_State *L = globalconf_get_lua_State();
176
+
177
+    if (state != XCB_PROPERTY_NEW_VALUE)
178
+        return 0;
179
+
180
+    if (selection_getter_find_by_window(L, window) == 0)
181
+        return 0;
182
+
183
+    selection_getter_t *selection = lua_touserdata(L, -1);
184
+
185
+    xcb_get_property_reply_t *property_r = xcb_get_property_reply(globalconf.connection,
186
+            xcb_get_property(globalconf.connection, true, selection->window, AWESOME_SELECTION_ATOM,
187
+                XCB_GET_PROPERTY_TYPE_ANY, 0, 0xffffffff), NULL);
188
+
189
+    if (property_r)
190
+    {
191
+        if (property_r->value_len > 0)
192
+        {
193
+            lua_pushlstring(L, xcb_get_property_value(property_r), xcb_get_property_value_length(property_r));
194
+            luaA_object_emit_signal(L, -2, "data", 1);
195
+        }
196
+        else
197
+        {
198
+            /* Transfer finished */
199
+            selection_transfer_finished(L, -1);
200
+        }
201
+
202
+        p_delete(&property_r);
203
+    }
204
+
205
+    lua_pop(L, 1);
206
+    return 0;
207
+}
208
+
209
+void
210
+event_handle_selectionnotify(xcb_selection_notify_event_t *ev)
211
+{
212
+    lua_State *L = globalconf_get_lua_State();
213
+
214
+    if (selection_getter_find_by_window(L, ev->requestor) == 0)
215
+        return;
216
+
217
+    selection_handle_selectionnotify(L, -1, ev->property);
218
+    lua_pop(L, 1);
149 219
 }
150 220
 
151 221
 void

+ 1
- 0
objects/selection_getter.h View File

@@ -27,6 +27,7 @@
27 27
 
28 28
 void selection_getter_class_setup(lua_State*);
29 29
 void event_handle_selectionnotify(xcb_selection_notify_event_t*);
30
+int property_handle_awesome_selection_atom(uint8_t, xcb_window_t);
30 31
 
31 32
 #endif
32 33
 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

+ 4
- 0
property.c View File

@@ -25,6 +25,7 @@
25 25
 #include "ewmh.h"
26 26
 #include "objects/client.h"
27 27
 #include "objects/drawin.h"
28
+#include "objects/selection_getter.h"
28 29
 #include "xwindow.h"
29 30
 
30 31
 #include <xcb/xcb_atom.h>
@@ -524,6 +525,9 @@ property_handle_propertynotify(xcb_property_notify_event_t *ev)
524 525
     /* background change */
525 526
     HANDLE(_XROOTPMAP_ID, property_handle_xrootpmap_id)
526 527
 
528
+    /* selection transfers */
529
+    HANDLE(AWESOME_SELECTION_ATOM, property_handle_awesome_selection_atom)
530
+
527 531
     /* If nothing was found, return */
528 532
     END;
529 533
 

Loading…
Cancel
Save