OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/aura/root_window_host_linux.h" | 5 #include "ui/aura/root_window_host_linux.h" |
6 | 6 |
7 #include <strings.h> | 7 #include <strings.h> |
8 #include <X11/cursorfont.h> | 8 #include <X11/cursorfont.h> |
9 #include <X11/extensions/Xfixes.h> | 9 #include <X11/extensions/Xfixes.h> |
10 #include <X11/extensions/XInput2.h> | 10 #include <X11/extensions/XInput2.h> |
11 #include <X11/extensions/Xrandr.h> | 11 #include <X11/extensions/Xrandr.h> |
12 #include <X11/Xatom.h> | 12 #include <X11/Xatom.h> |
13 #include <X11/Xcursor/Xcursor.h> | 13 #include <X11/Xcursor/Xcursor.h> |
14 #include <X11/Xlib.h> | 14 #include <X11/Xlib.h> |
15 | 15 |
16 #include <algorithm> | 16 #include <algorithm> |
17 #include <limits> | 17 #include <limits> |
18 #include <string> | 18 #include <string> |
19 | 19 |
20 #include "base/command_line.h" | 20 #include "base/command_line.h" |
21 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
22 #include "base/message_pump_aurax11.h" | 22 #include "base/message_pump_aurax11.h" |
23 #include "base/stl_util.h" | 23 #include "base/stl_util.h" |
24 #include "base/string_number_conversions.h" | |
25 #include "base/string_util.h" | |
24 #include "base/stringprintf.h" | 26 #include "base/stringprintf.h" |
25 #include "third_party/skia/include/core/SkBitmap.h" | 27 #include "third_party/skia/include/core/SkBitmap.h" |
26 #include "third_party/skia/include/core/SkCanvas.h" | 28 #include "third_party/skia/include/core/SkCanvas.h" |
27 #include "third_party/skia/include/core/SkPostConfig.h" | 29 #include "third_party/skia/include/core/SkPostConfig.h" |
28 #include "ui/aura/client/capture_client.h" | 30 #include "ui/aura/client/capture_client.h" |
29 #include "ui/aura/client/cursor_client.h" | 31 #include "ui/aura/client/cursor_client.h" |
30 #include "ui/aura/client/screen_position_client.h" | 32 #include "ui/aura/client/screen_position_client.h" |
31 #include "ui/aura/client/user_action_client.h" | 33 #include "ui/aura/client/user_action_client.h" |
32 #include "ui/aura/env.h" | 34 #include "ui/aura/env.h" |
33 #include "ui/aura/root_window.h" | 35 #include "ui/aura/root_window.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
54 using std::min; | 56 using std::min; |
55 | 57 |
56 namespace aura { | 58 namespace aura { |
57 | 59 |
58 namespace { | 60 namespace { |
59 | 61 |
60 // Standard Linux mouse buttons for going back and forward. | 62 // Standard Linux mouse buttons for going back and forward. |
61 const int kBackMouseButton = 8; | 63 const int kBackMouseButton = 8; |
62 const int kForwardMouseButton = 9; | 64 const int kForwardMouseButton = 9; |
63 | 65 |
64 // These are the same values that are used to calibrate touch events in | |
65 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). | |
66 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) | |
67 const int kXRootWindowPaddingLeft = 40; | |
68 const int kXRootWindowPaddingRight = 40; | |
69 const int kXRootWindowPaddingBottom = 30; | |
70 const int kXRootWindowPaddingTop = 0; | |
71 | |
72 const char* kAtomsToCache[] = { | 66 const char* kAtomsToCache[] = { |
73 "WM_DELETE_WINDOW", | 67 "WM_DELETE_WINDOW", |
74 "_NET_WM_PING", | 68 "_NET_WM_PING", |
75 "_NET_WM_PID", | 69 "_NET_WM_PID", |
76 "WM_S0", | 70 "WM_S0", |
77 #if defined(OS_CHROMEOS) | 71 #if defined(OS_CHROMEOS) |
78 "Tap Paused", // Defined in the gestures library. | 72 "Tap Paused", // Defined in the gestures library. |
79 #endif | 73 #endif |
80 NULL | 74 NULL |
81 }; | 75 }; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 return true; | 160 return true; |
167 default: | 161 default: |
168 return false; | 162 return false; |
169 } | 163 } |
170 } | 164 } |
171 | 165 |
172 } // namespace | 166 } // namespace |
173 | 167 |
174 namespace internal { | 168 namespace internal { |
175 | 169 |
176 // A very lightweight message-pump observer that routes all the touch events to | 170 // Accomplishes 2 tasks concerning touch event calibration: |
177 // the X root window so that they can be calibrated properly. | 171 // 1. Being a message-pump observer, |
172 // routes all the touch events to the X root window, | |
173 // where they can be calibrated later. | |
174 // 2. Has the Calibrate method that does the actual bezel calibration, | |
175 // when invoked from X root window's event dispatcher. | |
178 class TouchEventCalibrate : public base::MessagePumpObserver { | 176 class TouchEventCalibrate : public base::MessagePumpObserver { |
179 public: | 177 public: |
180 TouchEventCalibrate() { | 178 TouchEventCalibrate() |
179 : left_(0), | |
180 right_(0), | |
181 top_(0), | |
182 bottom_(0) { | |
181 MessageLoopForUI::current()->AddObserver(this); | 183 MessageLoopForUI::current()->AddObserver(this); |
184 #if defined(USE_XI2_MT) | |
185 std::vector<std::string> parts; | |
186 if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
187 switches::kTouchCalibration), ",", &parts) >= 4) { | |
188 if (!base::StringToInt(parts[0], &left_)) | |
189 DLOG(ERROR) << "Incorrect left border calibration value passed."; | |
190 if (!base::StringToInt(parts[1], &right_)) | |
191 DLOG(ERROR) << "Incorrect right border calibration value passed."; | |
192 if (!base::StringToInt(parts[2], &top_)) | |
193 DLOG(ERROR) << "Incorrect top border calibration value passed."; | |
194 if (!base::StringToInt(parts[3], &bottom_)) | |
195 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; | |
196 } | |
197 #endif // defined(USE_XI2_MT) | |
182 } | 198 } |
183 | 199 |
184 virtual ~TouchEventCalibrate() { | 200 virtual ~TouchEventCalibrate() { |
185 MessageLoopForUI::current()->RemoveObserver(this); | 201 MessageLoopForUI::current()->RemoveObserver(this); |
186 } | 202 } |
187 | 203 |
204 // Modify the location of the |event|, | |
205 // expanding it from |bounds| to (|bounds| + bezels). | |
206 // Required when touchscreen is bigger than screen (i.e. has bezels), | |
207 // because we receive events in touchscreen coordinates, | |
208 // which need to be expanded when converting to screen coordinates, | |
209 // so that location on bezels will be outside of screen area. | |
210 void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) { | |
211 #if defined(USE_XI2_MT) | |
212 int x = event->x(); | |
213 int y = event->y(); | |
214 | |
215 if (!left_ && !right_ && !top_ && !bottom_) | |
216 return; | |
217 | |
218 const int resolution_x = bounds.width(); | |
219 const int resolution_y = bounds.height(); | |
220 // The "grace area" (10% in this case) is to make it easier for the user to | |
221 // navigate to the corner. | |
222 const double kGraceAreaFraction = 0.1; | |
223 if (left_ || right_) { | |
224 // Offset the x position to the real | |
225 x -= left_; | |
226 // Check if we are in the grace area of the left side. | |
227 // Note: We might not want to do this when the gesture is locked? | |
228 if (x < 0 && x > -left_ * kGraceAreaFraction) | |
229 x = 0; | |
230 // Check if we are in the grace area of the right side. | |
231 // Note: We might not want to do this when the gesture is locked? | |
232 if (x > resolution_x - left_ && | |
233 x < resolution_x - left_ + right_ * kGraceAreaFraction) | |
234 x = resolution_x - left_; | |
235 // Scale the screen area back to the full resolution of the screen. | |
236 x = (x * resolution_x) / (resolution_x - (right_ + left_)); | |
237 } | |
238 if (top_ || bottom_) { | |
239 // When there is a top bezel we add our border, | |
240 y -= top_; | |
241 | |
242 // Check if we are in the grace area of the top side. | |
243 // Note: We might not want to do this when the gesture is locked? | |
244 if (y < 0 && y > -top_ * kGraceAreaFraction) | |
245 y = 0; | |
246 | |
247 // Check if we are in the grace area of the bottom side. | |
248 // Note: We might not want to do this when the gesture is locked? | |
249 if (y > resolution_y - top_ && | |
250 y < resolution_y - top_ + bottom_ * kGraceAreaFraction) | |
251 y = resolution_y - top_; | |
252 // Scale the screen area back to the full resolution of the screen. | |
253 y = (y * resolution_y) / (resolution_y - (bottom_ + top_)); | |
254 } | |
255 | |
256 // Set the modified coordinate back to the event. | |
257 if (event->root_location() == event->location()) { | |
258 // Usually those will be equal, | |
259 // if not, I am not sure what the correct value should be. | |
260 event->set_root_location(gfx::Point(x, y)); | |
261 } | |
262 event->set_location(gfx::Point(x, y)); | |
263 #endif // defined(USE_XI2_MT) | |
264 } | |
265 | |
188 private: | 266 private: |
189 // Overridden from base::MessagePumpObserver: | 267 // Overridden from base::MessagePumpObserver: |
190 virtual base::EventStatus WillProcessEvent( | 268 virtual base::EventStatus WillProcessEvent( |
191 const base::NativeEvent& event) OVERRIDE { | 269 const base::NativeEvent& event) OVERRIDE { |
192 #if defined(USE_XI2_MT) | 270 #if defined(USE_XI2_MT) |
193 if (event->type == GenericEvent && | 271 if (event->type == GenericEvent && |
194 (event->xgeneric.evtype == XI_TouchBegin || | 272 (event->xgeneric.evtype == XI_TouchBegin || |
195 event->xgeneric.evtype == XI_TouchUpdate || | 273 event->xgeneric.evtype == XI_TouchUpdate || |
196 event->xgeneric.evtype == XI_TouchEnd)) { | 274 event->xgeneric.evtype == XI_TouchEnd)) { |
197 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data); | 275 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data); |
198 xievent->event = xievent->root; | 276 xievent->event = xievent->root; |
199 xievent->event_x = xievent->root_x; | 277 xievent->event_x = xievent->root_x; |
200 xievent->event_y = xievent->root_y; | 278 xievent->event_y = xievent->root_y; |
201 } | 279 } |
202 #endif | 280 #endif // defined(USE_XI2_MT) |
203 return base::EVENT_CONTINUE; | 281 return base::EVENT_CONTINUE; |
204 } | 282 } |
205 | 283 |
206 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { | 284 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { |
207 } | 285 } |
208 | 286 |
287 // The calibration values for the four border sides. | |
Ben Goodger (Google)
2013/03/18 22:21:33
What does calibration mean? What are these values
ynovikov
2013/03/19 19:35:16
Done.
| |
288 int left_; | |
289 int right_; | |
290 int top_; | |
291 int bottom_; | |
292 | |
209 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate); | 293 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate); |
210 }; | 294 }; |
211 | 295 |
212 } // namespace internal | 296 } // namespace internal |
213 | 297 |
214 //////////////////////////////////////////////////////////////////////////////// | 298 //////////////////////////////////////////////////////////////////////////////// |
215 // RootWindowHostLinux::MouseMoveFilter filters out the move events that | 299 // RootWindowHostLinux::MouseMoveFilter filters out the move events that |
216 // jump back and forth between two points. This happens when sub pixel mouse | 300 // jump back and forth between two points. This happens when sub pixel mouse |
217 // move is enabled and mouse move events could be jumping between two neighbor | 301 // move is enabled and mouse move events could be jumping between two neighbor |
218 // pixels, e.g. move(0,0), move(1,0), move(0,0), move(1,0) and on and on. | 302 // pixels, e.g. move(0,0), move(1,0), move(0,0), move(1,0) and on and on. |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
897 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); | 981 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); |
898 if (num_coalesced > 0) | 982 if (num_coalesced > 0) |
899 xev = &last_event; | 983 xev = &last_event; |
900 // fallthrough | 984 // fallthrough |
901 case ui::ET_TOUCH_PRESSED: | 985 case ui::ET_TOUCH_PRESSED: |
902 case ui::ET_TOUCH_CANCELLED: | 986 case ui::ET_TOUCH_CANCELLED: |
903 case ui::ET_TOUCH_RELEASED: { | 987 case ui::ET_TOUCH_RELEASED: { |
904 ui::TouchEvent touchev(xev); | 988 ui::TouchEvent touchev(xev); |
905 #if defined(OS_CHROMEOS) | 989 #if defined(OS_CHROMEOS) |
906 if (base::chromeos::IsRunningOnChromeOS()) { | 990 if (base::chromeos::IsRunningOnChromeOS()) { |
907 if (!bounds_.Contains(touchev.location())) { | 991 if (!bounds_.Contains(touchev.location())) |
908 // This might still be in the bezel region. | 992 break; |
909 gfx::Rect expanded(bounds_); | 993 // X maps the touch-surface to the size of the X root-window. |
910 expanded.Inset(-kXRootWindowPaddingLeft, | 994 // In multi-monitor setup, Coordinate Transformation Matrix |
911 -kXRootWindowPaddingTop, | 995 // repositions the touch-surface onto part of X root-window |
912 -kXRootWindowPaddingRight, | 996 // containing aura root-window corresponding to the touchscreen. |
913 -kXRootWindowPaddingBottom); | 997 // However, if aura root-window has non-zero origin, |
914 if (!expanded.Contains(touchev.location())) | 998 // we need to relocate the event into aura root-window coordinates. |
915 break; | 999 touchev.Relocate(bounds_.origin()); |
916 } | 1000 #if defined(USE_XI2_MT) |
1001 if (is_internal_display_) | |
1002 touch_calibrate_->Calibrate(&touchev, bounds_); | |
1003 #endif // defined(USE_XI2_MT) | |
917 } | 1004 } |
918 // X maps the touch-surface to the size of the X root-window. | |
919 // In multi-monitor setup, Coordinate Transformation Matrix | |
920 // repositions the touch-surface onto part of X root-window | |
921 // containing aura root-window corresponding to the touchscreen. | |
922 // However, if aura root-window has non-zero origin, | |
923 // we need to relocate the event into aura root-window coordinates. | |
924 touchev.Relocate(bounds_.origin()); | |
925 #endif // defined(OS_CHROMEOS) | 1005 #endif // defined(OS_CHROMEOS) |
926 delegate_->OnHostTouchEvent(&touchev); | 1006 delegate_->OnHostTouchEvent(&touchev); |
927 break; | 1007 break; |
928 } | 1008 } |
929 case ui::ET_MOUSE_MOVED: | 1009 case ui::ET_MOUSE_MOVED: |
930 case ui::ET_MOUSE_DRAGGED: | 1010 case ui::ET_MOUSE_DRAGGED: |
931 case ui::ET_MOUSE_PRESSED: | 1011 case ui::ET_MOUSE_PRESSED: |
932 case ui::ET_MOUSE_RELEASED: | 1012 case ui::ET_MOUSE_RELEASED: |
933 case ui::ET_MOUSE_ENTERED: | 1013 case ui::ET_MOUSE_ENTERED: |
934 case ui::ET_MOUSE_EXITED: { | 1014 case ui::ET_MOUSE_EXITED: { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1045 return new RootWindowHostLinux(bounds); | 1125 return new RootWindowHostLinux(bounds); |
1046 } | 1126 } |
1047 | 1127 |
1048 // static | 1128 // static |
1049 gfx::Size RootWindowHost::GetNativeScreenSize() { | 1129 gfx::Size RootWindowHost::GetNativeScreenSize() { |
1050 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 1130 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
1051 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 1131 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
1052 } | 1132 } |
1053 | 1133 |
1054 } // namespace aura | 1134 } // namespace aura |
OLD | NEW |