diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/ui/platform_window | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/ui/platform_window')
11 files changed, 346 insertions, 78 deletions
diff --git a/chromium/ui/platform_window/BUILD.gn b/chromium/ui/platform_window/BUILD.gn index 4a96342b2ec..f06af0fb93c 100644 --- a/chromium/ui/platform_window/BUILD.gn +++ b/chromium/ui/platform_window/BUILD.gn @@ -16,6 +16,8 @@ component("platform_window") { defines = [ "IS_PLATFORM_WINDOW_IMPL" ] + public_deps = [ "//ui/base/cursor:cursor_base" ] + deps = [ "//base", "//ui/base", @@ -28,7 +30,7 @@ component("platform_window") { "fuchsia/initialize_presenter_api_view.h", ] - public_deps = [ + public_deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.policy", "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.views", "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp", diff --git a/chromium/ui/platform_window/fuchsia/initialize_presenter_api_view.cc b/chromium/ui/platform_window/fuchsia/initialize_presenter_api_view.cc index 292c4ae2cca..7500fcb198e 100644 --- a/chromium/ui/platform_window/fuchsia/initialize_presenter_api_view.cc +++ b/chromium/ui/platform_window/fuchsia/initialize_presenter_api_view.cc @@ -5,13 +5,14 @@ #include "ui/platform_window/fuchsia/initialize_presenter_api_view.h" #include <fuchsia/ui/policy/cpp/fidl.h> -#include <fuchsia/ui/views/cpp/fidl.h> #include <lib/sys/cpp/component_context.h> #include <lib/ui/scenic/cpp/view_ref_pair.h> #include <lib/ui/scenic/cpp/view_token_pair.h> -#include "base/fuchsia/default_context.h" +#include <utility> + #include "base/fuchsia/fuchsia_logging.h" +#include "base/fuchsia/process_context.h" namespace ui { namespace fuchsia { @@ -21,19 +22,19 @@ void InitializeViewTokenAndPresentView( DCHECK(window_properties_out); // Generate ViewToken and ViewHolderToken for the new view. - ::fuchsia::ui::views::ViewHolderToken view_holder_token; - std::tie(window_properties_out->view_token, view_holder_token) = - scenic::NewViewTokenPair(); + auto view_tokens = scenic::ViewTokenPair::New(); + window_properties_out->view_token = std::move(view_tokens.view_token); // Create a ViewRefPair so the view can be registered to the SemanticsManager. window_properties_out->view_ref_pair = scenic::ViewRefPair::New(); // Request Presenter to show the view full-screen. - auto presenter = base::fuchsia::ComponentContextForCurrentProcess() + auto presenter = base::ComponentContextForProcess() ->svc() ->Connect<::fuchsia::ui::policy::Presenter>(); - presenter->PresentView(std::move(view_holder_token), nullptr); + presenter->PresentOrReplaceView(std::move(view_tokens.view_holder_token), + nullptr); } } // namespace fuchsia diff --git a/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.cc b/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.cc index f559d426b49..5dafa35363a 100644 --- a/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.cc +++ b/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.cc @@ -13,6 +13,8 @@ namespace ui { DEFINE_UI_CLASS_PROPERTY_KEY(WmDragHandler*, kWmDragHandlerKey, nullptr) +WmDragHandler::Delegate::~Delegate() = default; + void SetWmDragHandler(PlatformWindow* platform_window, WmDragHandler* drag_handler) { platform_window->SetProperty(kWmDragHandlerKey, drag_handler); diff --git a/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.h b/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.h index 7f7d7933fab..d1f7510e0c2 100644 --- a/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.h +++ b/chromium/ui/platform_window/platform_window_handler/wm_drag_handler.h @@ -6,6 +6,8 @@ #define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_ #include "base/bind.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/gfx/geometry/point.h" #include "ui/gfx/native_widget_types.h" #include "ui/platform_window/platform_window_handler/wm_platform_export.h" @@ -15,15 +17,31 @@ class OSExchangeData; class WM_PLATFORM_EXPORT WmDragHandler { public: + // During the drag operation, the handler may send updates + class Delegate { + public: + // Called every time when the drag location has changed. + virtual void OnDragLocationChanged(const gfx::Point& screen_point_px) = 0; + // Called when the currently negotiated operation has changed. + virtual void OnDragOperationChanged( + DragDropTypes::DragOperation operation) = 0; + // Called once when the operation has finished. + virtual void OnDragFinished(int operation) = 0; + + protected: + virtual ~Delegate(); + }; + // Starts dragging with |data| which it wants to deliver to the destination. // |operation| is the suggested operation which is bitmask of DRAG_NONE, // DRAG_MOVE, DRAG_COPY and DRAG_LINK in DragDropTypes::DragOperation to the // destination and the destination sets the final operation when the drop - // action is performed. + // action is performed. In progress updates on the drag operation come back + // through the |delegate|. virtual void StartDrag(const OSExchangeData& data, int operation, gfx::NativeCursor cursor, - base::OnceCallback<void(int)> callback) = 0; + Delegate* delegate) = 0; protected: virtual ~WmDragHandler() {} diff --git a/chromium/ui/platform_window/x11/BUILD.gn b/chromium/ui/platform_window/x11/BUILD.gn index 60228f2c548..a9d6bc31204 100644 --- a/chromium/ui/platform_window/x11/BUILD.gn +++ b/chromium/ui/platform_window/x11/BUILD.gn @@ -4,6 +4,7 @@ import("//build/config/jumbo.gni") import("//build/config/ui.gni") +import("//testing/test.gni") import("//ui/ozone/ozone.gni") assert(use_x11 || ozone_platform_x11) @@ -49,3 +50,37 @@ jumbo_component("x11") { deps += [ "//ui/events/x" ] } } + +test("x11_unittests") { + sources = [ "test/x11_window_unittest.cc" ] + deps = [ + ":x11", + "//base/test:run_all_unittests", + "//base/test:test_support", + "//skia", + "//testing/gmock", + "//testing/gtest", + "//ui/base/x", + "//ui/base/x:test_support", + "//ui/events:test_support", + "//ui/events/platform/x11", + "//ui/events/x", + "//ui/gfx:test_support", + "//ui/gfx/x", + "//ui/platform_window", + "//ui/platform_window/extensions", + ] + configs += [ "//build/config:precompiled_headers" ] + + # Needed for tests. Please note that if you want to run tests locally, + # ensure that you start them from your out directory with the xvfb + # script so that openbox has time to start. Otherwise, the x11_unittests + # will time out. e.g. - + # + # 1) cd out/Debug. + # 2) ../../testing/xvfb.py ./x11_unittests. + # + #TODO(dpranke): move that to appropriate place after test() template is + # reworked. + data_deps = [ "//ui/base/x/xwmstartupcheck" ] +} diff --git a/chromium/ui/platform_window/x11/atk_event_conversion.cc b/chromium/ui/platform_window/x11/atk_event_conversion.cc index b79fff06bb0..6b5a82dbfe7 100644 --- a/chromium/ui/platform_window/x11/atk_event_conversion.cc +++ b/chromium/ui/platform_window/x11/atk_event_conversion.cc @@ -10,13 +10,15 @@ namespace ui { -std::unique_ptr<AtkKeyEventStruct> AtkKeyEventFromXEvent(XEvent* xevent) { - DCHECK(xevent); +std::unique_ptr<AtkKeyEventStruct> AtkKeyEventFromXEvent( + x11::Event* x11_event) { + DCHECK(x11_event); + XEvent* xevent = &x11_event->xlib_event(); auto atk_key_event = std::make_unique<AtkKeyEventStruct>(); - if (xevent->type == KeyPress) + if (xevent->type == x11::KeyEvent::Press) atk_key_event->type = ATK_KEY_EVENT_PRESS; - else if (xevent->type == KeyRelease) + else if (xevent->type == x11::KeyEvent::Release) atk_key_event->type = ATK_KEY_EVENT_RELEASE; else NOTREACHED() << xevent->type; @@ -35,7 +37,7 @@ std::unique_ptr<AtkKeyEventStruct> AtkKeyEventFromXEvent(XEvent* xevent) { atk_key_event->string = nullptr; atk_key_event->length = 0; - int flags = ui::EventFlagsFromXEvent(*xevent); + int flags = ui::EventFlagsFromXEvent(*x11_event); if (flags & ui::EF_SHIFT_DOWN) atk_key_event->state |= AtkKeyModifierMask::kAtkShiftMask; if (flags & ui::EF_CAPS_LOCK_ON) diff --git a/chromium/ui/platform_window/x11/atk_event_conversion.h b/chromium/ui/platform_window/x11/atk_event_conversion.h index 6a2dce7fbe6..ad15f27db48 100644 --- a/chromium/ui/platform_window/x11/atk_event_conversion.h +++ b/chromium/ui/platform_window/x11/atk_event_conversion.h @@ -9,6 +9,7 @@ #include <memory> +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11.h" namespace ui { @@ -27,7 +28,7 @@ typedef enum { KAtkMod5Mask = 1 << 7, } AtkKeyModifierMask; -std::unique_ptr<AtkKeyEventStruct> AtkKeyEventFromXEvent(XEvent* xev); +std::unique_ptr<AtkKeyEventStruct> AtkKeyEventFromXEvent(x11::Event* xev); } // namespace ui diff --git a/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc b/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc index 4163e3b9db3..2b8edfc02db 100644 --- a/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc +++ b/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc @@ -8,6 +8,7 @@ #include <vector> +#include "ui/gfx/native_widget_types.h" #include "ui/platform_window/x11/x11_window.h" #include "ui/platform_window/x11/x11_window_manager.h" @@ -17,7 +18,7 @@ X11TopmostWindowFinder::X11TopmostWindowFinder() = default; X11TopmostWindowFinder::~X11TopmostWindowFinder() = default; -XID X11TopmostWindowFinder::FindLocalProcessWindowAt( +x11::Window X11TopmostWindowFinder::FindLocalProcessWindowAt( const gfx::Point& screen_loc_in_pixels, const std::set<gfx::AcceleratedWidget>& ignore) { screen_loc_in_pixels_ = screen_loc_in_pixels; @@ -28,35 +29,37 @@ XID X11TopmostWindowFinder::FindLocalProcessWindowAt( if (std::none_of(local_process_windows.cbegin(), local_process_windows.cend(), [this](auto* window) { return ShouldStopIteratingAtLocalProcessWindow(window); - })) - return gfx::kNullAcceleratedWidget; + })) { + return x11::Window::None; + } EnumerateTopLevelWindows(this); return toplevel_; } -XID X11TopmostWindowFinder::FindWindowAt( +x11::Window X11TopmostWindowFinder::FindWindowAt( const gfx::Point& screen_loc_in_pixels) { screen_loc_in_pixels_ = screen_loc_in_pixels; EnumerateTopLevelWindows(this); return toplevel_; } -bool X11TopmostWindowFinder::ShouldStopIterating(XID xid) { - if (!IsWindowVisible(xid)) +bool X11TopmostWindowFinder::ShouldStopIterating(x11::Window xwindow) { + if (!IsWindowVisible(xwindow)) return false; - auto* window = X11WindowManager::GetInstance()->GetWindow(xid); + auto* window = X11WindowManager::GetInstance()->GetWindow( + static_cast<gfx::AcceleratedWidget>(xwindow)); if (window) { if (ShouldStopIteratingAtLocalProcessWindow(window)) { - toplevel_ = xid; + toplevel_ = xwindow; return true; } return false; } - if (WindowContainsPoint(xid, screen_loc_in_pixels_)) { - toplevel_ = xid; + if (WindowContainsPoint(xwindow, screen_loc_in_pixels_)) { + toplevel_ = xwindow; return true; } return false; @@ -72,7 +75,7 @@ bool X11TopmostWindowFinder::ShouldStopIteratingAtLocalProcessWindow( if (!window->IsVisible()) return false; - gfx::Rect window_bounds = window->GetOutterBounds(); + gfx::Rect window_bounds = window->GetOuterBounds(); if (!window_bounds.Contains(screen_loc_in_pixels_)) return false; diff --git a/chromium/ui/platform_window/x11/x11_topmost_window_finder.h b/chromium/ui/platform_window/x11/x11_topmost_window_finder.h index 62c9e138d72..0ad199f5ccf 100644 --- a/chromium/ui/platform_window/x11/x11_topmost_window_finder.h +++ b/chromium/ui/platform_window/x11/x11_topmost_window_finder.h @@ -30,15 +30,16 @@ class X11_WINDOW_EXPORT X11TopmostWindowFinder // Returns the topmost window at |screen_loc_in_pixels|, ignoring the windows // in |ignore|. Returns null widget if the topmost window at // |screen_loc_in_pixels| does not belong to Chrome. - XID FindLocalProcessWindowAt(const gfx::Point& screen_loc_in_pixels, - const std::set<gfx::AcceleratedWidget>& ignore); + x11::Window FindLocalProcessWindowAt( + const gfx::Point& screen_loc_in_pixels, + const std::set<gfx::AcceleratedWidget>& ignore); // Returns the topmost window at |screen_loc_in_pixels|. - XID FindWindowAt(const gfx::Point& screen_loc_in_pixels) override; + x11::Window FindWindowAt(const gfx::Point& screen_loc_in_pixels) override; private: // ui::EnumerateWindowsDelegate: - bool ShouldStopIterating(XID xid) override; + bool ShouldStopIterating(x11::Window window) override; // Returns true if |window| does not not belong to |ignore|, is visible and // contains |screen_loc_|. @@ -46,7 +47,7 @@ class X11_WINDOW_EXPORT X11TopmostWindowFinder gfx::Point screen_loc_in_pixels_; std::set<gfx::AcceleratedWidget> ignore_; - XID toplevel_ = x11::None; + x11::Window toplevel_ = x11::Window::None; DISALLOW_COPY_AND_ASSIGN(X11TopmostWindowFinder); }; diff --git a/chromium/ui/platform_window/x11/x11_window.cc b/chromium/ui/platform_window/x11/x11_window.cc index c9fc5e2670d..bc2c18233b7 100644 --- a/chromium/ui/platform_window/x11/x11_window.cc +++ b/chromium/ui/platform_window/x11/x11_window.cc @@ -7,6 +7,7 @@ #include "base/strings/string_number_conversions.h" #include "base/trace_event/trace_event.h" #include "ui/base/buildflags.h" +#include "ui/base/x/x11_cursor.h" #include "ui/base/x/x11_desktop_window_move_client.h" #include "ui/base/x/x11_util.h" #include "ui/base/x/x11_util_internal.h" @@ -24,7 +25,15 @@ #include "ui/platform_window/x11/x11_window_manager.h" #if defined(USE_OZONE) +#include "ui/base/dragdrop/os_exchange_data.h" +#include "ui/base/x/x11_os_exchange_data_provider.h" +#include "ui/base/x/x11_pointer_grab.h" +#include "ui/base/x/x11_topmost_window_finder.h" #include "ui/events/ozone/events_ozone.h" +#include "ui/platform_window/platform_window_handler/wm_drop_handler.h" +#include "ui/platform_window/x11/x11_topmost_window_finder.h" +#else +#include "ui/base/dragdrop/os_exchange_data_provider_x11.h" #endif // defined(USE_OZONE) #if BUILDFLAG(USE_ATK) @@ -35,6 +44,9 @@ namespace ui { namespace { +// Opacity for drag widget windows. +constexpr float kDragWidgetOpacity = .75f; + XWindow::WindowOpacity GetXWindowOpacity(PlatformWindowOpacity opacity) { using WindowOpacity = XWindow::WindowOpacity; switch (opacity) { @@ -91,12 +103,15 @@ ui::XWindow::Configuration ConvertInitPropertiesToXWindowConfig( } // Coalesce touch/mouse events if needed -bool CoalesceEventsIfNeeded(XEvent* const xev, EventType type, XEvent* out) { - if (xev->type == MotionNotify || - (xev->type == GenericEvent && +bool CoalesceEventsIfNeeded(x11::Event* const x11_event, + EventType type, + x11::Event* out) { + XEvent* xev = &x11_event->xlib_event(); + if (xev->type == x11::MotionNotifyEvent::opcode || + (xev->type == x11::GeGenericEvent::opcode && (type == ui::ET_TOUCH_MOVED || type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED))) { - return ui::CoalescePendingMotionEvents(xev, out) > 0; + return ui::CoalescePendingMotionEvents(x11_event, out) > 0; } return false; } @@ -130,11 +145,27 @@ void X11Window::Initialize(PlatformWindowInitProperties properties) { config.override_redirect = properties.x11_extension_delegate && properties.x11_extension_delegate->IsOverrideRedirect(IsWmTiling()); + if (config.type == WindowType::kDrag) { + config.opacity = ui::IsCompositingManagerPresent() + ? WindowOpacity::kTranslucentWindow + : WindowOpacity::kOpaqueWindow; + } workspace_extension_delegate_ = properties.workspace_extension_delegate; x11_extension_delegate_ = properties.x11_extension_delegate; Init(config); + + if (config.type == WindowType::kDrag && + config.opacity == WindowOpacity::kTranslucentWindow) { + SetOpacity(kDragWidgetOpacity); + } + +#if defined(USE_OZONE) + SetWmDragHandler(this, this); + + drag_drop_client_ = std::make_unique<XDragDropClient>(this, window()); +#endif } void X11Window::SetXEventDelegate(XEventDelegate* delegate) { @@ -359,11 +390,7 @@ bool X11Window::ShouldUseNativeFrame() const { } void X11Window::SetCursor(PlatformCursor cursor) { - // X11PlatformWindowOzone has different type of PlatformCursor. Thus, use this - // only for X11 and Ozone will manage this by itself. -#if defined(USE_X11) - XWindow::SetCursor(cursor); -#endif + XWindow::SetCursor(static_cast<X11Cursor*>(cursor)->xcursor()); } void X11Window::MoveCursorTo(const gfx::Point& location) { @@ -409,8 +436,8 @@ ZOrderLevel X11Window::GetZOrderLevel() const { } void X11Window::StackAbove(gfx::AcceleratedWidget widget) { - // Check comment in the GetWidget method about this this cast. - XWindow::StackXWindowAbove(static_cast<::Window>(widget)); + // Check comment in the GetWidget method about this cast. + XWindow::StackXWindowAbove(static_cast<x11::Window>(widget)); } void X11Window::StackAtTop() { @@ -482,7 +509,7 @@ void X11Window::OnCompleteSwapAfterResize() { } gfx::Rect X11Window::GetXRootWindowOuterBounds() const { - return XWindow::GetOutterBounds(); + return XWindow::GetOuterBounds(); } bool X11Window::ContainsPointInXRegion(const gfx::Point& point) const { @@ -501,17 +528,19 @@ void X11Window::SetX11ExtensionDelegate(X11ExtensionDelegate* delegate) { x11_extension_delegate_ = delegate; } -bool X11Window::HandleAsAtkEvent(XEvent* xev) { +bool X11Window::HandleAsAtkEvent(x11::Event* x11_event) { #if !BUILDFLAG(USE_ATK) // TODO(crbug.com/1014934): Support ATK in Ozone/X11. NOTREACHED(); return false; #else + XEvent* xev = &x11_event->xlib_event(); DCHECK(xev); - if (!x11_extension_delegate_ || - (xev->type != KeyPress && xev->type != KeyRelease)) + if (!x11_extension_delegate_ || (xev->type != x11::KeyEvent::Press && + xev->type != x11::KeyEvent::Release)) { return false; - auto atk_key_event = AtkKeyEventFromXEvent(xev); + } + auto atk_key_event = AtkKeyEventFromXEvent(x11_event); return x11_extension_delegate_->OnAtkKeyEvent(atk_key_event.get()); #endif } @@ -521,7 +550,7 @@ bool X11Window::HandleAsAtkEvent(XEvent* xev) { // able to process next translated event sent by it. So, it's done through // |handle_next_event_| internal flag, used in subsequent CanDispatchEvent // call. -void X11Window::CheckCanDispatchNextPlatformEvent(XEvent* xev) { +void X11Window::CheckCanDispatchNextPlatformEvent(x11::Event* xev) { if (is_shutting_down_) return; current_xevent_ = XWindow::IsTargetedBy(*xev) ? xev : nullptr; @@ -535,7 +564,7 @@ PlatformEventDispatcher* X11Window::GetPlatformEventDispatcher() { return this; } -bool X11Window::DispatchXEvent(XEvent* xev) { +bool X11Window::DispatchXEvent(x11::Event* xev) { if (!XWindow::IsTargetedBy(*xev)) return false; XWindow::ProcessEvent(xev); @@ -543,7 +572,7 @@ bool X11Window::DispatchXEvent(XEvent* xev) { } bool X11Window::CanDispatchEvent(const PlatformEvent& xev) { - DCHECK_NE(window(), x11::None); + DCHECK_NE(window(), x11::Window::None); return !!current_xevent_; } @@ -551,7 +580,7 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { TRACE_EVENT1("views", "X11PlatformWindow::Dispatch", "event->type()", event->type()); - DCHECK_NE(window(), x11::None); + DCHECK_NE(window(), x11::Window::None); DCHECK(event); DCHECK(current_xevent_); @@ -567,7 +596,7 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { return POST_DISPATCH_STOP_PROPAGATION; } -void X11Window::DispatchUiEvent(ui::Event* event, XEvent* xev) { +void X11Window::DispatchUiEvent(ui::Event* event, x11::Event* xev) { auto* window_manager = X11WindowManager::GetInstance(); DCHECK(window_manager); @@ -595,7 +624,7 @@ void X11Window::DispatchUiEvent(ui::Event* event, XEvent* xev) { return located_events_grabber->DispatchUiEvent(event, xev); } - XEvent last_xev; + x11::Event last_xev; std::unique_ptr<ui::Event> last_motion; bool coalesced = CoalesceEventsIfNeeded(xev, event->type(), &last_xev); if (coalesced) { @@ -619,9 +648,6 @@ void X11Window::DispatchUiEvent(ui::Event* event, XEvent* xev) { platform_window_delegate_->DispatchEvent(event); #endif } - - if (coalesced) - XFreeEventData(last_xev.xgeneric.display, &last_xev.xcookie); } void X11Window::OnXWindowCreated() { @@ -640,10 +666,6 @@ void X11Window::OnXWindowCreated() { platform_window_delegate_->OnAcceleratedWidgetAvailable(GetWidget()); } -bool X11Window::DispatchDraggingUiEvent(ui::Event* event) { - return false; -} - void X11Window::OnXWindowStateChanged() { // Determine the new window state information to be propagated to the client. // Note that the order of checks is important here, because window can have @@ -728,14 +750,22 @@ void X11Window::OnXWindowLostPointerGrab() { x11_extension_delegate_->OnLostMouseGrab(); } -void X11Window::OnXWindowSelectionEvent(XEvent* xev) { +void X11Window::OnXWindowSelectionEvent(x11::Event* xev) { if (x_event_delegate_) x_event_delegate_->OnXWindowSelectionEvent(xev); +#if defined(USE_OZONE) + DCHECK(drag_drop_client_); + drag_drop_client_->OnSelectionNotify(*xev->As<x11::SelectionNotifyEvent>()); +#endif } -void X11Window::OnXWindowDragDropEvent(XEvent* xev) { +void X11Window::OnXWindowDragDropEvent(x11::Event* xev) { if (x_event_delegate_) x_event_delegate_->OnXWindowDragDropEvent(xev); +#if defined(USE_OZONE) + DCHECK(drag_drop_client_); + drag_drop_client_->HandleXdndEvent(*xev->As<x11::ClientMessageEvent>()); +#endif } base::Optional<gfx::Size> X11Window::GetMinimumSizeForXWindow() { @@ -766,6 +796,136 @@ void X11Window::EndMoveLoop() { x11_window_move_client_->EndMoveLoop(); } +#if defined(USE_OZONE) +void X11Window::StartDrag(const OSExchangeData& data, + int operation, + gfx::NativeCursor cursor, + WmDragHandler::Delegate* delegate) { + DCHECK(drag_drop_client_); + DCHECK(!drag_handler_delegate_); + + drag_handler_delegate_ = delegate; + drag_drop_client_->InitDrag(operation, &data); + drag_operation_ = 0; + notified_enter_ = false; + + SetCapture(); + + dragging_ = true; +} + +std::unique_ptr<XTopmostWindowFinder> X11Window::CreateWindowFinder() { + return std::make_unique<X11TopmostWindowFinder>(); +} + +int X11Window::UpdateDrag(const gfx::Point& screen_point) { + WmDropHandler* drop_handler = GetWmDropHandler(*this); + if (!drop_handler) + return DragDropTypes::DRAG_NONE; + if (!notified_enter_) { + DCHECK(drag_drop_client_); + auto* target_current_context = drag_drop_client_->target_current_context(); + DCHECK(target_current_context); + drop_handler->OnDragEnter( + gfx::PointF(screen_point), + std::make_unique<ui::OSExchangeData>( + std::make_unique<ui::XOSExchangeDataProvider>( + drag_drop_client_->xwindow(), + target_current_context->fetched_targets())), + ui::DragDropTypes::DRAG_COPY); + notified_enter_ = true; + } + + drag_operation_ = drop_handler->OnDragMotion(gfx::PointF(screen_point), + ui::DragDropTypes::DRAG_COPY); + return drag_operation_; +} + +void X11Window::UpdateCursor( + DragDropTypes::DragOperation negotiated_operation) { + DCHECK(drag_handler_delegate_); + drag_handler_delegate_->OnDragOperationChanged(negotiated_operation); +} + +void X11Window::OnBeginForeignDrag(x11::Window window) { + NOTIMPLEMENTED_LOG_ONCE(); +} + +void X11Window::OnEndForeignDrag() { + NOTIMPLEMENTED_LOG_ONCE(); +} + +void X11Window::OnBeforeDragLeave() { + WmDropHandler* drop_handler = GetWmDropHandler(*this); + if (!drop_handler) + return; + drop_handler->OnDragLeave(); + notified_enter_ = false; +} + +int X11Window::PerformDrop() { + WmDropHandler* drop_handler = GetWmDropHandler(*this); + if (!drop_handler) + return DragDropTypes::DRAG_NONE; + + DCHECK(notified_enter_); + + // The drop data has been supplied on entering the window. The drop handler + // should have it since then. + drop_handler->OnDragDrop({}); + notified_enter_ = false; + return drag_operation_; +} + +void X11Window::EndDragLoop() { + DCHECK(drag_handler_delegate_); + drag_handler_delegate_->OnDragFinished(drag_operation_); + drag_handler_delegate_ = nullptr; +} +#endif // defined(USE_OZONE) + +bool X11Window::DispatchDraggingUiEvent(Event* event) { +#if defined(USE_OZONE) + // Drag and drop have a priority over other processing. + if (dragging_) { + DCHECK(drag_drop_client_); + + switch (event->type()) { + case ET_MOUSE_MOVED: + case ET_MOUSE_DRAGGED: { + drag_handler_delegate_->OnDragLocationChanged( + event->AsLocatedEvent()->root_location()); + drag_drop_client_->HandleMouseMovement( + event->AsLocatedEvent()->root_location(), + event->AsMouseEvent()->flags(), + event->AsMouseEvent()->time_stamp()); + return true; + } + case ET_MOUSE_RELEASED: + if (!event->AsMouseEvent()->IsLeftMouseButton()) + break; + // Assume that drags are being done with the left mouse button. Only + // break the drag if the left mouse button was released. + drag_drop_client_->HandleMouseReleased(); + dragging_ = false; + ReleaseCapture(); + return true; + case ET_KEY_PRESSED: + if (event->AsKeyEvent()->key_code() != VKEY_ESCAPE) + break; + EndMoveLoop(); + drag_drop_client_->HandleMoveLoopEnded(); + dragging_ = false; + ReleaseCapture(); + return true; + default: + break; + } + } +#endif // defined(USE_OZONE) + return false; +} + gfx::Size X11Window::AdjustSizeForDisplay( const gfx::Size& requested_size_in_pixels) { #if defined(OS_CHROMEOS) @@ -795,7 +955,7 @@ gfx::Size X11Window::AdjustSizeForDisplay( void X11Window::ConvertEventLocationToTargetLocation( const gfx::Rect& target_window_bounds, const gfx::Rect& current_window_bounds, - ui::LocatedEvent* located_event) { + LocatedEvent* located_event) { // TODO(msisov): for ozone, we need to access PlatformScreen instead and get // the displays. auto* display = display::Screen::GetScreen(); diff --git a/chromium/ui/platform_window/x11/x11_window.h b/chromium/ui/platform_window/x11/x11_window.h index 378512c1676..011fbee55c3 100644 --- a/chromium/ui/platform_window/x11/x11_window.h +++ b/chromium/ui/platform_window/x11/x11_window.h @@ -9,6 +9,7 @@ #include "ui/base/x/x11_window.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/events/platform/x11/x11_event_source.h" +#include "ui/gfx/x/event.h" #include "ui/platform_window/extensions/workspace_extension.h" #include "ui/platform_window/extensions/x11_extension.h" #include "ui/platform_window/platform_window.h" @@ -17,26 +18,32 @@ #include "ui/platform_window/platform_window_init_properties.h" #include "ui/platform_window/x11/x11_window_export.h" +#if defined(USE_OZONE) +#include "ui/base/x/x11_drag_drop_client.h" +#include "ui/platform_window/platform_window_handler/wm_drag_handler.h" +#endif + namespace ui { +class PlatformWindowDelegate; class X11ExtensionDelegate; class X11DesktopWindowMoveClient; class LocatedEvent; class WorkspaceExtensionDelegate; // Delegate interface used to communicate the X11PlatformWindow API client about -// XEvents of interest. +// x11::Events of interest. class X11_WINDOW_EXPORT XEventDelegate { public: - virtual ~XEventDelegate() {} + virtual ~XEventDelegate() = default; // TODO(crbug.com/990756): We need to implement/reuse ozone interface for // these. - virtual void OnXWindowSelectionEvent(XEvent* xev) = 0; - virtual void OnXWindowDragDropEvent(XEvent* xev) = 0; + virtual void OnXWindowSelectionEvent(x11::Event* xev) = 0; + virtual void OnXWindowDragDropEvent(x11::Event* xev) = 0; }; -// PlatformWindow implementation for X11. PlatformEvents are XEvents. +// PlatformWindow implementation for X11. class X11_WINDOW_EXPORT X11Window : public PlatformWindow, public WmMoveResizeHandler, public XWindow, @@ -44,6 +51,10 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, public XEventDispatcher, public WorkspaceExtension, public X11Extension, +#if defined(USE_OZONE) + public WmDragHandler, + public XDragDropClient::Delegate, +#endif public WmMoveLoopHandler { public: explicit X11Window(PlatformWindowDelegate* platform_window_delegate); @@ -120,10 +131,10 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, void SetX11ExtensionDelegate(X11ExtensionDelegate* delegate) override; // Overridden from ui::XEventDispatcher: - void CheckCanDispatchNextPlatformEvent(XEvent* xev) override; + void CheckCanDispatchNextPlatformEvent(x11::Event* xev) override; void PlatformEventDispatchFinished() override; PlatformEventDispatcher* GetPlatformEventDispatcher() override; - bool DispatchXEvent(XEvent* event) override; + bool DispatchXEvent(x11::Event* event) override; protected: PlatformWindowDelegate* platform_window_delegate() const { @@ -145,8 +156,8 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, void OnXWindowIsActiveChanged(bool active) override; void OnXWindowWorkspaceChanged() override; void OnXWindowLostPointerGrab() override; - void OnXWindowSelectionEvent(XEvent* xev) override; - void OnXWindowDragDropEvent(XEvent* xev) override; + void OnXWindowSelectionEvent(x11::Event* xev) override; + void OnXWindowDragDropEvent(x11::Event* xev) override; base::Optional<gfx::Size> GetMinimumSizeForXWindow() override; base::Optional<gfx::Size> GetMaximumSizeForXWindow() override; void GetWindowMaskForXWindow(const gfx::Size& size, @@ -157,7 +168,7 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, bool CanDispatchEvent(const PlatformEvent& event) override; uint32_t DispatchEvent(const PlatformEvent& event) override; - void DispatchUiEvent(ui::Event* event, XEvent* xev); + void DispatchUiEvent(ui::Event* event, x11::Event* xev); // WmMoveResizeHandler void DispatchHostWindowDragMovement( @@ -168,8 +179,27 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, bool RunMoveLoop(const gfx::Vector2d& drag_offset) override; void EndMoveLoop() override; +#if defined(USE_OZONE) + // WmDragHandler + void StartDrag(const ui::OSExchangeData& data, + int operation, + gfx::NativeCursor cursor, + WmDragHandler::Delegate* delegate) override; + + // ui::XDragDropClient::Delegate + std::unique_ptr<ui::XTopmostWindowFinder> CreateWindowFinder() override; + int UpdateDrag(const gfx::Point& screen_point) override; + void UpdateCursor( + ui::DragDropTypes::DragOperation negotiated_operation) override; + void OnBeginForeignDrag(x11::Window window) override; + void OnEndForeignDrag() override; + void OnBeforeDragLeave() override; + int PerformDrop() override; + void EndDragLoop() override; +#endif // defined(USE_OZONE) + // Handles |xevent| as a Atk Key Event - bool HandleAsAtkEvent(XEvent* xevent); + bool HandleAsAtkEvent(x11::Event* xevent); // Adjusts |requested_size_in_pixels| to avoid the WM "feature" where setting // the window size to the monitor size causes the WM to set the EWMH for @@ -205,12 +235,25 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, gfx::Rect restored_bounds_in_pixels_; // Tells if this dispatcher can process next translated event based on a - // previous check in ::CheckCanDispatchNextPlatformEvent based on a XID - // target. - XEvent* current_xevent_ = nullptr; + // previous check in ::CheckCanDispatchNextPlatformEvent based on a + // x11::Window target. + x11::Event* current_xevent_ = nullptr; std::unique_ptr<X11DesktopWindowMoveClient> x11_window_move_client_; +#if defined(USE_OZONE) + // True while the drag initiated in this window is in progress. + bool dragging_ = false; + // Whether the drop handler has notified that the drag has entered. + bool notified_enter_ = false; + // Keeps the last negotiated operation returned by the drop handler. + int drag_operation_ = 0; + + // Handles XDND events going through this window. + std::unique_ptr<XDragDropClient> drag_drop_client_; + WmDragHandler::Delegate* drag_handler_delegate_ = nullptr; +#endif // defined(USE_OZONE) + DISALLOW_COPY_AND_ASSIGN(X11Window); }; |