Commit 1c090989 authored by Maksim Sisov's avatar Maksim Sisov Committed by Commit Bot

[ozone/wayland] Add support for maximize/minimize/fullscreen.

This CL adds a preliminary support to maximize/minimize or set
Wayland windows to fullscreen.

WaylandWindow extends HandleSurfaceConfigure and stores new
states. As a result, Wayland windows will be sending changed
window states to the |delegate_| and notify ServerWindow
and thus aura::Window about changed states. This change is in
downstream now [1], but will be sent as a follow-up cl.

[1] https://github.com/Igalia/chromium

Bug: 784836, 578890
Change-Id: I4dee446b5d145ca2a15f168d78aacf7c96acb2e7
Reviewed-on: https://chromium-review.googlesource.com/768681
Commit-Queue: Maksim Sisov <msisov@igalia.com>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523733}
parent 9f8575b7
...@@ -34,6 +34,7 @@ source_set("wayland") { ...@@ -34,6 +34,7 @@ source_set("wayland") {
"wayland_surface_factory.h", "wayland_surface_factory.h",
"wayland_window.cc", "wayland_window.cc",
"wayland_window.h", "wayland_window.h",
"xdg_surface_wrapper.cc",
"xdg_surface_wrapper.h", "xdg_surface_wrapper.h",
"xdg_surface_wrapper_v5.cc", "xdg_surface_wrapper_v5.cc",
"xdg_surface_wrapper_v5.h", "xdg_surface_wrapper_v5.h",
......
...@@ -209,6 +209,18 @@ void UnsetMaximized(wl_client* client, wl_resource* resource) { ...@@ -209,6 +209,18 @@ void UnsetMaximized(wl_client* client, wl_resource* resource) {
->UnsetMaximized(); ->UnsetMaximized();
} }
void SetFullscreen(wl_client* client,
wl_resource* resource,
wl_resource* output) {
static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
->SetFullscreen();
}
void UnsetFullscreen(wl_client* client, wl_resource* resource) {
static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
->UnsetFullscreen();
}
void SetMinimized(wl_client* client, wl_resource* resource) { void SetMinimized(wl_client* client, wl_resource* resource) {
static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
->SetMinimized(); ->SetMinimized();
...@@ -226,8 +238,8 @@ const struct xdg_surface_interface xdg_surface_impl = { ...@@ -226,8 +238,8 @@ const struct xdg_surface_interface xdg_surface_impl = {
&SetWindowGeometry, // set_window_geometry &SetWindowGeometry, // set_window_geometry
&SetMaximized, // set_maximized &SetMaximized, // set_maximized
&UnsetMaximized, // set_unmaximized &UnsetMaximized, // set_unmaximized
nullptr, // set_fullscreen &SetFullscreen, // set_fullscreen
nullptr, // unset_fullscreen &UnsetFullscreen, // unset_fullscreen
&SetMinimized, // set_minimized &SetMinimized, // set_minimized
}; };
...@@ -270,8 +282,8 @@ const struct zxdg_toplevel_v6_interface zxdg_toplevel_v6_impl = { ...@@ -270,8 +282,8 @@ const struct zxdg_toplevel_v6_interface zxdg_toplevel_v6_impl = {
nullptr, // set_min_size nullptr, // set_min_size
&SetMaximized, // set_maximized &SetMaximized, // set_maximized
&UnsetMaximized, // set_unmaximized &UnsetMaximized, // set_unmaximized
nullptr, // set_fullscreen &SetFullscreen, // set_fullscreen
nullptr, // unset_fullscreen &UnsetFullscreen, // unset_fullscreen
&SetMinimized, // set_minimized &SetMinimized, // set_minimized
}; };
......
...@@ -57,6 +57,8 @@ class MockXdgSurface : public ServerObject { ...@@ -57,6 +57,8 @@ class MockXdgSurface : public ServerObject {
void(int32_t x, int32_t y, int32_t widht, int32_t height)); void(int32_t x, int32_t y, int32_t widht, int32_t height));
MOCK_METHOD0(SetMaximized, void()); MOCK_METHOD0(SetMaximized, void());
MOCK_METHOD0(UnsetMaximized, void()); MOCK_METHOD0(UnsetMaximized, void());
MOCK_METHOD0(SetFullscreen, void());
MOCK_METHOD0(UnsetFullscreen, void());
MOCK_METHOD0(SetMinimized, void()); MOCK_METHOD0(SetMinimized, void());
// Used when xdg v6 is used. // Used when xdg v6 is used.
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/xdg_surface_wrapper_v5.h" #include "ui/ozone/platform/wayland/xdg_surface_wrapper_v5.h"
#include "ui/ozone/platform/wayland/xdg_surface_wrapper_v6.h" #include "ui/ozone/platform/wayland/xdg_surface_wrapper_v6.h"
#include "ui/platform_window/platform_window_delegate.h"
namespace ui { namespace ui {
...@@ -48,7 +47,8 @@ WaylandWindow::WaylandWindow(PlatformWindowDelegate* delegate, ...@@ -48,7 +47,8 @@ WaylandWindow::WaylandWindow(PlatformWindowDelegate* delegate,
: delegate_(delegate), : delegate_(delegate),
connection_(connection), connection_(connection),
xdg_shell_objects_factory_(new XDGShellObjectFactory()), xdg_shell_objects_factory_(new XDGShellObjectFactory()),
bounds_(bounds) {} bounds_(bounds),
state_(ui::PlatformWindowState::PLATFORM_WINDOW_STATE_UNKNOWN) {}
WaylandWindow::~WaylandWindow() { WaylandWindow::~WaylandWindow() {
if (xdg_surface_) { if (xdg_surface_) {
...@@ -142,23 +142,51 @@ void WaylandWindow::ReleaseCapture() { ...@@ -142,23 +142,51 @@ void WaylandWindow::ReleaseCapture() {
} }
void WaylandWindow::ToggleFullscreen() { void WaylandWindow::ToggleFullscreen() {
NOTIMPLEMENTED(); DCHECK(xdg_surface_);
DCHECK(!IsMinimized());
// TODO(msisov, tonikitoo): add multiscreen support. As the documentation says
// if xdg_surface_set_fullscreen() is not provided with wl_output, it's up to
// the compositor to choose which display will be used to map this surface.
if (!IsFullscreen())
xdg_surface_->SetFullscreen();
else
xdg_surface_->UnSetFullscreen();
connection_->ScheduleFlush();
} }
void WaylandWindow::Maximize() { void WaylandWindow::Maximize() {
DCHECK(xdg_surface_); DCHECK(xdg_surface_);
DCHECK(!IsMaximized());
if (IsFullscreen())
ToggleFullscreen();
xdg_surface_->SetMaximized(); xdg_surface_->SetMaximized();
connection_->ScheduleFlush(); connection_->ScheduleFlush();
} }
void WaylandWindow::Minimize() { void WaylandWindow::Minimize() {
DCHECK(xdg_surface_);
DCHECK(!IsMinimized());
DCHECK(xdg_surface_); DCHECK(xdg_surface_);
xdg_surface_->SetMinimized(); xdg_surface_->SetMinimized();
connection_->ScheduleFlush(); connection_->ScheduleFlush();
// Wayland doesn't say if a window is minimized. Handle this case manually
// here. We can track if the window was unminimized once wayland sends the
// window is activated, and the previous state was minimized.
state_ = ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
} }
void WaylandWindow::Restore() { void WaylandWindow::Restore() {
DCHECK(xdg_surface_); DCHECK(xdg_surface_);
// Unfullscreen the window if it is fullscreen.
if (IsFullscreen())
ToggleFullscreen();
xdg_surface_->UnSetMaximized(); xdg_surface_->UnSetMaximized();
connection_->ScheduleFlush(); connection_->ScheduleFlush();
} }
...@@ -207,7 +235,27 @@ uint32_t WaylandWindow::DispatchEvent(const PlatformEvent& native_event) { ...@@ -207,7 +235,27 @@ uint32_t WaylandWindow::DispatchEvent(const PlatformEvent& native_event) {
return POST_DISPATCH_STOP_PROPAGATION; return POST_DISPATCH_STOP_PROPAGATION;
} }
void WaylandWindow::HandleSurfaceConfigure(int32_t width, int32_t height) { void WaylandWindow::HandleSurfaceConfigure(int32_t width,
int32_t height,
bool is_maximized,
bool is_fullscreen,
bool is_activated) {
// Change the window state only if the window is activated, because it's the
// only way to know if the window is not minimized.
if (is_activated) {
bool was_minimized = IsMinimized();
state_ = ui::PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL;
if (is_maximized && !is_fullscreen)
state_ = ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MAXIMIZED;
else if (is_fullscreen)
state_ = ui::PlatformWindowState::PLATFORM_WINDOW_STATE_FULLSCREEN;
// Do not flood the WindowServer unless the previous state was minimized.
if (was_minimized)
delegate_->OnWindowStateChanged(state_);
}
// Width or height set 0 means that we should decide on width and height by // Width or height set 0 means that we should decide on width and height by
// ourselves, but we don't want to set to anything else. Use previous size. // ourselves, but we don't want to set to anything else. Use previous size.
if (width == 0 || height == 0) { if (width == 0 || height == 0) {
...@@ -226,4 +274,16 @@ void WaylandWindow::OnCloseRequest() { ...@@ -226,4 +274,16 @@ void WaylandWindow::OnCloseRequest() {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
bool WaylandWindow::IsMinimized() const {
return state_ == ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
}
bool WaylandWindow::IsMaximized() const {
return state_ == ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MAXIMIZED;
}
bool WaylandWindow::IsFullscreen() const {
return state_ == ui::PlatformWindowState::PLATFORM_WINDOW_STATE_FULLSCREEN;
}
} // namespace ui } // namespace ui
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/wayland_object.h" #include "ui/ozone/platform/wayland/wayland_object.h"
#include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_delegate.h"
namespace ui { namespace ui {
...@@ -69,11 +70,19 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { ...@@ -69,11 +70,19 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
bool CanDispatchEvent(const PlatformEvent& event) override; bool CanDispatchEvent(const PlatformEvent& event) override;
uint32_t DispatchEvent(const PlatformEvent& event) override; uint32_t DispatchEvent(const PlatformEvent& event) override;
void HandleSurfaceConfigure(int32_t widht, int32_t height); void HandleSurfaceConfigure(int32_t widht,
int32_t height,
bool is_maximized,
bool is_fullscreen,
bool is_activated);
void OnCloseRequest(); void OnCloseRequest();
private: private:
bool IsMinimized() const;
bool IsMaximized() const;
bool IsFullscreen() const;
// Creates a surface window, which is visible as a main window. // Creates a surface window, which is visible as a main window.
void CreateXdgSurface(); void CreateXdgSurface();
...@@ -97,6 +106,9 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { ...@@ -97,6 +106,9 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
bool has_pointer_focus_ = false; bool has_pointer_focus_ = false;
bool has_keyboard_focus_ = false; bool has_keyboard_focus_ = false;
// Stores current states of the window.
ui::PlatformWindowState state_;
DISALLOW_COPY_AND_ASSIGN(WaylandWindow); DISALLOW_COPY_AND_ASSIGN(WaylandWindow);
}; };
......
...@@ -69,6 +69,17 @@ class WaylandWindowTest : public WaylandTest { ...@@ -69,6 +69,17 @@ class WaylandWindowTest : public WaylandTest {
return xdg_surface->xdg_toplevel.get(); return xdg_surface->xdg_toplevel.get();
} }
void SetWlArrayWithState(uint32_t state, wl_array* states) {
uint32_t* s;
s = static_cast<uint32_t*>(wl_array_add(states, sizeof *s));
*s = state;
}
void InitializeWlArrayWithActivatedState(wl_array* states) {
wl_array_init(states);
SetWlArrayWithState(XDG_SURFACE_STATE_ACTIVATED, states);
}
wl::MockXdgSurface* xdg_surface; wl::MockXdgSurface* xdg_surface;
MouseEvent test_mouse_event; MouseEvent test_mouse_event;
...@@ -82,9 +93,20 @@ TEST_P(WaylandWindowTest, SetTitle) { ...@@ -82,9 +93,20 @@ TEST_P(WaylandWindowTest, SetTitle) {
window.SetTitle(base::ASCIIToUTF16("hello")); window.SetTitle(base::ASCIIToUTF16("hello"));
} }
TEST_P(WaylandWindowTest, Maximize) { TEST_P(WaylandWindowTest, MaximizeAndRestore) {
uint32_t serial = 12;
wl_array states;
InitializeWlArrayWithActivatedState(&states);
SetWlArrayWithState(XDG_SURFACE_STATE_MAXIMIZED, &states);
EXPECT_CALL(*GetXdgSurface(), SetMaximized()); EXPECT_CALL(*GetXdgSurface(), SetMaximized());
EXPECT_CALL(*GetXdgSurface(), UnsetMaximized());
window.Maximize(); window.Maximize();
SendConfigureEvent(0, 0, serial, &states);
Sync();
window.Restore();
} }
TEST_P(WaylandWindowTest, Minimize) { TEST_P(WaylandWindowTest, Minimize) {
...@@ -92,8 +114,40 @@ TEST_P(WaylandWindowTest, Minimize) { ...@@ -92,8 +114,40 @@ TEST_P(WaylandWindowTest, Minimize) {
window.Minimize(); window.Minimize();
} }
TEST_P(WaylandWindowTest, Restore) { TEST_P(WaylandWindowTest, SetFullscreenAndRestore) {
wl_array states;
InitializeWlArrayWithActivatedState(&states);
SetWlArrayWithState(XDG_SURFACE_STATE_FULLSCREEN, &states);
EXPECT_CALL(*GetXdgSurface(), SetFullscreen());
EXPECT_CALL(*GetXdgSurface(), UnsetFullscreen());
window.ToggleFullscreen();
SendConfigureEvent(0, 0, 1, &states);
Sync();
window.Restore();
}
TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) {
wl_array states;
InitializeWlArrayWithActivatedState(&states);
EXPECT_CALL(*GetXdgSurface(), SetFullscreen());
EXPECT_CALL(*GetXdgSurface(), UnsetFullscreen());
EXPECT_CALL(*GetXdgSurface(), SetMaximized());
EXPECT_CALL(*GetXdgSurface(), UnsetMaximized()); EXPECT_CALL(*GetXdgSurface(), UnsetMaximized());
window.Maximize();
SetWlArrayWithState(XDG_SURFACE_STATE_MAXIMIZED, &states);
SendConfigureEvent(0, 0, 2, &states);
Sync();
window.ToggleFullscreen();
SetWlArrayWithState(XDG_SURFACE_STATE_FULLSCREEN, &states);
SendConfigureEvent(0, 0, 3, &states);
Sync();
window.Restore(); window.Restore();
} }
......
// Copyright 2017 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/ozone/platform/wayland/xdg_surface_wrapper.h"
namespace ui {
bool CheckIfWlArrayHasValue(struct wl_array* wl_array, uint32_t value) {
// wl_array_for_each has a bug in upstream. It tries to assign void* to
// uint32_t *, which is not allowed in C++. Explicit cast should be
// performed. In other words, one just cannot assign void * to other pointer
// type implicitly in C++ as in C. We can't modify wayland-util.h, because
// it is fetched with gclient sync. Thus, use own loop.
uint32_t* data = reinterpret_cast<uint32_t*>(wl_array->data);
size_t array_size = wl_array->size / sizeof(uint32_t);
for (size_t i = 0; i < array_size; i++) {
if (data[i] == value)
return true;
}
return false;
}
} // namespace ui
...@@ -57,6 +57,8 @@ class XDGSurfaceWrapper { ...@@ -57,6 +57,8 @@ class XDGSurfaceWrapper {
virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0; virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0;
}; };
bool CheckIfWlArrayHasValue(struct wl_array* wl_array, uint32_t value);
} // namespace ui } // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_XDG_SURFACE_WRAPPER_H_ #endif // UI_OZONE_PLATFORM_WAYLAND_XDG_SURFACE_WRAPPER_H_
...@@ -89,8 +89,17 @@ void XDGSurfaceWrapperV5::Configure(void* data, ...@@ -89,8 +89,17 @@ void XDGSurfaceWrapperV5::Configure(void* data,
wl_array* states, wl_array* states,
uint32_t serial) { uint32_t serial) {
XDGSurfaceWrapperV5* surface = static_cast<XDGSurfaceWrapperV5*>(data); XDGSurfaceWrapperV5* surface = static_cast<XDGSurfaceWrapperV5*>(data);
bool is_maximized =
CheckIfWlArrayHasValue(states, XDG_SURFACE_STATE_MAXIMIZED);
bool is_fullscreen =
CheckIfWlArrayHasValue(states, XDG_SURFACE_STATE_FULLSCREEN);
bool is_activated =
CheckIfWlArrayHasValue(states, XDG_SURFACE_STATE_ACTIVATED);
surface->pending_configure_serial_ = serial; surface->pending_configure_serial_ = serial;
surface->wayland_window_->HandleSurfaceConfigure(width, height); surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized,
is_fullscreen, is_activated);
} }
// static // static
......
...@@ -124,7 +124,16 @@ void XDGSurfaceWrapperV6::ConfigureTopLevel( ...@@ -124,7 +124,16 @@ void XDGSurfaceWrapperV6::ConfigureTopLevel(
int32_t height, int32_t height,
struct wl_array* states) { struct wl_array* states) {
XDGSurfaceWrapperV6* surface = static_cast<XDGSurfaceWrapperV6*>(data); XDGSurfaceWrapperV6* surface = static_cast<XDGSurfaceWrapperV6*>(data);
surface->wayland_window_->HandleSurfaceConfigure(width, height);
bool is_maximized =
CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED);
bool is_fullscreen =
CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN);
bool is_activated =
CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED);
surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized,
is_fullscreen, is_activated);
} }
// static // static
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment