diff --git a/ash/BUILD.gn b/ash/BUILD.gn index c483dc6a98d83..07101cdb14f2d 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn @@ -2300,6 +2300,7 @@ static_library("test_support") { "//base:i18n", "//base/test:test_support", "//cc:test_support", + "//ui/platform_window/common", # TODO(https://crbug.com/644336): Make CrasAudioHandler Chrome or Ash only. "//chromeos/audio", diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index 8cf21e608a6f7..435183f05ad46 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc @@ -55,7 +55,6 @@ #include "ui/aura/window.h" #include "ui/base/ime/init/input_method_initializer.h" #include "ui/base/material_design/material_design_controller.h" -#include "ui/base/platform_window_defaults.h" #include "ui/base/ui_base_switches_util.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/test/test_context_factories.h" @@ -64,6 +63,7 @@ #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" #include "ui/display/test/display_manager_test_api.h" +#include "ui/platform_window/common/platform_window_defaults.h" #include "ui/wm/core/capture_controller.h" #include "ui/wm/core/cursor_manager.h" #include "ui/wm/core/wm_state.h" diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index a72290f925cb5..7c43cf0149cdb 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn @@ -2479,6 +2479,7 @@ jumbo_split_static_library("ui") { "views/frame/browser_desktop_window_tree_host_platform.h", "views/frame/native_browser_frame_factory_ozone.cc", ] + deps += [ "//ui/platform_window" ] } if (use_gtk) { # This is the only component that can interact with gtk. diff --git a/components/viz/demo/demo_main.cc b/components/viz/demo/demo_main.cc index c12b97b8a6c5a..f5785dc076111 100644 --- a/components/viz/demo/demo_main.cc +++ b/components/viz/demo/demo_main.cc @@ -31,7 +31,7 @@ #endif #if defined(USE_X11) -#include "ui/platform_window/x11/x11_window.h" +#include "ui/platform_window/x11/x11_window.h" // nogncheck #endif namespace { @@ -119,7 +119,9 @@ class DemoWindow : public ui::PlatformWindowDelegate { #elif defined(OS_WIN) return std::make_unique<ui::WinWindow>(this, props.bounds); #elif defined(USE_X11) - return std::make_unique<ui::X11Window>(this, props.bounds); + auto x11_window = std::make_unique<ui::X11Window>(this, nullptr); + x11_window->Initialize(std::move(props)); + return x11_window; #else NOTIMPLEMENTED(); return nullptr; diff --git a/content/public/test/DEPS b/content/public/test/DEPS index 75250ec524ce9..ad1434cc38c14 100644 --- a/content/public/test/DEPS +++ b/content/public/test/DEPS @@ -16,6 +16,7 @@ include_rules = [ "+ui/ozone/public", "+ui/views/test", "+v8/include/v8.h", + "+ui/platform_window/common/platform_window_defaults.h", ] # Ensure we don't leak internal content headers through public headers. diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index ba65b011632cf..3546123a72fb3 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc @@ -64,12 +64,15 @@ #include "services/service_manager/embedder/switches.h" #include "services/service_manager/public/cpp/connector.h" #include "services/tracing/public/cpp/trace_startup.h" -#include "ui/base/platform_window_defaults.h" #include "ui/compositor/compositor_switches.h" #include "ui/display/display_switches.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_switches.h" +#if defined(OS_LINUX) +#include "ui/platform_window/common/platform_window_defaults.h" // nogncheck +#endif + #if defined(OS_ANDROID) #include "base/android/task_scheduler/post_task_android.h" #include "components/discardable_memory/service/discardable_shared_memory_manager.h" // nogncheck @@ -173,7 +176,9 @@ BrowserTestBase::BrowserTestBase() enable_pixel_output_(false), use_software_compositing_(false), set_up_called_(false) { +#if defined(OS_LINUX) ui::test::EnableTestConfigForPlatformWindows(); +#endif #if defined(OS_POSIX) handle_sigterm_ = true; diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index fb449d8e5148b..2b8672f6846f0 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn @@ -583,6 +583,10 @@ jumbo_static_library("test_support") { "//ui/accelerated_widget_mac", ] } + + if (is_linux) { + deps += [ "//ui/platform_window/common" ] + } } # browsertest_support can be used by targets that run content_shell based diff --git a/gpu/vulkan/demo/vulkan_demo.cc b/gpu/vulkan/demo/vulkan_demo.cc index 12bd91e6f342a..2e2bc6bc55bad 100644 --- a/gpu/vulkan/demo/vulkan_demo.cc +++ b/gpu/vulkan/demo/vulkan_demo.cc @@ -19,6 +19,7 @@ #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrContext.h" #include "ui/events/platform/platform_event_source.h" +#include "ui/platform_window/platform_window_init_properties.h" #include "ui/platform_window/x11/x11_window.h" namespace gpu { @@ -41,13 +42,17 @@ void VulkanDemo::Initialize() { event_source_ = ui::PlatformEventSource::CreateDefault(); - gfx::Size size(800, 600); - window_ = std::make_unique<ui::X11Window>( - this, gfx::Rect(gfx::Point(100, 100), size)); + ui::PlatformWindowInitProperties properties; + properties.bounds = gfx::Rect(100, 100, 800, 600); + auto x11_window = std::make_unique<ui::X11Window>(this, nullptr); + x11_window->Initialize(std::move(properties)); + + window_ = std::move(x11_window); window_->Show(); // Sync up size between |window_| and |vulkan_surface_| - vulkan_surface_->Reshape(size, gfx::OVERLAY_TRANSFORM_NONE); + vulkan_surface_->Reshape(window_->GetBounds().size(), + gfx::OVERLAY_TRANSFORM_NONE); sk_surfaces_.resize(vulkan_surface_->swap_chain()->num_images()); } diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn index bc5066649485a..355a27984b839 100644 --- a/ui/aura/BUILD.gn +++ b/ui/aura/BUILD.gn @@ -251,6 +251,10 @@ jumbo_static_library("test_support") { } sources += [ "test/ui_controls_factory_ozone.cc" ] } + + if (is_linux) { + deps += [ "//ui/platform_window/common" ] + } } executable("aura_demo") { diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc index 3a2e00b391e29..d17f4de889730 100644 --- a/ui/aura/test/aura_test_helper.cc +++ b/ui/aura/test/aura_test_helper.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/run_loop.h" +#include "build/build_config.h" #include "ui/aura/client/default_capture_client.h" #include "ui/aura/client/focus_client.h" #include "ui/aura/env.h" @@ -21,13 +22,16 @@ #include "ui/aura/window_targeter.h" #include "ui/base/ime/init/input_method_factory.h" #include "ui/base/ime/init/input_method_initializer.h" -#include "ui/base/platform_window_defaults.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/display/screen.h" #include "ui/wm/core/wm_state.h" +#if defined(OS_LINUX) +#include "ui/platform_window/common/platform_window_defaults.h" // nogncheck +#endif + #if defined(USE_X11) #include "ui/base/x/x11_util.h" // nogncheck #endif @@ -47,7 +51,9 @@ AuraTestHelper::AuraTestHelper(std::unique_ptr<Env> env) // Disable animations during tests. zero_duration_mode_ = std::make_unique<ui::ScopedAnimationDurationScaleMode>( ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); +#if defined(OS_LINUX) ui::test::EnableTestConfigForPlatformWindows(); +#endif } AuraTestHelper::~AuraTestHelper() { diff --git a/ui/aura/window_tree_host_platform.cc b/ui/aura/window_tree_host_platform.cc index fe8e2ba5a5046..fe1dc9acf0e0f 100644 --- a/ui/aura/window_tree_host_platform.cc +++ b/ui/aura/window_tree_host_platform.cc @@ -34,7 +34,7 @@ #endif #if defined(USE_X11) -#include "ui/platform_window/x11/x11_window.h" +#include "ui/platform_window/x11/x11_window.h" // nogncheck #endif namespace aura { @@ -72,9 +72,11 @@ void WindowTreeHostPlatform::CreateAndSetPlatformWindow( platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow( this, std::move(properties)); #elif defined(OS_WIN) - platform_window_ = std::make_unique<ui::WinWindow>(this, properties.bounds); + platform_window_.reset(new ui::WinWindow(this, properties.bounds)); #elif defined(USE_X11) - platform_window_ = std::make_unique<ui::X11Window>(this, properties.bounds); + auto x11_window = std::make_unique<ui::X11Window>(this, nullptr); + x11_window->Initialize(std::move(properties)); + SetPlatformWindow(std::move(x11_window)); #else NOTIMPLEMENTED(); #endif @@ -269,7 +271,6 @@ void WindowTreeHostPlatform::OnAcceleratedWidgetDestroyed() { widget_ = gfx::kNullAcceleratedWidget; } -void WindowTreeHostPlatform::OnActivationChanged(bool active) { -} +void WindowTreeHostPlatform::OnActivationChanged(bool active) {} } // namespace aura diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 234227d7e472b..0a3994cebd4a1 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn @@ -218,8 +218,6 @@ jumbo_component("base") { "nine_image_painter_factory.h", "page_transition_types.cc", "page_transition_types.h", - "platform_window_defaults.cc", - "platform_window_defaults.h", "resource/resource_bundle.cc", "resource/resource_bundle.h", "resource/resource_bundle_android.cc", diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn index f0175b4b4c784..d94dae6933b91 100644 --- a/ui/base/x/BUILD.gn +++ b/ui/base/x/BUILD.gn @@ -47,5 +47,6 @@ jumbo_component("x") { "//ui/events/x:x", "//ui/gfx", "//ui/gfx/x", + "//ui/platform_window/common", ] } diff --git a/ui/base/x/DEPS b/ui/base/x/DEPS new file mode 100644 index 0000000000000..edeb0030468d9 --- /dev/null +++ b/ui/base/x/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+ui/platform_window/common/platform_window_defaults.h", +] diff --git a/ui/base/x/x11_window.cc b/ui/base/x/x11_window.cc index fb188e0f8a5bb..1bb97da344812 100644 --- a/ui/base/x/x11_window.cc +++ b/ui/base/x/x11_window.cc @@ -26,6 +26,7 @@ #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_rep.h" #include "ui/gfx/x/x11_atom_cache.h" +#include "ui/platform_window/common/platform_window_defaults.h" namespace ui { @@ -104,11 +105,9 @@ XWindow::Configuration::Configuration(const Configuration&) = default; XWindow::Configuration::~Configuration() = default; -XWindow::XWindow(Delegate* delegate) - : delegate_(delegate), - xdisplay_(gfx::GetXDisplay()), +XWindow::XWindow() + : xdisplay_(gfx::GetXDisplay()), x_root_window_(DefaultRootWindow(xdisplay_)) { - DCHECK(delegate_); DCHECK(xdisplay_); DCHECK_NE(x_root_window_, x11::None); } @@ -153,6 +152,21 @@ void XWindow::Init(const Configuration& config) { if (!activatable_) swa.override_redirect = x11::True; +#if !defined(USE_X11) + // It seems like there is a difference how tests are instantiated in case of + // non-Ozone X11 and Ozone. See more details in + // EnableTestConfigForPlatformWindows. The reason why this must be here is + // that we removed X11WindowBase in favor of the XWindow. The X11WindowBase + // was only used with PlatformWindow, which meant non-Ozone X11 did not use it + // and set override_redirect based only on |activatable_| variable or + // WindowType. But now as XWindow is subclassed by X11Window, which is also a + // PlatformWindow, and non-Ozone X11 uses it, we have to add this workaround + // here. Otherwise, tests for non-Ozone X11 fail. + // TODO(msisov): figure out usage of this for non-Ozone X11. + if (UseTestConfigForPlatformWindows()) + swa.override_redirect = true; +#endif + override_redirect_ = swa.override_redirect == x11::True; if (override_redirect_) attribute_mask |= CWOverrideRedirect; @@ -197,8 +211,7 @@ void XWindow::Init(const Configuration& config) { bounds_in_pixels_.height(), 0, // border width depth, InputOutput, visual, attribute_mask, &swa); - - delegate_->OnXWindowCreated(); + OnXWindowCreated(); // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL(). @@ -753,7 +766,7 @@ void XWindow::OnWorkspaceUpdated() { workspace_ = base::nullopt; if (workspace_ != old_workspace) - delegate_->OnXWindowWorkspaceChanged(); + OnXWindowWorkspaceChanged(); } void XWindow::SetAlwaysOnTop(bool always_on_top) { @@ -782,21 +795,22 @@ void XWindow::FlashFrame(bool flash_frame) { } void XWindow::UpdateMinAndMaxSize() { - gfx::Size minimum_in_pixels = delegate_->GetMinimumSizeForXWindow(); - gfx::Size maximum_in_pixels = delegate_->GetMaximumSizeForXWindow(); - if (min_size_in_pixels_ == minimum_in_pixels && - max_size_in_pixels_ == maximum_in_pixels) + base::Optional<gfx::Size> minimum_in_pixels = GetMinimumSizeForXWindow(); + base::Optional<gfx::Size> maximum_in_pixels = GetMaximumSizeForXWindow(); + if ((!minimum_in_pixels || + min_size_in_pixels_ == minimum_in_pixels.value()) && + (!maximum_in_pixels || max_size_in_pixels_ == maximum_in_pixels.value())) return; - min_size_in_pixels_ = minimum_in_pixels; - max_size_in_pixels_ = maximum_in_pixels; + min_size_in_pixels_ = minimum_in_pixels.value(); + max_size_in_pixels_ = maximum_in_pixels.value(); XSizeHints hints; hints.flags = 0; long supplied_return; XGetWMNormalHints(xdisplay_, xwindow_, &hints, &supplied_return); - if (minimum_in_pixels.IsEmpty()) { + if (min_size_in_pixels_.IsEmpty()) { hints.flags &= ~PMinSize; } else { hints.flags |= PMinSize; @@ -804,7 +818,7 @@ void XWindow::UpdateMinAndMaxSize() { hints.min_height = min_size_in_pixels_.height(); } - if (maximum_in_pixels.IsEmpty()) { + if (max_size_in_pixels_.IsEmpty()) { hints.flags &= ~PMaxSize; } else { hints.flags |= PMaxSize; @@ -824,19 +838,19 @@ void XWindow::BeforeActivationStateChanged() { void XWindow::AfterActivationStateChanged() { if (had_pointer_grab_ && !has_pointer_grab_) - delegate_->OnXWindowLostPointerGrab(); + OnXWindowLostPointerGrab(); bool had_pointer_capture = had_pointer_ || had_pointer_grab_; bool has_pointer_capture = has_pointer_ || has_pointer_grab_; if (had_pointer_capture && !has_pointer_capture) - delegate_->OnXWindowLostCapture(); + OnXWindowLostCapture(); bool is_active = IsActive(); if (!was_active_ && is_active) FlashFrame(false); if (was_active_ != is_active) - delegate_->OnXWindowIsActiveChanged(is_active); + OnXWindowIsActiveChanged(is_active); } void XWindow::SetUseNativeFrame(bool use_native_frame) { @@ -1036,7 +1050,7 @@ void XWindow::ProcessEvent(XEvent* xev) { gfx::Point window_origin = gfx::Point() + (root_point - window_point); if (bounds_in_pixels_.origin() != window_origin) { bounds_in_pixels_.set_origin(window_origin); - delegate_->OnXWindowMoved(window_origin); + OnXWindowBoundsChanged(bounds_in_pixels_); } } @@ -1045,11 +1059,16 @@ void XWindow::ProcessEvent(XEvent* xev) { switch (xev->type) { case EnterNotify: case LeaveNotify: { +#if defined(USE_X11) // Ignore EventNotify and LeaveNotify events from children of |xwindow_|. // NativeViewGLSurfaceGLX adds a child to |xwindow_|. if (xev->xcrossing.detail != NotifyInferior) { - delegate_->OnXWindowChildCrossingEvent(xev); - } else { + DCHECK(xev); + ui::MouseEvent mouse_event(xev); + OnXWindowEvent(&mouse_event); + } else +#endif + { bool is_enter = xev->type == EnterNotify; OnCrossingEvent(is_enter, xev->xcrossing.focus, xev->xcrossing.mode, xev->xcrossing.detail); @@ -1059,13 +1078,13 @@ void XWindow::ProcessEvent(XEvent* xev) { case Expose: { gfx::Rect damage_rect_in_pixels(xev->xexpose.x, xev->xexpose.y, xev->xexpose.width, xev->xexpose.height); - delegate_->OnXWindowDamageEvent(damage_rect_in_pixels); + OnXWindowDamageEvent(damage_rect_in_pixels); break; } #if !defined(USE_OZONE) case KeyPress: case KeyRelease: - delegate_->OnXWindowRawKeyEvent(xev); + OnXWindowRawKeyEvent(xev); break; case ButtonPress: case ButtonRelease: { @@ -1073,13 +1092,13 @@ void XWindow::ProcessEvent(XEvent* xev) { switch (event_type) { case ui::ET_MOUSEWHEEL: { ui::MouseWheelEvent mouseev(xev); - delegate_->OnXWindowMouseEvent(&mouseev); + OnXWindowEvent(&mouseev); break; } case ui::ET_MOUSE_PRESSED: case ui::ET_MOUSE_RELEASED: { ui::MouseEvent mouseev(xev); - delegate_->OnXWindowMouseEvent(&mouseev); + OnXWindowEvent(&mouseev); break; } case ui::ET_UNKNOWN: @@ -1137,7 +1156,7 @@ void XWindow::ProcessEvent(XEvent* xev) { case ui::ET_TOUCH_PRESSED: case ui::ET_TOUCH_RELEASED: { ui::TouchEvent touchev(xev); - delegate_->OnXWindowTouchEvent(&touchev); + OnXWindowEvent(&touchev); break; } case ui::ET_MOUSE_MOVED: @@ -1162,12 +1181,12 @@ void XWindow::ProcessEvent(XEvent* xev) { // DT_CMT_SCROLL_ data. See more discussion in // https://crrev.com/c/853953 if (mouseev.type() != ui::ET_UNKNOWN) - delegate_->OnXWindowMouseEvent(&mouseev); + OnXWindowEvent(&mouseev); break; } case ui::ET_MOUSEWHEEL: { ui::MouseWheelEvent mouseev(xev); - delegate_->OnXWindowMouseEvent(&mouseev); + OnXWindowEvent(&mouseev); break; } case ui::ET_SCROLL_FLING_START: @@ -1179,13 +1198,13 @@ void XWindow::ProcessEvent(XEvent* xev) { // event and we need delta to determine which element to scroll on // phaseBegan. if (scrollev.x_offset() != 0.0 || scrollev.y_offset() != 0.0) - delegate_->OnXWindowScrollEvent(&scrollev); + OnXWindowEvent(&scrollev); break; } case ui::ET_KEY_PRESSED: case ui::ET_KEY_RELEASED: { ui::KeyEvent key_event(xev); - delegate_->OnXWindowKeyEvent(&key_event); + OnXWindowEvent(&key_event); break; } case ui::ET_UNKNOWN: @@ -1211,7 +1230,7 @@ void XWindow::ProcessEvent(XEvent* xev) { has_pointer_grab_ = false; has_pointer_focus_ = false; has_window_focus_ = false; - delegate_->OnXWindowUnmapped(); + OnXWindowUnmapped(); break; } case ClientMessage: { @@ -1220,7 +1239,7 @@ void XWindow::ProcessEvent(XEvent* xev) { Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]); if (protocol == gfx::GetAtom("WM_DELETE_WINDOW")) { // We have received a close message from the window manager. - delegate_->OnXWindowCloseRequested(); + OnXWindowCloseRequested(); } else if (protocol == gfx::GetAtom("_NET_WM_PING")) { XEvent reply_event = *xev; reply_event.xclient.window = x_root_window_; @@ -1235,7 +1254,7 @@ void XWindow::ProcessEvent(XEvent* xev) { pending_counter_value_is_extended_ = xev->xclient.data.l[4] != 0; } } else { - delegate_->OnXWindowDragDropEvent(xev); + OnXWindowDragDropEvent(xev); } break; } @@ -1274,7 +1293,7 @@ void XWindow::ProcessEvent(XEvent* xev) { } ui::MouseEvent mouseev(xev); - delegate_->OnXWindowMouseEvent(&mouseev); + OnXWindowEvent(&mouseev); break; } #endif @@ -1290,7 +1309,7 @@ void XWindow::ProcessEvent(XEvent* xev) { break; } case SelectionNotify: { - delegate_->OnXWindowSelectionEvent(xev); + OnXWindowSelectionEvent(xev); break; } } @@ -1314,7 +1333,7 @@ void XWindow::UpdateWMUserTime(XEvent* xev) { void XWindow::OnWindowMapped() { window_mapped_in_server_ = true; - delegate_->OnXWindowMapped(); + OnXWindowMapped(); // Some WMs only respect maximize hints after the window has been mapped. // Check whether we need to re-do a maximization. if (should_maximize_after_map_) { @@ -1353,11 +1372,10 @@ void XWindow::OnConfigureEvent(XEvent* xev) { previous_bounds_in_pixels_ = bounds_in_pixels_; bounds_in_pixels_ = bounds_in_pixels; - if (origin_changed) - delegate_->OnXWindowMoved(bounds_in_pixels_.origin()); - if (size_changed) - delegate_->OnXWindowSizeChanged(bounds_in_pixels_.size()); + DispatchResize(); + else if (origin_changed) + OnXWindowBoundsChanged(bounds_in_pixels_); } void XWindow::SetWMSpecState(bool enabled, XAtom state1, XAtom state2) { @@ -1403,8 +1421,7 @@ void XWindow::UpdateWindowProperties( is_always_on_top_ = ui::HasWMSpecProperty( window_properties_, gfx::GetAtom("_NET_WM_STATE_ABOVE")); - - delegate_->OnXWindowStateChanged(); + OnXWindowStateChanged(); } void XWindow::OnFrameExtentsUpdated() { @@ -1448,7 +1465,7 @@ void XWindow::DispatchResize() { // compositor. delayed_resize_task_.Reset(base::BindOnce(&XWindow::DelayedResize, weak_factory_.GetWeakPtr(), - bounds_in_pixels_.size())); + bounds_in_pixels_)); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, delayed_resize_task_.callback()); return; @@ -1465,10 +1482,10 @@ void XWindow::DispatchResize() { // If _NET_WM_SYNC_REQUEST is used to synchronize with compositor during // resizing, the compositor will not resize the window, until last resize is // handled, so we don't need accumulate resize events. - DelayedResize(bounds_in_pixels_.size()); + DelayedResize(bounds_in_pixels_); } -void XWindow::DelayedResize(const gfx::Size& size_in_pixels) { +void XWindow::DelayedResize(const gfx::Rect& bounds_in_pixels) { if (configure_counter_value_is_extended_ && (current_counter_value_ % 2) == 0) { // Increase the |extended_update_counter_|, so the compositor will know we @@ -1478,7 +1495,7 @@ void XWindow::DelayedResize(const gfx::Size& size_in_pixels) { SyncSetCounter(xdisplay_, extended_update_counter_, ++current_counter_value_); } - delegate_->OnXWindowSizeChanged(size_in_pixels); + OnXWindowBoundsChanged(bounds_in_pixels); CancelResize(); } @@ -1525,43 +1542,4 @@ void XWindow::UnconfineCursor() { has_pointer_barriers_ = false; } -// Empty/stub implementation of XWindow::Delegate methods, which are considered -// optional for ui::XWindow users, making it possible to handle only events of -// interest. -void XWindow::Delegate::OnXWindowMapped() {} - -void XWindow::Delegate::OnXWindowUnmapped() {} - -void XWindow::Delegate::OnXWindowMoved(const gfx::Point&) {} - -void XWindow::Delegate::OnXWindowWorkspaceChanged() {} - -void XWindow::Delegate::OnXWindowLostPointerGrab() {} - -void XWindow::Delegate::OnXWindowLostCapture() {} - -void XWindow::Delegate::OnXWindowKeyEvent(ui::KeyEvent*) {} - -void XWindow::Delegate::OnXWindowMouseEvent(ui::MouseEvent*) {} - -void XWindow::Delegate::OnXWindowTouchEvent(ui::TouchEvent*) {} - -void XWindow::Delegate::OnXWindowScrollEvent(ui::ScrollEvent*) {} - -void XWindow::Delegate::OnXWindowSelectionEvent(XEvent*) {} - -void XWindow::Delegate::OnXWindowDragDropEvent(XEvent*) {} - -void XWindow::Delegate::OnXWindowChildCrossingEvent(XEvent*) {} - -void XWindow::Delegate::OnXWindowRawKeyEvent(XEvent*) {} - -gfx::Size XWindow::Delegate::GetMinimumSizeForXWindow() { - return gfx::Size(); -} - -gfx::Size XWindow::Delegate::GetMaximumSizeForXWindow() { - return gfx::Size(); -} - } // namespace ui diff --git a/ui/base/x/x11_window.h b/ui/base/x/x11_window.h index 8d2e13844c8f3..9db97d2f52145 100644 --- a/ui/base/x/x11_window.h +++ b/ui/base/x/x11_window.h @@ -29,10 +29,7 @@ class ImageSkia; namespace ui { -class KeyEvent; -class MouseEvent; -class TouchEvent; -class ScrollEvent; +class Event; class XScopedEventSelector; //////////////////////////////////////////////////////////////////////////////// @@ -88,7 +85,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { std::string wm_role_name; }; - explicit XWindow(Delegate* delegate); + XWindow(); virtual ~XWindow(); void Init(const Configuration& config); @@ -188,7 +185,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { // Handle the state change since BeforeActivationStateChanged(). void AfterActivationStateChanged(); - void DelayedResize(const gfx::Size& size_in_pixels); + void DelayedResize(const gfx::Rect& bounds_in_pixels); // Updates |xwindow_|'s _NET_WM_USER_TIME if |xwindow_| is active. void UpdateWMUserTime(XEvent* event); @@ -209,7 +206,25 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { void UnconfineCursor(); - Delegate* delegate_; + // Interface that must be used by a class that inherits the XWindow to receive + // different messages from X Server. + virtual void OnXWindowCreated() = 0; + virtual void OnXWindowStateChanged() = 0; + virtual void OnXWindowDamageEvent(const gfx::Rect& damage_rect) = 0; + virtual void OnXWindowBoundsChanged(const gfx::Rect& size) = 0; + virtual void OnXWindowCloseRequested() = 0; + virtual void OnXWindowIsActiveChanged(bool active) = 0; + virtual void OnXWindowMapped() = 0; + virtual void OnXWindowUnmapped() = 0; + virtual void OnXWindowWorkspaceChanged() = 0; + virtual void OnXWindowLostPointerGrab() = 0; + virtual void OnXWindowLostCapture() = 0; + virtual void OnXWindowEvent(ui::Event* event) = 0; + virtual void OnXWindowSelectionEvent(XEvent* xev) = 0; + virtual void OnXWindowDragDropEvent(XEvent* xev) = 0; + virtual void OnXWindowRawKeyEvent(XEvent* xev) = 0; + virtual base::Optional<gfx::Size> GetMinimumSizeForXWindow() = 0; + virtual base::Optional<gfx::Size> GetMaximumSizeForXWindow() = 0; // The display and the native X window hosting the root window. XDisplay* xdisplay_ = nullptr; @@ -347,44 +362,6 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { DISALLOW_COPY_AND_ASSIGN(XWindow); }; -// Delegate interface used to communicate the XWindow API client about events -// of interest and request information which depends on external components. -class COMPONENT_EXPORT(UI_BASE_X) XWindow::Delegate { - public: - virtual void OnXWindowCreated() = 0; - virtual void OnXWindowStateChanged() = 0; - virtual void OnXWindowDamageEvent(const gfx::Rect& damage_rect) = 0; - virtual void OnXWindowSizeChanged(const gfx::Size& size) = 0; - virtual void OnXWindowCloseRequested() = 0; - virtual void OnXWindowIsActiveChanged(bool active) = 0; - - // Optional Hooks - virtual void OnXWindowMapped(); - virtual void OnXWindowUnmapped(); - virtual void OnXWindowMoved(const gfx::Point& window_origin); - virtual void OnXWindowWorkspaceChanged(); - virtual void OnXWindowLostPointerGrab(); - virtual void OnXWindowLostCapture(); - - // TODO(crbug.com/981606): Consider unifying event handling functions - virtual void OnXWindowKeyEvent(ui::KeyEvent* key_event); - virtual void OnXWindowMouseEvent(ui::MouseEvent* event); - virtual void OnXWindowTouchEvent(ui::TouchEvent* event); - virtual void OnXWindowScrollEvent(ui::ScrollEvent* event); - - virtual void OnXWindowSelectionEvent(XEvent* xev); - virtual void OnXWindowDragDropEvent(XEvent* xev); - virtual void OnXWindowChildCrossingEvent(XEvent* xev); - - // TODO(crbug.com/981606): DesktopWindowTreeHostX11 forward raw |XEvent|s to - // ATK components that currently live in views layer. Remove once ATK code - // is reworked to be reusable. - virtual void OnXWindowRawKeyEvent(XEvent* xev); - - virtual gfx::Size GetMinimumSizeForXWindow(); - virtual gfx::Size GetMaximumSizeForXWindow(); -}; - } // namespace ui #endif // UI_BASE_X_X11_WINDOW_H_ diff --git a/ui/events/platform/x11/x11_event_source.h b/ui/events/platform/x11/x11_event_source.h index e44fb018b8a28..a655cc82bead6 100644 --- a/ui/events/platform/x11/x11_event_source.h +++ b/ui/events/platform/x11/x11_event_source.h @@ -160,8 +160,8 @@ class EVENTS_EXPORT X11EventSource { // State necessary for UpdateLastSeenServerTime bool dummy_initialized_; - XWindow dummy_window_; - XAtom dummy_atom_; + ::XWindow dummy_window_; + ::XAtom dummy_atom_; std::unique_ptr<XScopedEventSelector> dummy_window_events_; // Keeps track of whether this source should continue to dispatch all the diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index fa26af644ae00..4657246ecf141 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn @@ -474,6 +474,10 @@ jumbo_static_library("test_support") { "//ui/base", ] + if (is_linux) { + deps += [ "//ui/platform_window/common" ] + } + if (use_x11) { configs += [ "//build/config/linux:x11" ] deps += [ "//ui/platform_window/x11" ] diff --git a/ui/gl/test/DEPS b/ui/gl/test/DEPS index 8330a1388fa01..0349f946eb8a7 100644 --- a/ui/gl/test/DEPS +++ b/ui/gl/test/DEPS @@ -5,4 +5,5 @@ include_rules = [ "+mojo/core/embedder", "+services/service_manager/public", "+services/viz/public", + "+ui/platform_window/common/platform_window_defaults.h", ] diff --git a/ui/gl/test/gl_surface_test_support.cc b/ui/gl/test/gl_surface_test_support.cc index b2e456bb19e42..0b446da9c1372 100644 --- a/ui/gl/test/gl_surface_test_support.cc +++ b/ui/gl/test/gl_surface_test_support.cc @@ -9,12 +9,15 @@ #include "base/command_line.h" #include "base/logging.h" #include "build/build_config.h" -#include "ui/base/platform_window_defaults.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_switches.h" #include "ui/gl/init/gl_factory.h" +#if defined(OS_LINUX) +#include "ui/platform_window/common/platform_window_defaults.h" // nogncheck +#endif + #if defined(USE_OZONE) #include "ui/ozone/public/ozone_platform.h" #endif @@ -40,7 +43,9 @@ void InitializeOneOffHelper(bool init_extensions) { ui::OzonePlatform::GetInstance()->AfterSandboxEntry(); #endif +#if defined(OS_LINUX) ui::test::EnableTestConfigForPlatformWindows(); +#endif bool use_software_gl = true; diff --git a/ui/ozone/platform/cast/platform_window_cast.cc b/ui/ozone/platform/cast/platform_window_cast.cc index 697a3e30463c7..84b68c891dfd6 100644 --- a/ui/ozone/platform/cast/platform_window_cast.cc +++ b/ui/ozone/platform/cast/platform_window_cast.cc @@ -10,7 +10,6 @@ #include "ui/events/platform/platform_event_source.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" -#include "ui/platform_window/platform_window_delegate.h" namespace ui { diff --git a/ui/ozone/platform/cast/platform_window_cast.h b/ui/ozone/platform/cast/platform_window_cast.h index 500a5bf83dc41..35fb374a2e89c 100644 --- a/ui/ozone/platform/cast/platform_window_cast.h +++ b/ui/ozone/platform/cast/platform_window_cast.h @@ -7,12 +7,11 @@ #include "base/macros.h" #include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/stub/stub_window.h" namespace ui { -class PlatformWindowDelegate; - class PlatformWindowCast : public StubWindow, public PlatformEventDispatcher { public: PlatformWindowCast(PlatformWindowDelegate* delegate, const gfx::Rect& bounds); diff --git a/ui/ozone/platform/drm/host/drm_window_host.cc b/ui/ozone/platform/drm/host/drm_window_host.cc index e76d4d4a15ba2..4c5a1b26ceb5a 100644 --- a/ui/ozone/platform/drm/host/drm_window_host.cc +++ b/ui/ozone/platform/drm/host/drm_window_host.cc @@ -17,7 +17,6 @@ #include "ui/ozone/platform/drm/host/drm_display_host_manager.h" #include "ui/ozone/platform/drm/host/drm_window_host_manager.h" #include "ui/ozone/platform/drm/host/gpu_thread_adapter.h" -#include "ui/platform_window/platform_window_delegate.h" namespace ui { diff --git a/ui/ozone/platform/drm/host/drm_window_host.h b/ui/ozone/platform/drm/host/drm_window_host.h index b4374978d5f56..2524f2175d9a2 100644 --- a/ui/ozone/platform/drm/host/drm_window_host.h +++ b/ui/ozone/platform/drm/host/drm_window_host.h @@ -16,6 +16,7 @@ #include "ui/gfx/native_widget_types.h" #include "ui/ozone/platform/drm/host/gpu_thread_observer.h" #include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_delegate.h" namespace ui { @@ -25,7 +26,6 @@ class DrmOverlayManager; class DrmWindowHostManager; class EventFactoryEvdev; class GpuThreadAdapter; -class PlatformWindowDelegate; // Implementation of the platform window. This object and its handle |widget_| // uniquely identify a window. Since the DRI/GBM platform is split into 2 diff --git a/ui/ozone/platform/headless/headless_window.cc b/ui/ozone/platform/headless/headless_window.cc index 3e3877068dbc5..d4444e3fd1645 100644 --- a/ui/ozone/platform/headless/headless_window.cc +++ b/ui/ozone/platform/headless/headless_window.cc @@ -9,7 +9,6 @@ #include "build/build_config.h" #include "ui/events/platform/platform_event_source.h" #include "ui/ozone/platform/headless/headless_window_manager.h" -#include "ui/platform_window/platform_window_delegate.h" namespace ui { diff --git a/ui/ozone/platform/headless/headless_window.h b/ui/ozone/platform/headless/headless_window.h index 069048012c85f..d13c5c72369fe 100644 --- a/ui/ozone/platform/headless/headless_window.h +++ b/ui/ozone/platform/headless/headless_window.h @@ -8,11 +8,11 @@ #include "base/macros.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" +#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/stub/stub_window.h" namespace ui { -class PlatformWindowDelegate; class HeadlessWindowManager; class HeadlessWindow : public StubWindow { diff --git a/ui/ozone/platform/magma/magma_window.cc b/ui/ozone/platform/magma/magma_window.cc index 4b7d841c8fef0..3e63cd61a0161 100644 --- a/ui/ozone/platform/magma/magma_window.cc +++ b/ui/ozone/platform/magma/magma_window.cc @@ -9,7 +9,6 @@ #include "build/build_config.h" #include "ui/events/platform/platform_event_source.h" #include "ui/ozone/platform/magma/magma_window_manager.h" -#include "ui/platform_window/platform_window_delegate.h" namespace ui { diff --git a/ui/ozone/platform/magma/magma_window.h b/ui/ozone/platform/magma/magma_window.h index 94847f999fb11..fc7186fb7db59 100644 --- a/ui/ozone/platform/magma/magma_window.h +++ b/ui/ozone/platform/magma/magma_window.h @@ -8,11 +8,11 @@ #include "base/macros.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" +#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/stub/stub_window.h" namespace ui { -class PlatformWindowDelegate; class MagmaWindowManager; class MagmaWindow : public StubWindow { diff --git a/ui/ozone/platform/scenic/scenic_window.cc b/ui/ozone/platform/scenic/scenic_window.cc index 2599ee7d3b707..b89d38b16fc9a 100644 --- a/ui/ozone/platform/scenic/scenic_window.cc +++ b/ui/ozone/platform/scenic/scenic_window.cc @@ -18,7 +18,6 @@ #include "ui/events/ozone/events_ozone.h" #include "ui/events/platform/platform_event_source.h" #include "ui/ozone/platform/scenic/scenic_window_manager.h" -#include "ui/platform_window/platform_window_delegate.h" namespace ui { diff --git a/ui/ozone/platform/scenic/scenic_window.h b/ui/ozone/platform/scenic/scenic_window.h index e8f85db55ca25..9376a08c7409b 100644 --- a/ui/ozone/platform/scenic/scenic_window.h +++ b/ui/ozone/platform/scenic/scenic_window.h @@ -22,11 +22,11 @@ #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/native_widget_types.h" #include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_delegate.h" namespace ui { class ScenicWindowManager; -class PlatformWindowDelegate; class COMPONENT_EXPORT(OZONE) ScenicWindow : public PlatformWindow, diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc index 4909a5d60d5a0..6d5533af606c5 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_window.cc @@ -166,6 +166,10 @@ bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) { is_tooltip_ = true; break; case ui::PlatformWindowType::kWindow: + case ui::PlatformWindowType::kBubble: + case ui::PlatformWindowType::kDrag: + // TODO(msisov): Figure out what kind of surface we need to create for + // bubble and drag windows. CreateXdgSurface(); break; } diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h index c5f4e55657a78..0548cbc3910a1 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.h +++ b/ui/ozone/platform/wayland/host/wayland_window.h @@ -31,7 +31,6 @@ namespace ui { class BitmapCursorOzone; class OSExchangeData; -class PlatformWindowDelegate; class WaylandConnection; class XDGPopupWrapper; class XDGSurfaceWrapper; diff --git a/ui/ozone/platform/windows/windows_window.cc b/ui/ozone/platform/windows/windows_window.cc index 8da06d171bf90..1e0ecdc03e5fd 100644 --- a/ui/ozone/platform/windows/windows_window.cc +++ b/ui/ozone/platform/windows/windows_window.cc @@ -9,7 +9,6 @@ #include "build/build_config.h" #include "ui/events/platform/platform_event_source.h" #include "ui/ozone/platform/windows/windows_window_manager.h" -#include "ui/platform_window/platform_window_delegate.h" namespace ui { diff --git a/ui/ozone/platform/windows/windows_window.h b/ui/ozone/platform/windows/windows_window.h index 87935e2cc3a16..fe5049d44047d 100644 --- a/ui/ozone/platform/windows/windows_window.h +++ b/ui/ozone/platform/windows/windows_window.h @@ -8,12 +8,11 @@ #include "base/macros.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" +#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/win/win_window.h" namespace ui { -class PlatformWindowDelegate; - class WindowsWindow : public WinWindow { public: WindowsWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds); diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc index 470673d7ca905..ed98346276abe 100644 --- a/ui/ozone/platform/x11/ozone_platform_x11.cc +++ b/ui/ozone/platform/x11/ozone_platform_x11.cc @@ -83,8 +83,9 @@ class OzonePlatformX11 : public OzonePlatform { std::unique_ptr<PlatformWindow> CreatePlatformWindow( PlatformWindowDelegate* delegate, PlatformWindowInitProperties properties) override { - std::unique_ptr<X11WindowOzone> window = std::make_unique<X11WindowOzone>( - delegate, properties, window_manager_.get()); + std::unique_ptr<X11WindowOzone> window = + std::make_unique<X11WindowOzone>(delegate, window_manager_.get()); + window->Initialize(std::move(properties)); window->SetTitle(base::ASCIIToUTF16("Ozone X11")); return std::move(window); } diff --git a/ui/ozone/platform/x11/x11_screen_ozone.cc b/ui/ozone/platform/x11/x11_screen_ozone.cc index d3b1f2522ba7b..54a8a076b8fe1 100644 --- a/ui/ozone/platform/x11/x11_screen_ozone.cc +++ b/ui/ozone/platform/x11/x11_screen_ozone.cc @@ -88,7 +88,7 @@ bool LocalProcessWindowFinder::MatchWindow(X11WindowOzone* window) const { if (!window_bounds.Contains(screen_point_in_pixels_)) return false; - ::Region shape = window->GetShape(); + ::Region shape = window->shape(); if (!shape) return true; diff --git a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc index b1bfba5b21bbf..2a4b03591c8d5 100644 --- a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc +++ b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc @@ -103,8 +103,10 @@ class X11ScreenOzoneTest : public testing::Test { EXPECT_CALL(*delegate, OnAcceleratedWidgetAvailable(_)) .WillOnce(StoreWidget(widget)); PlatformWindowInitProperties init_params(bounds); - return std::make_unique<X11WindowOzone>(delegate, init_params, - window_manager_.get()); + auto window = + std::make_unique<X11WindowOzone>(delegate, window_manager_.get()); + window->Initialize(std::move(init_params)); + return window; } MockDisplayObserver display_observer_; diff --git a/ui/ozone/platform/x11/x11_window_ozone.cc b/ui/ozone/platform/x11/x11_window_ozone.cc index 5f2b621196441..f62b39ef15638 100644 --- a/ui/ozone/platform/x11/x11_window_ozone.cc +++ b/ui/ozone/platform/x11/x11_window_ozone.cc @@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/platform_window_defaults.h" #include "ui/base/x/x11_util.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" @@ -24,71 +23,14 @@ namespace ui { -namespace { - -ui::XWindow::Configuration ConvertInitPropertiesToXWindowConfig( - const PlatformWindowInitProperties& properties) { - using WindowType = ui::XWindow::WindowType; - using WindowOpacity = ui::XWindow::WindowOpacity; - ui::XWindow::Configuration config; - - switch (properties.type) { - case PlatformWindowType::kWindow: - config.type = WindowType::kWindow; - break; - case PlatformWindowType::kMenu: - config.type = WindowType::kMenu; - break; - case PlatformWindowType::kTooltip: - config.type = WindowType::kTooltip; - break; - case PlatformWindowType::kPopup: - config.type = WindowType::kPopup; - break; - } - - switch (properties.opacity) { - case PlatformWindowOpacity::kInferOpacity: - config.opacity = WindowOpacity::kInferOpacity; - break; - case PlatformWindowOpacity::kOpaqueWindow: - config.opacity = WindowOpacity::kOpaqueWindow; - break; - case PlatformWindowOpacity::kTranslucentWindow: - config.opacity = WindowOpacity::kTranslucentWindow; - break; - } - - config.bounds = properties.bounds; - config.force_show_in_taskbar = properties.force_show_in_taskbar; - config.keep_on_top = properties.keep_on_top; - config.visible_on_all_workspaces = properties.visible_on_all_workspaces; - config.remove_standard_frame = properties.remove_standard_frame; - config.workspace = properties.workspace; - config.wm_class_name = properties.wm_class_name; - config.wm_class_class = properties.wm_class_class; - config.wm_role_name = properties.wm_role_name; - - // TODO(nickdiego): {Use,Enable}TestConfigForPlatformWindows are used by test - // infra to disable platform windows activation. Figure out another way to do - // this in case Widget::InitParams::activation is needed in the future. - config.activatable = - properties.activatable && !UseTestConfigForPlatformWindows(); - - return config; -} - -} // namespace - X11WindowOzone::X11WindowOzone(PlatformWindowDelegate* delegate, - const PlatformWindowInitProperties& properties, X11WindowManagerOzone* window_manager) - : delegate_(delegate), - window_manager_(window_manager), - x11_window_(std::make_unique<ui::XWindow>(this)) { - DCHECK(delegate_); + : X11Window(delegate, nullptr), window_manager_(window_manager) { DCHECK(window_manager_); - Init(properties); + + // 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)); } X11WindowOzone::~X11WindowOzone() { @@ -96,21 +38,8 @@ X11WindowOzone::~X11WindowOzone() { Close(); } -void X11WindowOzone::Init(const PlatformWindowInitProperties& params) { - XWindow::Configuration config = ConvertInitPropertiesToXWindowConfig(params); - 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() { - x11_window_->Map(); -} - -void X11WindowOzone::Hide() { - x11_window_->Hide(); +void X11WindowOzone::OnLostCapture() { + X11Window::OnXWindowLostCapture(); } void X11WindowOzone::Close() { @@ -121,39 +50,14 @@ void X11WindowOzone::Close() { RemoveFromWindowManager(); SetWidget(x11::None); - x11_window_->Close(); - delegate_->OnClosed(); -} - -void X11WindowOzone::SetBounds(const gfx::Rect& bounds) { - DCHECK(!bounds.size().IsEmpty()); - - // Assume that the resize will go through as requested, which should be the - // case if we're running without a window manager. If there's a window - // manager, it can modify or ignore the request, but (per ICCCM) we'll get a - // (possibly synthetic) ConfigureNotify about the actual size and correct - // |bounds_| later. - x11_window_->SetBounds(bounds); - - // Even if the pixel bounds didn't change this call to the delegate should - // still happen. The device scale factor may have changed which effectively - // changes the bounds. - delegate_->OnBoundsChanged(bounds); -} - -gfx::Rect X11WindowOzone::GetBounds() { - return x11_window_->bounds(); -} - -void X11WindowOzone::SetTitle(const base::string16& title) { - x11_window_->SetTitle(title); + X11Window::Close(); } void X11WindowOzone::SetCapture() { if (HasCapture()) return; - x11_window_->GrabPointer(); + X11Window::SetCapture(); window_manager_->GrabEvents(this); } @@ -161,90 +65,13 @@ void X11WindowOzone::ReleaseCapture() { if (!HasCapture()) return; - x11_window_->ReleasePointerGrab(); + X11Window::ReleasePointerGrab(); window_manager_->UngrabEvents(this); } bool X11WindowOzone::HasCapture() const { return window_manager_->event_grabber() == this; } - -void X11WindowOzone::OnLostCapture() { - delegate_->OnLostCapture(); -} - -void X11WindowOzone::ToggleFullscreen() { - bool is_fullscreen = state_ == PlatformWindowState::kFullScreen; - x11_window_->SetFullscreen(!is_fullscreen); -} - -void X11WindowOzone::Maximize() { - if (state_ == PlatformWindowState::kFullScreen) - ToggleFullscreen(); - - x11_window_->Maximize(); -} - -void X11WindowOzone::Minimize() { - x11_window_->Minimize(); -} - -void X11WindowOzone::Restore() { - if (state_ == PlatformWindowState::kFullScreen) - ToggleFullscreen(); - - if (state_ == PlatformWindowState::kMaximized) { - x11_window_->Unmaximize(); - } -} - -PlatformWindowState X11WindowOzone::GetPlatformWindowState() const { - return state_; -} - -void X11WindowOzone::Activate() { - x11_window_->Activate(); -} - -void X11WindowOzone::Deactivate() { - x11_window_->Deactivate(); -} - -void X11WindowOzone::SetUseNativeFrame(bool use_native_frame) { - x11_window_->SetUseNativeFrame(use_native_frame); -} - -void X11WindowOzone::MoveCursorTo(const gfx::Point& location) { - x11_window_->MoveCursorTo(location); -} - -void X11WindowOzone::ConfineCursorToBounds(const gfx::Rect& bounds) { - x11_window_->ConfineCursorTo(bounds); -} - -void X11WindowOzone::SetRestoredBoundsInPixels(const gfx::Rect& bounds) { - // TODO(crbug.com/848131): Restore bounds on restart - NOTIMPLEMENTED_LOG_ONCE(); -} - -gfx::Rect X11WindowOzone::GetRestoredBoundsInPixels() const { - // TODO(crbug.com/848131): Restore bounds on restart - NOTIMPLEMENTED_LOG_ONCE(); - return gfx::Rect(); -} - -bool X11WindowOzone::IsVisible() const { - return x11_window_->IsVisible(); -} - -gfx::Rect X11WindowOzone::GetOutterBounds() const { - return x11_window_->GetOutterBounds(); -} - -::Region X11WindowOzone::GetShape() const { - return x11_window_->shape(); -} - void X11WindowOzone::PrepareForShutdown() { DCHECK(X11EventSource::GetInstance()); X11EventSource::GetInstance()->RemoveXEventDispatcher(this); @@ -252,7 +79,7 @@ void X11WindowOzone::PrepareForShutdown() { void X11WindowOzone::SetCursor(PlatformCursor cursor) { X11CursorOzone* cursor_ozone = static_cast<X11CursorOzone*>(cursor); - x11_window_->SetCursor(cursor_ozone->xcursor()); + XWindow::SetCursor(cursor_ozone->xcursor()); } void X11WindowOzone::RemoveFromWindowManager() { @@ -271,7 +98,7 @@ void X11WindowOzone::CheckCanDispatchNextPlatformEvent(XEvent* xev) { if (is_shutting_down_) return; - handle_next_event_ = x11_window_->IsTargetedBy(*xev); + handle_next_event_ = XWindow::IsTargetedBy(*xev); } void X11WindowOzone::PlatformEventDispatchFinished() { @@ -283,20 +110,20 @@ PlatformEventDispatcher* X11WindowOzone::GetPlatformEventDispatcher() { } bool X11WindowOzone::DispatchXEvent(XEvent* xev) { - if (!x11_window_->IsTargetedBy(*xev)) + if (!XWindow::IsTargetedBy(*xev)) return false; - x11_window_->ProcessEvent(xev); + XWindow::ProcessEvent(xev); return true; } bool X11WindowOzone::CanDispatchEvent(const PlatformEvent& event) { - DCHECK_NE(x11_window_->window(), x11::None); + DCHECK_NE(XWindow::window(), x11::None); return handle_next_event_; } uint32_t X11WindowOzone::DispatchEvent(const PlatformEvent& event) { - DCHECK_NE(x11_window_->window(), x11::None); + DCHECK_NE(XWindow::window(), x11::None); if (!window_manager_->event_grabber() || window_manager_->event_grabber() == this) { @@ -304,7 +131,7 @@ uint32_t X11WindowOzone::DispatchEvent(const PlatformEvent& event) { // (eg. double click) are broken. DispatchEventFromNativeUiEvent( event, base::BindOnce(&PlatformWindowDelegate::DispatchEvent, - base::Unretained(delegate_))); + base::Unretained(platform_window_delegate()))); return POST_DISPATCH_STOP_PROPAGATION; } @@ -321,7 +148,7 @@ uint32_t X11WindowOzone::DispatchEvent(const PlatformEvent& event) { void X11WindowOzone::DispatchHostWindowDragMovement( int hittest, const gfx::Point& pointer_location) { - x11_window_->WmMoveResize(hittest, pointer_location); + XWindow::WmMoveResize(hittest, pointer_location); } void X11WindowOzone::SetWidget(XID xid) { @@ -330,58 +157,19 @@ void X11WindowOzone::SetWidget(XID xid) { // than 32 bits values on the wire (see https://crbug.com/607014 for more // details). So, It's safe to use static_cast here. widget_ = static_cast<gfx::AcceleratedWidget>(xid); - if (widget_ != gfx::kNullAcceleratedWidget) - delegate_->OnAcceleratedWidgetAvailable(widget_); } void X11WindowOzone::OnXWindowCreated() { - DCHECK_NE(x11_window_->window(), x11::None); - SetWidget(x11_window_->window()); + DCHECK_NE(XWindow::window(), x11::None); + SetWidget(XWindow::window()); window_manager_->AddWindow(this); + X11Window::OnXWindowCreated(); +} +void X11WindowOzone::SetPlatformEventDispatcher() { DCHECK(X11EventSource::GetInstance()); X11EventSource::GetInstance()->AddXEventDispatcher(this); } -void X11WindowOzone::OnXWindowStateChanged() { - // Propagate the window state information to the client. Note that the order - // of checks is important here, because window can have several proprties at - // the same time. - PlatformWindowState old_state = state_; - if (x11_window_->IsMinimized()) { - state_ = PlatformWindowState::kMinimized; - } else if (x11_window_->IsFullscreen()) { - state_ = PlatformWindowState::kFullScreen; - } else if (x11_window_->IsMaximized()) { - state_ = PlatformWindowState::kMaximized; - } else { - state_ = PlatformWindowState::kNormal; - } - - if (old_state != state_) - delegate_->OnWindowStateChanged(state_); -} - -void X11WindowOzone::OnXWindowDamageEvent( - const gfx::Rect& damage_rect_in_pixels) { - delegate_->OnDamageRect(damage_rect_in_pixels); -} - -void X11WindowOzone::OnXWindowSizeChanged(const gfx::Size&) { - delegate_->OnBoundsChanged(x11_window_->bounds()); -} - -void X11WindowOzone::OnXWindowCloseRequested() { - delegate_->OnCloseRequest(); -} - -void X11WindowOzone::OnXWindowLostCapture() { - OnLostCapture(); -} - -void X11WindowOzone::OnXWindowIsActiveChanged(bool active) { - delegate_->OnActivationChanged(active); -} - } // namespace ui diff --git a/ui/ozone/platform/x11/x11_window_ozone.h b/ui/ozone/platform/x11/x11_window_ozone.h index 33e60a8083cf3..8b66d6ef3a888 100644 --- a/ui/ozone/platform/x11/x11_window_ozone.h +++ b/ui/ozone/platform/x11/x11_window_ozone.h @@ -16,8 +16,8 @@ #include "ui/events/x/x11_window_event_manager.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/x/x11_types.h" -#include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/platform_window/x11/x11_window.h" namespace ui { @@ -25,44 +25,21 @@ class X11WindowManagerOzone; struct PlatformWindowInitProperties; // PlatformWindow implementation for X11 Ozone. PlatformEvents are ui::Events. -class X11WindowOzone : public PlatformWindow, - public PlatformEventDispatcher, +class X11WindowOzone : public X11Window, public WmMoveResizeHandler, - public XEventDispatcher, - public XWindow::Delegate { + public XEventDispatcher { public: X11WindowOzone(PlatformWindowDelegate* delegate, - const PlatformWindowInitProperties& properties, X11WindowManagerOzone* window_manager); ~X11WindowOzone() override; gfx::AcceleratedWidget widget() const { return widget_; } - bool IsVisible() const; - gfx::Rect GetOutterBounds() const; - ::Region GetShape() const; // Called by |window_manager_| once capture is set to another X11WindowOzone. void OnLostCapture(); // Overridden from PlatformWindow: - void Show() override; - void Hide() override; void Close() override; - void SetBounds(const gfx::Rect& bounds) override; - gfx::Rect GetBounds() override; - void SetTitle(const base::string16& title) override; - void ToggleFullscreen() override; - void Maximize() override; - void Minimize() override; - void Restore() override; - void Activate() override; - void Deactivate() override; - void SetUseNativeFrame(bool use_native_frame) override; - PlatformWindowState GetPlatformWindowState() const override; - void MoveCursorTo(const gfx::Point& location) override; - void ConfineCursorToBounds(const gfx::Rect& bounds) override; - void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override; - gfx::Rect GetRestoredBoundsInPixels() const override; void PrepareForShutdown() override; void SetCapture() override; void ReleaseCapture() override; @@ -76,14 +53,11 @@ class X11WindowOzone : public PlatformWindow, bool DispatchXEvent(XEvent* event) override; private: - // Overridden from ui::XWindow::Delegate + // XWindow overrides: void OnXWindowCreated() override; - void OnXWindowStateChanged() override; - void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override; - void OnXWindowSizeChanged(const gfx::Size& size) override; - void OnXWindowCloseRequested() override; - void OnXWindowLostCapture() override; - void OnXWindowIsActiveChanged(bool active) override; + + // X11Window overrides: + void SetPlatformEventDispatcher() override; // PlatformEventDispatcher: bool CanDispatchEvent(const PlatformEvent& event) override; @@ -98,14 +72,10 @@ class X11WindowOzone : public PlatformWindow, void SetWidget(XID xwindow); void RemoveFromWindowManager(); - PlatformWindowDelegate* const delegate_; X11WindowManagerOzone* const window_manager_; - PlatformWindowState state_ = PlatformWindowState::kUnknown; gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget; - std::unique_ptr<ui::XWindow> x11_window_; - bool is_shutting_down_ = false; // Tells if this dispatcher can process next translated event based on a diff --git a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc index edbc7738e6fa4..0d11004a12711 100644 --- a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc +++ b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc @@ -61,8 +61,9 @@ class X11WindowOzoneTest : public testing::Test { EXPECT_CALL(*delegate, OnAcceleratedWidgetAvailable(_)) .WillOnce(StoreWidget(widget)); PlatformWindowInitProperties init_params(bounds); - auto window = std::make_unique<X11WindowOzone>(delegate, init_params, - window_manager_.get()); + auto window = + std::make_unique<X11WindowOzone>(delegate, window_manager_.get()); + window->Initialize(std::move(init_params)); return std::move(window); } diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h index c345533ef4dab..0e9d076dacb41 100644 --- a/ui/ozone/public/ozone_platform.h +++ b/ui/ozone/public/ozone_platform.h @@ -14,6 +14,7 @@ #include "base/message_loop/message_pump_type.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "ui/gfx/buffer_types.h" +#include "ui/platform_window/platform_window_delegate.h" namespace display { class NativeDisplayDelegate; @@ -31,7 +32,6 @@ class GpuPlatformSupportHost; class OverlayManagerOzone; class PlatformScreen; class PlatformWindow; -class PlatformWindowDelegate; class SurfaceFactoryOzone; class SystemInputInjector; class PlatformClipboard; diff --git a/ui/platform_window/BUILD.gn b/ui/platform_window/BUILD.gn index 21f48b583165c..dea6ac20cea6c 100644 --- a/ui/platform_window/BUILD.gn +++ b/ui/platform_window/BUILD.gn @@ -8,6 +8,8 @@ source_set("platform_window") { sources = [ "platform_window.h", "platform_window_delegate.h", + "platform_window_delegate_base.cc", + "platform_window_delegate_base.h", "platform_window_init_properties.cc", "platform_window_init_properties.h", ] @@ -30,6 +32,13 @@ source_set("platform_window") { "//third_party/fuchsia-sdk/sdk:ui_views", ] } + + if (is_linux) { + sources += [ + "platform_window_delegate_linux.cc", + "platform_window_delegate_linux.h", + ] + } } group("platform_impls") { diff --git a/ui/platform_window/common/BUILD.gn b/ui/platform_window/common/BUILD.gn new file mode 100644 index 0000000000000..ce68072a52a72 --- /dev/null +++ b/ui/platform_window/common/BUILD.gn @@ -0,0 +1,12 @@ +# 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. + +import("//build/config/ui.gni") + +source_set("common") { + sources = [ + "platform_window_defaults.cc", + "platform_window_defaults.h", + ] +} diff --git a/ui/base/platform_window_defaults.cc b/ui/platform_window/common/platform_window_defaults.cc similarity index 87% rename from ui/base/platform_window_defaults.cc rename to ui/platform_window/common/platform_window_defaults.cc index 6f87bf7e8b62c..59208f4e54300 100644 --- a/ui/base/platform_window_defaults.cc +++ b/ui/platform_window/common/platform_window_defaults.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/platform_window_defaults.h" +#include "ui/platform_window/common/platform_window_defaults.h" namespace ui { namespace { diff --git a/ui/base/platform_window_defaults.h b/ui/platform_window/common/platform_window_defaults.h similarity index 76% rename from ui/base/platform_window_defaults.h rename to ui/platform_window/common/platform_window_defaults.h index 7e4dedf5b94ec..fdb4a1c271a27 100644 --- a/ui/base/platform_window_defaults.h +++ b/ui/platform_window/common/platform_window_defaults.h @@ -2,17 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_PLATFORM_WINDOW_DEFAULTS_H_ -#define UI_BASE_PLATFORM_WINDOW_DEFAULTS_H_ - -#include "ui/base/ui_base_export.h" +#ifndef UI_PLATFORM_WINDOW_COMMON_PLATFORM_WINDOW_DEFAULTS_H_ +#define UI_PLATFORM_WINDOW_COMMON_PLATFORM_WINDOW_DEFAULTS_H_ namespace ui { // Returns true if PlatformWindow should use test configuration. Will return // false by default, unless test::EnableTestConfigForPlatformWindows() has been // called, then it will return true. -UI_BASE_EXPORT bool UseTestConfigForPlatformWindows(); +bool UseTestConfigForPlatformWindows(); namespace test { @@ -24,9 +22,9 @@ namespace test { // various tests, otherwise the call to Show() blocks because it never receives // the MapNotify event. It is unclear why this is necessary, but might be // related to calls to XInitThreads(). -UI_BASE_EXPORT void EnableTestConfigForPlatformWindows(); +void EnableTestConfigForPlatformWindows(); } // namespace test } // namespace ui -#endif // UI_BASE_PLATFORM_WINDOW_DEFAULTS_H_ +#endif // UI_PLATFORM_WINDOW_COMMON_PLATFORM_WINDOW_DEFAULTS_H_ diff --git a/ui/platform_window/platform_window_delegate.h b/ui/platform_window/platform_window_delegate.h index 0b6bdb897eb96..fe4059ff7e0b4 100644 --- a/ui/platform_window/platform_window_delegate.h +++ b/ui/platform_window/platform_window_delegate.h @@ -5,53 +5,23 @@ #ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_ #define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_ -#include "ui/gfx/native_widget_types.h" +#include "build/build_config.h" -namespace gfx { -class Rect; -} +// By default, PlatformWindowDelegateBase is used. However, different platforms +// should specify what delegate they would like to use if needed. +#if defined(OS_LINUX) +#include "ui/platform_window/platform_window_delegate_linux.h" +#else +#include "ui/platform_window/platform_window_delegate_base.h" +#endif namespace ui { -class Event; - -enum class PlatformWindowState { - kUnknown, - kMaximized, - kMinimized, - kNormal, - kFullScreen, -}; - -class PlatformWindowDelegate { - public: - virtual ~PlatformWindowDelegate() {} - - // Note that |new_bounds| is in physical screen coordinates. - virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0; - - // Note that |damaged_region| is in the platform-window's coordinates, in - // physical pixels. - virtual void OnDamageRect(const gfx::Rect& damaged_region) = 0; - - virtual void DispatchEvent(Event* event) = 0; - - virtual void OnCloseRequest() = 0; - virtual void OnClosed() = 0; - - virtual void OnWindowStateChanged(PlatformWindowState new_state) = 0; - - virtual void OnLostCapture() = 0; - - virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0; - - // Notifies the delegate that the widget cannot be used anymore until - // a new widget is made available through OnAcceleratedWidgetAvailable(). - // Must not be called when the PlatformWindow is being destroyed. - virtual void OnAcceleratedWidgetDestroyed() = 0; - - virtual void OnActivationChanged(bool active) = 0; -}; +#if defined(OS_LINUX) +using PlatformWindowDelegate = PlatformWindowDelegateLinux; +#else +using PlatformWindowDelegate = PlatformWindowDelegateBase; +#endif } // namespace ui diff --git a/ui/platform_window/platform_window_delegate_base.cc b/ui/platform_window/platform_window_delegate_base.cc new file mode 100644 index 0000000000000..cb3a992322a59 --- /dev/null +++ b/ui/platform_window/platform_window_delegate_base.cc @@ -0,0 +1,25 @@ +// 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/platform_window/platform_window_delegate_base.h" + +#include "ui/gfx/geometry/size.h" + +namespace ui { + +PlatformWindowDelegateBase::PlatformWindowDelegateBase() = default; + +PlatformWindowDelegateBase::~PlatformWindowDelegateBase() = default; + +base::Optional<gfx::Size> +PlatformWindowDelegateBase::GetMinimumSizeForWindow() { + return base::nullopt; +} + +base::Optional<gfx::Size> +PlatformWindowDelegateBase::GetMaximumSizeForWindow() { + return base::nullopt; +} + +} // namespace ui diff --git a/ui/platform_window/platform_window_delegate_base.h b/ui/platform_window/platform_window_delegate_base.h new file mode 100644 index 0000000000000..e76ae56199a0a --- /dev/null +++ b/ui/platform_window/platform_window_delegate_base.h @@ -0,0 +1,68 @@ +// 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_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_ +#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_ + +#include "base/optional.h" +#include "ui/gfx/native_widget_types.h" + +namespace gfx { +class Rect; +class Size; +} // namespace gfx + +namespace ui { + +class Event; + +enum class PlatformWindowState { + kUnknown, + kMaximized, + kMinimized, + kNormal, + kFullScreen, +}; + +// This is the bare minimum for PlatformWindowDeelegate, but some platforms may +// require more, and should do so in a subclass. Please refer to +// PlatformWindowDelegateLinux for an example. +class PlatformWindowDelegateBase { + public: + PlatformWindowDelegateBase(); + virtual ~PlatformWindowDelegateBase(); + + // Note that |new_bounds| is in physical screen coordinates. + virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0; + + // Note that |damaged_region| is in the platform-window's coordinates, in + // physical pixels. + virtual void OnDamageRect(const gfx::Rect& damaged_region) = 0; + + virtual void DispatchEvent(Event* event) = 0; + + virtual void OnCloseRequest() = 0; + virtual void OnClosed() = 0; + + virtual void OnWindowStateChanged(PlatformWindowState new_state) = 0; + + virtual void OnLostCapture() = 0; + + virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0; + + // Notifies the delegate that the widget cannot be used anymore until + // a new widget is made available through OnAcceleratedWidgetAvailable(). + // Must not be called when the PlatformWindow is being destroyed. + virtual void OnAcceleratedWidgetDestroyed() = 0; + + virtual void OnActivationChanged(bool active) = 0; + + // Requests size constraints for the PlatformWindow. + virtual base::Optional<gfx::Size> GetMinimumSizeForWindow(); + virtual base::Optional<gfx::Size> GetMaximumSizeForWindow(); +}; + +} // namespace ui + +#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_ diff --git a/ui/platform_window/platform_window_delegate_linux.cc b/ui/platform_window/platform_window_delegate_linux.cc new file mode 100644 index 0000000000000..c66e2ca234d74 --- /dev/null +++ b/ui/platform_window/platform_window_delegate_linux.cc @@ -0,0 +1,31 @@ +// 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/platform_window/platform_window_delegate_linux.h" + +#include "base/logging.h" + +namespace ui { + +PlatformWindowDelegateLinux::PlatformWindowDelegateLinux() = default; + +PlatformWindowDelegateLinux::~PlatformWindowDelegateLinux() = default; + +void PlatformWindowDelegateLinux::OnXWindowMapped() { + NOTIMPLEMENTED_LOG_ONCE(); +} + +void PlatformWindowDelegateLinux::OnXWindowUnmapped() { + NOTIMPLEMENTED_LOG_ONCE(); +} + +void PlatformWindowDelegateLinux::OnLostMouseGrab() { + NOTIMPLEMENTED_LOG_ONCE(); +} + +void PlatformWindowDelegateLinux::OnWorkspaceChanged() { + NOTIMPLEMENTED_LOG_ONCE(); +} + +} // namespace ui diff --git a/ui/platform_window/platform_window_delegate_linux.h b/ui/platform_window/platform_window_delegate_linux.h new file mode 100644 index 0000000000000..6290c691cf1fa --- /dev/null +++ b/ui/platform_window/platform_window_delegate_linux.h @@ -0,0 +1,39 @@ +// 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_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_ +#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_ + +#include "ui/platform_window/platform_window_delegate_base.h" + +namespace ui { + +// This is an optional linux delegate interface, which should be implemented by +// linux-based platforms. It contains both Wayland and X11 specific and common +// interfaces. +class PlatformWindowDelegateLinux : public PlatformWindowDelegateBase { + public: + PlatformWindowDelegateLinux(); + ~PlatformWindowDelegateLinux() override; + + // Notifies the delegate that the window got mapped in the X server. Wayland + // does not support this interface. + virtual void OnXWindowMapped(); + virtual void OnXWindowUnmapped(); + + // Notifies if the PlatformWindow looses a mouse grab. This can be useful for + // Wayland or X11. Both of them provide pointer enter and leave notifications, + // which non-ozone X11 (just an example) use to be using to notify about lost + // pointer grab along with explicit grabs. Wayland also has this technique. + // However, explicit grab is available only for popup (menu) windows. + virtual void OnLostMouseGrab(); + + // Notifies the delegate if the PlatformWindow has changed the workspace it is + // located in. + virtual void OnWorkspaceChanged(); +}; + +} // namespace ui + +#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_ diff --git a/ui/platform_window/platform_window_init_properties.h b/ui/platform_window/platform_window_init_properties.h index 46af9ec30aea1..38e538224a552 100644 --- a/ui/platform_window/platform_window_init_properties.h +++ b/ui/platform_window/platform_window_init_properties.h @@ -7,6 +7,7 @@ #include <string> +#include "base/optional.h" #include "build/build_config.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" @@ -16,6 +17,10 @@ #include <lib/ui/scenic/cpp/view_ref_pair.h> #endif +namespace gfx { +class ImageSkia; +} + namespace ui { enum class PlatformWindowType { @@ -23,6 +28,8 @@ enum class PlatformWindowType { kPopup, kMenu, kTooltip, + kDrag, + kBubble, }; enum class PlatformWindowOpacity { @@ -66,7 +73,13 @@ struct PlatformWindowInitProperties { bool remove_standard_frame = false; std::string workspace; - // Only used by X11. Specifies the res_name and res_class fields, +#if defined(USE_X11) + // Only used by X11: + bool prefer_dark_theme = false; + gfx::ImageSkia* icon = nullptr; + base::Optional<int> background_color; +#endif + // Specifies the res_name and res_class fields, // respectively, of the WM_CLASS window property. Controls window grouping // and desktop file matching in Linux window managers. std::string wm_role_name; diff --git a/ui/platform_window/stub/stub_window.h b/ui/platform_window/stub/stub_window.h index 0593f4dbf5373..0574b19cac0a2 100644 --- a/ui/platform_window/stub/stub_window.h +++ b/ui/platform_window/stub/stub_window.h @@ -9,12 +9,11 @@ #include "base/macros.h" #include "ui/gfx/geometry/rect.h" #include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/stub/stub_window_export.h" namespace ui { -class PlatformWindowDelegate; - // StubWindow is useful for tests, as well as implementations that only care // about bounds. class STUB_WINDOW_EXPORT StubWindow : public PlatformWindow { diff --git a/ui/platform_window/win/win_window.cc b/ui/platform_window/win/win_window.cc index 8cd1ce8ac59c0..548f56a11270c 100644 --- a/ui/platform_window/win/win_window.cc +++ b/ui/platform_window/win/win_window.cc @@ -11,7 +11,6 @@ #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/gfx/win/msg_util.h" -#include "ui/platform_window/platform_window_delegate.h" #include <windows.h> diff --git a/ui/platform_window/win/win_window.h b/ui/platform_window/win/win_window.h index 1e4bd938fbd74..f74cddb0a91bb 100644 --- a/ui/platform_window/win/win_window.h +++ b/ui/platform_window/win/win_window.h @@ -10,14 +10,13 @@ #include "base/memory/weak_ptr.h" #include "ui/gfx/win/window_impl.h" #include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/win/win_window_export.h" #include <windows.h> namespace ui { -class PlatformWindowDelegate; - class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow, public gfx::WindowImpl { public: diff --git a/ui/platform_window/x11/BUILD.gn b/ui/platform_window/x11/BUILD.gn index f0d40e73b83a1..64259a6c44979 100644 --- a/ui/platform_window/x11/BUILD.gn +++ b/ui/platform_window/x11/BUILD.gn @@ -30,15 +30,8 @@ jumbo_component("x11") { defines = [ "X11_WINDOW_IMPLEMENTATION" ] sources = [ - "x11_window_base.cc", - "x11_window_base.h", + "x11_window.cc", + "x11_window.h", "x11_window_export.h", ] - - if (use_x11) { - sources += [ - "x11_window.cc", - "x11_window.h", - ] - } } diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc index c466ef0ee1221..b0a73656b4184 100644 --- a/ui/platform_window/x11/x11_window.cc +++ b/ui/platform_window/x11/x11_window.cc @@ -4,146 +4,326 @@ #include "ui/platform_window/x11/x11_window.h" +#include "base/trace_event/trace_event.h" #include "ui/events/devices/x11/touch_factory_x11.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/platform/platform_event_source.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/x/x11.h" -#include "ui/platform_window/platform_window_delegate.h" +#include "ui/platform_window/platform_window_delegate_linux.h" namespace ui { -X11Window::X11Window(PlatformWindowDelegate* delegate, const gfx::Rect& bounds) - : X11WindowBase(delegate, bounds) { - DCHECK(PlatformEventSource::GetInstance()); - PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); +namespace { + +ui::XWindow::Configuration ConvertInitPropertiesToXWindowConfig( + const PlatformWindowInitProperties& properties) { + using WindowType = ui::XWindow::WindowType; + using WindowOpacity = ui::XWindow::WindowOpacity; + ui::XWindow::Configuration config; + + switch (properties.type) { + case PlatformWindowType::kWindow: + config.type = WindowType::kWindow; + break; + case PlatformWindowType::kMenu: + config.type = WindowType::kMenu; + break; + case PlatformWindowType::kTooltip: + config.type = WindowType::kTooltip; + break; + case PlatformWindowType::kPopup: + config.type = WindowType::kPopup; + break; + case PlatformWindowType::kDrag: + config.type = WindowType::kDrag; + break; + case PlatformWindowType::kBubble: + config.type = WindowType::kBubble; + break; + } + + switch (properties.opacity) { + case PlatformWindowOpacity::kInferOpacity: + config.opacity = WindowOpacity::kInferOpacity; + break; + case PlatformWindowOpacity::kOpaqueWindow: + config.opacity = WindowOpacity::kOpaqueWindow; + break; + case PlatformWindowOpacity::kTranslucentWindow: + config.opacity = WindowOpacity::kTranslucentWindow; + break; + } + + config.bounds = properties.bounds; + config.force_show_in_taskbar = properties.force_show_in_taskbar; + config.keep_on_top = properties.keep_on_top; + config.visible_on_all_workspaces = properties.visible_on_all_workspaces; + config.remove_standard_frame = properties.remove_standard_frame; + config.workspace = properties.workspace; + config.wm_class_name = properties.wm_class_name; + config.wm_class_class = properties.wm_class_class; + config.wm_role_name = properties.wm_role_name; + config.activatable = properties.activatable; + return config; } +} // namespace + +X11Window::X11Window(PlatformWindowDelegateLinux* platform_window_delegate, + XEventDelegate* x_event_delegate) + : platform_window_delegate_(platform_window_delegate), + x_event_delegate_(x_event_delegate) {} + X11Window::~X11Window() { - X11Window::PrepareForShutdown(); + PrepareForShutdown(); + Close(); +} + +void X11Window::Initialize(PlatformWindowInitProperties properties) { + XWindow::Configuration config = + ConvertInitPropertiesToXWindowConfig(properties); + Init(config); +} + +void X11Window::Show() { + // TODO(msisov): pass inactivity to PlatformWindow::Show. + XWindow::Map(false /* inactive */); +} + +void X11Window::Hide() { + XWindow::Hide(); +} + +void X11Window::Close() { + if (is_shutting_down_) + return; + + is_shutting_down_ = true; + XWindow::Close(); + platform_window_delegate_->OnClosed(); } void X11Window::PrepareForShutdown() { PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); } -void X11Window::SetUseNativeFrame(bool use_native_frame) { +void X11Window::SetBounds(const gfx::Rect& bounds) { + // Assume that the resize will go through as requested, which should be the + // case if we're running without a window manager. If there's a window + // manager, it can modify or ignore the request, but (per ICCCM) we'll get a + // (possibly synthetic) ConfigureNotify about the actual size and correct + // |bounds_| later. + XWindow::SetBounds(bounds); + + // Even if the pixel bounds didn't change this call to the delegate should + // still happen. The device scale factor may have changed which effectively + // changes the bounds. + platform_window_delegate_->OnBoundsChanged(bounds); +} + +gfx::Rect X11Window::GetBounds() { + return XWindow::bounds(); +} + +void X11Window::SetTitle(const base::string16& title) { + XWindow::SetTitle(title); +} + +void X11Window::SetCapture() { + XWindow::GrabPointer(); +} + +void X11Window::ReleaseCapture() { + XWindow::ReleasePointerGrab(); +} + +bool X11Window::HasCapture() const { NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +void X11Window::ToggleFullscreen() { + bool is_fullscreen = IsFullscreen(); + SetFullscreen(!is_fullscreen); +} + +void X11Window::Maximize() { + if (IsFullscreen()) + SetFullscreen(false); + XWindow::Maximize(); +} + +void X11Window::Minimize() { + XWindow::Minimize(); +} + +void X11Window::Restore() { + if (IsFullscreen()) + ToggleFullscreen(); + if (IsMaximized()) + Unmaximize(); +} + +PlatformWindowState X11Window::GetPlatformWindowState() const { + return state_; +} + +void X11Window::Activate() { + XWindow::Activate(); +} + +void X11Window::Deactivate() { + XWindow::Deactivate(); +} + +void X11Window::SetUseNativeFrame(bool use_native_frame) { + XWindow::SetUseNativeFrame(use_native_frame); } void X11Window::SetCursor(PlatformCursor cursor) { - XDefineCursor(xdisplay(), xwindow(), 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 } -void X11Window::ProcessXInput2Event(XEvent* xev) { - if (!TouchFactory::GetInstance()->ShouldProcessXI2Event(xev)) - return; - EventType event_type = EventTypeFromNative(xev); - switch (event_type) { - case ET_KEY_PRESSED: - case ET_KEY_RELEASED: { - KeyEvent key_event(xev); - delegate()->DispatchEvent(&key_event); - break; - } - case ET_MOUSE_PRESSED: - case ET_MOUSE_MOVED: - case ET_MOUSE_DRAGGED: - case ET_MOUSE_RELEASED: { - MouseEvent mouse_event(xev); - delegate()->DispatchEvent(&mouse_event); - break; - } - case ET_MOUSEWHEEL: { - MouseWheelEvent wheel_event(xev); - delegate()->DispatchEvent(&wheel_event); - break; - } - case ET_SCROLL_FLING_START: - case ET_SCROLL_FLING_CANCEL: - case ET_SCROLL: { - ScrollEvent scroll_event(xev); - delegate()->DispatchEvent(&scroll_event); - break; - } - case ET_TOUCH_MOVED: - case ET_TOUCH_PRESSED: - case ET_TOUCH_CANCELLED: - case ET_TOUCH_RELEASED: { - TouchEvent touch_event(xev); - delegate()->DispatchEvent(&touch_event); - break; - } - default: - break; - } +void X11Window::MoveCursorTo(const gfx::Point& location) { + XWindow::MoveCursorTo(location); +} + +void X11Window::ConfineCursorToBounds(const gfx::Rect& bounds) { + XWindow::ConfineCursorTo(bounds); +} + +void X11Window::SetRestoredBoundsInPixels(const gfx::Rect& bounds) { + // TODO(crbug.com/848131): Restore bounds on restart + NOTIMPLEMENTED_LOG_ONCE(); +} + +gfx::Rect X11Window::GetRestoredBoundsInPixels() const { + // TODO(crbug.com/848131): Restore bounds on restart + NOTIMPLEMENTED_LOG_ONCE(); + return gfx::Rect(); +} + +void X11Window::SetPlatformEventDispatcher() { + DCHECK(PlatformEventSource::GetInstance()); + PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); } bool X11Window::CanDispatchEvent(const PlatformEvent& xev) { - return IsEventForXWindow(*xev); +#if defined(USE_X11) + return XWindow::IsTargetedBy(*xev); +#else + NOTREACHED() << "Ozone must use own dispatcher as it has different type of " + "PlatformEvent"; + return false; +#endif } uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { - XEvent* xev = event; - switch (xev->type) { - case EnterNotify: { - MouseEvent mouse_event(xev); - CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type()); - delegate()->DispatchEvent(&mouse_event); - break; - } - case LeaveNotify: { - MouseEvent mouse_event(xev); - delegate()->DispatchEvent(&mouse_event); - break; - } +#if defined(USE_X11) + TRACE_EVENT1("views", "X11PlatformWindow::Dispatch", "event->type", + event->type); - case KeyPress: - case KeyRelease: { - KeyEvent key_event(xev); - delegate()->DispatchEvent(&key_event); - break; - } - - case ButtonPress: - case ButtonRelease: { - switch (EventTypeFromNative(xev)) { - case ET_MOUSEWHEEL: { - MouseWheelEvent mouseev(xev); - delegate()->DispatchEvent(&mouseev); - break; - } - case ET_MOUSE_PRESSED: - case ET_MOUSE_RELEASED: { - MouseEvent mouseev(xev); - delegate()->DispatchEvent(&mouseev); - break; - } - case ET_UNKNOWN: - // No event is created for X11-release events for mouse-wheel - // buttons. - break; - default: - NOTREACHED(); - } - break; - } - - case Expose: - case x11::FocusOut: - case ConfigureNotify: - case ClientMessage: { - ProcessXWindowEvent(xev); - break; - } - - case GenericEvent: { - ProcessXInput2Event(xev); - break; - } - } + ProcessEvent(event); return POST_DISPATCH_STOP_PROPAGATION; +#else + NOTREACHED() << "Ozone must use own dispatcher as it has different type of " + "PlatformEvent"; + return false; +#endif +} + +void X11Window::OnXWindowCreated() { + // X11WindowOzone overrides this method and manages events by itself. + SetPlatformEventDispatcher(); + platform_window_delegate_->OnAcceleratedWidgetAvailable(window()); +} + +void X11Window::OnXWindowStateChanged() { + // Propagate the window state information to the client. Note that the order + // of checks is important here, because window can have several properties + // at the same time. + PlatformWindowState old_state = state_; + if (IsMinimized()) { + state_ = PlatformWindowState::kMinimized; + } else if (IsFullscreen()) { + state_ = PlatformWindowState::kFullScreen; + } else if (IsMaximized()) { + state_ = PlatformWindowState::kMaximized; + } else { + state_ = PlatformWindowState::kNormal; + } + + if (old_state != state_) + platform_window_delegate_->OnWindowStateChanged(state_); +} + +void X11Window::OnXWindowDamageEvent(const gfx::Rect& damage_rect) { + platform_window_delegate_->OnDamageRect(damage_rect); +} + +void X11Window::OnXWindowBoundsChanged(const gfx::Rect& bounds) { + platform_window_delegate_->OnBoundsChanged(bounds); +} + +void X11Window::OnXWindowCloseRequested() { + platform_window_delegate_->OnCloseRequest(); +} + +void X11Window::OnXWindowIsActiveChanged(bool active) { + platform_window_delegate_->OnActivationChanged(active); +} + +void X11Window::OnXWindowMapped() { + platform_window_delegate_->OnXWindowMapped(); +} + +void X11Window::OnXWindowUnmapped() { + platform_window_delegate_->OnXWindowUnmapped(); +} + +void X11Window::OnXWindowWorkspaceChanged() { + platform_window_delegate_->OnWorkspaceChanged(); +} + +void X11Window::OnXWindowLostPointerGrab() { + platform_window_delegate_->OnLostMouseGrab(); +} + +void X11Window::OnXWindowLostCapture() { + platform_window_delegate_->OnLostCapture(); +} + +void X11Window::OnXWindowEvent(ui::Event* event) { + platform_window_delegate_->DispatchEvent(event); +} + +void X11Window::OnXWindowSelectionEvent(XEvent* xev) { + if (x_event_delegate_) + x_event_delegate_->OnXWindowSelectionEvent(xev); +} + +void X11Window::OnXWindowDragDropEvent(XEvent* xev) { + if (x_event_delegate_) + x_event_delegate_->OnXWindowDragDropEvent(xev); +} + +void X11Window::OnXWindowRawKeyEvent(XEvent* xev) { + if (x_event_delegate_) + x_event_delegate_->OnXWindowRawKeyEvent(xev); +} + +base::Optional<gfx::Size> X11Window::GetMinimumSizeForXWindow() { + return platform_window_delegate_->GetMinimumSizeForWindow(); +} + +base::Optional<gfx::Size> X11Window::GetMaximumSizeForXWindow() { + return platform_window_delegate_->GetMaximumSizeForWindow(); } } // namespace ui diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h index 2b91e5ceb0338..62ae8fbcb4ed1 100644 --- a/ui/platform_window/x11/x11_window.h +++ b/ui/platform_window/x11/x11_window.h @@ -6,23 +6,77 @@ #define UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_ #include "base/macros.h" +#include "ui/base/x/x11_window.h" #include "ui/events/platform/platform_event_dispatcher.h" -#include "ui/platform_window/x11/x11_window_base.h" +#include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_init_properties.h" #include "ui/platform_window/x11/x11_window_export.h" namespace ui { +class PlatformWindowDelegateLinux; + +// Delegate interface used to communicate the X11PlatformWindow API client about +// XEvents of interest. +class X11_WINDOW_EXPORT XEventDelegate { + public: + virtual ~XEventDelegate() {} + + // 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; + + // TODO(crbug.com/981606): DesktopWindowTreeHostX11 forward raw |XEvent|s to + // ATK components that currently live in views layer. Remove once ATK code + // is reworked to be reusable. + virtual void OnXWindowRawKeyEvent(XEvent* xev) = 0; +}; + // PlatformWindow implementation for X11. PlatformEvents are XEvents. -class X11_WINDOW_EXPORT X11Window : public X11WindowBase, +class X11_WINDOW_EXPORT X11Window : public PlatformWindow, + public XWindow, public PlatformEventDispatcher { public: - X11Window(PlatformWindowDelegate* delegate, const gfx::Rect& bounds); + X11Window(PlatformWindowDelegateLinux* platform_window_delegate, + XEventDelegate* x_event_delegate); ~X11Window() override; + void Initialize(PlatformWindowInitProperties properties); + // PlatformWindow: + void Show() override; + void Hide() override; + void Close() override; void PrepareForShutdown() override; + void SetBounds(const gfx::Rect& bounds) override; + gfx::Rect GetBounds() override; + void SetTitle(const base::string16& title) override; + void SetCapture() override; + void ReleaseCapture() override; + bool HasCapture() const override; + void ToggleFullscreen() override; + void Maximize() override; + void Minimize() override; + void Restore() override; + PlatformWindowState GetPlatformWindowState() const override; + void Activate() override; + void Deactivate() override; void SetUseNativeFrame(bool use_native_frame) override; void SetCursor(PlatformCursor cursor) override; + void MoveCursorTo(const gfx::Point& location) override; + void ConfineCursorToBounds(const gfx::Rect& bounds) override; + void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override; + gfx::Rect GetRestoredBoundsInPixels() const override; + + protected: + PlatformWindowDelegateLinux* platform_window_delegate() const { + return platform_window_delegate_; + } + + // XWindow: + void OnXWindowCreated() override; + void OnXWindowLostCapture() override; private: void ProcessXInput2Event(XEvent* xev); @@ -31,6 +85,36 @@ class X11_WINDOW_EXPORT X11Window : public X11WindowBase, bool CanDispatchEvent(const PlatformEvent& event) override; uint32_t DispatchEvent(const PlatformEvent& event) override; + // XWindow: + void OnXWindowStateChanged() override; + void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override; + void OnXWindowBoundsChanged(const gfx::Rect& size) override; + void OnXWindowCloseRequested() override; + void OnXWindowIsActiveChanged(bool active) override; + void OnXWindowMapped() override; + void OnXWindowUnmapped() override; + void OnXWindowWorkspaceChanged() override; + void OnXWindowLostPointerGrab() override; + void OnXWindowEvent(ui::Event* event) override; + void OnXWindowSelectionEvent(XEvent* xev) override; + void OnXWindowDragDropEvent(XEvent* xev) override; + void OnXWindowRawKeyEvent(XEvent* xev) override; + base::Optional<gfx::Size> GetMinimumSizeForXWindow() override; + base::Optional<gfx::Size> GetMaximumSizeForXWindow() override; + + // X11WindowOzone sets own event dispatcher now. + virtual void SetPlatformEventDispatcher(); + + // Stores current state of this window. + PlatformWindowState state_ = PlatformWindowState::kUnknown; + + PlatformWindowDelegateLinux* const platform_window_delegate_; + + XEventDelegate* const x_event_delegate_; + + // Tells if the window got a ::Close call. + bool is_shutting_down_ = false; + DISALLOW_COPY_AND_ASSIGN(X11Window); }; diff --git a/ui/platform_window/x11/x11_window_base.cc b/ui/platform_window/x11/x11_window_base.cc deleted file mode 100644 index 221ad51101eaa..0000000000000 --- a/ui/platform_window/x11/x11_window_base.cc +++ /dev/null @@ -1,437 +0,0 @@ -// Copyright 2016 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/platform_window/x11/x11_window_base.h" - -#include <string> - -#include "base/strings/utf_string_conversions.h" -#include "ui/base/platform_window_defaults.h" -#include "ui/base/x/x11_util.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/events/platform/platform_event_dispatcher.h" -#include "ui/events/platform/platform_event_source.h" -#include "ui/events/platform/x11/x11_event_source.h" -#include "ui/events/x/x11_window_event_manager.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/x/x11_atom_cache.h" -#include "ui/platform_window/platform_window_delegate.h" - -namespace ui { - -namespace { - -XID FindXEventTarget(const XEvent& xev) { - XID target = xev.xany.window; - if (xev.type == GenericEvent) - target = static_cast<XIDeviceEvent*>(xev.xcookie.data)->event; - return target; -} - -} // namespace - -X11WindowBase::X11WindowBase(PlatformWindowDelegate* delegate, - const gfx::Rect& bounds) - : delegate_(delegate), - xdisplay_(gfx::GetXDisplay()), - xroot_window_(DefaultRootWindow(xdisplay_)), - bounds_(bounds), - state_(PlatformWindowState::kUnknown) { - DCHECK(delegate_); - Create(); - pointer_barriers_.fill(x11::None); -} - -X11WindowBase::~X11WindowBase() { - UnConfineCursor(); - Destroy(); -} - -void X11WindowBase::Destroy() { - if (xwindow_ == x11::None) - return; - - // Stop processing events. - XID xwindow = xwindow_; - XDisplay* xdisplay = xdisplay_; - xwindow_ = x11::None; - delegate_->OnClosed(); - // |this| might be deleted because of the above call. - - XDestroyWindow(xdisplay, xwindow); -} - -void X11WindowBase::Create() { - DCHECK(!bounds_.size().IsEmpty()); - - XSetWindowAttributes swa; - memset(&swa, 0, sizeof(swa)); - swa.background_pixmap = x11::None; - swa.bit_gravity = NorthWestGravity; - swa.override_redirect = UseTestConfigForPlatformWindows(); - xwindow_ = - XCreateWindow(xdisplay_, xroot_window_, bounds_.x(), bounds_.y(), - bounds_.width(), bounds_.height(), - 0, // border width - CopyFromParent, // depth - InputOutput, - CopyFromParent, // visual - CWBackPixmap | CWBitGravity | CWOverrideRedirect, &swa); - - // Setup XInput event mask. - long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | - KeyPressMask | KeyReleaseMask | EnterWindowMask | - LeaveWindowMask | ExposureMask | VisibilityChangeMask | - StructureNotifyMask | PropertyChangeMask | - PointerMotionMask; - xwindow_events_ = - std::make_unique<ui::XScopedEventSelector>(xwindow_, event_mask); - - // Setup XInput2 event mask. - unsigned char mask[XIMaskLen(XI_LASTEVENT)]; - memset(mask, 0, sizeof(mask)); - - XISetMask(mask, XI_TouchBegin); - XISetMask(mask, XI_TouchUpdate); - XISetMask(mask, XI_TouchEnd); - XISetMask(mask, XI_ButtonPress); - XISetMask(mask, XI_ButtonRelease); - XISetMask(mask, XI_Motion); - XISetMask(mask, XI_KeyPress); - XISetMask(mask, XI_KeyRelease); - XISetMask(mask, XI_HierarchyChanged); - - XIEventMask evmask; - evmask.deviceid = XIAllDevices; - evmask.mask_len = sizeof(mask); - evmask.mask = mask; - XISelectEvents(xdisplay_, xwindow_, &evmask, 1); - XFlush(xdisplay_); - - ::Atom protocols[2]; - protocols[0] = gfx::GetAtom("WM_DELETE_WINDOW"); - protocols[1] = gfx::GetAtom("_NET_WM_PING"); - XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); - - // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with - // the desktop environment. - XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL); - - // Likewise, the X server needs to know this window's pid so it knows which - // program to kill if the window hangs. - // XChangeProperty() expects "pid" to be long. - static_assert(sizeof(long) >= sizeof(pid_t), - "pid_t should not be larger than long"); - long pid = getpid(); - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_PID"), XA_CARDINAL, - 32, PropModeReplace, reinterpret_cast<unsigned char*>(&pid), - 1); - // Before we map the window, set size hints. Otherwise, some window managers - // will ignore toplevel XMoveWindow commands. - XSizeHints size_hints; - size_hints.flags = PPosition | PWinGravity; - size_hints.x = bounds_.x(); - size_hints.y = bounds_.y(); - // Set StaticGravity so that the window position is not affected by the - // frame width when running with window manager. - size_hints.win_gravity = StaticGravity; - XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); - - delegate_->OnAcceleratedWidgetAvailable(xwindow_); -} - -void X11WindowBase::Show() { - if (window_mapped_) - return; - - XMapWindow(xdisplay_, xwindow_); - // TODO(thomasanderson): Find out why this flush is necessary. - XFlush(xdisplay_); - window_mapped_ = true; -} - -void X11WindowBase::Hide() { - if (!window_mapped_) - return; - - XWithdrawWindow(xdisplay_, xwindow_, 0); - window_mapped_ = false; -} - -void X11WindowBase::Close() { - Destroy(); -} - -void X11WindowBase::SetBounds(const gfx::Rect& bounds) { - DCHECK(!bounds.size().IsEmpty()); - - if (xwindow_ != x11::None) { - XWindowChanges changes = {0}; - unsigned value_mask = 0; - - if (bounds_.size() != bounds.size()) { - changes.width = bounds.width(); - changes.height = bounds.height(); - value_mask |= CWHeight | CWWidth; - } - - if (bounds_.origin() != bounds.origin()) { - changes.x = bounds.x(); - changes.y = bounds.y(); - value_mask |= CWX | CWY; - } - - if (value_mask) - XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); - } - - // Assume that the resize will go through as requested, which should be the - // case if we're running without a window manager. If there's a window - // manager, it can modify or ignore the request, but (per ICCCM) we'll get a - // (possibly synthetic) ConfigureNotify about the actual size and correct - // |bounds_| later. - bounds_ = bounds; - - // Even if the pixel bounds didn't change this call to the delegate should - // still happen. The device scale factor may have changed which effectively - // changes the bounds. - delegate_->OnBoundsChanged(bounds_); -} - -gfx::Rect X11WindowBase::GetBounds() { - return bounds_; -} - -void X11WindowBase::SetTitle(const base::string16& title) { - if (window_title_ == title) - return; - window_title_ = title; - std::string utf8str = base::UTF16ToUTF8(title); - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_NAME"), - gfx::GetAtom("UTF8_STRING"), 8, PropModeReplace, - reinterpret_cast<const unsigned char*>(utf8str.c_str()), - utf8str.size()); - XTextProperty xtp; - char* c_utf8_str = const_cast<char*>(utf8str.c_str()); - if (Xutf8TextListToTextProperty(xdisplay_, &c_utf8_str, 1, XUTF8StringStyle, - &xtp) == x11::Success) { - XSetWMName(xdisplay_, xwindow_, &xtp); - XFree(xtp.value); - } -} - -void X11WindowBase::SetCapture() {} - -void X11WindowBase::ReleaseCapture() {} - -bool X11WindowBase::HasCapture() const { - return false; -} - -void X11WindowBase::ToggleFullscreen() { - ui::SetWMSpecState(xwindow_, !IsFullscreen(), - gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"), x11::None); -} - -void X11WindowBase::Maximize() { - if (IsFullscreen()) - ToggleFullscreen(); - - ui::SetWMSpecState(xwindow_, true, - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"), - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")); -} - -void X11WindowBase::Minimize() { - XIconifyWindow(xdisplay_, xwindow_, 0); -} - -void X11WindowBase::Restore() { - if (IsFullscreen()) - ToggleFullscreen(); - - if (IsMaximized()) { - ui::SetWMSpecState(xwindow_, false, - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"), - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")); - } -} - -PlatformWindowState X11WindowBase::GetPlatformWindowState() const { - return state_; -} - -void X11WindowBase::Activate() { - NOTIMPLEMENTED_LOG_ONCE(); -} - -void X11WindowBase::Deactivate() { - NOTIMPLEMENTED_LOG_ONCE(); -} - -void X11WindowBase::MoveCursorTo(const gfx::Point& location) { - XWarpPointer(xdisplay_, x11::None, xroot_window_, 0, 0, 0, 0, - bounds_.x() + location.x(), bounds_.y() + location.y()); -} - -void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) { - UnConfineCursor(); - - if (bounds.IsEmpty()) - return; - - gfx::Rect barrier = bounds + bounds_.OffsetFromOrigin(); - - // Top horizontal barrier. - pointer_barriers_[0] = XFixesCreatePointerBarrier( - xdisplay_, xroot_window_, barrier.x(), barrier.y(), barrier.right(), - barrier.y(), BarrierPositiveY, 0, XIAllDevices); - // Bottom horizontal barrier. - pointer_barriers_[1] = XFixesCreatePointerBarrier( - xdisplay_, xroot_window_, barrier.x(), barrier.bottom(), barrier.right(), - barrier.bottom(), BarrierNegativeY, 0, XIAllDevices); - // Left vertical barrier. - pointer_barriers_[2] = XFixesCreatePointerBarrier( - xdisplay_, xroot_window_, barrier.x(), barrier.y(), barrier.x(), - barrier.bottom(), BarrierPositiveX, 0, XIAllDevices); - // Right vertical barrier. - pointer_barriers_[3] = XFixesCreatePointerBarrier( - xdisplay_, xroot_window_, barrier.right(), barrier.y(), barrier.right(), - barrier.bottom(), BarrierNegativeX, 0, XIAllDevices); - - has_pointer_barriers_ = true; -} - -void X11WindowBase::SetRestoredBoundsInPixels(const gfx::Rect& bounds) { - // TODO: https://crbug.com/848131 - NOTIMPLEMENTED(); -} - -gfx::Rect X11WindowBase::GetRestoredBoundsInPixels() const { - // TODO: https://crbug.com/848131 - NOTIMPLEMENTED(); - return gfx::Rect(); -} - -void X11WindowBase::UnConfineCursor() { - if (!has_pointer_barriers_) - return; - - for (XID pointer_barrier : pointer_barriers_) - XFixesDestroyPointerBarrier(xdisplay_, pointer_barrier); - pointer_barriers_.fill(x11::None); - - has_pointer_barriers_ = false; -} - -bool X11WindowBase::IsEventForXWindow(const XEvent& xev) const { - return xwindow_ != x11::None && FindXEventTarget(xev) == xwindow_; -} - -void X11WindowBase::ProcessXWindowEvent(XEvent* xev) { - switch (xev->type) { - case Expose: { - gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, xev->xexpose.width, - xev->xexpose.height); - delegate_->OnDamageRect(damage_rect); - break; - } - - case x11::FocusOut: - if (xev->xfocus.mode != NotifyGrab) - delegate_->OnLostCapture(); - break; - - case ConfigureNotify: { - DCHECK_EQ(xwindow_, xev->xconfigure.event); - DCHECK_EQ(xwindow_, xev->xconfigure.window); - // It's possible that the X window may be resized by some other means than - // from within aura (e.g. the X window manager can change the size). Make - // sure the root window size is maintained properly. - int translated_x_in_pixels = xev->xconfigure.x; - int translated_y_in_pixels = xev->xconfigure.y; - if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) { - Window unused; - XTranslateCoordinates(xdisplay_, xwindow_, xroot_window_, 0, 0, - &translated_x_in_pixels, &translated_y_in_pixels, - &unused); - } - gfx::Rect bounds(translated_x_in_pixels, translated_y_in_pixels, - xev->xconfigure.width, xev->xconfigure.height); - if (bounds_ != bounds) { - bounds_ = bounds; - delegate_->OnBoundsChanged(bounds_); - } - break; - } - - case ClientMessage: { - Atom message = static_cast<Atom>(xev->xclient.data.l[0]); - if (message == gfx::GetAtom("WM_DELETE_WINDOW")) { - delegate_->OnCloseRequest(); - } else if (message == gfx::GetAtom("_NET_WM_PING")) { - XEvent reply_event = *xev; - reply_event.xclient.window = xroot_window_; - - XSendEvent(xdisplay_, reply_event.xclient.window, x11::False, - SubstructureRedirectMask | SubstructureNotifyMask, - &reply_event); - XFlush(xdisplay_); - } - break; - } - case PropertyNotify: { - ::Atom changed_atom = xev->xproperty.atom; - if (changed_atom == gfx::GetAtom("_NET_WM_STATE")) - OnWMStateUpdated(); - break; - } - } -} - -void X11WindowBase::OnWMStateUpdated() { - std::vector<::Atom> atom_list; - // Ignore the return value of ui::GetAtomArrayProperty(). Fluxbox removes the - // _NET_WM_STATE property when no _NET_WM_STATE atoms are set. - ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list); - - window_properties_.clear(); - std::copy(atom_list.begin(), atom_list.end(), - inserter(window_properties_, window_properties_.begin())); - - // Propagate the window state information to the client. - // Note that the order of checks is important here, because window can have - // several proprties at the same time. - PlatformWindowState old_state = state_; - if (ui::HasWMSpecProperty(window_properties_, - gfx::GetAtom("_NET_WM_STATE_HIDDEN"))) { - state_ = PlatformWindowState::kMinimized; - } else if (ui::HasWMSpecProperty(window_properties_, - gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"))) { - state_ = PlatformWindowState::kFullScreen; - } else if (ui::HasWMSpecProperty( - window_properties_, - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) && - ui::HasWMSpecProperty( - window_properties_, - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"))) { - state_ = PlatformWindowState::kMaximized; - } else { - state_ = PlatformWindowState::kNormal; - } - - if (old_state != state_) - delegate_->OnWindowStateChanged(state_); -} - -bool X11WindowBase::IsMaximized() const { - return state_ == PlatformWindowState::kMaximized; -} - -bool X11WindowBase::IsFullscreen() const { - return state_ == PlatformWindowState::kFullScreen; -} - -} // namespace ui diff --git a/ui/platform_window/x11/x11_window_base.h b/ui/platform_window/x11/x11_window_base.h deleted file mode 100644 index 05b8dd1941185..0000000000000 --- a/ui/platform_window/x11/x11_window_base.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 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_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_ -#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_ - -#include <stdint.h> - -#include <array> - -#include "base/callback.h" -#include "base/containers/flat_set.h" -#include "base/macros.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/x/x11.h" -#include "ui/gfx/x/x11_types.h" -#include "ui/platform_window/platform_window.h" -#include "ui/platform_window/platform_window_delegate.h" -#include "ui/platform_window/x11/x11_window_export.h" - -namespace ui { - -class XScopedEventSelector; - -// Abstract base implementation for a X11 based PlatformWindow. Methods that -// are platform specific are left unimplemented. -class X11_WINDOW_EXPORT X11WindowBase : public PlatformWindow { - public: - X11WindowBase(PlatformWindowDelegate* delegate, const gfx::Rect& bounds); - ~X11WindowBase() override; - - // PlatformWindow: - void Show() override; - void Hide() override; - void Close() override; - void SetBounds(const gfx::Rect& bounds) override; - gfx::Rect GetBounds() override; - void SetTitle(const base::string16& title) override; - void SetCapture() override; - void ReleaseCapture() override; - bool HasCapture() const override; - void ToggleFullscreen() override; - void Maximize() override; - void Minimize() override; - void Restore() override; - PlatformWindowState GetPlatformWindowState() const override; - void Activate() override; - void Deactivate() override; - void MoveCursorTo(const gfx::Point& location) override; - void ConfineCursorToBounds(const gfx::Rect& bounds) override; - void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override; - gfx::Rect GetRestoredBoundsInPixels() const override; - - protected: - // Creates new underlying XWindow. Does not map XWindow. - void Create(); - - void Destroy(); - - PlatformWindowDelegate* delegate() { return delegate_; } - XDisplay* xdisplay() { return xdisplay_; } - XID xwindow() const { return xwindow_; } - - void UnConfineCursor(); - - // Checks if XEvent is for this XWindow. - bool IsEventForXWindow(const XEvent& xev) const; - - // Processes events for this XWindow. - void ProcessXWindowEvent(XEvent* xev); - - private: - // Called when WM_STATE property is changed. - void OnWMStateUpdated(); - - bool IsMaximized() const; - bool IsFullscreen() const; - - PlatformWindowDelegate* const delegate_; - - XDisplay* xdisplay_; - XID xwindow_ = x11::None; - XID xroot_window_; - std::unique_ptr<ui::XScopedEventSelector> xwindow_events_; - - base::string16 window_title_; - - // The bounds of |xwindow_|. - gfx::Rect bounds_; - - // The window manager state bits. - base::flat_set<::Atom> window_properties_; - - // Stores current state of this window. - PlatformWindowState state_; - - // Keep track of barriers to confine cursor. - bool has_pointer_barriers_ = false; - std::array<XID, 4> pointer_barriers_; - - bool window_mapped_ = false; - - DISALLOW_COPY_AND_ASSIGN(X11WindowBase); -}; - -} // namespace ui - -#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_ diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index e585e00624ad9..7872cc66bd456 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn @@ -707,6 +707,7 @@ jumbo_component("views") { "widget/desktop_aura/desktop_window_tree_host.cc", ] if (use_x11) { + deps += [ "//ui/platform_window/x11" ] public += [ "widget/desktop_aura/desktop_drag_drop_client_aurax11.h", "widget/desktop_aura/desktop_screen_x11.h", @@ -762,7 +763,7 @@ jumbo_component("views") { ] deps += [ "//ui/base:hit_test" ] } - if ((is_linux && !use_x11) || is_fuchsia) { + if (is_linux || is_fuchsia) { public += [ "widget/desktop_aura/desktop_window_tree_host_platform.h" ] sources += [ "widget/desktop_aura/desktop_window_tree_host_platform.cc" ] diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc index 4331c2a2e85ce..f494d1ff45169 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc @@ -26,62 +26,6 @@ namespace views { -namespace { - -ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties( - const Widget::InitParams& params) { - ui::PlatformWindowInitProperties properties; - - switch (params.type) { - case Widget::InitParams::TYPE_WINDOW: - properties.type = ui::PlatformWindowType::kWindow; - break; - - case Widget::InitParams::TYPE_MENU: - properties.type = ui::PlatformWindowType::kMenu; - break; - - case Widget::InitParams::TYPE_TOOLTIP: - properties.type = ui::PlatformWindowType::kTooltip; - break; - - default: - properties.type = ui::PlatformWindowType::kPopup; - break; - } - - properties.bounds = params.bounds; - properties.activatable = - params.activatable == Widget::InitParams::ACTIVATABLE_YES; - properties.force_show_in_taskbar = params.force_show_in_taskbar; - properties.keep_on_top = - params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal; - properties.visible_on_all_workspaces = params.visible_on_all_workspaces; - properties.remove_standard_frame = params.remove_standard_frame; - properties.workspace = params.workspace; - properties.wm_class_name = params.wm_class_name; - properties.wm_class_class = params.wm_class_class; - properties.wm_role_name = params.wm_role_name; - - if (params.parent && params.parent->GetHost()) - properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget(); - - switch (params.opacity) { - case Widget::InitParams::WindowOpacity::INFER_OPACITY: - properties.opacity = ui::PlatformWindowOpacity::kInferOpacity; - break; - case Widget::InitParams::WindowOpacity::OPAQUE_WINDOW: - properties.opacity = ui::PlatformWindowOpacity::kOpaqueWindow; - break; - case Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW: - properties.opacity = ui::PlatformWindowOpacity::kTranslucentWindow; - break; - } - - return properties; -} - -} // namespace //////////////////////////////////////////////////////////////////////////////// // DesktopWindowTreeHostPlatform: @@ -92,9 +36,13 @@ DesktopWindowTreeHostPlatform::DesktopWindowTreeHostPlatform( desktop_native_widget_aura_(desktop_native_widget_aura) {} DesktopWindowTreeHostPlatform::~DesktopWindowTreeHostPlatform() { +// TODO(msisov): Once destruction goes from DWTHX11 to DWTHPlatform, remove this +// guard. +#if !defined(USE_X11) DCHECK(got_on_closed_); desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this); DestroyDispatcher(); +#endif } void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) { @@ -138,6 +86,18 @@ void DesktopWindowTreeHostPlatform::OnWidgetInitDone() {} void DesktopWindowTreeHostPlatform::OnActiveWindowChanged(bool active) {} +base::Optional<gfx::Size> +DesktopWindowTreeHostPlatform::GetMinimumSizeForWindow() { + return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMinimumSize())) + .size(); +} + +base::Optional<gfx::Size> +DesktopWindowTreeHostPlatform::GetMaximumSizeForWindow() { + return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMaximumSize())) + .size(); +} + std::unique_ptr<corewm::Tooltip> DesktopWindowTreeHostPlatform::CreateTooltip() { return std::make_unique<corewm::TooltipAura>(); @@ -146,6 +106,7 @@ DesktopWindowTreeHostPlatform::CreateTooltip() { std::unique_ptr<aura::client::DragDropClient> DesktopWindowTreeHostPlatform::CreateDragDropClient( DesktopNativeCursorManager* cursor_manager) { +#if !defined(USE_X11) ui::WmDragHandler* drag_handler = ui::GetWmDragHandler(*(platform_window())); std::unique_ptr<DesktopDragDropClientOzone> drag_drop_client = std::make_unique<DesktopDragDropClientOzone>(window(), cursor_manager, @@ -154,6 +115,11 @@ DesktopWindowTreeHostPlatform::CreateDragDropClient( // drop action. SetWmDropHandler(platform_window(), drag_drop_client.get()); return std::move(drag_drop_client); +#else + // TODO(https://crbug.com/990756): Move the X11 initialization of dnd here. + NOTIMPLEMENTED_LOG_ONCE(); + return nullptr; +#endif } void DesktopWindowTreeHostPlatform::Close() { @@ -571,6 +537,72 @@ void DesktopWindowTreeHostPlatform::OnActivationChanged(bool active) { desktop_native_widget_aura_->HandleActivationChanged(active); } +ui::PlatformWindowInitProperties +DesktopWindowTreeHostPlatform::ConvertWidgetInitParamsToInitProperties( + const Widget::InitParams& params) { + ui::PlatformWindowInitProperties properties; + + switch (params.type) { + case Widget::InitParams::TYPE_WINDOW: + properties.type = ui::PlatformWindowType::kWindow; + break; + + case Widget::InitParams::TYPE_MENU: + properties.type = ui::PlatformWindowType::kMenu; + break; + + case Widget::InitParams::TYPE_TOOLTIP: + properties.type = ui::PlatformWindowType::kTooltip; + break; + + case Widget::InitParams::TYPE_DRAG: + properties.type = ui::PlatformWindowType::kDrag; + break; + + case Widget::InitParams::TYPE_BUBBLE: + properties.type = ui::PlatformWindowType::kBubble; + break; + + default: + properties.type = ui::PlatformWindowType::kPopup; + break; + } + + properties.bounds = params.bounds; + properties.activatable = + params.activatable == Widget::InitParams::ACTIVATABLE_YES; + properties.force_show_in_taskbar = params.force_show_in_taskbar; + properties.keep_on_top = + params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal; + properties.visible_on_all_workspaces = params.visible_on_all_workspaces; + properties.remove_standard_frame = params.remove_standard_frame; + properties.workspace = params.workspace; + properties.wm_class_name = params.wm_class_name; + properties.wm_class_class = params.wm_class_class; + properties.wm_role_name = params.wm_role_name; + + if (params.parent && params.parent->GetHost()) + properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget(); + + switch (params.opacity) { + case Widget::InitParams::WindowOpacity::INFER_OPACITY: + properties.opacity = ui::PlatformWindowOpacity::kInferOpacity; + break; + case Widget::InitParams::WindowOpacity::OPAQUE_WINDOW: + properties.opacity = ui::PlatformWindowOpacity::kOpaqueWindow; + break; + case Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW: + properties.opacity = ui::PlatformWindowOpacity::kTranslucentWindow; + break; + } + + return properties; +} + +aura::Window* DesktopWindowTreeHostPlatform::content_window() { + return desktop_native_widget_aura_->content_window(); +} + void DesktopWindowTreeHostPlatform::Relayout() { Widget* widget = native_widget_delegate_->AsWidget(); NonClientView* non_client_view = widget->non_client_view(); @@ -612,6 +644,11 @@ gfx::Rect DesktopWindowTreeHostPlatform::ToPixelRect( //////////////////////////////////////////////////////////////////////////////// // DesktopWindowTreeHost: +// As DWTHX11 subclasses DWTHPlatform now (during transition period. see +// https://crbug.com/990756), we need to guard this factory method. +// TODO(msisov): remove this guard once DWTHX11 is finally merged into +// DWTHPlatform. +#if !defined(USE_X11) // static DesktopWindowTreeHost* DesktopWindowTreeHost::Create( internal::NativeWidgetDelegate* native_widget_delegate, @@ -619,5 +656,6 @@ DesktopWindowTreeHost* DesktopWindowTreeHost::Create( return new DesktopWindowTreeHostPlatform(native_widget_delegate, desktop_native_widget_aura); } +#endif } // namespace views diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h index d826f8550b2c7..f3f9ace2e551f 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h @@ -90,12 +90,29 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform bool ShouldUseDesktopNativeCursorManager() const override; bool ShouldCreateVisibilityController() const override; - // WindowTreeHostPlatform: + // PlatformWindowDelegateBase: void DispatchEvent(ui::Event* event) override; void OnClosed() override; void OnWindowStateChanged(ui::PlatformWindowState new_state) override; void OnCloseRequest() override; void OnActivationChanged(bool active) override; + base::Optional<gfx::Size> GetMinimumSizeForWindow() override; + base::Optional<gfx::Size> GetMaximumSizeForWindow() override; + + protected: + // TODO(https://crbug.com/990756): move this back to unnamed namespace, when + // DWTHX11 stops initialization of the PlatformWindow. Also, remove these + // accessor methods. + ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties( + const Widget::InitParams& params); + internal::NativeWidgetDelegate* native_widget_delegate() { + return native_widget_delegate_; + } + DesktopNativeWidgetAura* desktop_native_widget_aura() { + return desktop_native_widget_aura_; + } + // Accessor for DesktopNativeWidgetAura::content_window(). + aura::Window* content_window(); private: FRIEND_TEST_ALL_PREFIXES(DesktopWindowTreeHostPlatformTest, HitTest); diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index d47565e8acc91..312df3e906973 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc @@ -22,7 +22,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" -#include "base/trace_event/trace_event.h" #include "third_party/skia/include/core/SkPath.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/cursor_client.h" @@ -54,6 +53,7 @@ #include "ui/gfx/path_x11.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" +#include "ui/platform_window/x11/x11_window.h" #include "ui/views/corewm/tooltip_aura.h" #include "ui/views/linux_ui/linux_ui.h" #include "ui/views/views_delegate.h" @@ -88,61 +88,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(DesktopWindowTreeHostX11*, namespace { -ui::XWindow::Configuration ConvertInitParamsToX11WindowConfig( - const Widget::InitParams& params) { - using WindowType = ui::XWindow::WindowType; - using WindowOpacity = ui::XWindow::WindowOpacity; - ui::XWindow::Configuration config; - - switch (params.type) { - case Widget::InitParams::TYPE_WINDOW: - config.type = WindowType::kWindow; - break; - case Widget::InitParams::TYPE_MENU: - config.type = WindowType::kMenu; - break; - case Widget::InitParams::TYPE_TOOLTIP: - config.type = WindowType::kTooltip; - break; - case Widget::InitParams::TYPE_DRAG: - config.type = WindowType::kDrag; - break; - case Widget::InitParams::TYPE_BUBBLE: - config.type = WindowType::kBubble; - break; - default: - config.type = WindowType::kPopup; - break; - } - - switch (params.opacity) { - case Widget::InitParams::WindowOpacity::INFER_OPACITY: - config.opacity = WindowOpacity::kInferOpacity; - break; - case Widget::InitParams::WindowOpacity::OPAQUE_WINDOW: - config.opacity = WindowOpacity::kOpaqueWindow; - break; - case Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW: - config.opacity = WindowOpacity::kTranslucentWindow; - break; - } - - config.activatable = - params.activatable == Widget::InitParams::ACTIVATABLE_YES; - config.force_show_in_taskbar = params.force_show_in_taskbar; - config.keep_on_top = - params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal; - config.visible_on_all_workspaces = params.visible_on_all_workspaces; - config.remove_standard_frame = params.remove_standard_frame; - - config.workspace = params.workspace; - config.wm_class_name = params.wm_class_name; - config.wm_class_class = params.wm_class_class; - config.wm_role_name = params.wm_role_name; - - return config; -} - // Returns the whole path from |window| to the root. std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) { ::Window parent_win, root_win; @@ -152,8 +97,8 @@ std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) { while (window) { result.push_back(window); - if (!XQueryTree(xdisplay, window, - &root_win, &parent_win, &child_windows, &num_child_windows)) + if (!XQueryTree(xdisplay, window, &root_win, &parent_win, &child_windows, + &num_child_windows)) break; if (child_windows) XFree(child_windows); @@ -210,14 +155,14 @@ bool ShouldDiscardKeyEvent(XEvent* xev) { DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( internal::NativeWidgetDelegate* native_widget_delegate, DesktopNativeWidgetAura* desktop_native_widget_aura) - : native_widget_delegate_(native_widget_delegate), - desktop_native_widget_aura_(desktop_native_widget_aura), - x11_window_(std::make_unique<ui::XWindow>(this)) {} + : DesktopWindowTreeHostPlatform(native_widget_delegate, + desktop_native_widget_aura), + x11_window_(std::make_unique<ui::X11Window>(this, this)) {} DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() { window()->ClearProperty(kHostForRootWindow); wm::SetWindowMoveClient(window(), nullptr); - desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this); + desktop_native_widget_aura()->OnDesktopWindowTreeHostDestroyed(this); DestroyDispatcher(); } @@ -238,9 +183,7 @@ DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::GetHostForXID(XID xid) { // static std::vector<aura::Window*> DesktopWindowTreeHostX11::GetAllOpenWindows() { std::vector<aura::Window*> windows(open_windows().size()); - std::transform(open_windows().begin(), - open_windows().end(), - windows.begin(), + std::transform(open_windows().begin(), open_windows().end(), windows.begin(), GetContentWindowForXID); return windows; } @@ -327,7 +270,7 @@ void DesktopWindowTreeHostX11::OnNativeWidgetCreated( SetWindowTransparency(); - native_widget_delegate_->OnNativeWidgetCreated(); + native_widget_delegate()->OnNativeWidgetCreated(); } void DesktopWindowTreeHostX11::OnWidgetInitDone() {} @@ -367,10 +310,11 @@ void DesktopWindowTreeHostX11::Close() { void DesktopWindowTreeHostX11::CloseNow() { if (x11_window_->window() == x11::None) return; + x11_window_->PrepareForShutdown(); ReleaseCapture(); RemoveNonClientEventFilter(); - native_widget_delegate_->OnNativeWidgetDestroying(); + native_widget_delegate()->OnNativeWidgetDestroying(); // If we have children, close them. Use a copy for iteration because they'll // remove themselves. @@ -391,12 +335,8 @@ void DesktopWindowTreeHostX11::CloseNow() { DestroyCompositor(); open_windows().remove(x11_window_->window()); - // Actually free our native resources. - if (auto* source = ui::PlatformEventSource::GetInstance()) - source->RemovePlatformEventDispatcher(this); x11_window_->Close(); - desktop_native_widget_aura_->OnHostClosed(); } aura::WindowTreeHost* DesktopWindowTreeHostX11::AsWindowTreeHost() { @@ -430,7 +370,7 @@ void DesktopWindowTreeHostX11::Show(ui::WindowShowState show_state, break; } - native_widget_delegate_->AsWidget()->SetInitialFocus(show_state); + native_widget_delegate()->AsWidget()->SetInitialFocus(show_state); content_window()->Show(); } @@ -695,7 +635,7 @@ void DesktopWindowTreeHostX11::SetVisible(bool visible) { if (compositor()) compositor()->SetVisible(visible); - native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible); + native_widget_delegate()->OnNativeWidgetVisibilityChanged(visible); } void DesktopWindowTreeHostX11::SetVisibleOnAllWorkspaces(bool always_visible) { @@ -707,7 +647,9 @@ bool DesktopWindowTreeHostX11::IsVisibleOnAllWorkspaces() const { } bool DesktopWindowTreeHostX11::SetWindowTitle(const base::string16& title) { - return x11_window_->SetTitle(title); + auto* x_window = static_cast<ui::XWindow*>(x11_window_.get()); + DCHECK(x_window); + return x_window->SetTitle(title); } void DesktopWindowTreeHostX11::ClearNativeFocus() { @@ -748,7 +690,7 @@ void DesktopWindowTreeHostX11::SetVisibilityChangedAnimationsEnabled( NonClientFrameView* DesktopWindowTreeHostX11::CreateNonClientFrameView() { return ShouldUseNativeFrame() - ? new NativeFrameView(native_widget_delegate_->AsWidget()) + ? new NativeFrameView(native_widget_delegate()->AsWidget()) : nullptr; } @@ -762,7 +704,7 @@ bool DesktopWindowTreeHostX11::ShouldWindowContentsBeTransparent() const { void DesktopWindowTreeHostX11::FrameTypeChanged() { Widget::FrameType new_type = - native_widget_delegate_->AsWidget()->frame_type(); + native_widget_delegate()->AsWidget()->frame_type(); if (new_type == Widget::FrameType::kDefault) { // The default is determined by Widget::InitParams::remove_standard_frame // and does not change. @@ -841,8 +783,8 @@ void DesktopWindowTreeHostX11::SetAspectRatio(const gfx::SizeF& aspect_ratio) { x11_window_->SetAspectRatio(aspect_ratio); } -void DesktopWindowTreeHostX11::SetWindowIcons( - const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) { +void DesktopWindowTreeHostX11::SetWindowIcons(const gfx::ImageSkia& window_icon, + const gfx::ImageSkia& app_icon) { x11_window_->SetWindowIcons(window_icon, app_icon); } @@ -918,7 +860,9 @@ void DesktopWindowTreeHostX11::ShowImpl() { } void DesktopWindowTreeHostX11::HideImpl() { - if (x11_window_->Hide()) + auto* x_window = static_cast<ui::XWindow*>(x11_window_.get()); + DCHECK(x_window); + if (x_window->Hide()) SetVisible(false); } @@ -932,7 +876,6 @@ void DesktopWindowTreeHostX11::SetBoundsInPixels( gfx::Rect bounds_in_pixels(requested_bounds_in_pixel.origin(), AdjustSize(requested_bounds_in_pixel.size())); - bool origin_changed = bounds.origin() != bounds_in_pixels.origin(); bool size_changed = bounds.size() != bounds_in_pixels.size(); if (size_changed) { @@ -942,14 +885,6 @@ void DesktopWindowTreeHostX11::SetBoundsInPixels( } x11_window_->SetBounds(bounds_in_pixels); - - if (origin_changed) - native_widget_delegate_->AsWidget()->OnNativeWidgetMove(); - - if (size_changed) { - OnHostResizedInPixels(bounds_in_pixels.size()); - ResetWindowRegion(); - } } gfx::Point DesktopWindowTreeHostX11::GetLocationOnScreenInPixels() const { @@ -1046,204 +981,16 @@ void DesktopWindowTreeHostX11::OnDisplayMetricsChanged( } } -void DesktopWindowTreeHostX11::OnXWindowCreated() { - if (auto* source = ui::PlatformEventSource::GetInstance()) - source->AddPlatformEventDispatcher(this); - - open_windows().push_front(x11_window_->window()); -} - -void DesktopWindowTreeHostX11::OnXWindowMapped() { - for (DesktopWindowTreeHostObserverX11& observer : observer_list_) - observer.OnWindowMapped(x11_window_->window()); -} - -void DesktopWindowTreeHostX11::OnXWindowUnmapped() { - for (DesktopWindowTreeHostObserverX11& observer : observer_list_) - observer.OnWindowUnmapped(x11_window_->window()); -} - -void DesktopWindowTreeHostX11::OnXWindowStateChanged() { - bool was_minimized = x11_window_->was_minimized(); - bool is_minimized = IsMinimized(); - - // Propagate the window minimization information to the content window, so - // the render side can update its visibility properly. OnWMStateUpdated() is - // called by PropertyNofify event from DispatchEvent() when the browser is - // minimized or shown from minimized state. On Windows, this is realized by - // calling OnHostResizedInPixels() with an empty size. In particular, - // HWNDMessageHandler::GetClientAreaBounds() returns an empty size when the - // window is minimized. On Linux, returning empty size in GetBounds() or - // SetBoundsInPixels() does not work. - // We also propagate the minimization to the compositor, to makes sure that we - // don't draw any 'blank' frames that could be noticed in applications such as - // window manager previews, which show content even when a window is - // minimized. - if (is_minimized != was_minimized) { - if (is_minimized) { - SetVisible(false); - content_window()->Hide(); - } else { - content_window()->Show(); - SetVisible(true); - } - } - - if (restored_bounds_in_pixels_.IsEmpty()) { - if (IsMaximized()) { - // The request that we become maximized originated from a different - // process. |bounds_in_pixels_| already contains our maximized bounds. Do - // a best effort attempt to get restored bounds by setting it to our - // previously set bounds (and if we get this wrong, we aren't any worse - // off since we'd otherwise be returning our maximized bounds). - restored_bounds_in_pixels_ = x11_window_->previous_bounds(); - } - } else if (!IsMaximized() && !IsFullscreen()) { - // If we have restored bounds, but WM_STATE no longer claims to be - // maximized or fullscreen, we should clear our restored bounds. - restored_bounds_in_pixels_ = gfx::Rect(); - } - - // Now that we have different window properties, we may need to relayout the - // window. (The windows code doesn't need this because their window change is - // synchronous.) - Relayout(); - ResetWindowRegion(); -} - -void DesktopWindowTreeHostX11::OnXWindowWorkspaceChanged() { - OnHostWorkspaceChanged(); -} - -void DesktopWindowTreeHostX11::OnXWindowDamageEvent( - const gfx::Rect& damage_rect_in_pixels) { - compositor()->ScheduleRedrawRect(damage_rect_in_pixels); -} - -void DesktopWindowTreeHostX11::OnXWindowKeyEvent(ui::KeyEvent* key_event) { - DispatchKeyEvent(key_event); -} - -void DesktopWindowTreeHostX11::OnXWindowMouseEvent(ui::MouseEvent* mouseev) { - DispatchMouseEvent(mouseev); -} - -void DesktopWindowTreeHostX11::OnXWindowTouchEvent( - ui::TouchEvent* touch_event) { - DispatchTouchEvent(touch_event); -} - -void DesktopWindowTreeHostX11::OnXWindowScrollEvent( - ui::ScrollEvent* scroll_event) { - SendEventToSink(scroll_event); -} - -void DesktopWindowTreeHostX11::OnXWindowSelectionEvent(XEvent* xev) { - DCHECK(xev); - DCHECK(drag_drop_client_); - drag_drop_client_->OnSelectionNotify(xev->xselection); -} - -void DesktopWindowTreeHostX11::OnXWindowDragDropEvent(XEvent* xev) { - DCHECK(xev); - DCHECK(drag_drop_client_); - - ::Atom message_type = xev->xclient.message_type; - if (message_type == gfx::GetAtom("XdndEnter")) { - drag_drop_client_->OnXdndEnter(xev->xclient); - } else if (message_type == gfx::GetAtom("XdndLeave")) { - drag_drop_client_->OnXdndLeave(xev->xclient); - } else if (message_type == gfx::GetAtom("XdndPosition")) { - drag_drop_client_->OnXdndPosition(xev->xclient); - } else if (message_type == gfx::GetAtom("XdndStatus")) { - drag_drop_client_->OnXdndStatus(xev->xclient); - } else if (message_type == gfx::GetAtom("XdndFinished")) { - drag_drop_client_->OnXdndFinished(xev->xclient); - } else if (message_type == gfx::GetAtom("XdndDrop")) { - drag_drop_client_->OnXdndDrop(xev->xclient); - } -} - -void DesktopWindowTreeHostX11::OnXWindowRawKeyEvent(XEvent* xev) { - switch (xev->type) { - case KeyPress: - if (!ShouldDiscardKeyEvent(xev)) { - ui::KeyEvent keydown_event(xev); - DispatchKeyEvent(&keydown_event); - } - break; - case KeyRelease: - - // There is no way to deactivate a window in X11 so ignore input if - // window is supposed to be 'inactive'. - if (!IsActive() && !HasCapture()) - break; - - if (!ShouldDiscardKeyEvent(xev)) { - ui::KeyEvent keyup_event(xev); - DispatchKeyEvent(&keyup_event); - } - break; - default: - NOTREACHED() << xev->type; - break; - } -} - -void DesktopWindowTreeHostX11::OnXWindowChildCrossingEvent(XEvent* xev) { - DCHECK(xev); - ui::MouseEvent mouse_event(xev); - DispatchMouseEvent(&mouse_event); -} - -void DesktopWindowTreeHostX11::OnXWindowSizeChanged( - const gfx::Size& size_in_pixels) { - OnHostResizedInPixels(size_in_pixels); - ResetWindowRegion(); -} - -void DesktopWindowTreeHostX11::OnXWindowCloseRequested() { - OnHostCloseRequested(); -} - -void DesktopWindowTreeHostX11::OnXWindowMoved(const gfx::Point& window_origin) { - OnHostMovedInPixels(window_origin); -} - -void DesktopWindowTreeHostX11::OnXWindowLostPointerGrab() { - dispatcher()->OnHostLostMouseGrab(); -} - -void DesktopWindowTreeHostX11::OnXWindowLostCapture() { - OnHostLostWindowCapture(); -} - -void DesktopWindowTreeHostX11::OnXWindowIsActiveChanged(bool active) { - if (active) { - // TODO(thomasanderson): Remove this window shuffling and use XWindowCache - // instead. - ::Window xwindow = x11_window_->window(); - open_windows().remove(xwindow); - open_windows().insert(open_windows().begin(), xwindow); - } - desktop_native_widget_aura_->HandleActivationChanged(active); - native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint(); -} - -gfx::Size DesktopWindowTreeHostX11::GetMinimumSizeForXWindow() { - return ToPixelRect(gfx::Rect(native_widget_delegate_->GetMinimumSize())) - .size(); -} - -gfx::Size DesktopWindowTreeHostX11::GetMaximumSizeForXWindow() { - return ToPixelRect(gfx::Rect(native_widget_delegate_->GetMaximumSize())) - .size(); -} - //////////////////////////////////////////////////////////////////////////////// // DesktopWindowTreeHostX11, private: void DesktopWindowTreeHostX11::InitX11Window(const Widget::InitParams& params) { + // Disable compositing on tooltips as a workaround for + // https://crbug.com/442111. + CreateCompositor(viz::FrameSinkId(), + params.force_software_compositing || + params.type == Widget::InitParams::TYPE_TOOLTIP); + // Calculate initial bounds gfx::Rect bounds_in_pixels = ToPixelRect(params.bounds); gfx::Size adjusted_size = AdjustSize(bounds_in_pixels.size()); @@ -1272,20 +1019,14 @@ void DesktopWindowTreeHostX11::InitX11Window(const Widget::InitParams& params) { background_color = theme->GetSystemColor(target_color); } - // Create window configuration and initialize it - ui::XWindow::Configuration config = - ConvertInitParamsToX11WindowConfig(params); - config.bounds = bounds_in_pixels; - config.background_color = background_color; - config.prefer_dark_theme = linux_ui && linux_ui->PreferDarkTheme(); - config.icon = ViewsDelegate::GetInstance()->GetDefaultWindowIcon(); - x11_window_->Init(config); - - // Disable compositing on tooltips as a workaround for - // https://crbug.com/442111. - CreateCompositor(viz::FrameSinkId(), - params.force_software_compositing || - params.type == Widget::InitParams::TYPE_TOOLTIP); + // Create PlatformWindowInitProperties and initialize it + ui::PlatformWindowInitProperties properties = + ConvertWidgetInitParamsToInitProperties(params); + properties.bounds = bounds_in_pixels; + properties.background_color = background_color; + properties.prefer_dark_theme = linux_ui && linux_ui->PreferDarkTheme(); + properties.icon = ViewsDelegate::GetInstance()->GetDefaultWindowIcon(); + x11_window_->Initialize(std::move(properties)); if (ui::IsSyncExtensionAvailable()) { compositor_observer_ = std::make_unique<SwapWithNewSizeObserverHelper>( @@ -1293,7 +1034,6 @@ void DesktopWindowTreeHostX11::InitX11Window(const Widget::InitParams& params) { &DesktopWindowTreeHostX11::OnCompleteSwapWithNewSize, base::Unretained(this))); } - OnAcceleratedWidgetAvailable(); } void DesktopWindowTreeHostX11::DispatchHostWindowDragMovement( @@ -1388,7 +1128,7 @@ void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) { } void DesktopWindowTreeHostX11::DispatchKeyEvent(ui::KeyEvent* event) { - if (native_widget_delegate_->AsWidget()->IsActive()) + if (native_widget_delegate()->AsWidget()->IsActive()) SendEventToSink(event); } @@ -1396,7 +1136,7 @@ void DesktopWindowTreeHostX11::ResetWindowRegion() { _XRegion* xregion = nullptr; if (!x11_window_->use_custom_shape() && !IsMaximized() && !IsFullscreen()) { SkPath window_mask; - Widget* widget = native_widget_delegate_->AsWidget(); + Widget* widget = native_widget_delegate()->AsWidget(); if (widget->non_client_view()) { // Some frame views define a custom (non-rectangular) window mask. If // so, use it to define the window shape. If not, fall through. @@ -1410,7 +1150,6 @@ void DesktopWindowTreeHostX11::ResetWindowRegion() { x11_window_->UpdateWindowRegion(xregion); } - std::list<XID>& DesktopWindowTreeHostX11::open_windows() { if (!open_windows_) open_windows_ = new std::list<XID>(); @@ -1443,7 +1182,7 @@ void DesktopWindowTreeHostX11::SetWindowTransparency() { } void DesktopWindowTreeHostX11::Relayout() { - Widget* widget = native_widget_delegate_->AsWidget(); + Widget* widget = native_widget_delegate()->AsWidget(); NonClientView* non_client_view = widget->non_client_view(); // non_client_view may be NULL, especially during creation. if (non_client_view) { @@ -1453,30 +1192,14 @@ void DesktopWindowTreeHostX11::Relayout() { } //////////////////////////////////////////////////////////////////////////////// -// DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation: - -bool DesktopWindowTreeHostX11::CanDispatchEvent( - const ui::PlatformEvent& event) { - return x11_window_->IsTargetedBy(*event); -} - -uint32_t DesktopWindowTreeHostX11::DispatchEvent( - const ui::PlatformEvent& event) { - XEvent* xev = event; - - TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch", - "event->type", event->type); - - x11_window_->ProcessEvent(xev); - return ui::POST_DISPATCH_STOP_PROPAGATION; -} +// DesktopWindowTreeHostX11 implementation: void DesktopWindowTreeHostX11::DelayedChangeFrameType(Widget::FrameType type) { SetUseNativeFrame(type == Widget::FrameType::kForceNative); // Replace the frame and layout the contents. Even though we don't have a // swappable glass frame like on Windows, we still replace the frame because // the button assets don't update otherwise. - native_widget_delegate_->AsWidget()->non_client_view()->UpdateFrame(); + native_widget_delegate()->AsWidget()->non_client_view()->UpdateFrame(); } gfx::Rect DesktopWindowTreeHostX11::ToDIPRect( @@ -1513,10 +1236,6 @@ void DesktopWindowTreeHostX11::EnableEventListening() { targeter_for_modal_.reset(); } -aura::Window* DesktopWindowTreeHostX11::content_window() { - return desktop_native_widget_aura_->content_window(); -} - void DesktopWindowTreeHostX11::OnCompleteSwapWithNewSize( const gfx::Size& size) { x11_window_->NotifySwapAfterResize(); @@ -1534,6 +1253,165 @@ void DesktopWindowTreeHostX11::SetVisualId(VisualID visual_id) { x11_window_->set_visual_id(visual_id); } +void DesktopWindowTreeHostX11::OnBoundsChanged(const gfx::Rect& new_bounds) { + ResetWindowRegion(); + WindowTreeHostPlatform::OnBoundsChanged(new_bounds); +} + +void DesktopWindowTreeHostX11::DispatchEvent(ui::Event* event) { + if (event->IsKeyEvent()) + DispatchKeyEvent(event->AsKeyEvent()); + else if (event->IsMouseEvent()) + DispatchMouseEvent(event->AsMouseEvent()); + else if (event->IsTouchEvent()) + DispatchTouchEvent(event->AsTouchEvent()); + else + SendEventToSink(event); +} + +void DesktopWindowTreeHostX11::OnClosed() { + desktop_native_widget_aura()->OnHostClosed(); +} + +void DesktopWindowTreeHostX11::OnWindowStateChanged( + ui::PlatformWindowState new_state) { + bool was_minimized = x11_window_->was_minimized(); + bool is_minimized = IsMinimized(); + + // Propagate the window minimization information to the content window, so + // the render side can update its visibility properly. OnWMStateUpdated() is + // called by PropertyNofify event from DispatchEvent() when the browser is + // minimized or shown from minimized state. On Windows, this is realized by + // calling OnHostResizedInPixels() with an empty size. In particular, + // HWNDMessageHandler::GetClientAreaBounds() returns an empty size when the + // window is minimized. On Linux, returning empty size in GetBounds() or + // SetBoundsInPixels() does not work. + // We also propagate the minimization to the compositor, to makes sure that we + // don't draw any 'blank' frames that could be noticed in applications such as + // window manager previews, which show content even when a window is + // minimized. + if (is_minimized != was_minimized) { + if (is_minimized) { + SetVisible(false); + content_window()->Hide(); + } else { + content_window()->Show(); + SetVisible(true); + } + } + + if (restored_bounds_in_pixels_.IsEmpty()) { + if (IsMaximized()) { + // The request that we become maximized originated from a different + // process. |bounds_in_pixels_| already contains our maximized bounds. Do + // a best effort attempt to get restored bounds by setting it to our + // previously set bounds (and if we get this wrong, we aren't any worse + // off since we'd otherwise be returning our maximized bounds). + restored_bounds_in_pixels_ = x11_window_->previous_bounds(); + } + } else if (!IsMaximized() && !IsFullscreen()) { + // If we have restored bounds, but WM_STATE no longer claims to be + // maximized or fullscreen, we should clear our restored bounds. + restored_bounds_in_pixels_ = gfx::Rect(); + } + + // Now that we have different window properties, we may need to relayout the + // window. (The windows code doesn't need this because their window change is + // synchronous.) + Relayout(); + ResetWindowRegion(); +} + +void DesktopWindowTreeHostX11::OnAcceleratedWidgetAvailable( + gfx::AcceleratedWidget widget) { + open_windows().push_front(x11_window_->window()); + WindowTreeHost::OnAcceleratedWidgetAvailable(); +} + +void DesktopWindowTreeHostX11::OnAcceleratedWidgetDestroyed() {} + +void DesktopWindowTreeHostX11::OnActivationChanged(bool active) { + if (active) { + // TODO(thomasanderson): Remove this window shuffling and use XWindowCache + // instead. + ::Window xwindow = x11_window_->window(); + open_windows().remove(xwindow); + open_windows().insert(open_windows().begin(), xwindow); + } + desktop_native_widget_aura()->HandleActivationChanged(active); + native_widget_delegate()->AsWidget()->GetRootView()->SchedulePaint(); +} + +void DesktopWindowTreeHostX11::OnXWindowMapped() { + for (DesktopWindowTreeHostObserverX11& observer : observer_list_) + observer.OnWindowMapped(x11_window_->window()); +} + +void DesktopWindowTreeHostX11::OnXWindowUnmapped() { + for (DesktopWindowTreeHostObserverX11& observer : observer_list_) + observer.OnWindowUnmapped(x11_window_->window()); +} + +void DesktopWindowTreeHostX11::OnLostMouseGrab() { + dispatcher()->OnHostLostMouseGrab(); +} + +void DesktopWindowTreeHostX11::OnWorkspaceChanged() { + OnHostWorkspaceChanged(); +} + +void DesktopWindowTreeHostX11::OnXWindowSelectionEvent(XEvent* xev) { + DCHECK(xev); + DCHECK(drag_drop_client_); + drag_drop_client_->OnSelectionNotify(xev->xselection); +} + +void DesktopWindowTreeHostX11::OnXWindowDragDropEvent(XEvent* xev) { + DCHECK(xev); + DCHECK(drag_drop_client_); + + ::Atom message_type = xev->xclient.message_type; + if (message_type == gfx::GetAtom("XdndEnter")) { + drag_drop_client_->OnXdndEnter(xev->xclient); + } else if (message_type == gfx::GetAtom("XdndLeave")) { + drag_drop_client_->OnXdndLeave(xev->xclient); + } else if (message_type == gfx::GetAtom("XdndPosition")) { + drag_drop_client_->OnXdndPosition(xev->xclient); + } else if (message_type == gfx::GetAtom("XdndStatus")) { + drag_drop_client_->OnXdndStatus(xev->xclient); + } else if (message_type == gfx::GetAtom("XdndFinished")) { + drag_drop_client_->OnXdndFinished(xev->xclient); + } else if (message_type == gfx::GetAtom("XdndDrop")) { + drag_drop_client_->OnXdndDrop(xev->xclient); + } +} + +void DesktopWindowTreeHostX11::OnXWindowRawKeyEvent(XEvent* xev) { + switch (xev->type) { + case KeyPress: + if (!ShouldDiscardKeyEvent(xev)) { + ui::KeyEvent keydown_event(xev); + DispatchKeyEvent(&keydown_event); + } + break; + case KeyRelease: + + // There is no way to deactivate a window in X11 so ignore input if + // window is supposed to be 'inactive'. + if (!IsActive() && !HasCapture()) + break; + + if (!ShouldDiscardKeyEvent(xev)) { + ui::KeyEvent keyup_event(xev); + DispatchKeyEvent(&keyup_event); + } + break; + default: + NOTREACHED() << xev->type; + break; + } +} + //////////////////////////////////////////////////////////////////////////////// // DesktopWindowTreeHost, public: diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h index f1806257b0b01..4a9949a2c19bf 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h @@ -20,14 +20,14 @@ #include "base/observer_list.h" #include "ui/aura/scoped_window_targeter.h" #include "ui/aura/window_tree_host.h" -#include "ui/base/x/x11_window.h" -#include "ui/events/platform/platform_event_dispatcher.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/x/x11_types.h" +#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/platform_window/x11/x11_window.h" #include "ui/views/views_export.h" -#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h" +#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h" namespace gfx { class ImageSkia; @@ -39,8 +39,8 @@ class KeyboardHook; class KeyEvent; class MouseEvent; class TouchEvent; -class ScrollEvent; -} +class X11Window; +} // namespace ui namespace views { class DesktopDragDropClientAuraX11; @@ -50,11 +50,9 @@ class X11DesktopWindowMoveClient; class WindowEventFilter; class VIEWS_EXPORT DesktopWindowTreeHostX11 - : public DesktopWindowTreeHost, - public aura::WindowTreeHost, - public ui::PlatformEventDispatcher, + : public DesktopWindowTreeHostPlatform, public ui::WmMoveResizeHandler, - public ui::XWindow::Delegate { + public ui::XEventDelegate { public: DesktopWindowTreeHostX11( internal::NativeWidgetDelegate* native_widget_delegate, @@ -195,30 +193,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; - // Overridden from ui::XWindow::Delegate - void OnXWindowCreated() override; - void OnXWindowMapped() override; - void OnXWindowUnmapped() override; - void OnXWindowStateChanged() override; - void OnXWindowWorkspaceChanged() override; - void OnXWindowKeyEvent(ui::KeyEvent* key_event) override; - void OnXWindowMouseEvent(ui::MouseEvent* mouseev) override; - void OnXWindowTouchEvent(ui::TouchEvent* touch_event) override; - void OnXWindowScrollEvent(ui::ScrollEvent* scroll_event) override; - void OnXWindowSelectionEvent(XEvent* xev) override; - void OnXWindowDragDropEvent(XEvent* xev) override; - void OnXWindowChildCrossingEvent(XEvent* xev) override; - void OnXWindowRawKeyEvent(XEvent* xev) override; - void OnXWindowSizeChanged(const gfx::Size& size) override; - void OnXWindowCloseRequested() override; - void OnXWindowMoved(const gfx::Point& window_origin) override; - void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override; - void OnXWindowLostPointerGrab() override; - void OnXWindowLostCapture() override; - void OnXWindowIsActiveChanged(bool active) override; - gfx::Size GetMinimumSizeForXWindow() override; - gfx::Size GetMaximumSizeForXWindow() override; - private: friend class DesktopWindowTreeHostX11HighDPITest; @@ -270,10 +244,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 // Relayout the widget's client and non-client views. void Relayout(); - // ui::PlatformEventDispatcher: - bool CanDispatchEvent(const ui::PlatformEvent& event) override; - uint32_t DispatchEvent(const ui::PlatformEvent& event) override; - void DelayedChangeFrameType(Widget::FrameType new_type); gfx::Rect ToDIPRect(const gfx::Rect& rect_in_pixels) const; @@ -285,12 +255,31 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 // Set visibility and fire OnNativeWidgetVisibilityChanged() if it changed. void SetVisible(bool visible); - // Accessor for DesktopNativeWidgetAura::content_window(). - aura::Window* content_window(); - // Callback for a swapbuffer after resize. void OnCompleteSwapWithNewSize(const gfx::Size& size); + // PlatformWindowDelegate overrides: + // + // DWTHX11 temporarily overrides the PlatformWindowDelegate methods instead of + // underlying DWTHPlatform and WTHPlatform. Eventually, these will be removed + // from here as we progress in https://crbug.com/990756. + void OnBoundsChanged(const gfx::Rect& new_bounds) override; + void DispatchEvent(ui::Event* event) override; + void OnClosed() override; + void OnWindowStateChanged(ui::PlatformWindowState new_state) override; + void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override; + void OnAcceleratedWidgetDestroyed() override; + void OnActivationChanged(bool active) override; + void OnXWindowMapped() override; + void OnXWindowUnmapped() override; + void OnLostMouseGrab() override; + void OnWorkspaceChanged() override; + + // Overridden from ui::XEventDelegate. + void OnXWindowSelectionEvent(XEvent* xev) override; + void OnXWindowDragDropEvent(XEvent* xev) override; + void OnXWindowRawKeyEvent(XEvent* xev) override; + // The bounds of our window before we were maximized. gfx::Rect restored_bounds_in_pixels_; @@ -306,12 +295,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 std::unique_ptr<WindowEventFilter> non_client_event_filter_; std::unique_ptr<X11DesktopWindowMoveClient> x11_window_move_client_; - // TODO(beng): Consider providing an interface to DesktopNativeWidgetAura - // instead of providing this route back to Widget. - internal::NativeWidgetDelegate* native_widget_delegate_; - - DesktopNativeWidgetAura* desktop_native_widget_aura_; - // We can optionally have a parent which can order us to close, or own // children who we're responsible for closing when we CloseNow(). DesktopWindowTreeHostX11* window_parent_ = nullptr; @@ -340,7 +323,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 std::unique_ptr<CompositorObserver> compositor_observer_; - std::unique_ptr<ui::XWindow> x11_window_; + std::unique_ptr<ui::X11Window> x11_window_; // The display and the native X window hosting the root window. base::WeakPtrFactory<DesktopWindowTreeHostX11> close_widget_factory_{this}; diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc index 5f1541184e0b4..8bd27d22979f4 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc @@ -14,6 +14,7 @@ #include "ui/base/x/x11_util.h" #include "ui/events/event_handler.h" #include "ui/events/platform/x11/x11_event_source.h" +#include "ui/events/platform/x11/x11_event_source_glib.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" @@ -106,7 +107,8 @@ void DispatchMouseMotionEvent(DesktopWindowTreeHostX11* desktop_host, xev.xmotion.is_hint = NotifyNormal; xev.xmotion.same_screen = x11::True; - static_cast<ui::PlatformEventDispatcher*>(desktop_host)->DispatchEvent(&xev); + static_cast<ui::X11EventSourceGlib*>(ui::PlatformEventSource::GetInstance()) + ->ProcessXEvent(&xev); } } // namespace