Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc

Issue 380943003: Do not release capture when transferring capture between Chrome windows on Linux (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698