From d92e26d0234a0719ed76dc14325998d5ed797b38 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 16 Sep 2019 18:38:42 +0200 Subject: [PATCH] WindowServer+LibGUI: Allow switching windows in/out of fullscreen mode You can now call GWindow::set_fullscreen(bool) and it will go in or out of fullscreen mode. WindowServer will also remember the previous window rect when switching to fullscreen, and restore it when switching back. :^) --- Libraries/LibGUI/GWindow.cpp | 15 ++++++++++++++ Libraries/LibGUI/GWindow.h | 2 +- Servers/WindowServer/WSAPITypes.h | 2 ++ Servers/WindowServer/WSClientConnection.cpp | 22 +++++++++++++++++++++ Servers/WindowServer/WSClientConnection.h | 1 + Servers/WindowServer/WSEvent.h | 18 +++++++++++++++++ Servers/WindowServer/WSWindow.cpp | 17 ++++++++++++++++ Servers/WindowServer/WSWindow.h | 2 ++ 8 files changed, 78 insertions(+), 1 deletion(-) diff --git a/Libraries/LibGUI/GWindow.cpp b/Libraries/LibGUI/GWindow.cpp index d341bef256..997b587e78 100644 --- a/Libraries/LibGUI/GWindow.cpp +++ b/Libraries/LibGUI/GWindow.cpp @@ -714,3 +714,18 @@ void GWindow::save_to(AK::JsonObject& json) json.set("size_increment", size_increment().to_string()); CObject::save_to(json); } + +void GWindow::set_fullscreen(bool fullscreen) +{ + if (m_fullscreen == fullscreen) + return; + m_fullscreen = fullscreen; + if (!m_window_id) + return; + + WSAPI_ClientMessage request; + request.type = WSAPI_ClientMessage::Type::SetFullscreen; + request.window_id = m_window_id; + request.value = fullscreen; + GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetFullscreen); +} diff --git a/Libraries/LibGUI/GWindow.h b/Libraries/LibGUI/GWindow.h index e563cb1322..7591a66ad8 100644 --- a/Libraries/LibGUI/GWindow.h +++ b/Libraries/LibGUI/GWindow.h @@ -33,7 +33,7 @@ public: void set_modal(bool); bool is_fullscreen() const { return m_fullscreen; } - void set_fullscreen(bool fullscreen) { m_fullscreen = fullscreen; } + void set_fullscreen(bool); bool is_resizable() const { return m_resizable; } void set_resizable(bool resizable) { m_resizable = resizable; } diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index 501ba20ba0..bdb14ebf84 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -113,6 +113,7 @@ struct WSAPI_ServerMessage { DidSetWindowHasAlphaChannel, ScreenRectChanged, ClipboardContentsChanged, + DidSetFullscreen, __Begin_WM_Events__, WM_WindowRemoved, @@ -237,6 +238,7 @@ struct WSAPI_ClientMessage { SetWindowHasAlphaChannel, MoveWindowToFront, SetWindowIconBitmap, + SetFullscreen, }; Type type { Invalid }; int window_id { -1 }; diff --git a/Servers/WindowServer/WSClientConnection.cpp b/Servers/WindowServer/WSClientConnection.cpp index c583c30499..6bf2dae12f 100644 --- a/Servers/WindowServer/WSClientConnection.cpp +++ b/Servers/WindowServer/WSClientConnection.cpp @@ -330,6 +330,9 @@ bool WSClientConnection::handle_message(const WSAPI_ClientMessage& message, cons case WSAPI_ClientMessage::Type::MoveWindowToFront: CEventLoop::current().post_event(*this, make(client_id(), message.window_id)); break; + case WSAPI_ClientMessage::Type::SetFullscreen: + CEventLoop::current().post_event(*this, make(client_id(), message.window_id, message.value)); + break; default: break; } @@ -544,6 +547,23 @@ void WSClientConnection::handle_request(const WSAPIMoveWindowToFrontRequest& req WSWindowManager::the().move_to_front_and_make_active(window); } +void WSClientConnection::handle_request(const WSAPISetFullscreenRequest& request) +{ + int window_id = request.window_id(); + auto it = m_windows.find(window_id); + if (it == m_windows.end()) { + post_error("WSAPISetFullscreenRequest: Bad window ID"); + return; + } + auto& window = *(*it).value; + window.set_fullscreen(request.fullscreen()); + + WSAPI_ServerMessage response; + response.type = WSAPI_ServerMessage::Type::DidSetFullscreen; + response.window_id = window_id; + post_message(response); +} + void WSClientConnection::handle_request(const WSAPISetWindowOpacityRequest& request) { int window_id = request.window_id(); @@ -1038,6 +1058,8 @@ void WSClientConnection::on_request(const WSAPIClientRequest& request) return handle_request(static_cast(request)); case WSEvent::APIMoveWindowToFrontRequest: return handle_request(static_cast(request)); + case WSEvent::APISetFullscreenRequest: + return handle_request(static_cast(request)); default: break; } diff --git a/Servers/WindowServer/WSClientConnection.h b/Servers/WindowServer/WSClientConnection.h index 65fc37de6a..55cdec0bc3 100644 --- a/Servers/WindowServer/WSClientConnection.h +++ b/Servers/WindowServer/WSClientConnection.h @@ -84,6 +84,7 @@ private: void handle_request(const WSAPIDismissMenuRequest&); void handle_request(const WSAPISetWindowHasAlphaChannelRequest&); void handle_request(const WSAPIMoveWindowToFrontRequest&); + void handle_request(const WSAPISetFullscreenRequest&); void post_error(const String&); diff --git a/Servers/WindowServer/WSEvent.h b/Servers/WindowServer/WSEvent.h index d829b43215..0a6f556eda 100644 --- a/Servers/WindowServer/WSEvent.h +++ b/Servers/WindowServer/WSEvent.h @@ -65,6 +65,7 @@ public: APISetWindowOverrideCursorRequest, APISetWindowHasAlphaChannelRequest, APIMoveWindowToFrontRequest, + APISetFullscreenRequest, WMAPISetActiveWindowRequest, WMAPISetWindowMinimizedRequest, WMAPIStartWindowResizeRequest, @@ -502,6 +503,23 @@ private: int m_window_id { 0 }; }; +class WSAPISetFullscreenRequest final : public WSAPIClientRequest { +public: + explicit WSAPISetFullscreenRequest(int client_id, int window_id, bool fullscreen) + : WSAPIClientRequest(WSEvent::APISetFullscreenRequest, client_id) + , m_window_id(window_id) + , m_fullscreen(fullscreen) + { + } + + int window_id() const { return m_window_id; } + bool fullscreen() const { return m_fullscreen; } + +private: + int m_window_id { 0 }; + bool m_fullscreen; +}; + class WSAPISetClipboardContentsRequest final : public WSAPIClientRequest { public: explicit WSAPISetClipboardContentsRequest(int client_id, int shared_buffer_id, int size, const String& data_type) diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index 93b037ce97..18a235a1d6 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -1,6 +1,7 @@ #include "WSWindow.h" #include "WSEvent.h" #include "WSEventLoop.h" +#include "WSScreen.h" #include "WSWindowManager.h" #include #include @@ -354,3 +355,19 @@ void WSWindow::request_close() WSEvent close_request(WSEvent::WindowCloseRequest); event(close_request); } + +void WSWindow::set_fullscreen(bool fullscreen) +{ + if (m_fullscreen == fullscreen) + return; + m_fullscreen = fullscreen; + Rect new_window_rect = m_rect; + if (m_fullscreen) { + m_saved_nonfullscreen_rect = m_rect; + new_window_rect = WSScreen::the().rect(); + } else if (!m_saved_nonfullscreen_rect.is_empty()) { + new_window_rect = m_saved_nonfullscreen_rect; + } + CEventLoop::current().post_event(*this, make(m_rect, new_window_rect)); + set_rect(new_window_rect); +} diff --git a/Servers/WindowServer/WSWindow.h b/Servers/WindowServer/WSWindow.h index aa01ae7731..c014c9df81 100644 --- a/Servers/WindowServer/WSWindow.h +++ b/Servers/WindowServer/WSWindow.h @@ -38,6 +38,7 @@ public: void set_maximized(bool); bool is_fullscreen() const { return m_fullscreen; } + void set_fullscreen(bool); bool show_titlebar() const { return m_show_titlebar; } void set_show_titlebar(bool show) { m_show_titlebar = show; } @@ -155,6 +156,7 @@ private: WSClientConnection* m_client { nullptr }; String m_title; Rect m_rect; + Rect m_saved_nonfullscreen_rect; WSWindowType m_type { WSWindowType::Normal }; bool m_global_cursor_tracking_enabled { false }; bool m_automatic_cursor_tracking_enabled { false };