~chasedouglas/frame/ubuntu-upstream-xi

« back to all changes in this revision

Viewing changes to src/v2/x11/window_x11.cpp

  • Committer: Chase Douglas
  • Date: 2011-12-09 01:36:45 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: chase.douglas@ubuntu.com-20111209013645-n24l4myiumblzsfu
* New upstream release.
  - Version 2 adds a new API built on top of XInput multitouch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 *
 
3
 * utouch-frame - Touch Frame Library
 
4
 *
 
5
 * Copyright (C) 2011 Canonical Ltd.
 
6
 *
 
7
 * This program is free software: you can redistribute it and/or modify it
 
8
 * under the terms of the GNU General Public License as published by the
 
9
 * Free Software Foundation, either version 3 of the License, or (at your
 
10
 * option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along
 
18
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 *
 
20
 ****************************************************************************/
 
21
 
 
22
#include "v2/x11/window_x11.h"
 
23
 
 
24
#include <stdio.h>
 
25
 
 
26
#include "utouch/frame_x11.h"
 
27
#include "v2/frame.h"
 
28
#include "v2/touch.h"
 
29
#include "v2/value.h"
 
30
#include "v2/x11/device_x11.h"
 
31
 
 
32
namespace utouch {
 
33
namespace frame {
 
34
 
 
35
WindowX11::WindowX11(::Window window, const SharedUFDevice& device,
 
36
                     Display* display)
 
37
    : window_(window),
 
38
      display_(display),
 
39
      device_(static_cast<UFDeviceX11*>(device.get())) {
 
40
}
 
41
 
 
42
namespace {
 
43
 
 
44
void CopyOldValue(const UFFrame* frame, UFTouch* touch, UFAxisType type) {
 
45
  float value;
 
46
  UFStatus status;
 
47
 
 
48
  status = frame->GetPreviousTouchValue(touch, type, &value);
 
49
  if (status != UFStatusSuccess) {
 
50
    fprintf(stderr, "Warning: failed to get previous touch value\n");
 
51
    return;
 
52
  }
 
53
 
 
54
  touch->SetValue(type, value);
 
55
}
 
56
 
 
57
} // namespace
 
58
 
 
59
bool WindowX11::HandleDeviceEvent(const XIDeviceEvent* event,
 
60
                                  SharedUFFrame* frame) {
 
61
  UFTouchState state;
 
62
  switch (event->evtype) {
 
63
    case XI_TouchBegin:
 
64
      state = UFTouchStateBegin;
 
65
      break;
 
66
 
 
67
    case XI_TouchUpdate:
 
68
    case XI_TouchUpdateUnowned:
 
69
      state = UFTouchStateUpdate;
 
70
      break;
 
71
 
 
72
    case XI_TouchEnd:
 
73
      state = UFTouchStateEnd;
 
74
      break;
 
75
 
 
76
    default:
 
77
      return false;
 
78
  }
 
79
 
 
80
  *frame = SharedUFFrame(new UFFrame(shared_from_this(), current_frame_));
 
81
 
 
82
  const Value* value = new Value(frame_x11_create_window_id(window_));
 
83
  (*frame)->InsertProperty(UFFramePropertyWindowId, value);
 
84
  value = new Value(device_->shared_from_this());
 
85
  (*frame)->InsertProperty(UFFramePropertyDevice, value);
 
86
 
 
87
  UFTouchId touch_id = frame_x11_create_touch_id(event->detail);
 
88
  std::shared_ptr<UFTouch> touch(new UFTouch(state, touch_id, event->event_x,
 
89
                                             event->event_y, event->time));
 
90
 
 
91
  if (event->evtype == XI_TouchBegin) {
 
92
    value = new Value(false);
 
93
    touch->InsertProperty(UFTouchPropertyOwned, value);
 
94
  } else {
 
95
    bool owned = current_frame_->IsTouchOwned(touch_id);
 
96
    value = new Value(owned);
 
97
    touch->InsertProperty(UFTouchPropertyOwned, value);
 
98
  }
 
99
 
 
100
  value = new Value(event->flags & XITouchPendingEnd);
 
101
  touch->InsertProperty(UFTouchPropertyPendingEnd, value);
 
102
 
 
103
  int i;
 
104
  int j;
 
105
  for (i = 0, j = 0;
 
106
       i < event->valuators.mask_len * 8 &&
 
107
       i < static_cast<int>(device_->axis_map().size());
 
108
       ++i) {
 
109
    UFAxisType type = device_->axis_map().find(i)->second;
 
110
    if (XIMaskIsSet(event->valuators.mask, i))
 
111
      touch->SetValue(type, event->valuators.values[j++]);
 
112
    else
 
113
      CopyOldValue(frame->get(), touch.get(), type);
 
114
  }
 
115
 
 
116
  for (; i < static_cast<int>(device_->axis_map().size()); ++i) {
 
117
    UFAxisType type = device_->axis_map().find(i)->second;
 
118
    CopyOldValue(frame->get(), touch.get(), type);
 
119
  }
 
120
 
 
121
  (*frame)->UpdateTouch(touch);
 
122
 
 
123
  current_frame_ = *frame;
 
124
 
 
125
  return true;
 
126
}
 
127
 
 
128
bool WindowX11::HandleOwnershipEvent(const XITouchOwnershipEvent* event,
 
129
                                     SharedUFFrame* frame) {
 
130
  *frame = SharedUFFrame(new UFFrame(shared_from_this(), current_frame_));
 
131
 
 
132
  const Value* value = new Value(frame_x11_create_window_id(window_));
 
133
  (*frame)->InsertProperty(UFFramePropertyWindowId, value);
 
134
  value = new Value(device_->shared_from_this());
 
135
  (*frame)->InsertProperty(UFFramePropertyDevice, value);
 
136
 
 
137
  UFTouch* touch = (*frame)->CopyTouch(event->touchid, UFTouchStateUpdate);
 
138
  if (!touch)
 
139
    return false;
 
140
 
 
141
  value = new Value(event->time);
 
142
  touch->InsertProperty(UFTouchPropertyTime, value);
 
143
  value = new Value(true);
 
144
  touch->InsertProperty(UFTouchPropertyOwned, value);
 
145
 
 
146
  (*frame)->UpdateTouch(SharedUFTouch(touch));
 
147
 
 
148
  current_frame_ = *frame;
 
149
 
 
150
  if (accepted_touches_.count(event->touchid)) {
 
151
    XIAllowTouchEvents(display_, device_->id(), event->touchid,
 
152
                          XITouchOwnerAccept);
 
153
    accepted_touches_.erase(event->touchid);
 
154
  } else if (rejected_touches_.count(event->touchid)) {
 
155
    XIAllowTouchEvents(display_, device_->id(), event->touchid,
 
156
                          XITouchOwnerRejectEnd);
 
157
    rejected_touches_.erase(event->touchid);
 
158
  }
 
159
 
 
160
  return true;
 
161
}
 
162
 
 
163
UFStatus WindowX11::AcceptTouch(UFTouchId touch_id) {
 
164
  if (current_frame_->IsTouchOwned(touch_id)) {
 
165
    if (XIAllowTouchEvents(display_, device_->id(), touch_id,
 
166
                              XITouchOwnerAccept))
 
167
      return UFStatusErrorGeneric;
 
168
 
 
169
    /* Flush output buffer so touches are actually accepted ASAP. The server
 
170
     * can't perform pointer emulation while the currently emulated touch is
 
171
     * still potentially active for pointer emulation. */
 
172
    XFlush(display_);
 
173
  } else {
 
174
    accepted_touches_.insert(touch_id);
 
175
  }
 
176
 
 
177
  return UFStatusSuccess;
 
178
}
 
179
 
 
180
UFStatus WindowX11::RejectTouch(UFTouchId touch_id) {
 
181
  if (current_frame_->IsTouchOwned(touch_id)) {
 
182
    if (XIAllowTouchEvents(display_, device_->id(), touch_id,
 
183
                              XITouchOwnerRejectEnd))
 
184
      return UFStatusErrorGeneric;
 
185
 
 
186
    /* Flush output buffer so touches are actually rejected ASAP. The server
 
187
     * can't perform pointer emulation while the currently emulated touch is
 
188
     * still potentially active for pointer emulation. */
 
189
    XFlush(display_);
 
190
  } else {
 
191
    rejected_touches_.insert(touch_id);
 
192
  }
 
193
 
 
194
  return UFStatusSuccess;
 
195
}
 
196
 
 
197
} // namespace frame
 
198
} // namespace utouch