~ubuntu-branches/ubuntu/trusty/geis/trusty

« back to all changes in this revision

Viewing changes to libgeis/backend/grail/geis_grail_window_grab.c

  • Committer: Package Import Robot
  • Author(s): Chase Douglas
  • Date: 2012-07-30 08:51:42 UTC
  • Revision ID: package-import@ubuntu.com-20120730085142-jrc33ygjvt0ob1wl
Tags: upstream-2.2.11
ImportĀ upstreamĀ versionĀ 2.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file geis_grail_window_grab.c
 
3
 * @brief window grab handling for the GEIS grail back end
 
4
 */
 
5
/*
 
6
 * Copyright 2011-2012 Canonical Ltd.
 
7
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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/>.
 
19
 */
 
20
#include "geis_config.h"
 
21
#include "geis_grail_window_grab.h"
 
22
 
 
23
#include "geis_bag.h"
 
24
#include "geis_logging.h"
 
25
#include <X11/extensions/XInput2.h>
 
26
 
 
27
 
 
28
/**
 
29
 * Tracks the number of grabs for each X window.
 
30
 */
 
31
struct GeisGrailWindowGrab
 
32
{
 
33
  Window window_id;
 
34
  int    grab_count;
 
35
};
 
36
typedef struct GeisGrailWindowGrab *GeisGrailWindowGrab;
 
37
 
 
38
/**
 
39
 * Stores all tracked window grabs.
 
40
 */
 
41
struct GeisGrailWindowGrabStore 
 
42
{
 
43
  Display *display;
 
44
  GeisBag  grabs;
 
45
};
 
46
 
 
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;
 
49
 
 
50
 
 
51
static GeisGrailWindowGrabStore
 
52
_window_grab_allocate()
 
53
{
 
54
  GeisGrailWindowGrabStore wgs = malloc(sizeof(struct GeisGrailWindowGrabStore));
 
55
  if (!wgs)
 
56
  {
 
57
    geis_error("failed to allocate window grab store");
 
58
  }
 
59
  return wgs;
 
60
}
 
61
 
 
62
 
 
63
static void
 
64
_window_grab_deallocate(GeisGrailWindowGrabStore wgs)
 
65
{
 
66
  free(wgs);
 
67
}
 
68
 
 
69
 
 
70
/*
 
71
 * Constructs a new window grab store.
 
72
 */
 
73
GeisGrailWindowGrabStore
 
74
geis_grail_window_grab_store_new(Display *display)
 
75
{
 
76
  GeisGrailWindowGrabStore wgs = _window_grab_allocate();
 
77
  if (wgs)
 
78
  {
 
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); 
 
83
    if (!wgs->grabs)
 
84
    {
 
85
      free(wgs);
 
86
      wgs = NULL;
 
87
    }
 
88
  }
 
89
  return wgs;
 
90
}
 
91
 
 
92
 
 
93
/*
 
94
 * Destroys a window grab store.
 
95
 */
 
96
void
 
97
geis_grail_window_grab_store_delete(GeisGrailWindowGrabStore wgs)
 
98
{
 
99
  for (GeisSize i = 0; i < geis_bag_count(wgs->grabs); ++i)
 
100
  {
 
101
    /* @todo: ungrab */
 
102
  }
 
103
  geis_bag_delete(wgs->grabs);
 
104
  _window_grab_deallocate(wgs);
 
105
}
 
106
 
 
107
 
 
108
static GeisGrailWindowGrab
 
109
_window_grab_store_find(GeisGrailWindowGrabStore wgs, Window window_id)
 
110
{
 
111
  for (GeisSize i = 0; i < geis_bag_count(wgs->grabs); ++i)
 
112
  {
 
113
    GeisGrailWindowGrab grab = (GeisGrailWindowGrab)geis_bag_at(wgs->grabs, i);
 
114
    if (grab->window_id == window_id)
 
115
    {
 
116
      return grab;
 
117
    }
 
118
  }
 
119
  return NULL;
 
120
}
 
121
 
 
122
 
 
123
/*
 
124
 * Grabs a window through a window grab store.
 
125
 */
 
126
GeisStatus
 
127
geis_grail_window_grab_store_grab(GeisGrailWindowGrabStore wgs, Window window_id)
 
128
{
 
129
  GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
 
130
  GeisGrailWindowGrab grab = _window_grab_store_find(wgs, window_id);
 
131
  if (!grab)
 
132
  {
 
133
    struct GeisGrailWindowGrab new_grab = { window_id, 1 };
 
134
    geis_bag_append(wgs->grabs, &new_grab);
 
135
 
 
136
    XIEventMask mask = {
 
137
      XIAllMasterDevices,
 
138
      XIMaskLen(XI_LASTEVENT),
 
139
      calloc(XIMaskLen(XI_LASTEVENT), sizeof(char))
 
140
    };
 
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,
 
148
                                 window_id,
 
149
                                 0, &mask, 1, &mods);
 
150
    free(mask.mask);
 
151
    if (xstat)
 
152
    {
 
153
      geis_error("error %d returned from XIGrabTouchBegin()", xstat);
 
154
      goto final_exit;
 
155
    }
 
156
    else if (mods.status != XIGrabSuccess)
 
157
    {
 
158
      geis_error("status %d returned from XIGrabTouchBegin()", mods.status);
 
159
      goto final_exit;
 
160
    }
 
161
    status = GEIS_STATUS_SUCCESS;
 
162
  }
 
163
  else
 
164
  {
 
165
    ++grab->grab_count;
 
166
    status = GEIS_STATUS_SUCCESS;
 
167
  }
 
168
 
 
169
final_exit:
 
170
  return status;
 
171
}
 
172
 
 
173
 
 
174
/*
 
175
 * Ungrabs a window through a window grab store.
 
176
 * @param window The window to ungrab.
 
177
 */
 
178
void
 
179
geis_grail_window_grab_store_ungrab(GeisGrailWindowGrabStore wgs,
 
180
                                    Window window_id)
 
181
{
 
182
  GeisGrailWindowGrab grab = _window_grab_store_find(wgs, window_id);
 
183
  if (grab)
 
184
  {
 
185
    --grab->grab_count;
 
186
    if (0 == grab->grab_count)
 
187
    {
 
188
      XIGrabModifiers mods = { XIAnyModifier, 0 };
 
189
      Status xstat = XIUngrabTouchBegin(wgs->display,
 
190
                                        XIAllMasterDevices,
 
191
                                        window_id,
 
192
                                        1, &mods);
 
193
      if (xstat)
 
194
      {
 
195
        geis_error("error %d returned from XIUngrabTouchBegin()", xstat);
 
196
      }
 
197
 
 
198
      XSync(wgs->display, False);
 
199
    }
 
200
  }
 
201
}
 
202
 
 
203