Commit 830286c2 authored by Alexander Dunaev's avatar Alexander Dunaev Committed by Commit Bot

[ozone/x11] Fixed the host window drag movement.

This CL adds the missing handlers that enable window move via the non-client
area of the window.

Bug: 991512
Change-Id: I4890969ea8fc4c0aa405cdf0db7fca7769dc7b15
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1741684
Commit-Queue: Alexander Dunaev <adunaev@igalia.com>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#687352}
parent 8e096d3a
...@@ -63,6 +63,20 @@ buildflag_header("buildflags") { ...@@ -63,6 +63,20 @@ buildflag_header("buildflags") {
] ]
} }
source_set("hit_test") {
sources = [
"hit_test.cc",
"hit_test.h",
]
if (use_x11 || use_ozone) {
sources += [
"hit_test_x11.cc",
"hit_test_x11.h",
]
}
}
jumbo_component("base") { jumbo_component("base") {
output_name = "ui_base" output_name = "ui_base"
...@@ -166,8 +180,6 @@ jumbo_component("base") { ...@@ -166,8 +180,6 @@ jumbo_component("base") {
"dragdrop/os_exchange_data_provider_mac.mm", "dragdrop/os_exchange_data_provider_mac.mm",
"dragdrop/os_exchange_data_provider_win.cc", "dragdrop/os_exchange_data_provider_win.cc",
"dragdrop/os_exchange_data_provider_win.h", "dragdrop/os_exchange_data_provider_win.h",
"hit_test.cc",
"hit_test.h",
"l10n/formatter.cc", "l10n/formatter.cc",
"l10n/formatter.h", "l10n/formatter.h",
"l10n/l10n_font_util.cc", "l10n/l10n_font_util.cc",
...@@ -386,6 +398,7 @@ jumbo_component("base") { ...@@ -386,6 +398,7 @@ jumbo_component("base") {
public_deps = [ public_deps = [
":buildflags", ":buildflags",
":features", ":features",
":hit_test",
":ui_data_pack", ":ui_data_pack",
"//base", "//base",
"//skia", "//skia",
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
#ifndef UI_BASE_HIT_TEST_H_ #ifndef UI_BASE_HIT_TEST_H_
#define UI_BASE_HIT_TEST_H_ #define UI_BASE_HIT_TEST_H_
#include "build/build_config.h"
#include "ui/base/ui_base_export.h"
#if !defined(OS_WIN) #if !defined(OS_WIN)
// Defines the same symbolic names used by the WM_NCHITTEST Notification under // Defines the same symbolic names used by the WM_NCHITTEST Notification under
...@@ -48,11 +45,11 @@ enum HitTestCompat { ...@@ -48,11 +45,11 @@ enum HitTestCompat {
namespace ui { namespace ui {
// Returns true if the |component| is for resizing, like HTTOP or HTBOTTOM. // Returns true if the |component| is for resizing, like HTTOP or HTBOTTOM.
UI_BASE_EXPORT bool IsResizingComponent(int component); bool IsResizingComponent(int component);
// Returns true if the |component| is HTCAPTION or one of the resizing // Returns true if the |component| is HTCAPTION or one of the resizing
// components. // components.
UI_BASE_EXPORT bool CanPerformDragOrResize(int component); bool CanPerformDragOrResize(int component);
} // namespace ui } // namespace ui
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/base/hit_test_x11.h"
#include "ui/base/hit_test.h"
namespace ui {
namespace {
// These constants are said to be defined in the Extended Window Manager Hints
// standard but to be not found in any headers...
constexpr int kSizeTopLeft = 0;
constexpr int kSizeTop = 1;
constexpr int kSizeTopRight = 2;
constexpr int kSizeRight = 3;
constexpr int kSizeBottomRight = 4;
constexpr int kSizeBottom = 5;
constexpr int kSizeBottomLeft = 6;
constexpr int kSizeLeft = 7;
constexpr int kMove = 8;
} // namespace
int HitTestToWmMoveResizeDirection(int hittest) {
switch (hittest) {
case HTBOTTOM:
return kSizeBottom;
case HTBOTTOMLEFT:
return kSizeBottomLeft;
case HTBOTTOMRIGHT:
return kSizeBottomRight;
case HTCAPTION:
return kMove;
case HTLEFT:
return kSizeLeft;
case HTRIGHT:
return kSizeRight;
case HTTOP:
return kSizeTop;
case HTTOPLEFT:
return kSizeTopLeft;
case HTTOPRIGHT:
return kSizeTopRight;
default:
return -1;
}
}
} // namespace ui
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_HIT_TEST_X11_H_
#define UI_BASE_HIT_TEST_X11_H_
namespace ui {
// Converts a HitTestCompat into an X11 direction recognisable by
// NET_WM_MOVERESIZE event. Returns -1 if no conversion is possible.
int HitTestToWmMoveResizeDirection(int hittest);
} // namespace ui
#endif // UI_BASE_HIT_TEST_X11_H_
...@@ -38,6 +38,7 @@ jumbo_component("x") { ...@@ -38,6 +38,7 @@ jumbo_component("x") {
"//base", "//base",
"//base:i18n", "//base:i18n",
"//skia", "//skia",
"//ui/base:hit_test",
"//ui/display/util", "//ui/display/util",
"//ui/events", "//ui/events",
"//ui/events/devices/x11", "//ui/events/devices/x11",
......
...@@ -944,6 +944,32 @@ void SetWMSpecState(XID window, bool enabled, XAtom state1, XAtom state2) { ...@@ -944,6 +944,32 @@ void SetWMSpecState(XID window, bool enabled, XAtom state1, XAtom state2) {
SubstructureRedirectMask | SubstructureNotifyMask, &xclient); SubstructureRedirectMask | SubstructureNotifyMask, &xclient);
} }
void DoWMMoveResize(XDisplay* display,
XID root_window,
XID window,
const gfx::Point& location_px,
int direction) {
// This handler is usually sent when the window has the implicit grab. We
// need to dump it because what we're about to do is tell the window manager
// that it's now responsible for moving the window around; it immediately
// grabs when it receives the event below.
XUngrabPointer(display, x11::CurrentTime);
XEvent event;
memset(&event, 0, sizeof(event));
event.xclient.type = ClientMessage;
event.xclient.display = display;
event.xclient.window = window;
event.xclient.message_type = gfx::GetAtom("_NET_WM_MOVERESIZE");
event.xclient.format = 32;
event.xclient.data.l[0] = location_px.x();
event.xclient.data.l[1] = location_px.y();
event.xclient.data.l[2] = direction;
XSendEvent(display, root_window, x11::False,
SubstructureRedirectMask | SubstructureNotifyMask, &event);
}
bool HasWMSpecProperty(const base::flat_set<XAtom>& properties, XAtom atom) { bool HasWMSpecProperty(const base::flat_set<XAtom>& properties, XAtom atom) {
return properties.find(atom) != properties.end(); return properties.find(atom) != properties.end();
} }
......
...@@ -33,7 +33,7 @@ namespace gfx { ...@@ -33,7 +33,7 @@ namespace gfx {
class Insets; class Insets;
class Point; class Point;
class Rect; class Rect;
} } // namespace gfx
class SkBitmap; class SkBitmap;
namespace ui { namespace ui {
...@@ -206,6 +206,18 @@ void SetWindowRole(XDisplay* display, XID window, const std::string& role); ...@@ -206,6 +206,18 @@ void SetWindowRole(XDisplay* display, XID window, const std::string& role);
COMPONENT_EXPORT(UI_BASE_X) COMPONENT_EXPORT(UI_BASE_X)
void SetWMSpecState(XID window, bool enabled, XAtom state1, XAtom state2); void SetWMSpecState(XID window, bool enabled, XAtom state1, XAtom state2);
// Sends a NET_WM_MOVERESIZE message to the x11 window manager, enabling the
// move/resize mode. As per NET_WM_MOVERESIZE spec, |location| is the position
// in pixels (relative to the root window) of mouse button press, and
// |direction| indicates whether this is a move or resize event, and if it is a
// resize event, which edges of the window the size grip applies to.
COMPONENT_EXPORT(UI_BASE_X)
void DoWMMoveResize(XDisplay* display,
XID root_window,
XID window,
const gfx::Point& location_px,
int direction);
// Checks if the window manager has set a specific state. // Checks if the window manager has set a specific state.
COMPONENT_EXPORT(UI_BASE_X) COMPONENT_EXPORT(UI_BASE_X)
bool HasWMSpecProperty(const base::flat_set<XAtom>& properties, XAtom atom); bool HasWMSpecProperty(const base::flat_set<XAtom>& properties, XAtom atom);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "ui/base/hit_test_x11.h"
#include "ui/base/x/x11_pointer_grab.h" #include "ui/base/x/x11_pointer_grab.h"
#include "ui/base/x/x11_util.h" #include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_util_internal.h" #include "ui/base/x/x11_util_internal.h"
...@@ -1005,6 +1006,14 @@ bool XWindow::IsTargetedBy(const XEvent& xev) const { ...@@ -1005,6 +1006,14 @@ bool XWindow::IsTargetedBy(const XEvent& xev) const {
return target_window == xwindow_; return target_window == xwindow_;
} }
void XWindow::WmMoveResize(int hittest, const gfx::Point& location) const {
int direction = HitTestToWmMoveResizeDirection(hittest);
if (direction == -1)
return;
DoWMMoveResize(xdisplay_, x_root_window_, xwindow_, location, direction);
}
// In Ozone, there are no ui::*Event constructors receiving XEvent* as input, // In Ozone, there are no ui::*Event constructors receiving XEvent* as input,
// in this case ui::PlatformEvent is expected. Furthermore, // in this case ui::PlatformEvent is expected. Furthermore,
// X11EventSourceLibevent is used in that case, which already translates // X11EventSourceLibevent is used in that case, which already translates
......
...@@ -107,6 +107,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { ...@@ -107,6 +107,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
void ReleasePointerGrab(); void ReleasePointerGrab();
void StackAtTop(); void StackAtTop();
bool IsTargetedBy(const XEvent& xev) const; bool IsTargetedBy(const XEvent& xev) const;
void WmMoveResize(int hittest, const gfx::Point& location) const;
void ProcessEvent(XEvent* xev); void ProcessEvent(XEvent* xev);
void SetSize(const gfx::Size& size_in_pixels); void SetSize(const gfx::Size& size_in_pixels);
......
...@@ -57,6 +57,7 @@ source_set("x11") { ...@@ -57,6 +57,7 @@ source_set("x11") {
"//ui/ozone:ozone_base", "//ui/ozone:ozone_base",
"//ui/ozone/common", "//ui/ozone/common",
"//ui/platform_window", "//ui/platform_window",
"//ui/platform_window/platform_window_handler",
"//ui/platform_window/x11", "//ui/platform_window/x11",
] ]
......
...@@ -99,6 +99,10 @@ X11WindowOzone::~X11WindowOzone() { ...@@ -99,6 +99,10 @@ X11WindowOzone::~X11WindowOzone() {
void X11WindowOzone::Init(const PlatformWindowInitProperties& params) { void X11WindowOzone::Init(const PlatformWindowInitProperties& params) {
XWindow::Configuration config = ConvertInitPropertiesToXWindowConfig(params); XWindow::Configuration config = ConvertInitPropertiesToXWindowConfig(params);
x11_window_->Init(config); x11_window_->Init(config);
// Set a class property key, which allows |this| to be used for interactive
// events, e.g. move or resize.
SetWmMoveResizeHandler(this, static_cast<WmMoveResizeHandler*>(this));
} }
void X11WindowOzone::Show() { void X11WindowOzone::Show() {
...@@ -314,6 +318,12 @@ uint32_t X11WindowOzone::DispatchEvent(const PlatformEvent& event) { ...@@ -314,6 +318,12 @@ uint32_t X11WindowOzone::DispatchEvent(const PlatformEvent& event) {
return window_manager_->event_grabber()->DispatchEvent(event); return window_manager_->event_grabber()->DispatchEvent(event);
} }
void X11WindowOzone::DispatchHostWindowDragMovement(
int hittest,
const gfx::Point& pointer_location) {
x11_window_->WmMoveResize(hittest, pointer_location);
}
void X11WindowOzone::SetWidget(XID xid) { void X11WindowOzone::SetWidget(XID xid) {
// In spite of being defined in Xlib as `unsigned long`, XID (|xid|'s type) // In spite of being defined in Xlib as `unsigned long`, XID (|xid|'s type)
// is fixed at 32-bits (CARD32) in X11 Protocol, therefore can't be larger // is fixed at 32-bits (CARD32) in X11 Protocol, therefore can't be larger
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/x/x11_types.h" #include "ui/gfx/x/x11_types.h"
#include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
namespace ui { namespace ui {
...@@ -26,6 +27,7 @@ struct PlatformWindowInitProperties; ...@@ -26,6 +27,7 @@ struct PlatformWindowInitProperties;
// PlatformWindow implementation for X11 Ozone. PlatformEvents are ui::Events. // PlatformWindow implementation for X11 Ozone. PlatformEvents are ui::Events.
class X11WindowOzone : public PlatformWindow, class X11WindowOzone : public PlatformWindow,
public PlatformEventDispatcher, public PlatformEventDispatcher,
public WmMoveResizeHandler,
public XEventDispatcher, public XEventDispatcher,
public XWindow::Delegate { public XWindow::Delegate {
public: public:
...@@ -87,6 +89,11 @@ class X11WindowOzone : public PlatformWindow, ...@@ -87,6 +89,11 @@ class X11WindowOzone : public PlatformWindow,
bool CanDispatchEvent(const PlatformEvent& event) override; bool CanDispatchEvent(const PlatformEvent& event) override;
uint32_t DispatchEvent(const PlatformEvent& event) override; uint32_t DispatchEvent(const PlatformEvent& event) override;
// WmMoveResizeHandler
void DispatchHostWindowDragMovement(
int hittest,
const gfx::Point& pointer_location) override;
void Init(const PlatformWindowInitProperties& params); void Init(const PlatformWindowInitProperties& params);
void SetWidget(XID xwindow); void SetWidget(XID xwindow);
void RemoveFromWindowManager(); void RemoveFromWindowManager();
......
...@@ -762,6 +762,7 @@ jumbo_component("views") { ...@@ -762,6 +762,7 @@ jumbo_component("views") {
"widget/desktop_aura/window_event_filter.cc", "widget/desktop_aura/window_event_filter.cc",
"widget/desktop_aura/window_event_filter.h", "widget/desktop_aura/window_event_filter.h",
] ]
deps += [ "//ui/base:hit_test" ]
} }
if ((is_linux && !use_x11) || is_fuchsia) { if ((is_linux && !use_x11) || is_fuchsia) {
public += [ "widget/desktop_aura/desktop_window_tree_host_platform.h" ] public += [ "widget/desktop_aura/desktop_window_tree_host_platform.h" ]
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_delegate.h" #include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test_x11.h"
#include "ui/base/x/x11_util.h"
#include "ui/display/display.h" #include "ui/display/display.h"
#include "ui/display/screen.h" #include "ui/display/screen.h"
#include "ui/events/event.h" #include "ui/events/event.h"
...@@ -21,22 +22,6 @@ ...@@ -21,22 +22,6 @@
#include "ui/views/widget/native_widget_aura.h" #include "ui/views/widget/native_widget_aura.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
namespace {
// These constants are defined in the Extended Window Manager Hints
// standard...and aren't in any header that I can find.
constexpr int k_NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
constexpr int k_NET_WM_MOVERESIZE_SIZE_TOP = 1;
constexpr int k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
constexpr int k_NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
constexpr int k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
constexpr int k_NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
constexpr int k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
constexpr int k_NET_WM_MOVERESIZE_SIZE_LEFT = 7;
constexpr int k_NET_WM_MOVERESIZE_MOVE = 8;
} // namespace
namespace views { namespace views {
X11WindowEventFilter::X11WindowEventFilter( X11WindowEventFilter::X11WindowEventFilter(
...@@ -67,61 +52,12 @@ void X11WindowEventFilter::LowerWindow() { ...@@ -67,61 +52,12 @@ void X11WindowEventFilter::LowerWindow() {
bool X11WindowEventFilter::DispatchHostWindowDragMovement( bool X11WindowEventFilter::DispatchHostWindowDragMovement(
int hittest, int hittest,
const gfx::Point& screen_location) { const gfx::Point& screen_location) {
int direction = -1; int direction = ui::HitTestToWmMoveResizeDirection(hittest);
switch (hittest) { if (direction == -1)
case HTBOTTOM: return false;
direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOM;
break;
case HTBOTTOMLEFT:
direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
break;
case HTBOTTOMRIGHT:
direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
break;
case HTCAPTION:
direction = k_NET_WM_MOVERESIZE_MOVE;
break;
case HTLEFT:
direction = k_NET_WM_MOVERESIZE_SIZE_LEFT;
break;
case HTRIGHT:
direction = k_NET_WM_MOVERESIZE_SIZE_RIGHT;
break;
case HTTOP:
direction = k_NET_WM_MOVERESIZE_SIZE_TOP;
break;
case HTTOPLEFT:
direction = k_NET_WM_MOVERESIZE_SIZE_TOPLEFT;
break;
case HTTOPRIGHT:
direction = k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
break;
default:
return false;
}
// We most likely have an implicit grab right here. We need to dump it
// because what we're about to do is tell the window manager
// that it's now responsible for moving the window around; it immediately
// grabs when it receives the event below.
XUngrabPointer(xdisplay_, x11::CurrentTime);
XEvent event;
memset(&event, 0, sizeof(event));
event.xclient.type = ClientMessage;
event.xclient.display = xdisplay_;
event.xclient.window = xwindow_;
event.xclient.message_type = gfx::GetAtom("_NET_WM_MOVERESIZE");
event.xclient.format = 32;
event.xclient.data.l[0] = screen_location.x();
event.xclient.data.l[1] = screen_location.y();
event.xclient.data.l[2] = direction;
event.xclient.data.l[3] = 0;
event.xclient.data.l[4] = 0;
XSendEvent(xdisplay_, x_root_window_, x11::False,
SubstructureRedirectMask | SubstructureNotifyMask, &event);
ui::DoWMMoveResize(xdisplay_, x_root_window_, xwindow_, screen_location,
direction);
return true; return true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment