2
* @file xcb/geis_xcb_backend.c
3
* @brief Implements the GEIS XCB back end.
5
* Copyright 2011 Canonical Ltd.
7
* This library is free software; you can redistribute it and/or modify it under
8
* the terms of the GNU Lesser General Public License as published by the Free
9
* Software Foundation; either version 3 of the License, or (at your option) any
12
* This library is distributed in the hope that it will be useful, but WITHOUT
13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17
* You should have received a copy of the GNU Lesser General Public License
18
* along with this program; if not, write to the Free Software Foundation, Inc.,
19
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
#include "geis_xcb_backend.h"
23
#include "geis_attr.h"
24
#include "geis_backend_protected.h"
25
#include "geis_class.h"
26
#include "geis_event.h"
27
#include "geis_logging.h"
28
#include "geis_private.h"
29
#include "grail_gestures.h"
30
#include <grail-types.h>
31
#include "xcb_gesture.h"
33
#include <X11/Xlib-xcb.h>
37
typedef struct _GeisXcbBackend
39
struct _GeisBackend base;
42
xcb_connection_t *xcb_connection;
46
static void _finalize(GeisBackend g);
47
static void _fd_callback(int fd, GeisBackendMultiplexorEvent ev, void *ctx);
48
static GeisStatus _subscribe(GeisBackend be, GeisSubscription sub);
49
static GeisStatus _unsubscribe(GeisBackend be, GeisSubscription sub);
52
static struct _GeisBackendVtable be_vtbl = {
60
_verify_xcb_version(xcb_connection_t *xcb_connection)
62
int is_valid_version = 0;
63
xcb_gesture_query_version_cookie_t version_cookie;
64
xcb_gesture_query_version_reply_t *version_reply = NULL;
65
xcb_generic_error_t *error = NULL;
67
version_cookie = xcb_gesture_query_version(xcb_connection,
68
XCB_GESTURE_MAJOR_VERSION,
69
XCB_GESTURE_MINOR_VERSION);
70
version_reply = xcb_gesture_query_version_reply(xcb_connection,
75
geis_error("failed to receive XCB gesture version reply.");
79
if (version_reply->major_version != XCB_GESTURE_MAJOR_VERSION
80
&& version_reply->minor_version != XCB_GESTURE_MINOR_VERSION)
82
geis_error("server supports unrecognized version: %d.%d",
83
version_reply->major_version, version_reply->minor_version);
92
return is_valid_version;
97
_finalize(GeisBackend g)
99
GeisXcbBackend be = (GeisXcbBackend)g;
101
geis_debug("XCB back end finalized");
106
* Dispatches events coming from XCB.
109
_xcb_dispatch(GeisXcbBackend be)
111
geis_debug("begins");
112
if (be->xcb_connection)
114
const xcb_query_extension_reply_t *extension_info;
115
extension_info = xcb_get_extension_data(be->xcb_connection, &xcb_gesture_id);
116
xcb_generic_event_t *event = NULL;
118
while ((event = xcb_poll_for_event(be->xcb_connection)))
120
xcb_gesture_notify_event_t *gesture_event = NULL;
121
if (event->response_type != GenericEvent) {
122
geis_warning("received non-generic event type: %d",
123
event->response_type);
127
gesture_event = (xcb_gesture_notify_event_t*)event;
128
if (gesture_event->extension != extension_info->major_opcode)
130
geis_warning("received non-gesture extension event: %d",
131
gesture_event->extension);
135
if (gesture_event->event_type != XCB_GESTURE_NOTIFY)
137
geis_warning("received unrecognized gesture event type: %d",
138
gesture_event->event_type);
146
/** @todo implement this */
148
_fd_callback(int fd __attribute__((unused)),
149
GeisBackendMultiplexorEvent ev __attribute__((unused)),
152
geis_debug("begins");
153
GeisXcbBackend be = (GeisXcbBackend)ctx;
159
/** @todo implement this */
161
_subscribe(GeisBackend be, GeisSubscription sub)
163
geis_debug("begins");
164
GeisStatus status = GEIS_STATUS_NOT_SUPPORTED;
170
/** @todo implement this */
172
_unsubscribe(GeisBackend be, GeisSubscription sub)
174
geis_debug("begins");
175
GeisStatus status = GEIS_STATUS_NOT_SUPPORTED;
181
/** @todo implement this */
183
_report_xcb_devices(GeisXcbBackend be)
189
* Generates the events for gesture classes.
192
_report_grail_classes(GeisXcbBackend be)
194
GeisGestureClass drag_class = geis_gesture_class_new(GEIS_GESTURE_DRAG,
196
geis_xcb_backend_add_drag_attrs(drag_class);
197
GeisEvent event_drag = geis_event_new(GEIS_EVENT_CLASS_AVAILABLE);
198
GeisAttr attr_drag = geis_attr_new(GEIS_EVENT_ATTRIBUTE_CLASS,
199
GEIS_ATTR_TYPE_POINTER,
201
geis_event_add_attr(event_drag, attr_drag);
202
geis_post_event(be->geis, event_drag);
204
GeisGestureClass pinch_class = geis_gesture_class_new(GEIS_GESTURE_DRAG,
206
geis_xcb_backend_add_pinch_attrs(pinch_class);
207
GeisEvent event_pinch = geis_event_new(GEIS_EVENT_CLASS_AVAILABLE);
208
GeisAttr attr_pinch = geis_attr_new(GEIS_EVENT_ATTRIBUTE_CLASS,
209
GEIS_ATTR_TYPE_POINTER,
211
geis_event_add_attr(event_pinch, attr_pinch);
212
geis_post_event(be->geis, event_pinch);
214
GeisGestureClass rotate_class = geis_gesture_class_new(GEIS_GESTURE_DRAG,
216
geis_xcb_backend_add_rotate_attrs(rotate_class);
217
GeisEvent event_rotate = geis_event_new(GEIS_EVENT_CLASS_AVAILABLE);
218
GeisAttr attr_rotate = geis_attr_new(GEIS_EVENT_ATTRIBUTE_CLASS,
219
GEIS_ATTR_TYPE_POINTER,
221
geis_event_add_attr(event_rotate, attr_rotate);
222
geis_post_event(be->geis, event_rotate);
224
GeisGestureClass tap_class = geis_gesture_class_new(GEIS_GESTURE_DRAG,
226
geis_xcb_backend_add_tap_attrs(tap_class);
227
GeisEvent event_tap = geis_event_new(GEIS_EVENT_CLASS_AVAILABLE);
228
GeisAttr attr_tap = geis_attr_new(GEIS_EVENT_ATTRIBUTE_CLASS,
229
GEIS_ATTR_TYPE_POINTER,
231
geis_event_add_attr(event_tap, attr_tap);
232
geis_post_event(be->geis, event_tap);
237
geis_xcb_backend_new(Geis geis,
238
GeisBoolean track_devices,
239
GeisBoolean track_classes)
241
geis_debug("begins");
242
GeisXcbBackend be = calloc(1, sizeof(struct _GeisXcbBackend));
245
geis_error("failed to allocate GEIS XCB back end");
249
geis_backend_init_base(&be->base, &be_vtbl, "GEIS2 XCB");
252
be->x11_display = XOpenDisplay(NULL);
253
if (!be->x11_display)
255
geis_error("error opening X server.");
259
be->xcb_connection = XGetXCBConnection(be->x11_display);
260
if (!be->xcb_connection)
262
geis_error("error connecting to X server.");
265
if (!_verify_xcb_version(be->xcb_connection))
270
be->xcb_fd = xcb_get_file_descriptor(be->xcb_connection);
271
geis_multiplex_fd(be->geis, be->xcb_fd, _fd_callback, be);
275
_report_xcb_devices(be);
280
_report_grail_classes(be);
286
XCloseDisplay(be->x11_display);