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/views/widget/desktop_aura/desktop_window_tree_host_x11.h" | 5 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" |
6 | 6 |
7 #include <X11/extensions/shape.h> | 7 #include <X11/extensions/shape.h> |
8 #include <X11/extensions/XInput2.h> | 8 #include <X11/extensions/XInput2.h> |
9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
10 #include <X11/Xregion.h> | 10 #include <X11/Xregion.h> |
11 #include <X11/Xutil.h> | 11 #include <X11/Xutil.h> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
15 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
18 #include "third_party/skia/include/core/SkPath.h" | 18 #include "third_party/skia/include/core/SkPath.h" |
19 #include "ui/aura/client/cursor_client.h" | 19 #include "ui/aura/client/cursor_client.h" |
20 #include "ui/aura/client/focus_client.h" | 20 #include "ui/aura/client/focus_client.h" |
21 #include "ui/aura/client/screen_position_client.h" | |
21 #include "ui/aura/window.h" | 22 #include "ui/aura/window.h" |
22 #include "ui/aura/window_event_dispatcher.h" | 23 #include "ui/aura/window_event_dispatcher.h" |
23 #include "ui/aura/window_property.h" | 24 #include "ui/aura/window_property.h" |
24 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" | 25 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" |
25 #include "ui/base/hit_test.h" | 26 #include "ui/base/hit_test.h" |
26 #include "ui/base/x/x11_util.h" | 27 #include "ui/base/x/x11_util.h" |
27 #include "ui/events/event_utils.h" | 28 #include "ui/events/event_utils.h" |
28 #include "ui/events/platform/platform_event_source.h" | 29 #include "ui/events/platform/platform_event_source.h" |
29 #include "ui/events/platform/x11/x11_event_source.h" | 30 #include "ui/events/platform/x11/x11_event_source.h" |
30 #include "ui/events/x/device_data_manager_x11.h" | 31 #include "ui/events/x/device_data_manager_x11.h" |
31 #include "ui/events/x/device_list_cache_x.h" | 32 #include "ui/events/x/device_list_cache_x.h" |
32 #include "ui/events/x/touch_factory_x11.h" | 33 #include "ui/events/x/touch_factory_x11.h" |
33 #include "ui/gfx/image/image_skia.h" | 34 #include "ui/gfx/image/image_skia.h" |
34 #include "ui/gfx/image/image_skia_rep.h" | 35 #include "ui/gfx/image/image_skia_rep.h" |
35 #include "ui/gfx/insets.h" | 36 #include "ui/gfx/insets.h" |
36 #include "ui/gfx/path.h" | 37 #include "ui/gfx/path.h" |
37 #include "ui/gfx/path_x11.h" | 38 #include "ui/gfx/path_x11.h" |
38 #include "ui/gfx/screen.h" | 39 #include "ui/gfx/screen.h" |
39 #include "ui/native_theme/native_theme.h" | 40 #include "ui/native_theme/native_theme.h" |
40 #include "ui/views/corewm/tooltip_aura.h" | 41 #include "ui/views/corewm/tooltip_aura.h" |
41 #include "ui/views/ime/input_method.h" | 42 #include "ui/views/ime/input_method.h" |
42 #include "ui/views/linux_ui/linux_ui.h" | 43 #include "ui/views/linux_ui/linux_ui.h" |
43 #include "ui/views/views_delegate.h" | 44 #include "ui/views/views_delegate.h" |
44 #include "ui/views/views_switches.h" | 45 #include "ui/views/views_switches.h" |
45 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" | 46 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" |
46 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" | 47 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" |
47 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" | 48 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" |
48 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h" | 49 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h" |
50 #include "ui/views/widget/desktop_aura/x11_capture_window.h" | |
49 #include "ui/views/widget/desktop_aura/x11_desktop_handler.h" | 51 #include "ui/views/widget/desktop_aura/x11_desktop_handler.h" |
50 #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h" | 52 #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h" |
51 #include "ui/views/widget/desktop_aura/x11_scoped_capture.h" | |
52 #include "ui/views/widget/desktop_aura/x11_window_event_filter.h" | 53 #include "ui/views/widget/desktop_aura/x11_window_event_filter.h" |
53 #include "ui/wm/core/compound_event_filter.h" | 54 #include "ui/wm/core/compound_event_filter.h" |
54 #include "ui/wm/core/window_util.h" | 55 #include "ui/wm/core/window_util.h" |
55 | 56 |
56 namespace views { | 57 namespace views { |
57 | 58 |
58 DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::g_current_capture = | 59 DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::g_current_capture = |
59 NULL; | 60 NULL; |
60 std::list<XID>* DesktopWindowTreeHostX11::open_windows_ = NULL; | 61 std::list<XID>* DesktopWindowTreeHostX11::open_windows_ = NULL; |
61 | 62 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 "XdndFinished", | 115 "XdndFinished", |
115 "XdndLeave", | 116 "XdndLeave", |
116 "XdndPosition", | 117 "XdndPosition", |
117 "XdndProxy", // Proxy windows? | 118 "XdndProxy", // Proxy windows? |
118 "XdndSelection", | 119 "XdndSelection", |
119 "XdndStatus", | 120 "XdndStatus", |
120 "XdndTypeList", | 121 "XdndTypeList", |
121 NULL | 122 NULL |
122 }; | 123 }; |
123 | 124 |
125 // Returns |native_event|'s target. | |
126 XID EventTargetFromNative(const base::NativeEvent& native_event) { | |
127 return (native_event->type == GenericEvent) ? | |
128 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->event : | |
129 native_event->xany.window; | |
130 } | |
131 | |
124 } // namespace | 132 } // namespace |
125 | 133 |
126 //////////////////////////////////////////////////////////////////////////////// | 134 //////////////////////////////////////////////////////////////////////////////// |
127 // DesktopWindowTreeHostX11, public: | 135 // DesktopWindowTreeHostX11, public: |
128 | 136 |
129 DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( | 137 DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( |
130 internal::NativeWidgetDelegate* native_widget_delegate, | 138 internal::NativeWidgetDelegate* native_widget_delegate, |
131 DesktopNativeWidgetAura* desktop_native_widget_aura) | 139 DesktopNativeWidgetAura* desktop_native_widget_aura) |
132 : close_widget_factory_(this), | 140 : close_widget_factory_(this), |
133 xdisplay_(gfx::GetXDisplay()), | 141 xdisplay_(gfx::GetXDisplay()), |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 OnHostResized(bounds.size()); | 904 OnHostResized(bounds.size()); |
897 ResetWindowRegion(); | 905 ResetWindowRegion(); |
898 } | 906 } |
899 } | 907 } |
900 | 908 |
901 gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { | 909 gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { |
902 return bounds_.origin(); | 910 return bounds_.origin(); |
903 } | 911 } |
904 | 912 |
905 void DesktopWindowTreeHostX11::SetCapture() { | 913 void DesktopWindowTreeHostX11::SetCapture() { |
906 // This is vaguely based on the old NativeWidgetGtk implementation. | 914 DesktopWindowTreeHostX11* old_capture = g_current_capture; |
907 // | 915 g_current_capture = this; |
908 // X11's XPointerGrab() shouldn't be used for everything; it doesn't map | 916 if (old_capture) { |
909 // cleanly to Windows' SetCapture(). GTK only provides a separate concept of | 917 // Take ownership of |old_capture|'s capture window which already has a |
910 // a grab that wasn't the X11 pointer grab, but was instead a manual | 918 // mouse grab. Because there is no X11 mouse grab or mouse ungrab, the |
911 // redirection of the event. (You need to drop into GDK if you want to | 919 // capture change is sychronous. |
912 // perform a raw X11 grab). | 920 capture_window_ = old_capture->ReleaseCaptureWindow().Pass(); |
913 | 921 |
914 if (g_current_capture) | 922 old_capture->OnHostLostWindowCapture(); |
915 g_current_capture->OnCaptureReleased(); | 923 } |
916 | 924 |
917 g_current_capture = this; | 925 if (!capture_window_) { |
918 x11_capture_.reset(new X11ScopedCapture(xwindow_)); | 926 // Create an X11CaptureWindow to asynchronously grab the mouse. As |
927 // |xwindow_| is likely the topmost window underneath the mouse, we will | |
928 // likely not miss any mouse events. | |
929 capture_window_.reset(new X11CaptureWindow); | |
930 } | |
919 } | 931 } |
920 | 932 |
921 void DesktopWindowTreeHostX11::ReleaseCapture() { | 933 void DesktopWindowTreeHostX11::ReleaseCapture() { |
922 if (g_current_capture == this) | 934 if (g_current_capture == this) { |
923 g_current_capture->OnCaptureReleased(); | 935 // Release mouse grab asynchronously. |xwindow_| is likely the topmost |
936 // window underneath the mouse so the capture release being asynchronous is | |
937 // likely inconsequential. | |
938 g_current_capture = NULL; | |
939 capture_window_.reset(); | |
940 | |
941 OnHostLostWindowCapture(); | |
942 } | |
924 } | 943 } |
925 | 944 |
926 void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) { | 945 void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) { |
927 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); | 946 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); |
928 } | 947 } |
929 | 948 |
930 void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) { | 949 void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) { |
931 XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0, | 950 XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0, |
932 bounds_.x() + location.x(), bounds_.y() + location.y()); | 951 bounds_.x() + location.x(), bounds_.y() + location.y()); |
933 } | 952 } |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1326 return window_properties_.find(atom_cache_.GetAtom(property)) != | 1345 return window_properties_.find(atom_cache_.GetAtom(property)) != |
1327 window_properties_.end(); | 1346 window_properties_.end(); |
1328 } | 1347 } |
1329 | 1348 |
1330 void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) { | 1349 void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) { |
1331 use_native_frame_ = use_native_frame; | 1350 use_native_frame_ = use_native_frame; |
1332 ui::SetUseOSWindowFrame(xwindow_, use_native_frame); | 1351 ui::SetUseOSWindowFrame(xwindow_, use_native_frame); |
1333 ResetWindowRegion(); | 1352 ResetWindowRegion(); |
1334 } | 1353 } |
1335 | 1354 |
1336 void DesktopWindowTreeHostX11::OnCaptureReleased() { | 1355 scoped_ptr<X11CaptureWindow> DesktopWindowTreeHostX11::ReleaseCaptureWindow() { |
1337 x11_capture_.reset(); | 1356 return capture_window_.Pass(); |
1338 g_current_capture = NULL; | |
1339 OnHostLostWindowCapture(); | |
1340 } | 1357 } |
1341 | 1358 |
1342 void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) { | 1359 void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) { |
1343 // In Windows, the native events sent to chrome are separated into client | 1360 // In Windows, the native events sent to chrome are separated into client |
1344 // and non-client versions of events, which we record on our LocatedEvent | 1361 // and non-client versions of events, which we record on our LocatedEvent |
1345 // structures. On X11, we emulate the concept of non-client. Before we pass | 1362 // structures. On X11, we emulate the concept of non-client. Before we pass |
1346 // this event to the cross platform event handling framework, we need to | 1363 // this event to the cross platform event handling framework, we need to |
1347 // make sure it is appropriately marked as non-client if it's in the non | 1364 // make sure it is appropriately marked as non-client if it's in the non |
1348 // client area, or otherwise, we can get into a state where the a window is | 1365 // client area, or otherwise, we can get into a state where the a window is |
1349 // set as the |mouse_pressed_handler_| in window_event_dispatcher.cc | 1366 // set as the |mouse_pressed_handler_| in window_event_dispatcher.cc |
(...skipping 13 matching lines...) Expand all Loading... | |
1363 if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE) | 1380 if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE) |
1364 flags |= ui::EF_IS_NON_CLIENT; | 1381 flags |= ui::EF_IS_NON_CLIENT; |
1365 event->set_flags(flags); | 1382 event->set_flags(flags); |
1366 } | 1383 } |
1367 | 1384 |
1368 // While we unset the urgency hint when we gain focus, we also must remove it | 1385 // While we unset the urgency hint when we gain focus, we also must remove it |
1369 // on mouse clicks because we can call FlashFrame() on an active window. | 1386 // on mouse clicks because we can call FlashFrame() on an active window. |
1370 if (event->IsAnyButton() || event->IsMouseWheelEvent()) | 1387 if (event->IsAnyButton() || event->IsMouseWheelEvent()) |
1371 FlashFrame(false); | 1388 FlashFrame(false); |
1372 | 1389 |
1390 if (EventTargetFromNative(event->native_event()) != xwindow_) { | |
1391 // The event was targeted at |capture_window_|'s X window. | |
1392 gfx::Point location = | |
1393 ui::EventSystemLocationFromNative(event->native_event()); | |
1394 aura::client::GetScreenPositionClient(window())->ConvertPointFromScreen( | |
1395 window(), &location); | |
1396 event->set_root_location(location); | |
1397 event->set_location(location); | |
1398 } | |
1399 | |
1373 if (!g_current_capture || g_current_capture == this) { | 1400 if (!g_current_capture || g_current_capture == this) { |
1374 SendEventToProcessor(event); | 1401 SendEventToProcessor(event); |
1375 } else { | 1402 } else { |
1376 // Another DesktopWindowTreeHostX11 has installed itself as | 1403 // Another DesktopWindowTreeHostX11 has capture. Translate the event's |
1377 // capture. Translate the event's location and dispatch to the other. | 1404 // location and dispatch to the other DesktopWindowTreeHostX11. |
1378 event->ConvertLocationToTarget(window(), g_current_capture->window()); | 1405 gfx::Point location = event->location(); |
1406 aura::Window::ConvertPointToTarget(window(), | |
1407 g_current_capture->window(), | |
1408 &location); | |
1409 event->set_root_location(location); | |
1410 event->set_location(location); | |
sadrul
2014/07/29 18:47:50
ConvertLocationToTarget() should work correctly he
pkotwicz
2014/08/01 03:35:00
I am splitting this change out to a different CL b
pkotwicz
2014/08/01 04:32:14
You are right ConvertLocationToTarget() does work
| |
1379 g_current_capture->SendEventToProcessor(event); | 1411 g_current_capture->SendEventToProcessor(event); |
1380 } | 1412 } |
1381 } | 1413 } |
1382 | 1414 |
1383 void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) { | 1415 void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) { |
1416 DCHECK_EQ(EventTargetFromNative(event->native_event()), xwindow_); | |
1384 if (g_current_capture && g_current_capture != this && | 1417 if (g_current_capture && g_current_capture != this && |
1385 event->type() == ui::ET_TOUCH_PRESSED) { | 1418 event->type() == ui::ET_TOUCH_PRESSED) { |
1386 event->ConvertLocationToTarget(window(), g_current_capture->window()); | 1419 event->ConvertLocationToTarget(window(), g_current_capture->window()); |
1387 g_current_capture->SendEventToProcessor(event); | 1420 g_current_capture->SendEventToProcessor(event); |
1388 } else { | 1421 } else { |
1389 SendEventToProcessor(event); | 1422 SendEventToProcessor(event); |
1390 } | 1423 } |
1391 } | 1424 } |
1392 | 1425 |
1393 void DesktopWindowTreeHostX11::ResetWindowRegion() { | 1426 void DesktopWindowTreeHostX11::ResetWindowRegion() { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1552 non_client_view->InvalidateLayout(); | 1585 non_client_view->InvalidateLayout(); |
1553 } | 1586 } |
1554 widget->GetRootView()->Layout(); | 1587 widget->GetRootView()->Layout(); |
1555 } | 1588 } |
1556 | 1589 |
1557 //////////////////////////////////////////////////////////////////////////////// | 1590 //////////////////////////////////////////////////////////////////////////////// |
1558 // DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation: | 1591 // DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation: |
1559 | 1592 |
1560 bool DesktopWindowTreeHostX11::CanDispatchEvent( | 1593 bool DesktopWindowTreeHostX11::CanDispatchEvent( |
1561 const ui::PlatformEvent& event) { | 1594 const ui::PlatformEvent& event) { |
1562 return event->xany.window == xwindow_ || | 1595 return EventTargetFromNative(event) == xwindow_ || |
1563 (event->type == GenericEvent && | 1596 (capture_window_ && capture_window_->CanDispatchEventToOwner(event)); |
1564 static_cast<XIDeviceEvent*>(event->xcookie.data)->event == xwindow_); | |
1565 } | 1597 } |
1566 | 1598 |
1567 uint32_t DesktopWindowTreeHostX11::DispatchEvent( | 1599 uint32_t DesktopWindowTreeHostX11::DispatchEvent( |
1568 const ui::PlatformEvent& event) { | 1600 const ui::PlatformEvent& event) { |
1569 XEvent* xev = event; | 1601 XEvent* xev = event; |
1570 | 1602 |
1571 TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch", | 1603 TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch", |
1572 "event->type", event->type); | 1604 "event->type", event->type); |
1573 | 1605 |
1574 UpdateWMUserTime(event); | 1606 UpdateWMUserTime(event); |
1575 | 1607 |
1576 // May want to factor CheckXEventForConsistency(xev); into a common location | 1608 // May want to factor CheckXEventForConsistency(xev); into a common location |
1577 // since it is called here. | 1609 // since it is called here. |
1578 switch (xev->type) { | 1610 switch (xev->type) { |
1579 case EnterNotify: | 1611 case EnterNotify: |
1580 case LeaveNotify: { | 1612 case LeaveNotify: { |
1581 // Ignore EventNotify and LeaveNotify events from children of |xwindow_|. | 1613 // Ignore EventNotify and LeaveNotify events from children of |xwindow_|. |
1582 // NativeViewGLSurfaceGLX adds a child to |xwindow_|. | 1614 // NativeViewGLSurfaceGLX adds a child to |xwindow_|. |
1583 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is | 1615 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is |
1584 // necessary. crbug.com/385716 | 1616 // necessary. crbug.com/385716 |
1585 if (xev->xcrossing.detail == NotifyInferior) | 1617 if (xev->xcrossing.detail == NotifyInferior) |
1586 break; | 1618 break; |
1587 | 1619 |
1588 ui::MouseEvent mouse_event(xev); | 1620 if (xev->xcrossing.mode == NotifyGrab || |
1589 DispatchMouseEvent(&mouse_event); | 1621 xev->xcrossing.mode == NotifyUngrab) { |
1622 ReleaseCapture(); | |
sadrul
2014/07/29 18:47:50
Should NotifyGrab really trigger ReleaseCapture()?
pkotwicz
2014/08/01 03:35:00
I am going to differ releasing capture as a result
| |
1623 } else { | |
1624 ui::MouseEvent mouse_event(xev); | |
1625 DispatchMouseEvent(&mouse_event); | |
1626 } | |
1590 break; | 1627 break; |
1591 } | 1628 } |
1592 case Expose: { | 1629 case Expose: { |
1593 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, | 1630 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, |
1594 xev->xexpose.width, xev->xexpose.height); | 1631 xev->xexpose.width, xev->xexpose.height); |
1595 compositor()->ScheduleRedrawRect(damage_rect); | 1632 compositor()->ScheduleRedrawRect(damage_rect); |
1596 break; | 1633 break; |
1597 } | 1634 } |
1598 case KeyPress: { | 1635 case KeyPress: { |
1599 ui::KeyEvent keydown_event(xev); | 1636 ui::KeyEvent keydown_event(xev); |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1860 if (linux_ui) { | 1897 if (linux_ui) { |
1861 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window); | 1898 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window); |
1862 if (native_theme) | 1899 if (native_theme) |
1863 return native_theme; | 1900 return native_theme; |
1864 } | 1901 } |
1865 | 1902 |
1866 return ui::NativeTheme::instance(); | 1903 return ui::NativeTheme::instance(); |
1867 } | 1904 } |
1868 | 1905 |
1869 } // namespace views | 1906 } // namespace views |
OLD | NEW |