| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/platform_window/x11/x11_window.h" | 5 #include "ui/platform_window/x11/x11_window.h" |
| 6 | 6 |
| 7 #include <X11/extensions/XInput2.h> | 7 #include <X11/extensions/XInput2.h> |
| 8 #include <X11/Xatom.h> | 8 #include <X11/Xatom.h> |
| 9 #include <X11/Xlib.h> | 9 #include <X11/Xlib.h> |
| 10 #include <X11/Xutil.h> | 10 #include <X11/Xutil.h> |
| 11 | 11 |
| 12 #include "base/bind.h" |
| 12 #include "ui/events/devices/x11/touch_factory_x11.h" | 13 #include "ui/events/devices/x11/touch_factory_x11.h" |
| 13 #include "ui/events/event.h" | 14 #include "ui/events/event.h" |
| 14 #include "ui/events/event_utils.h" | 15 #include "ui/events/event_utils.h" |
| 16 #include "ui/events/ozone/events_ozone.h" |
| 15 #include "ui/events/platform/platform_event_dispatcher.h" | 17 #include "ui/events/platform/platform_event_dispatcher.h" |
| 16 #include "ui/events/platform/platform_event_source.h" | 18 #include "ui/events/platform/platform_event_source.h" |
| 17 #include "ui/events/platform/x11/x11_event_source.h" | 19 #include "ui/events/platform/x11/x11_event_source.h" |
| 18 #include "ui/gfx/geometry/rect.h" | 20 #include "ui/gfx/geometry/rect.h" |
| 19 #include "ui/gfx/x/x11_atom_cache.h" | 21 #include "ui/gfx/x/x11_atom_cache.h" |
| 20 #include "ui/gfx/x/x11_types.h" | 22 #include "ui/gfx/x/x11_types.h" |
| 21 #include "ui/platform_window/platform_window_delegate.h" | 23 #include "ui/platform_window/platform_window_delegate.h" |
| 22 | 24 |
| 23 namespace ui { | 25 namespace ui { |
| 24 | 26 |
| 25 namespace { | 27 namespace { |
| 26 | 28 |
| 27 const char* kAtomsToCache[] = { | 29 const char* kAtomsToCache[] = { |
| 28 "WM_DELETE_WINDOW", | 30 "WM_DELETE_WINDOW", |
| 29 "_NET_WM_PING", | 31 "_NET_WM_PING", |
| 30 "_NET_WM_PID", | 32 "_NET_WM_PID", |
| 31 NULL | 33 NULL |
| 32 }; | 34 }; |
| 33 | 35 |
| 34 XID FindXEventTarget(XEvent* xevent) { | 36 } // namespace |
| 35 XID target = xevent->xany.window; | 37 |
| 36 if (xevent->type == GenericEvent) | 38 X11WindowManager::X11WindowManager() { |
| 37 target = static_cast<XIDeviceEvent*>(xevent->xcookie.data)->event; | 39 } |
| 38 return target; | 40 X11WindowManager::~X11WindowManager() { |
| 39 } | 41 } |
| 40 | 42 |
| 41 } // namespace | 43 scoped_ptr<X11Window> X11WindowManager::CreatePlatformWindow( |
| 44 PlatformWindowDelegate* delegate) { |
| 45 return scoped_ptr<X11Window>(new X11Window( |
| 46 delegate, base::Bind(&X11WindowManager::OnWindowCreate, this), |
| 47 base::Bind(&X11WindowManager::OnWindowDestroy, this))); |
| 48 } |
| 42 | 49 |
| 43 X11Window::X11Window(PlatformWindowDelegate* delegate) | 50 X11Window* X11WindowManager::FindWindow(XID id) { |
| 51 auto iter = window_map_.find(id); |
| 52 if (iter == window_map_.end()) |
| 53 return nullptr; |
| 54 return iter->second; |
| 55 } |
| 56 |
| 57 void X11WindowManager::OnWindowCreate(XID id, X11Window* window) { |
| 58 window_map_[id] = window; |
| 59 } |
| 60 |
| 61 void X11WindowManager::OnWindowDestroy(XID id, X11Window* window) { |
| 62 window_map_.erase(id); |
| 63 } |
| 64 |
| 65 X11Window::X11Window(PlatformWindowDelegate* delegate, |
| 66 WindowStatusCallback on_create_callback, |
| 67 WindowStatusCallback on_destroy_callback) |
| 44 : delegate_(delegate), | 68 : delegate_(delegate), |
| 69 on_create_callback_(on_create_callback), |
| 70 on_destroy_callback_(on_destroy_callback), |
| 45 xdisplay_(gfx::GetXDisplay()), | 71 xdisplay_(gfx::GetXDisplay()), |
| 46 xwindow_(None), | 72 xwindow_(None), |
| 47 xroot_window_(DefaultRootWindow(xdisplay_)), | 73 xroot_window_(DefaultRootWindow(xdisplay_)), |
| 48 atom_cache_(xdisplay_, kAtomsToCache), | 74 atom_cache_(xdisplay_, kAtomsToCache), |
| 49 window_mapped_(false) { | 75 window_mapped_(false) { |
| 50 CHECK(delegate_); | 76 CHECK(delegate_); |
| 51 TouchFactory::SetTouchDeviceListFromCommandLine(); | 77 TouchFactory::SetTouchDeviceListFromCommandLine(); |
| 52 } | 78 } |
| 53 | 79 |
| 54 X11Window::~X11Window() { | 80 X11Window::~X11Window() { |
| 55 Destroy(); | 81 Destroy(); |
| 56 } | 82 } |
| 57 | 83 |
| 58 void X11Window::Destroy() { | 84 void X11Window::Destroy() { |
| 59 delegate_->OnClosed(); | 85 delegate_->OnClosed(); |
| 60 if (xwindow_ == None) | 86 if (xwindow_ == None) |
| 61 return; | 87 return; |
| 62 | 88 |
| 63 // Stop processing events. | 89 // Stop processing events. |
| 90 on_destroy_callback_.Run(xwindow_, this); |
| 64 PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); | 91 PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); |
| 65 XDestroyWindow(xdisplay_, xwindow_); | 92 XDestroyWindow(xdisplay_, xwindow_); |
| 66 xwindow_ = None; | 93 xwindow_ = None; |
| 67 } | 94 } |
| 68 | 95 |
| 69 void X11Window::ProcessXInput2Event(XEvent* xev) { | 96 void X11Window::Create() { |
| 70 if (!TouchFactory::GetInstance()->ShouldProcessXI2Event(xev)) | |
| 71 return; | |
| 72 EventType event_type = EventTypeFromNative(xev); | |
| 73 switch (event_type) { | |
| 74 case ET_KEY_PRESSED: | |
| 75 case ET_KEY_RELEASED: { | |
| 76 KeyEvent key_event(xev); | |
| 77 delegate_->DispatchEvent(&key_event); | |
| 78 break; | |
| 79 } | |
| 80 case ET_MOUSE_PRESSED: | |
| 81 case ET_MOUSE_MOVED: | |
| 82 case ET_MOUSE_DRAGGED: | |
| 83 case ET_MOUSE_RELEASED: { | |
| 84 MouseEvent mouse_event(xev); | |
| 85 delegate_->DispatchEvent(&mouse_event); | |
| 86 break; | |
| 87 } | |
| 88 case ET_MOUSEWHEEL: { | |
| 89 MouseWheelEvent wheel_event(xev); | |
| 90 delegate_->DispatchEvent(&wheel_event); | |
| 91 break; | |
| 92 } | |
| 93 case ET_SCROLL_FLING_START: | |
| 94 case ET_SCROLL_FLING_CANCEL: | |
| 95 case ET_SCROLL: { | |
| 96 ScrollEvent scroll_event(xev); | |
| 97 delegate_->DispatchEvent(&scroll_event); | |
| 98 break; | |
| 99 } | |
| 100 case ET_TOUCH_MOVED: | |
| 101 case ET_TOUCH_PRESSED: | |
| 102 case ET_TOUCH_CANCELLED: | |
| 103 case ET_TOUCH_RELEASED: { | |
| 104 TouchEvent touch_event(xev); | |
| 105 delegate_->DispatchEvent(&touch_event); | |
| 106 break; | |
| 107 } | |
| 108 default: | |
| 109 break; | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 void X11Window::Show() { | |
| 114 if (window_mapped_) | |
| 115 return; | |
| 116 | |
| 117 CHECK(PlatformEventSource::GetInstance()); | 97 CHECK(PlatformEventSource::GetInstance()); |
| 118 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); | 98 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); |
| 119 | 99 |
| 120 XSetWindowAttributes swa; | 100 XSetWindowAttributes swa; |
| 121 memset(&swa, 0, sizeof(swa)); | 101 memset(&swa, 0, sizeof(swa)); |
| 122 swa.background_pixmap = None; | 102 swa.background_pixmap = None; |
| 123 swa.override_redirect = False; | 103 swa.override_redirect = False; |
| 124 xwindow_ = XCreateWindow(xdisplay_, | 104 xwindow_ = XCreateWindow(xdisplay_, |
| 125 xroot_window_, | 105 xroot_window_, |
| 126 requested_bounds_.x(), | 106 requested_bounds_.x(), |
| 127 requested_bounds_.y(), | 107 requested_bounds_.y(), |
| 128 requested_bounds_.width(), | 108 requested_bounds_.width(), |
| 129 requested_bounds_.height(), | 109 requested_bounds_.height(), |
| 130 0, // border width | 110 0, // border width |
| 131 CopyFromParent, // depth | 111 CopyFromParent, // depth |
| 132 InputOutput, | 112 InputOutput, |
| 133 CopyFromParent, // visual | 113 CopyFromParent, // visual |
| 134 CWBackPixmap | CWOverrideRedirect, | 114 CWBackPixmap | CWOverrideRedirect, |
| 135 &swa); | 115 &swa); |
| 116 on_create_callback_.Run(xwindow_, this); |
| 136 | 117 |
| 137 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 118 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
| 138 KeyPressMask | KeyReleaseMask | EnterWindowMask | | 119 KeyPressMask | KeyReleaseMask | EnterWindowMask | |
| 139 LeaveWindowMask | ExposureMask | VisibilityChangeMask | | 120 LeaveWindowMask | ExposureMask | VisibilityChangeMask | |
| 140 StructureNotifyMask | PropertyChangeMask | | 121 StructureNotifyMask | PropertyChangeMask | |
| 141 PointerMotionMask; | 122 PointerMotionMask; |
| 142 XSelectInput(xdisplay_, xwindow_, event_mask); | 123 XSelectInput(xdisplay_, xwindow_, event_mask); |
| 143 | 124 |
| 144 unsigned char mask[XIMaskLen(XI_LASTEVENT)]; | 125 unsigned char mask[XIMaskLen(XI_LASTEVENT)]; |
| 145 memset(mask, 0, sizeof(mask)); | 126 memset(mask, 0, sizeof(mask)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 XSizeHints size_hints; | 169 XSizeHints size_hints; |
| 189 size_hints.flags = PPosition | PWinGravity; | 170 size_hints.flags = PPosition | PWinGravity; |
| 190 size_hints.x = requested_bounds_.x(); | 171 size_hints.x = requested_bounds_.x(); |
| 191 size_hints.y = requested_bounds_.y(); | 172 size_hints.y = requested_bounds_.y(); |
| 192 // Set StaticGravity so that the window position is not affected by the | 173 // Set StaticGravity so that the window position is not affected by the |
| 193 // frame width when running with window manager. | 174 // frame width when running with window manager. |
| 194 size_hints.win_gravity = StaticGravity; | 175 size_hints.win_gravity = StaticGravity; |
| 195 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); | 176 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); |
| 196 | 177 |
| 197 delegate_->OnAcceleratedWidgetAvailable(xwindow_); | 178 delegate_->OnAcceleratedWidgetAvailable(xwindow_); |
| 179 } |
| 180 |
| 181 void X11Window::Show() { |
| 182 if (window_mapped_) |
| 183 return; |
| 184 if (xwindow_ == None) |
| 185 Create(); |
| 198 | 186 |
| 199 XMapWindow(xdisplay_, xwindow_); | 187 XMapWindow(xdisplay_, xwindow_); |
| 200 | 188 |
| 201 // We now block until our window is mapped. Some X11 APIs will crash and | 189 // We now block until our window is mapped. Some X11 APIs will crash and |
| 202 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is | 190 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is |
| 203 // asynchronous. | 191 // asynchronous. |
| 204 if (X11EventSource::GetInstance()) | 192 if (X11EventSource::GetInstance()) |
| 205 X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_); | 193 X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_); |
| 206 window_mapped_ = true; | 194 window_mapped_ = true; |
| 207 } | 195 } |
| 208 | 196 |
| 209 void X11Window::Hide() { | 197 void X11Window::Hide() { |
| 210 if (!window_mapped_) | 198 if (!window_mapped_) |
| 211 return; | 199 return; |
| 212 XWithdrawWindow(xdisplay_, xwindow_, 0); | 200 XWithdrawWindow(xdisplay_, xwindow_, 0); |
| 213 window_mapped_ = false; | 201 window_mapped_ = false; |
| 214 } | 202 } |
| 215 | 203 |
| 216 void X11Window::Close() { | 204 void X11Window::Close() { |
| 217 Destroy(); | 205 Destroy(); |
| 218 } | 206 } |
| 219 | 207 |
| 220 void X11Window::SetBounds(const gfx::Rect& bounds) { | 208 void X11Window::SetBounds(const gfx::Rect& bounds) { |
| 221 requested_bounds_ = bounds; | 209 requested_bounds_ = bounds; |
| 222 if (!window_mapped_) | 210 if (!window_mapped_ || bounds == confirmed_bounds_) |
| 223 return; | 211 return; |
| 224 XWindowChanges changes = {0}; | 212 XWindowChanges changes = {0}; |
| 225 unsigned value_mask = CWX | CWY | CWWidth | CWHeight; | 213 unsigned value_mask = CWX | CWY | CWWidth | CWHeight; |
| 226 changes.x = bounds.x(); | 214 changes.x = bounds.x(); |
| 227 changes.y = bounds.y(); | 215 changes.y = bounds.y(); |
| 228 changes.width = bounds.width(); | 216 changes.width = bounds.width(); |
| 229 changes.height = bounds.height(); | 217 changes.height = bounds.height(); |
| 230 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); | 218 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); |
| 231 } | 219 } |
| 232 | 220 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 244 | 232 |
| 245 void X11Window::Minimize() {} | 233 void X11Window::Minimize() {} |
| 246 | 234 |
| 247 void X11Window::Restore() {} | 235 void X11Window::Restore() {} |
| 248 | 236 |
| 249 void X11Window::SetCursor(PlatformCursor cursor) {} | 237 void X11Window::SetCursor(PlatformCursor cursor) {} |
| 250 | 238 |
| 251 void X11Window::MoveCursorTo(const gfx::Point& location) {} | 239 void X11Window::MoveCursorTo(const gfx::Point& location) {} |
| 252 | 240 |
| 253 bool X11Window::CanDispatchEvent(const PlatformEvent& event) { | 241 bool X11Window::CanDispatchEvent(const PlatformEvent& event) { |
| 254 return FindXEventTarget(event) == xwindow_; | 242 return true; |
| 255 } | 243 } |
| 256 | 244 |
| 257 uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { | 245 void X11Window::ProcessWindowEvent(XEvent* xev) { |
| 258 XEvent* xev = event; | |
| 259 switch (xev->type) { | 246 switch (xev->type) { |
| 260 case EnterNotify: { | |
| 261 // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is | |
| 262 // not real mouse move event. | |
| 263 MouseEvent mouse_event(xev); | |
| 264 CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type()); | |
| 265 mouse_event.set_flags(mouse_event.flags() | EF_IS_SYNTHESIZED); | |
| 266 delegate_->DispatchEvent(&mouse_event); | |
| 267 break; | |
| 268 } | |
| 269 case LeaveNotify: { | |
| 270 MouseEvent mouse_event(xev); | |
| 271 delegate_->DispatchEvent(&mouse_event); | |
| 272 break; | |
| 273 } | |
| 274 | |
| 275 case Expose: { | 247 case Expose: { |
| 276 gfx::Rect damage_rect(xev->xexpose.x, | 248 gfx::Rect damage_rect(xev->xexpose.x, |
| 277 xev->xexpose.y, | 249 xev->xexpose.y, |
| 278 xev->xexpose.width, | 250 xev->xexpose.width, |
| 279 xev->xexpose.height); | 251 xev->xexpose.height); |
| 280 delegate_->OnDamageRect(damage_rect); | 252 delegate_->OnDamageRect(damage_rect); |
| 281 break; | 253 break; |
| 282 } | 254 } |
| 283 | 255 |
| 284 case KeyPress: | |
| 285 case KeyRelease: { | |
| 286 KeyEvent key_event(xev); | |
| 287 delegate_->DispatchEvent(&key_event); | |
| 288 break; | |
| 289 } | |
| 290 | |
| 291 case ButtonPress: | |
| 292 case ButtonRelease: { | |
| 293 switch (EventTypeFromNative(xev)) { | |
| 294 case ET_MOUSEWHEEL: { | |
| 295 MouseWheelEvent mouseev(xev); | |
| 296 delegate_->DispatchEvent(&mouseev); | |
| 297 break; | |
| 298 } | |
| 299 case ET_MOUSE_PRESSED: | |
| 300 case ET_MOUSE_RELEASED: { | |
| 301 MouseEvent mouseev(xev); | |
| 302 delegate_->DispatchEvent(&mouseev); | |
| 303 break; | |
| 304 } | |
| 305 case ET_UNKNOWN: | |
| 306 // No event is created for X11-release events for mouse-wheel | |
| 307 // buttons. | |
| 308 break; | |
| 309 default: | |
| 310 NOTREACHED(); | |
| 311 } | |
| 312 break; | |
| 313 } | |
| 314 | |
| 315 case FocusOut: | 256 case FocusOut: |
| 316 if (xev->xfocus.mode != NotifyGrab) | 257 if (xev->xfocus.mode != NotifyGrab) |
| 317 delegate_->OnLostCapture(); | 258 delegate_->OnLostCapture(); |
| 318 break; | 259 break; |
| 319 | 260 |
| 320 case ConfigureNotify: { | 261 case ConfigureNotify: { |
| 321 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 262 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 322 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 263 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 323 gfx::Rect bounds(xev->xconfigure.x, | 264 gfx::Rect bounds(xev->xconfigure.x, |
| 324 xev->xconfigure.y, | 265 xev->xconfigure.y, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 341 | 282 |
| 342 XSendEvent(xdisplay_, | 283 XSendEvent(xdisplay_, |
| 343 reply_event.xclient.window, | 284 reply_event.xclient.window, |
| 344 False, | 285 False, |
| 345 SubstructureRedirectMask | SubstructureNotifyMask, | 286 SubstructureRedirectMask | SubstructureNotifyMask, |
| 346 &reply_event); | 287 &reply_event); |
| 347 XFlush(xdisplay_); | 288 XFlush(xdisplay_); |
| 348 } | 289 } |
| 349 break; | 290 break; |
| 350 } | 291 } |
| 292 } |
| 293 } |
| 351 | 294 |
| 352 case GenericEvent: { | 295 uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { |
| 353 ProcessXInput2Event(xev); | 296 DispatchEventFromNativeUiEvent( |
| 354 break; | 297 event, base::Bind(&PlatformWindowDelegate::DispatchEvent, |
| 355 } | 298 base::Unretained(delegate_))); |
| 356 } | 299 |
| 357 return POST_DISPATCH_STOP_PROPAGATION; | 300 return POST_DISPATCH_STOP_PROPAGATION; |
| 358 } | 301 } |
| 359 | 302 |
| 360 } // namespace ui | 303 } // namespace ui |
| OLD | NEW |