diff options
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.patch | 665 |
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 - |