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 6b82ec8f8c7..12752d43b04 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 e7662718b61..3afb370a89b 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 ae41ad7da1f..34e06ea0c75 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 c1384ebe976..1dff4f2f746 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 be8027c98e4..e5f3be767a2 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 b1dec3740d9..2f3514e0110 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 3cd66a537e0..da5eeb94b01 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 a22dd4cb172..a7d5b21df59 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 c69722a5f6f..89449d0e622 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;