summarylogtreecommitdiffstats
path: root/0009-ozone-wayland-window-state-change-must-be-synchronou.patch
diff options
context:
space:
mode:
Diffstat (limited to '0009-ozone-wayland-window-state-change-must-be-synchronou.patch')
-rw-r--r--0009-ozone-wayland-window-state-change-must-be-synchronou.patch665
1 files changed, 0 insertions, 665 deletions
diff --git a/0009-ozone-wayland-window-state-change-must-be-synchronou.patch b/0009-ozone-wayland-window-state-change-must-be-synchronou.patch
deleted file mode 100644
index 1386e82e4e62..000000000000
--- a/0009-ozone-wayland-window-state-change-must-be-synchronou.patch
+++ /dev/null
@@ -1,665 +0,0 @@
-From f70d9e1475b402cc70ff0b4539c26ff86ef1116c Mon Sep 17 00:00:00 2001
-From: Maksim Sisov <msisov@igalia.com>
-Date: Tue, 7 Jan 2020 18:17:05 +0000
-Subject: [PATCH 9/9] ozone/wayland: window state change must be synchronous.
-
-This CL fixes two issues:
-
-1) After we changed to only create ShellSurfaces after Show calls, starting the
-browser with maximized or fullscreen modes broke. That is, in Wayland, it
-is required to assign a role to wl_surface and make higher level objects like
-xdg_surface and xdg_toplevel that are used by desktop xdg shell.
-
-State manipulation can only be done through those higher level objects and
-we must defer setting state to maximized/fullscreen until they are created.
-
-2) Also, this CL changes the intermidiate result of state changes: now, all of
-them are considered synchronous and if Wayland decides to change the state
-to something else, the state will be overriden and OnWindowStateChange will
-be called. Otherwise, if it was the client, who changed the state, no
-notification is sent.
-
-Test: StartMaximized, StartWithFullscreen, CompositorSideChanges
-Bug: 1033525
-
-Change-Id: I89728297d572d62db59f2d3b1628f2d735dbd4b0
-Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1965031
-Reviewed-by: Michael Spang <spang@chromium.org>
-Commit-Queue: Maksim Sisov <msisov@igalia.com>
-Cr-Commit-Position: refs/heads/master@{#728996}
----
- .../platform/wayland/host/wayland_surface.cc | 173 ++++++--------
- .../platform/wayland/host/wayland_surface.h | 17 +-
- .../wayland/host/wayland_window_unittest.cc | 212 +++++++++++++++---
- 3 files changed, 249 insertions(+), 153 deletions(-)
-
-diff --git a/ui/ozone/platform/wayland/host/wayland_surface.cc b/ui/ozone/platform/wayland/host/wayland_surface.cc
-index b800a526e64e..c90e499fc796 100644
---- a/ui/ozone/platform/wayland/host/wayland_surface.cc
-+++ b/ui/ozone/platform/wayland/host/wayland_surface.cc
-@@ -19,8 +19,7 @@ namespace ui {
- WaylandSurface::WaylandSurface(PlatformWindowDelegate* delegate,
- WaylandConnection* connection)
- : WaylandWindow(delegate, connection),
-- state_(PlatformWindowState::kNormal),
-- pending_state_(PlatformWindowState::kUnknown) {
-+ state_(PlatformWindowState::kNormal) {
- // Set a class property key, which allows |this| to be used for interactive
- // events, e.g. move or resize.
- SetWmMoveResizeHandler(this, AsWmMoveResizeHandler());
-@@ -47,6 +46,7 @@ bool WaylandSurface::CreateShellSurface() {
- shell_surface_->SetAppId(app_id_);
- shell_surface_->SetTitle(window_title_);
- SetSizeConstraints();
-+ TriggerStateChanges();
- return true;
- }
-
-@@ -117,7 +117,7 @@ void WaylandSurface::Hide() {
- bool WaylandSurface::IsVisible() const {
- // X and Windows return true if the window is minimized. For consistency, do
- // the same.
-- return !!shell_surface_ || IsMinimized();
-+ return !!shell_surface_ || state_ == PlatformWindowState::kMinimized;
- }
-
- void WaylandSurface::SetTitle(const base::string16& title) {
-@@ -133,74 +133,36 @@ void WaylandSurface::SetTitle(const base::string16& title) {
- }
-
- void WaylandSurface::ToggleFullscreen() {
-- DCHECK(shell_surface_);
--
-- // There are some cases, when Chromium triggers a fullscreen state change
-- // before the surface is activated. In such cases, Wayland may ignore state
-- // changes and such flags as --kiosk or --start-fullscreen will be ignored.
-- // To overcome this, set a pending state, and once the surface is activated,
-- // trigger the change.
-- if (!is_active_) {
-- DCHECK(!IsFullscreen());
-- pending_state_ = PlatformWindowState::kFullScreen;
-- return;
-- }
--
- // TODO(msisov, tonikitoo): add multiscreen support. As the documentation says
-- // if shell_surface_set_fullscreen() is not provided with wl_output, it's up
-+ // if xdg_toplevel_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()) {
-- // Fullscreen state changes have to be handled manually and then checked
-- // against configuration events, which come from a compositor. The reason
-- // of manually changing the |state_| is that the compositor answers about
-- // state changes asynchronously, which leads to a wrong return value in
-- // DesktopWindowTreeHostPlatform::IsFullscreen, for example, and media
-- // files can never be set to fullscreen.
-- state_ = PlatformWindowState::kFullScreen;
-- shell_surface_->SetFullscreen();
-+
-+ // We must track the previous state to correctly say our state as long as it
-+ // can be the maximized instead of normal one.
-+ PlatformWindowState new_state = PlatformWindowState::kUnknown;
-+ if (state_ == PlatformWindowState::kFullScreen) {
-+ if (previous_state_ == PlatformWindowState::kMaximized)
-+ new_state = previous_state_;
-+ else
-+ new_state = PlatformWindowState::kNormal;
- } else {
-- // Check the comment above. If it's not handled synchronously, media files
-- // may not leave the fullscreen mode.
-- state_ = PlatformWindowState::kUnknown;
-- shell_surface_->UnSetFullscreen();
-+ new_state = PlatformWindowState::kFullScreen;
- }
-
-- connection()->ScheduleFlush();
-+ SetWindowState(new_state);
- }
-
- void WaylandSurface::Maximize() {
-- DCHECK(shell_surface_);
--
-- if (IsFullscreen())
-- ToggleFullscreen();
--
-- shell_surface_->SetMaximized();
-- connection()->ScheduleFlush();
-+ SetWindowState(PlatformWindowState::kMaximized);
- }
-
- void WaylandSurface::Minimize() {
-- DCHECK(shell_surface_);
-- DCHECK(!is_minimizing_);
-- // Wayland doesn't explicitly say if a window is minimized. Instead, it
-- // notifies that the window is not activated. But there are many cases, when
-- // the window is not minimized and deactivated. In order to properly record
-- // the minimized state, mark this window as being minimized. And as soon as a
-- // configuration event comes, check if the window has been deactivated and has
-- // |is_minimizing_| set.
-- is_minimizing_ = true;
-- shell_surface_->SetMinimized();
-- connection()->ScheduleFlush();
-+ SetWindowState(PlatformWindowState::kMinimized);
- }
-
- void WaylandSurface::Restore() {
- DCHECK(shell_surface_);
--
-- // Unfullscreen the window if it is fullscreen.
-- if (IsFullscreen())
-- ToggleFullscreen();
--
-- shell_surface_->UnSetMaximized();
-- connection()->ScheduleFlush();
-+ SetWindowState(PlatformWindowState::kNormal);
- }
-
- PlatformWindowState WaylandSurface::GetPlatformWindowState() const {
-@@ -223,34 +185,21 @@ void WaylandSurface::HandleSurfaceConfigure(int32_t width,
- bool is_maximized,
- bool is_fullscreen,
- bool is_activated) {
-- // Propagate the window state information to the client.
-+ // Store the old state to propagte state changes if Wayland decides to change
-+ // the state to something else.
- PlatformWindowState old_state = state_;
--
-- // Ensure that manually handled state changes to fullscreen correspond to the
-- // configuration events from a compositor.
-- DCHECK_EQ(is_fullscreen, IsFullscreen());
--
-- // There are two cases, which must be handled for the minimized state.
-- // The first one is the case, when the surface goes into the minimized state
-- // (check comment in WaylandSurface::Minimize), and the second case is when
-- // the surface still has been minimized, but another configuration event with
-- // !is_activated comes. For this, check if the WaylandSurface has been
-- // minimized before and !is_activated is sent.
-- if ((is_minimizing_ || IsMinimized()) && !is_activated) {
-- is_minimizing_ = false;
-+ if (state_ == PlatformWindowState::kMinimized && !is_activated) {
- state_ = PlatformWindowState::kMinimized;
- } else if (is_fullscreen) {
-- // To ensure the |delegate()| is notified about state changes to fullscreen,
-- // assume the old_state is UNKNOWN (check comment in ToggleFullscreen).
-- old_state = PlatformWindowState::kUnknown;
-- DCHECK(state_ == PlatformWindowState::kFullScreen);
-+ state_ = PlatformWindowState::kFullScreen;
- } else if (is_maximized) {
- state_ = PlatformWindowState::kMaximized;
- } else {
- state_ = PlatformWindowState::kNormal;
- }
-+
- const bool state_changed = old_state != state_;
-- const bool is_normal = !IsFullscreen() && !IsMaximized();
-+ const bool is_normal = state_ == PlatformWindowState::kNormal;
-
- // Update state before notifying delegate.
- const bool did_active_change = is_active_ != is_activated;
-@@ -281,28 +230,17 @@ void WaylandSurface::HandleSurfaceConfigure(int32_t width,
- 1.0 / buffer_scale()));
- }
-
-- if (state_changed) {
-- // The |restored_bounds_| are used when the window gets back to normal
-- // state after it went maximized or fullscreen. So we reset these if the
-- // window has just become normal and store the current bounds if it is
-- // either going out of normal state or simply changes the state and we don't
-- // have any meaningful value stored.
-- if (is_normal) {
-- SetRestoredBoundsInPixels({});
-- } else if (old_state == PlatformWindowState::kNormal ||
-- GetRestoredBoundsInPixels().IsEmpty()) {
-- SetRestoredBoundsInPixels(GetBounds());
-- }
-+ // Store the restored bounds of current state differs from the normal state.
-+ // It can be client or compositor side change from normal to something else.
-+ // Thus, we must store previous bounds to restore later.
-+ SetOrResetRestoredBounds();
-+ ApplyPendingBounds();
-
-+ if (state_changed)
- delegate()->OnWindowStateChanged(state_);
-- }
--
-- ApplyPendingBounds();
-
- if (did_active_change)
- delegate()->OnActivationChanged(is_active_);
--
-- MaybeTriggerPendingStateChange();
- }
-
- void WaylandSurface::OnDragEnter(const gfx::PointF& point,
-@@ -348,24 +286,34 @@ bool WaylandSurface::OnInitialize(PlatformWindowInitProperties properties) {
- return true;
- }
-
--bool WaylandSurface::IsMinimized() const {
-- return state_ == PlatformWindowState::kMinimized;
--}
-+void WaylandSurface::TriggerStateChanges() {
-+ if (!shell_surface_)
-+ return;
-
--bool WaylandSurface::IsMaximized() const {
-- return state_ == PlatformWindowState::kMaximized;
--}
-+ if (state_ == PlatformWindowState::kFullScreen)
-+ shell_surface_->SetFullscreen();
-+ else
-+ shell_surface_->UnSetFullscreen();
-+
-+ // Call UnSetMaximized only if current state is normal. Otherwise, if the
-+ // current state is fullscreen and the previous is maximized, calling
-+ // UnSetMaximized may result in wrong restored window position that clients
-+ // are not allowed to know about.
-+ if (state_ == PlatformWindowState::kMaximized)
-+ shell_surface_->SetMaximized();
-+ else if (state_ == PlatformWindowState::kNormal)
-+ shell_surface_->UnSetMaximized();
-+
-+ if (state_ == PlatformWindowState::kMinimized)
-+ shell_surface_->SetMinimized();
-
--bool WaylandSurface::IsFullscreen() const {
-- return state_ == PlatformWindowState::kFullScreen;
-+ connection()->ScheduleFlush();
- }
-
--void WaylandSurface::MaybeTriggerPendingStateChange() {
-- if (pending_state_ == PlatformWindowState::kUnknown || !is_active_)
-- return;
-- DCHECK_EQ(pending_state_, PlatformWindowState::kFullScreen);
-- pending_state_ = PlatformWindowState::kUnknown;
-- ToggleFullscreen();
-+void WaylandSurface::SetWindowState(PlatformWindowState state) {
-+ previous_state_ = state_;
-+ state_ = state;
-+ TriggerStateChanges();
- }
-
- WmMoveResizeHandler* WaylandSurface::AsWmMoveResizeHandler() {
-@@ -381,4 +329,17 @@ void WaylandSurface::SetSizeConstraints() {
- connection()->ScheduleFlush();
- }
-
-+void WaylandSurface::SetOrResetRestoredBounds() {
-+ // The |restored_bounds_| are used when the window gets back to normal
-+ // state after it went maximized or fullscreen. So we reset these if the
-+ // window has just become normal and store the current bounds if it is
-+ // either going out of normal state or simply changes the state and we don't
-+ // have any meaningful value stored.
-+ if (GetPlatformWindowState() == PlatformWindowState::kNormal) {
-+ SetRestoredBoundsInPixels({});
-+ } else if (GetRestoredBoundsInPixels().IsEmpty()) {
-+ SetRestoredBoundsInPixels(GetBounds());
-+ }
-+}
-+
- } // namespace ui
-diff --git a/ui/ozone/platform/wayland/host/wayland_surface.h b/ui/ozone/platform/wayland/host/wayland_surface.h
-index 677eaca6ef56..ceda32d24a7c 100644
---- a/ui/ozone/platform/wayland/host/wayland_surface.h
-+++ b/ui/ozone/platform/wayland/host/wayland_surface.h
-@@ -69,11 +69,8 @@ class WaylandSurface : public WaylandWindow,
- void OnDragSessionClose(uint32_t dnd_action) override;
- bool OnInitialize(PlatformWindowInitProperties properties) override;
-
-- bool IsMinimized() const;
-- bool IsMaximized() const;
-- bool IsFullscreen() const;
--
-- void MaybeTriggerPendingStateChange();
-+ void TriggerStateChanges();
-+ void SetWindowState(PlatformWindowState state);
-
- // Creates a surface window, which is visible as a main window.
- bool CreateShellSurface();
-@@ -83,6 +80,8 @@ class WaylandSurface : public WaylandWindow,
- // Propagates the |min_size_| and |max_size_| to the ShellSurface.
- void SetSizeConstraints();
-
-+ void SetOrResetRestoredBounds();
-+
- // Wrappers around shell surface.
- std::unique_ptr<ShellSurfaceWrapper> shell_surface_;
-
-@@ -100,14 +99,12 @@ class WaylandSurface : public WaylandWindow,
- // handler that receives DIP from Wayland.
- gfx::Rect pending_bounds_dip_;
-
-- // Stores current states of the window.
-+ // Contains the current state of the window.
- PlatformWindowState state_;
-- // Stores a pending state of the window, which is used before the surface is
-- // activated.
-- PlatformWindowState pending_state_;
-+ // Contains the previous state of the window.
-+ PlatformWindowState previous_state_;
-
- bool is_active_ = false;
-- bool is_minimizing_ = false;
-
- // Id of the chromium app passed through
- // PlatformWindowInitProperties::wm_class_class. This is used by Wayland
-diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
-index f56b96690eea..c72d27edff66 100644
---- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
-+++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
-@@ -233,8 +233,7 @@ TEST_P(WaylandWindowTest, MaximizeAndRestore) {
- kMaximizedBounds.height()));
- EXPECT_CALL(delegate_, OnActivationChanged(Eq(true)));
- EXPECT_CALL(delegate_, OnBoundsChanged(kMaximizedBounds));
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kMaximized)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- window_->Maximize();
- SendConfigureEvent(kMaximizedBounds.width(), kMaximizedBounds.height(), 1,
- active_maximized.get());
-@@ -262,8 +261,7 @@ TEST_P(WaylandWindowTest, MaximizeAndRestore) {
-
- EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds.width(),
- kNormalBounds.height()));
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kNormal)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- EXPECT_CALL(delegate_, OnActivationChanged(_)).Times(0);
- EXPECT_CALL(delegate_, OnBoundsChanged(kNormalBounds));
- EXPECT_CALL(*GetXdgToplevel(), UnsetMaximized());
-@@ -283,19 +281,21 @@ TEST_P(WaylandWindowTest, Minimize) {
- Sync();
-
- EXPECT_CALL(*GetXdgToplevel(), SetMinimized());
-- // Wayland compositor doesn't notify clients about minimized state, but rather
-- // if a window is not activated. Thus, a WaylandWindow marks itself as being
-- // minimized and as soon as a configuration event with not activated state
-- // comes, its state is changed to minimized. This EXPECT_CALL ensures this
-- // behaviour.
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kMinimized)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- window_->Minimize();
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kMinimized);
-+
- // Reinitialize wl_array, which removes previous old states.
- states = ScopedWlArray();
- SendConfigureEvent(0, 0, 2, states.get());
- Sync();
-
-+ // Wayland compositor doesn't notify clients about minimized state, but rather
-+ // if a window is not activated. Thus, a WaylandSurface marks itself as being
-+ // minimized and and sets state to minimized. Thus, the state mustn't change
-+ // after the configuration event is sent.
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kMinimized);
-+
- // Send one additional empty configuration event (which means the surface is
- // not maximized, fullscreen or activated) to ensure, WaylandWindow stays in
- // the same minimized state and doesn't notify its delegate.
-@@ -319,8 +319,7 @@ TEST_P(WaylandWindowTest, SetFullscreenAndRestore) {
- AddStateToWlArray(XDG_TOPLEVEL_STATE_FULLSCREEN, states.get());
-
- EXPECT_CALL(*GetXdgToplevel(), SetFullscreen());
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kFullScreen)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- window_->ToggleFullscreen();
- // Make sure than WaylandWindow manually handles fullscreen states. Check the
- // comment in the WaylandWindow::ToggleFullscreen.
-@@ -330,51 +329,181 @@ TEST_P(WaylandWindowTest, SetFullscreenAndRestore) {
- Sync();
-
- EXPECT_CALL(*GetXdgToplevel(), UnsetFullscreen());
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kNormal)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- window_->Restore();
-- EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kUnknown);
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kNormal);
- // Reinitialize wl_array, which removes previous old states.
- states = InitializeWlArrayWithActivatedState();
- SendConfigureEvent(0, 0, 3, states.get());
- Sync();
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kNormal);
- }
-
- TEST_P(WaylandWindowTest, StartWithFullscreen) {
-+ MockPlatformWindowDelegate delegate;
-+ PlatformWindowInitProperties properties;
-+ properties.bounds = gfx::Rect(0, 0, 100, 100);
-+ properties.type = PlatformWindowType::kWindow;
-+ // We need to create a window avoid calling Show() on it as it is what upper
-+ // views layer does - when Widget initialize DesktopWindowTreeHost, the Show()
-+ // is called later down the road, but Maximize may be called earlier. We
-+ // cannot process them and set a pending state instead, because ShellSurface
-+ // is not created by that moment.
-+ auto window = WaylandWindow::Create(&delegate, connection_.get(),
-+ std::move(properties));
-+
-+ Sync();
-+
-+ // Make sure the window is initialized to normal state from the beginning.
-+ EXPECT_EQ(PlatformWindowState::kNormal, window->GetPlatformWindowState());
-+
-+ // The state must not be changed to the fullscreen before the surface is
-+ // activated.
-+ auto* mock_surface = server_.GetObject<wl::MockSurface>(window->GetWidget());
-+ EXPECT_FALSE(mock_surface->xdg_surface());
-+ EXPECT_CALL(delegate, OnWindowStateChanged(_)).Times(0);
-+ window->ToggleFullscreen();
-+ // The state of the window must already be fullscreen one.
-+ EXPECT_EQ(window->GetPlatformWindowState(), PlatformWindowState::kFullScreen);
-+
-+ Sync();
-+
-+ // We mustn't receive any state changes if that does not differ from the last
-+ // state.
-+ EXPECT_CALL(delegate, OnWindowStateChanged(_)).Times(0);
-+
-+ // Activate the surface.
-+ ScopedWlArray states = InitializeWlArrayWithActivatedState();
-+ AddStateToWlArray(XDG_TOPLEVEL_STATE_FULLSCREEN, states.get());
-+ SendConfigureEvent(0, 0, 1, states.get());
-+
-+ Sync();
-+
-+ // It must be still the same state.
-+ EXPECT_EQ(window->GetPlatformWindowState(), PlatformWindowState::kFullScreen);
-+}
-+
-+TEST_P(WaylandWindowTest, StartMaximized) {
-+ MockPlatformWindowDelegate delegate;
-+ PlatformWindowInitProperties properties;
-+ properties.bounds = gfx::Rect(0, 0, 100, 100);
-+ properties.type = PlatformWindowType::kWindow;
-+ // We need to create a window avoid calling Show() on it as it is what upper
-+ // views layer does - when Widget initialize DesktopWindowTreeHost, the Show()
-+ // is called later down the road, but Maximize may be called earlier. We
-+ // cannot process them and set a pending state instead, because ShellSurface
-+ // is not created by that moment.
-+ auto window = WaylandWindow::Create(&delegate, connection_.get(),
-+ std::move(properties));
-+
-+ Sync();
-+
- // Make sure the window is initialized to normal state from the beginning.
- EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState());
-
- // The state must not be changed to the fullscreen before the surface is
- // activated.
-- EXPECT_CALL(*GetXdgToplevel(), SetFullscreen()).Times(0);
-+ auto* mock_surface = server_.GetObject<wl::MockSurface>(window->GetWidget());
-+ EXPECT_FALSE(mock_surface->xdg_surface());
- EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
-- window_->ToggleFullscreen();
-- // The state of the window must still be a normal one.
-- EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kNormal);
-+
-+ window_->Maximize();
-+ // The state of the window must already be fullscreen one.
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kMaximized);
-
- Sync();
-
-- // Once the surface will be activated, the window will automatically trigger
-- // the state change.
-- EXPECT_CALL(*GetXdgToplevel(), SetFullscreen());
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kFullScreen)));
-+ // Once the surface will be activated, the window state mustn't be changed
-+ // and retain the same.
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kMaximized);
-
- // Activate the surface.
- ScopedWlArray states = InitializeWlArrayWithActivatedState();
-+ AddStateToWlArray(XDG_TOPLEVEL_STATE_MAXIMIZED, states.get());
- SendConfigureEvent(0, 0, 1, states.get());
-
- Sync();
-
-- // The wayland window manually handles the fullscreen state changes, and it
-- // must change to a fullscreen before the state change is confirmed by the
-- // wayland. See comment in the WaylandWindow::ToggleFullscreen.
-- EXPECT_EQ(window_->GetPlatformWindowState(),
-- PlatformWindowState::kFullScreen);
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kMaximized);
-+}
-
-- AddStateToWlArray(XDG_TOPLEVEL_STATE_FULLSCREEN, states.get());
-+TEST_P(WaylandWindowTest, CompositorSideStateChanges) {
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kNormal);
-+ auto normal_bounds = window_->GetBounds();
-+
-+ ScopedWlArray states = InitializeWlArrayWithActivatedState();
-+ AddStateToWlArray(XDG_TOPLEVEL_STATE_MAXIMIZED, states.get());
-+ SendConfigureEvent(2000, 2000, 1, states.get());
-+
-+ EXPECT_CALL(delegate_,
-+ OnWindowStateChanged(Eq(PlatformWindowState::kMaximized)))
-+ .Times(1);
-+ EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, 2000, 2000));
-+
-+ Sync();
-+
-+ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kMaximized);
-+
-+ // Unmaximize
-+ states = InitializeWlArrayWithActivatedState();
- SendConfigureEvent(0, 0, 2, states.get());
-
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(Eq(PlatformWindowState::kNormal)))
-+ .Times(1);
-+ EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, normal_bounds.width(),
-+ normal_bounds.height()));
-+
-+ // Now, set to fullscreen.
-+ AddStateToWlArray(XDG_TOPLEVEL_STATE_FULLSCREEN, states.get());
-+ SendConfigureEvent(2005, 2005, 3, states.get());
-+ EXPECT_CALL(delegate_,
-+ OnWindowStateChanged(Eq(PlatformWindowState::kFullScreen)))
-+ .Times(1);
-+ EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, 2005, 2005));
-+
-+ Sync();
-+
-+ // Unfullscreen
-+ states = InitializeWlArrayWithActivatedState();
-+ SendConfigureEvent(0, 0, 4, states.get());
-+
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(Eq(PlatformWindowState::kNormal)))
-+ .Times(1);
-+ EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, normal_bounds.width(),
-+ normal_bounds.height()));
-+
-+ Sync();
-+
-+ // Now, maximize, fullscreen and restore.
-+ states = InitializeWlArrayWithActivatedState();
-+ AddStateToWlArray(XDG_TOPLEVEL_STATE_MAXIMIZED, states.get());
-+ SendConfigureEvent(2000, 2000, 1, states.get());
-+
-+ EXPECT_CALL(delegate_,
-+ OnWindowStateChanged(Eq(PlatformWindowState::kMaximized)))
-+ .Times(1);
-+ EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, 2000, 2000));
-+
-+ Sync();
-+
-+ AddStateToWlArray(XDG_TOPLEVEL_STATE_FULLSCREEN, states.get());
-+ SendConfigureEvent(2005, 2005, 1, states.get());
-+
-+ EXPECT_CALL(delegate_,
-+ OnWindowStateChanged(Eq(PlatformWindowState::kFullScreen)))
-+ .Times(1);
-+ EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, 2005, 2005));
-+
-+ // Restore
-+ states = InitializeWlArrayWithActivatedState();
-+ SendConfigureEvent(0, 0, 4, states.get());
-+
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(Eq(PlatformWindowState::kNormal)))
-+ .Times(1);
-+ EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, normal_bounds.width(),
-+ normal_bounds.height()));
-+
- Sync();
- }
-
-@@ -395,25 +524,33 @@ TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) {
- kMaximizedBounds.height()));
- EXPECT_CALL(delegate_, OnActivationChanged(Eq(true)));
- EXPECT_CALL(delegate_, OnBoundsChanged(kMaximizedBounds));
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kMaximized)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- window_->Maximize();
-+ // State changes are synchronous.
-+ EXPECT_EQ(PlatformWindowState::kMaximized, window_->GetPlatformWindowState());
- SendConfigureEvent(kMaximizedBounds.width(), kMaximizedBounds.height(), 2,
- active_maximized.get());
- Sync();
-+ // Verify that the state has not been changed.
-+ EXPECT_EQ(PlatformWindowState::kMaximized, window_->GetPlatformWindowState());
- VerifyAndClearExpectations();
-
- EXPECT_CALL(*GetXdgToplevel(), SetFullscreen());
- EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kMaximizedBounds.width(),
- kMaximizedBounds.height()));
- EXPECT_CALL(delegate_, OnBoundsChanged(_)).Times(0);
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kFullScreen)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- window_->ToggleFullscreen();
-+ // State changes are synchronous.
-+ EXPECT_EQ(PlatformWindowState::kFullScreen,
-+ window_->GetPlatformWindowState());
- AddStateToWlArray(XDG_TOPLEVEL_STATE_FULLSCREEN, active_maximized.get());
- SendConfigureEvent(kMaximizedBounds.width(), kMaximizedBounds.height(), 3,
- active_maximized.get());
- Sync();
-+ // Verify that the state has not been changed.
-+ EXPECT_EQ(PlatformWindowState::kFullScreen,
-+ window_->GetPlatformWindowState());
- VerifyAndClearExpectations();
-
- EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds.width(),
-@@ -421,13 +558,14 @@ TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) {
- EXPECT_CALL(*GetXdgToplevel(), UnsetFullscreen());
- EXPECT_CALL(*GetXdgToplevel(), UnsetMaximized());
- EXPECT_CALL(delegate_, OnBoundsChanged(kNormalBounds));
-- EXPECT_CALL(delegate_,
-- OnWindowStateChanged(Eq(PlatformWindowState::kNormal)));
-+ EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0);
- window_->Restore();
-+ EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState());
- // Reinitialize wl_array, which removes previous old states.
- auto active = InitializeWlArrayWithActivatedState();
- SendConfigureEvent(0, 0, 4, active.get());
- Sync();
-+ EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState());
- }
-
- TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximize) {
---
-2.24.1
-