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 |