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 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 OnHostResized(bounds.size()); | 895 OnHostResized(bounds.size()); |
895 ResetWindowRegion(); | 896 ResetWindowRegion(); |
896 } | 897 } |
897 } | 898 } |
898 | 899 |
899 gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { | 900 gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { |
900 return bounds_.origin(); | 901 return bounds_.origin(); |
901 } | 902 } |
902 | 903 |
903 void DesktopWindowTreeHostX11::SetCapture() { | 904 void DesktopWindowTreeHostX11::SetCapture() { |
904 // This is vaguely based on the old NativeWidgetGtk implementation. | 905 DesktopWindowTreeHostX11* old_capture = g_current_capture; |
905 // | 906 g_current_capture = this; |
906 // X11's XPointerGrab() shouldn't be used for everything; it doesn't map | 907 if (old_capture) { |
907 // cleanly to Windows' SetCapture(). GTK only provides a separate concept of | 908 // Take ownership of |old_capture|'s capture window which already has a |
908 // a grab that wasn't the X11 pointer grab, but was instead a manual | 909 // mouse grab. Because there is no X11 mouse grab or mouse ungrab, the |
909 // redirection of the event. (You need to drop into GDK if you want to | 910 // capture change is sychronous. |
910 // perform a raw X11 grab). | 911 capture_window_ = old_capture->ReleaseCaptureWindow().Pass(); |
911 | 912 |
912 if (g_current_capture) | 913 old_capture->OnHostLostWindowCapture(); |
913 g_current_capture->OnCaptureReleased(); | 914 } |
914 | 915 |
915 g_current_capture = this; | 916 if (!capture_window_) { |
916 x11_capture_.reset(new X11ScopedCapture(xwindow_)); | 917 // Create an X11CaptureWindow to asynchronously grab the mouse. As |
| 918 // |xwindow_| is likely the topmost window underneath the mouse, we will |
| 919 // likely not miss any mouse events. |
| 920 capture_window_.reset(new X11CaptureWindow); |
| 921 } |
917 } | 922 } |
918 | 923 |
919 void DesktopWindowTreeHostX11::ReleaseCapture() { | 924 void DesktopWindowTreeHostX11::ReleaseCapture() { |
920 if (g_current_capture == this) | 925 if (g_current_capture == this) { |
921 g_current_capture->OnCaptureReleased(); | 926 // Release mouse grab asynchronously. |xwindow_| is likely the topmost |
| 927 // window underneath the mouse so the capture release being asynchronous is |
| 928 // likely inconsequential. |
| 929 g_current_capture = NULL; |
| 930 capture_window_.reset(); |
| 931 |
| 932 OnHostLostWindowCapture(); |
| 933 } |
922 } | 934 } |
923 | 935 |
924 void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) { | 936 void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) { |
925 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); | 937 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); |
926 } | 938 } |
927 | 939 |
928 void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) { | 940 void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) { |
929 XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0, | 941 XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0, |
930 bounds_.x() + location.x(), bounds_.y() + location.y()); | 942 bounds_.x() + location.x(), bounds_.y() + location.y()); |
931 } | 943 } |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 return window_properties_.find(atom_cache_.GetAtom(property)) != | 1305 return window_properties_.find(atom_cache_.GetAtom(property)) != |
1294 window_properties_.end(); | 1306 window_properties_.end(); |
1295 } | 1307 } |
1296 | 1308 |
1297 void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) { | 1309 void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) { |
1298 use_native_frame_ = use_native_frame; | 1310 use_native_frame_ = use_native_frame; |
1299 ui::SetUseOSWindowFrame(xwindow_, use_native_frame); | 1311 ui::SetUseOSWindowFrame(xwindow_, use_native_frame); |
1300 ResetWindowRegion(); | 1312 ResetWindowRegion(); |
1301 } | 1313 } |
1302 | 1314 |
1303 void DesktopWindowTreeHostX11::OnCaptureReleased() { | 1315 scoped_ptr<X11CaptureWindow> DesktopWindowTreeHostX11::ReleaseCaptureWindow() { |
1304 x11_capture_.reset(); | 1316 return capture_window_.Pass(); |
1305 g_current_capture = NULL; | |
1306 OnHostLostWindowCapture(); | |
1307 } | 1317 } |
1308 | 1318 |
1309 void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) { | 1319 void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) { |
1310 // In Windows, the native events sent to chrome are separated into client | 1320 // In Windows, the native events sent to chrome are separated into client |
1311 // and non-client versions of events, which we record on our LocatedEvent | 1321 // and non-client versions of events, which we record on our LocatedEvent |
1312 // structures. On X11, we emulate the concept of non-client. Before we pass | 1322 // structures. On X11, we emulate the concept of non-client. Before we pass |
1313 // this event to the cross platform event handling framework, we need to | 1323 // this event to the cross platform event handling framework, we need to |
1314 // make sure it is appropriately marked as non-client if it's in the non | 1324 // make sure it is appropriately marked as non-client if it's in the non |
1315 // client area, or otherwise, we can get into a state where the a window is | 1325 // client area, or otherwise, we can get into a state where the a window is |
1316 // set as the |mouse_pressed_handler_| in window_event_dispatcher.cc | 1326 // set as the |mouse_pressed_handler_| in window_event_dispatcher.cc |
(...skipping 13 matching lines...) Expand all Loading... |
1330 if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE) | 1340 if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE) |
1331 flags |= ui::EF_IS_NON_CLIENT; | 1341 flags |= ui::EF_IS_NON_CLIENT; |
1332 event->set_flags(flags); | 1342 event->set_flags(flags); |
1333 } | 1343 } |
1334 | 1344 |
1335 // While we unset the urgency hint when we gain focus, we also must remove it | 1345 // While we unset the urgency hint when we gain focus, we also must remove it |
1336 // on mouse clicks because we can call FlashFrame() on an active window. | 1346 // on mouse clicks because we can call FlashFrame() on an active window. |
1337 if (event->IsAnyButton() || event->IsMouseWheelEvent()) | 1347 if (event->IsAnyButton() || event->IsMouseWheelEvent()) |
1338 FlashFrame(false); | 1348 FlashFrame(false); |
1339 | 1349 |
| 1350 if (ui::EventTargetFromNative(event->native_event()) != xwindow_) { |
| 1351 // The event was targeted at |capture_window_|'s X window. |
| 1352 gfx::Point location = |
| 1353 ui::EventSystemLocationFromNative(event->native_event()); |
| 1354 aura::client::GetScreenPositionClient(window())->ConvertPointFromScreen( |
| 1355 window(), &location); |
| 1356 event->set_location(location); |
| 1357 } |
| 1358 |
1340 if (!g_current_capture || g_current_capture == this) { | 1359 if (!g_current_capture || g_current_capture == this) { |
1341 SendEventToProcessor(event); | 1360 SendEventToProcessor(event); |
1342 } else { | 1361 } else { |
1343 // Another DesktopWindowTreeHostX11 has installed itself as | 1362 // Another DesktopWindowTreeHostX11 has capture. Translate the event's |
1344 // capture. Translate the event's location and dispatch to the other. | 1363 // location and dispatch to the other DesktopWindowTreeHostX11. |
1345 event->ConvertLocationToTarget(window(), g_current_capture->window()); | 1364 event->ConvertLocationToTarget(window(), g_current_capture->window()); |
1346 g_current_capture->SendEventToProcessor(event); | 1365 g_current_capture->SendEventToProcessor(event); |
1347 } | 1366 } |
1348 } | 1367 } |
1349 | 1368 |
1350 void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) { | 1369 void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) { |
| 1370 DCHECK_EQ(ui::EventTargetFromNative(event->native_event()), xwindow_); |
1351 if (g_current_capture && g_current_capture != this && | 1371 if (g_current_capture && g_current_capture != this && |
1352 event->type() == ui::ET_TOUCH_PRESSED) { | 1372 event->type() == ui::ET_TOUCH_PRESSED) { |
1353 event->ConvertLocationToTarget(window(), g_current_capture->window()); | 1373 event->ConvertLocationToTarget(window(), g_current_capture->window()); |
1354 g_current_capture->SendEventToProcessor(event); | 1374 g_current_capture->SendEventToProcessor(event); |
1355 } else { | 1375 } else { |
1356 SendEventToProcessor(event); | 1376 SendEventToProcessor(event); |
1357 } | 1377 } |
1358 } | 1378 } |
1359 | 1379 |
1360 void DesktopWindowTreeHostX11::ResetWindowRegion() { | 1380 void DesktopWindowTreeHostX11::ResetWindowRegion() { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 non_client_view->InvalidateLayout(); | 1539 non_client_view->InvalidateLayout(); |
1520 } | 1540 } |
1521 widget->GetRootView()->Layout(); | 1541 widget->GetRootView()->Layout(); |
1522 } | 1542 } |
1523 | 1543 |
1524 //////////////////////////////////////////////////////////////////////////////// | 1544 //////////////////////////////////////////////////////////////////////////////// |
1525 // DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation: | 1545 // DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation: |
1526 | 1546 |
1527 bool DesktopWindowTreeHostX11::CanDispatchEvent( | 1547 bool DesktopWindowTreeHostX11::CanDispatchEvent( |
1528 const ui::PlatformEvent& event) { | 1548 const ui::PlatformEvent& event) { |
1529 return event->xany.window == xwindow_ || | 1549 XID target = ui::EventTargetFromNative(event); |
1530 (event->type == GenericEvent && | 1550 return target == xwindow_ || |
1531 static_cast<XIDeviceEvent*>(event->xcookie.data)->event == xwindow_); | 1551 (capture_window_ && target == capture_window_->xwindow()); |
1532 } | 1552 } |
1533 | 1553 |
1534 uint32_t DesktopWindowTreeHostX11::DispatchEvent( | 1554 uint32_t DesktopWindowTreeHostX11::DispatchEvent( |
1535 const ui::PlatformEvent& event) { | 1555 const ui::PlatformEvent& event) { |
1536 XEvent* xev = event; | 1556 XEvent* xev = event; |
1537 | 1557 |
1538 TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch", | 1558 TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch", |
1539 "event->type", event->type); | 1559 "event->type", event->type); |
1540 | 1560 |
1541 UpdateWMUserTime(event); | 1561 UpdateWMUserTime(event); |
1542 | 1562 |
1543 // May want to factor CheckXEventForConsistency(xev); into a common location | 1563 // May want to factor CheckXEventForConsistency(xev); into a common location |
1544 // since it is called here. | 1564 // since it is called here. |
1545 switch (xev->type) { | 1565 switch (xev->type) { |
1546 case EnterNotify: | 1566 case EnterNotify: |
1547 case LeaveNotify: { | 1567 case LeaveNotify: { |
1548 // Ignore EventNotify and LeaveNotify events from children of |xwindow_|. | 1568 // Ignore EventNotify and LeaveNotify events from children of |xwindow_|. |
1549 // NativeViewGLSurfaceGLX adds a child to |xwindow_|. | 1569 // NativeViewGLSurfaceGLX adds a child to |xwindow_|. |
1550 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is | 1570 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is |
1551 // necessary. crbug.com/385716 | 1571 // necessary. crbug.com/385716 |
1552 if (xev->xcrossing.detail == NotifyInferior) | 1572 if (xev->xcrossing.detail == NotifyInferior) |
1553 break; | 1573 break; |
1554 | 1574 |
1555 ui::MouseEvent mouse_event(xev); | 1575 ui::MouseEvent mouse_event(xev); |
1556 DispatchMouseEvent(&mouse_event); | 1576 DispatchMouseEvent(&mouse_event); |
| 1577 |
| 1578 if (xev->xcrossing.mode == NotifyGrab || |
| 1579 xev->xcrossing.mode == NotifyUngrab) { |
| 1580 ReleaseCapture(); |
| 1581 } |
1557 break; | 1582 break; |
1558 } | 1583 } |
1559 case Expose: { | 1584 case Expose: { |
1560 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, | 1585 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, |
1561 xev->xexpose.width, xev->xexpose.height); | 1586 xev->xexpose.width, xev->xexpose.height); |
1562 compositor()->ScheduleRedrawRect(damage_rect); | 1587 compositor()->ScheduleRedrawRect(damage_rect); |
1563 break; | 1588 break; |
1564 } | 1589 } |
1565 case KeyPress: | 1590 case KeyPress: |
1566 case KeyRelease: { | 1591 case KeyRelease: { |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 if (linux_ui) { | 1831 if (linux_ui) { |
1807 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window); | 1832 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window); |
1808 if (native_theme) | 1833 if (native_theme) |
1809 return native_theme; | 1834 return native_theme; |
1810 } | 1835 } |
1811 | 1836 |
1812 return ui::NativeTheme::instance(); | 1837 return ui::NativeTheme::instance(); |
1813 } | 1838 } |
1814 | 1839 |
1815 } // namespace views | 1840 } // namespace views |
OLD | NEW |