| 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 |