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 difference in screen's native resolution pixels between |
| 288 // the border of the touchscreen and the border of the screen, |
| 289 // aka bezel sizes. |
| 290 int left_; |
| 291 int right_; |
| 292 int top_; |
| 293 int bottom_; |
| 294 |
209 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate); | 295 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate); |
210 }; | 296 }; |
211 | 297 |
212 } // namespace internal | 298 } // namespace internal |
213 | 299 |
214 //////////////////////////////////////////////////////////////////////////////// | 300 //////////////////////////////////////////////////////////////////////////////// |
215 // RootWindowHostLinux::MouseMoveFilter filters out the move events that | 301 // RootWindowHostLinux::MouseMoveFilter filters out the move events that |
216 // jump back and forth between two points. This happens when sub pixel mouse | 302 // 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 | 303 // 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. | 304 // 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); | 983 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); |
898 if (num_coalesced > 0) | 984 if (num_coalesced > 0) |
899 xev = &last_event; | 985 xev = &last_event; |
900 // fallthrough | 986 // fallthrough |
901 case ui::ET_TOUCH_PRESSED: | 987 case ui::ET_TOUCH_PRESSED: |
902 case ui::ET_TOUCH_CANCELLED: | 988 case ui::ET_TOUCH_CANCELLED: |
903 case ui::ET_TOUCH_RELEASED: { | 989 case ui::ET_TOUCH_RELEASED: { |
904 ui::TouchEvent touchev(xev); | 990 ui::TouchEvent touchev(xev); |
905 #if defined(OS_CHROMEOS) | 991 #if defined(OS_CHROMEOS) |
906 if (base::chromeos::IsRunningOnChromeOS()) { | 992 if (base::chromeos::IsRunningOnChromeOS()) { |
907 if (!bounds_.Contains(touchev.location())) { | 993 if (!bounds_.Contains(touchev.location())) |
908 // This might still be in the bezel region. | 994 break; |
909 gfx::Rect expanded(bounds_); | 995 // X maps the touch-surface to the size of the X root-window. |
910 expanded.Inset(-kXRootWindowPaddingLeft, | 996 // In multi-monitor setup, Coordinate Transformation Matrix |
911 -kXRootWindowPaddingTop, | 997 // repositions the touch-surface onto part of X root-window |
912 -kXRootWindowPaddingRight, | 998 // containing aura root-window corresponding to the touchscreen. |
913 -kXRootWindowPaddingBottom); | 999 // However, if aura root-window has non-zero origin, |
914 if (!expanded.Contains(touchev.location())) | 1000 // we need to relocate the event into aura root-window coordinates. |
915 break; | 1001 touchev.Relocate(bounds_.origin()); |
916 } | 1002 #if defined(USE_XI2_MT) |
| 1003 if (is_internal_display_) |
| 1004 touch_calibrate_->Calibrate(&touchev, bounds_); |
| 1005 #endif // defined(USE_XI2_MT) |
917 } | 1006 } |
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) | 1007 #endif // defined(OS_CHROMEOS) |
926 delegate_->OnHostTouchEvent(&touchev); | 1008 delegate_->OnHostTouchEvent(&touchev); |
927 break; | 1009 break; |
928 } | 1010 } |
929 case ui::ET_MOUSE_MOVED: | 1011 case ui::ET_MOUSE_MOVED: |
930 case ui::ET_MOUSE_DRAGGED: | 1012 case ui::ET_MOUSE_DRAGGED: |
931 case ui::ET_MOUSE_PRESSED: | 1013 case ui::ET_MOUSE_PRESSED: |
932 case ui::ET_MOUSE_RELEASED: | 1014 case ui::ET_MOUSE_RELEASED: |
933 case ui::ET_MOUSE_ENTERED: | 1015 case ui::ET_MOUSE_ENTERED: |
934 case ui::ET_MOUSE_EXITED: { | 1016 case ui::ET_MOUSE_EXITED: { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1045 return new RootWindowHostLinux(bounds); | 1127 return new RootWindowHostLinux(bounds); |
1046 } | 1128 } |
1047 | 1129 |
1048 // static | 1130 // static |
1049 gfx::Size RootWindowHost::GetNativeScreenSize() { | 1131 gfx::Size RootWindowHost::GetNativeScreenSize() { |
1050 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 1132 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
1051 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 1133 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
1052 } | 1134 } |
1053 | 1135 |
1054 } // namespace aura | 1136 } // namespace aura |
OLD | NEW |