From 6a5d92f0ad9c5e03d8cfe0257497d65fc0e93c17 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 3 May 2019 21:07:16 +0200 Subject: [PATCH] WindowServer+LibGUI: Allow changing whether windows have alpha channels. Use this in Terminal to tell the window server to not bother with the alpha channel in the backing store if we're running without transparency. Semi-transparent terminals look neat but they slow everything down, so this keeps things fast while making it easy to switch to the flashy mode. :^) --- Applications/Terminal/Terminal.cpp | 1 + Applications/Terminal/main.cpp | 2 +- LibGUI/GEventLoop.cpp | 3 +++ LibGUI/GWindow.cpp | 17 ++++++++++++++++- Servers/WindowServer/WSAPITypes.h | 2 ++ Servers/WindowServer/WSClientConnection.cpp | 20 ++++++++++++++++++++ Servers/WindowServer/WSClientConnection.h | 1 + Servers/WindowServer/WSEvent.h | 18 ++++++++++++++++++ Servers/WindowServer/WSEventLoop.cpp | 3 +++ 9 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Applications/Terminal/Terminal.cpp b/Applications/Terminal/Terminal.cpp index 6b82ec8f8c..12752d43b0 100644 --- a/Applications/Terminal/Terminal.cpp +++ b/Applications/Terminal/Terminal.cpp @@ -891,6 +891,7 @@ void Terminal::set_opacity(float opacity) { if (m_opacity == opacity) return; + window()->set_has_alpha_channel(opacity < 1); m_opacity = opacity; force_repaint(); } diff --git a/Applications/Terminal/main.cpp b/Applications/Terminal/main.cpp index e7662718b6..3afb370a89 100644 --- a/Applications/Terminal/main.cpp +++ b/Applications/Terminal/main.cpp @@ -116,7 +116,7 @@ int main(int argc, char** argv) }; slider->set_range(0, 100); - slider->set_value(80); + slider->set_value(100); auto menubar = make(); diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp index ae41ad7da1..34e06ea0c7 100644 --- a/LibGUI/GEventLoop.cpp +++ b/LibGUI/GEventLoop.cpp @@ -376,6 +376,9 @@ bool GEventLoop::wait_for_specific_event(WSAPI_ServerMessage::Type type, WSAPI_S FD_ZERO(&rfds); FD_SET(s_event_fd, &rfds); int rc = select(s_event_fd + 1, &rfds, nullptr, nullptr, nullptr); + if (rc < 0) { + perror("select"); + } ASSERT(rc > 0); ASSERT(FD_ISSET(s_event_fd, &rfds)); bool success = drain_messages_from_server(); diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index c1384ebe97..1dff4f2f74 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -386,8 +386,23 @@ void GWindow::set_automatic_cursor_tracking_widget(GWidget* widget) void GWindow::set_has_alpha_channel(bool value) { - ASSERT(!m_window_id); + if (m_has_alpha_channel == value) + return; m_has_alpha_channel = value; + if (!m_window_id) + return; + + m_pending_paint_event_rects.clear(); + m_back_bitmap = nullptr; + m_front_bitmap = nullptr; + + WSAPI_ClientMessage message; + message.type = WSAPI_ClientMessage::Type::SetWindowHasAlphaChannel; + message.window_id = m_window_id; + message.value = value; + GEventLoop::current().sync_request(message, WSAPI_ServerMessage::DidSetWindowHasAlphaChannel); + + update(); } void GWindow::set_double_buffering_enabled(bool value) diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index be8027c98e..e5f3be767a 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -103,6 +103,7 @@ struct WSAPI_ServerMessage { DidSetWindowBackingStore, DidSetWallpaper, DidGetWallpaper, + DidSetWindowHasAlphaChannel, ScreenRectChanged, WM_WindowRemoved, WM_WindowStateChanged, @@ -218,6 +219,7 @@ struct WSAPI_ClientMessage { PopupMenu, DismissMenu, SetWindowIcon, + SetWindowHasAlphaChannel, }; Type type { Invalid }; int window_id { -1 }; diff --git a/Servers/WindowServer/WSClientConnection.cpp b/Servers/WindowServer/WSClientConnection.cpp index b1dec3740d..2f3514e011 100644 --- a/Servers/WindowServer/WSClientConnection.cpp +++ b/Servers/WindowServer/WSClientConnection.cpp @@ -629,6 +629,24 @@ void WSClientConnection::handle_request(const WSAPISetWindowOverrideCursorReques window.set_override_cursor(WSCursor::create(request.cursor())); } +void WSClientConnection::handle_request(const WSAPISetWindowHasAlphaChannelRequest& request) +{ + int window_id = request.window_id(); + auto it = m_windows.find(window_id); + if (it == m_windows.end()) { + post_error("WSAPISetWindowHasAlphaChannelRequest: Bad window ID"); + return; + } + auto& window = *(*it).value; + window.set_has_alpha_channel(request.value()); + + WSAPI_ServerMessage response; + response.type = WSAPI_ServerMessage::Type::DidSetWindowHasAlphaChannel; + response.window_id = window_id; + response.value = request.value(); + post_message(response); +} + void WSClientConnection::handle_request(const WSWMAPISetActiveWindowRequest& request) { auto* client = WSClientConnection::from_client_id(request.target_client_id()); @@ -747,6 +765,8 @@ void WSClientConnection::on_request(const WSAPIClientRequest& request) return handle_request(static_cast(request)); case WSEvent::APIDismissMenuRequest: return handle_request(static_cast(request)); + case WSEvent::APISetWindowHasAlphaChannelRequest: + return handle_request(static_cast(request)); default: break; } diff --git a/Servers/WindowServer/WSClientConnection.h b/Servers/WindowServer/WSClientConnection.h index 3cd66a537e..da5eeb94b0 100644 --- a/Servers/WindowServer/WSClientConnection.h +++ b/Servers/WindowServer/WSClientConnection.h @@ -77,6 +77,7 @@ private: void handle_request(const WSWMAPIStartWindowResizeRequest&); void handle_request(const WSAPIPopupMenuRequest&); void handle_request(const WSAPIDismissMenuRequest&); + void handle_request(const WSAPISetWindowHasAlphaChannelRequest&); void post_error(const String&); diff --git a/Servers/WindowServer/WSEvent.h b/Servers/WindowServer/WSEvent.h index a22dd4cb17..a7d5b21df5 100644 --- a/Servers/WindowServer/WSEvent.h +++ b/Servers/WindowServer/WSEvent.h @@ -60,6 +60,7 @@ public: APISetWallpaperRequest, APIGetWallpaperRequest, APISetWindowOverrideCursorRequest, + APISetWindowHasAlphaChannelRequest, WMAPISetActiveWindowRequest, WMAPISetWindowMinimizedRequest, WMAPIStartWindowResizeRequest, @@ -387,6 +388,23 @@ private: WSStandardCursor m_cursor { WSStandardCursor::None }; }; +class WSAPISetWindowHasAlphaChannelRequest final : public WSAPIClientRequest { +public: + explicit WSAPISetWindowHasAlphaChannelRequest(int client_id, int window_id, bool value) + : WSAPIClientRequest(WSEvent::APISetWindowHasAlphaChannelRequest, client_id) + , m_window_id(window_id) + , m_value(value) + { + } + + int window_id() const { return m_window_id; } + bool value() const { return m_value; } + +private: + int m_window_id { 0 }; + bool m_value { 0 }; +}; + class WSAPISetWallpaperRequest final : public WSAPIClientRequest { public: explicit WSAPISetWallpaperRequest(int client_id, String&& wallpaper) diff --git a/Servers/WindowServer/WSEventLoop.cpp b/Servers/WindowServer/WSEventLoop.cpp index c69722a5f6..89449d0e62 100644 --- a/Servers/WindowServer/WSEventLoop.cpp +++ b/Servers/WindowServer/WSEventLoop.cpp @@ -244,6 +244,9 @@ bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag case WSAPI_ClientMessage::Type::SetWindowOverrideCursor: post_event(client, make(client_id, message.window_id, (WSStandardCursor)message.cursor.cursor)); break; + case WSAPI_ClientMessage::SetWindowHasAlphaChannel: + post_event(client, make(client_id, message.window_id, message.value)); + break; case WSAPI_ClientMessage::Type::WM_SetActiveWindow: post_event(client, make(client_id, message.wm.client_id, message.wm.window_id)); break;