2
* @file geis_grail_window_grab.c
3
* @brief window grab handling for the GEIS grail back end
6
* Copyright 2011-2012 Canonical Ltd.
8
* This library is free software: you can redistribute it and/or modify it
9
* under the terms of the GNU Lesser General Public License version 3
10
* as published by the Free Software Foundation.
12
* This library is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranties of
14
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15
* PURPOSE. See the GNU Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public License
18
* along with this library. If not, see <http://www.gnu.org/licenses/>.
20
#include "geis_config.h"
21
#include "geis_grail_window_grab.h"
24
#include "geis_logging.h"
25
#include <X11/extensions/XInput2.h>
29
* Tracks the number of grabs for each X window.
31
struct GeisGrailWindowGrab
36
typedef struct GeisGrailWindowGrab *GeisGrailWindowGrab;
39
* Stores all tracked window grabs.
41
struct GeisGrailWindowGrabStore
47
static const GeisSize _geis_grail_window_grab_store_default_size = 2;
48
static const GeisFloat _geis_grail_window_grab_store_growth_factor = 1.7;
51
static GeisGrailWindowGrabStore
52
_window_grab_allocate()
54
GeisGrailWindowGrabStore wgs = malloc(sizeof(struct GeisGrailWindowGrabStore));
57
geis_error("failed to allocate window grab store");
64
_window_grab_deallocate(GeisGrailWindowGrabStore wgs)
71
* Constructs a new window grab store.
73
GeisGrailWindowGrabStore
74
geis_grail_window_grab_store_new(Display *display)
76
GeisGrailWindowGrabStore wgs = _window_grab_allocate();
79
wgs->display = display;
80
wgs->grabs = geis_bag_new(sizeof(struct GeisGrailWindowGrab),
81
_geis_grail_window_grab_store_default_size,
82
_geis_grail_window_grab_store_growth_factor);
94
* Destroys a window grab store.
97
geis_grail_window_grab_store_delete(GeisGrailWindowGrabStore wgs)
99
for (GeisSize i = 0; i < geis_bag_count(wgs->grabs); ++i)
103
geis_bag_delete(wgs->grabs);
104
_window_grab_deallocate(wgs);
108
static GeisGrailWindowGrab
109
_window_grab_store_find(GeisGrailWindowGrabStore wgs, Window window_id)
111
for (GeisSize i = 0; i < geis_bag_count(wgs->grabs); ++i)
113
GeisGrailWindowGrab grab = (GeisGrailWindowGrab)geis_bag_at(wgs->grabs, i);
114
if (grab->window_id == window_id)
124
* Grabs a window through a window grab store.
127
geis_grail_window_grab_store_grab(GeisGrailWindowGrabStore wgs, Window window_id)
129
GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
130
GeisGrailWindowGrab grab = _window_grab_store_find(wgs, window_id);
133
struct GeisGrailWindowGrab new_grab = { window_id, 1 };
134
geis_bag_append(wgs->grabs, &new_grab);
138
XIMaskLen(XI_LASTEVENT),
139
calloc(XIMaskLen(XI_LASTEVENT), sizeof(char))
141
XISetMask(mask.mask, XI_TouchBegin);
142
XISetMask(mask.mask, XI_TouchUpdate);
143
XISetMask(mask.mask, XI_TouchEnd);
144
XISetMask(mask.mask, XI_TouchOwnership);
145
XISetMask(mask.mask, XI_HierarchyChanged);
146
XIGrabModifiers mods = { XIAnyModifier, 0 };
147
int xstat = XIGrabTouchBegin(wgs->display, XIAllMasterDevices,
153
geis_error("error %d returned from XIGrabTouchBegin()", xstat);
156
else if (mods.status != XIGrabSuccess)
158
geis_error("status %d returned from XIGrabTouchBegin()", mods.status);
161
status = GEIS_STATUS_SUCCESS;
166
status = GEIS_STATUS_SUCCESS;
175
* Ungrabs a window through a window grab store.
176
* @param window The window to ungrab.
179
geis_grail_window_grab_store_ungrab(GeisGrailWindowGrabStore wgs,
182
GeisGrailWindowGrab grab = _window_grab_store_find(wgs, window_id);
186
if (0 == grab->grab_count)
188
XIGrabModifiers mods = { XIAnyModifier, 0 };
189
Status xstat = XIUngrabTouchBegin(wgs->display,
195
geis_error("error %d returned from XIUngrabTouchBegin()", xstat);
198
XSync(wgs->display, False);