mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:27:35 +00:00
LibGUI+WindowServer: Separate window manager IPC from regular IPC
With this patch the window manager related functionality is split out onto a new endpoint pair named WindowManagerServer/Client. This allows window manager functionality to be potentially privilege separated in the future. To this end, a new client named WMConnectionClient is used to maintain a window manager connection. When a process connects to the endpoint and greets the WindowServer as a window manager (via Window::make_window_manager(int)), they're subscribed to the events they requested via the WM event mask. This patch also removes the hardcoding of the Taskbar WindowType to receive WM events automatically. However, being a window manager still requires having an active window, at the moment.
This commit is contained in:
parent
139c04a6e5
commit
aa56f9a1e0
24 changed files with 522 additions and 230 deletions
|
@ -63,7 +63,7 @@ User=anon
|
|||
BootModes=text,graphical
|
||||
|
||||
[WindowServer]
|
||||
Socket=/tmp/portal/window
|
||||
Socket=/tmp/portal/window,/tmp/portal/wm
|
||||
SocketPermissions=660
|
||||
Priority=high
|
||||
KeepAlive=1
|
||||
|
|
|
@ -96,6 +96,7 @@ set(SOURCES
|
|||
Widget.cpp
|
||||
Window.cpp
|
||||
WindowServerConnection.cpp
|
||||
WindowManagerServerConnection.cpp
|
||||
Wizards/WizardDialog.cpp
|
||||
Wizards/AbstractWizardPage.cpp
|
||||
Wizards/CoverWizardPage.cpp
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <LibGUI/Painter.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
#include <LibGUI/Window.h>
|
||||
#include <LibGUI/WindowManagerServerConnection.h>
|
||||
#include <LibGUI/WindowServerConnection.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -315,6 +316,14 @@ void Window::set_window_type(WindowType window_type)
|
|||
}
|
||||
}
|
||||
|
||||
void Window::make_window_manager(unsigned event_mask)
|
||||
{
|
||||
GUI::WindowManagerServerConnection::the()
|
||||
.post_message(Messages::WindowManagerServer::SetEventMask(event_mask));
|
||||
GUI::WindowManagerServerConnection::the()
|
||||
.post_message(Messages::WindowManagerServer::SetManagerWindow(m_window_id));
|
||||
}
|
||||
|
||||
void Window::set_cursor(Gfx::StandardCursor cursor)
|
||||
{
|
||||
if (m_cursor == cursor)
|
||||
|
|
|
@ -80,6 +80,8 @@ public:
|
|||
|
||||
int window_id() const { return m_window_id; }
|
||||
|
||||
void make_window_manager(unsigned event_mask);
|
||||
|
||||
String title() const;
|
||||
void set_title(String);
|
||||
|
||||
|
|
77
Userland/Libraries/LibGUI/WindowManagerServerConnection.cpp
Normal file
77
Userland/Libraries/LibGUI/WindowManagerServerConnection.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2021, the SerenityOS developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <LibGUI/Event.h>
|
||||
#include <LibGUI/Window.h>
|
||||
#include <LibGUI/WindowManagerServerConnection.h>
|
||||
#include <WindowServer/Window.h>
|
||||
|
||||
namespace GUI {
|
||||
|
||||
WindowManagerServerConnection& WindowManagerServerConnection::the()
|
||||
{
|
||||
static WindowManagerServerConnection* s_connection = nullptr;
|
||||
if (!s_connection)
|
||||
s_connection = new WindowManagerServerConnection;
|
||||
return *s_connection;
|
||||
}
|
||||
|
||||
void WindowManagerServerConnection::handshake()
|
||||
{
|
||||
// :^)
|
||||
}
|
||||
|
||||
void WindowManagerServerConnection::handle(const Messages::WindowManagerClient::WindowStateChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowStateChangedEvent>(message.client_id(), message.window_id(), message.parent_client_id(), message.parent_window_id(), message.title(), message.rect(), message.is_active(), message.is_modal(), static_cast<WindowType>(message.window_type()), message.is_minimized(), message.is_frameless(), message.progress()));
|
||||
}
|
||||
|
||||
void WindowManagerServerConnection::handle(const Messages::WindowManagerClient::AppletAreaSizeChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMAppletAreaSizeChangedEvent>(message.size()));
|
||||
}
|
||||
|
||||
void WindowManagerServerConnection::handle(const Messages::WindowManagerClient::WindowRectChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowRectChangedEvent>(message.client_id(), message.window_id(), message.rect()));
|
||||
}
|
||||
|
||||
void WindowManagerServerConnection::handle(const Messages::WindowManagerClient::WindowIconBitmapChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id())) {
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowIconBitmapChangedEvent>(message.client_id(), message.window_id(), message.bitmap().bitmap()));
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManagerServerConnection::handle(const Messages::WindowManagerClient::WindowRemoved& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowRemovedEvent>(message.client_id(), message.window_id()));
|
||||
}
|
||||
}
|
57
Userland/Libraries/LibGUI/WindowManagerServerConnection.h
Normal file
57
Userland/Libraries/LibGUI/WindowManagerServerConnection.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2021, the SerenityOS developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibIPC/ServerConnection.h>
|
||||
#include <WindowServer/WindowManagerClientEndpoint.h>
|
||||
#include <WindowServer/WindowManagerServerEndpoint.h>
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class WindowManagerServerConnection
|
||||
: public IPC::ServerConnection<WindowManagerClientEndpoint, WindowManagerServerEndpoint>
|
||||
, public WindowManagerClientEndpoint {
|
||||
C_OBJECT(WindowManagerServerConnection)
|
||||
public:
|
||||
WindowManagerServerConnection()
|
||||
: IPC::ServerConnection<WindowManagerClientEndpoint, WindowManagerServerEndpoint>(*this, "/tmp/portal/wm")
|
||||
{
|
||||
handshake();
|
||||
}
|
||||
|
||||
virtual void handshake() override;
|
||||
static WindowManagerServerConnection& the();
|
||||
|
||||
private:
|
||||
virtual void handle(const Messages::WindowManagerClient::WindowRemoved&) override;
|
||||
virtual void handle(const Messages::WindowManagerClient::WindowStateChanged&) override;
|
||||
virtual void handle(const Messages::WindowManagerClient::WindowIconBitmapChanged&) override;
|
||||
virtual void handle(const Messages::WindowManagerClient::WindowRectChanged&) override;
|
||||
virtual void handle(const Messages::WindowManagerClient::AppletAreaSizeChanged&) override;
|
||||
};
|
||||
|
||||
}
|
|
@ -273,37 +273,6 @@ void WindowServerConnection::handle(const Messages::WindowClient::MenuItemActiva
|
|||
action->activate(menu);
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WM_WindowStateChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowStateChangedEvent>(message.client_id(), message.window_id(), message.parent_client_id(), message.parent_window_id(), message.title(), message.rect(), message.is_active(), message.is_modal(), static_cast<WindowType>(message.window_type()), message.is_minimized(), message.is_frameless(), message.progress()));
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WM_AppletAreaSizeChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMAppletAreaSizeChangedEvent>(message.size()));
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WM_WindowRectChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowRectChangedEvent>(message.client_id(), message.window_id(), message.rect()));
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WM_WindowIconBitmapChanged& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id())) {
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowIconBitmapChangedEvent>(message.client_id(), message.window_id(), message.bitmap().bitmap()));
|
||||
}
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WM_WindowRemoved& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.wm_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<WMWindowRemovedEvent>(message.client_id(), message.window_id()));
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::ScreenRectChanged& message)
|
||||
{
|
||||
Desktop::the().did_receive_screen_rect({}, message.rect());
|
||||
|
|
|
@ -66,11 +66,6 @@ private:
|
|||
virtual void handle(const Messages::WindowClient::MenuItemActivated&) override;
|
||||
virtual void handle(const Messages::WindowClient::MenuVisibilityDidChange&) override;
|
||||
virtual void handle(const Messages::WindowClient::ScreenRectChanged&) override;
|
||||
virtual void handle(const Messages::WindowClient::WM_WindowRemoved&) override;
|
||||
virtual void handle(const Messages::WindowClient::WM_WindowStateChanged&) override;
|
||||
virtual void handle(const Messages::WindowClient::WM_WindowIconBitmapChanged&) override;
|
||||
virtual void handle(const Messages::WindowClient::WM_WindowRectChanged&) override;
|
||||
virtual void handle(const Messages::WindowClient::WM_AppletAreaSizeChanged&) override;
|
||||
virtual void handle(const Messages::WindowClient::AsyncSetWallpaperFinished&) override;
|
||||
virtual void handle(const Messages::WindowClient::DragDropped&) override;
|
||||
virtual void handle(const Messages::WindowClient::DragAccepted&) override;
|
||||
|
|
|
@ -155,7 +155,7 @@ void AppletManager::relayout()
|
|||
|
||||
repaint();
|
||||
|
||||
WindowManager::the().tell_wm_listeners_applet_area_size_changed(rect.size());
|
||||
WindowManager::the().tell_wms_applet_area_size_changed(rect.size());
|
||||
}
|
||||
|
||||
void AppletManager::repaint()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
compile_ipc(WindowServer.ipc WindowServerEndpoint.h)
|
||||
compile_ipc(WindowClient.ipc WindowClientEndpoint.h)
|
||||
compile_ipc(WindowManagerServer.ipc WindowManagerServerEndpoint.h)
|
||||
compile_ipc(WindowManagerClient.ipc WindowManagerClientEndpoint.h)
|
||||
|
||||
set(SOURCES
|
||||
AppletManager.cpp
|
||||
|
@ -20,6 +22,9 @@ set(SOURCES
|
|||
WindowSwitcher.cpp
|
||||
WindowServerEndpoint.h
|
||||
WindowClientEndpoint.h
|
||||
WindowManagerServerEndpoint.h
|
||||
WindowManagerClientEndpoint.h
|
||||
WMClientConnection.cpp
|
||||
)
|
||||
|
||||
serenity_bin(WindowServer)
|
||||
|
|
|
@ -302,7 +302,7 @@ OwnPtr<Messages::WindowServer::SetFramelessResponse> ClientConnection::handle(co
|
|||
return {};
|
||||
}
|
||||
it->value->set_frameless(message.frameless());
|
||||
WindowManager::the().tell_wm_listeners_window_state_changed(*it->value);
|
||||
WindowManager::the().tell_wms_window_state_changed(*it->value);
|
||||
return make<Messages::WindowServer::SetFramelessResponse>();
|
||||
}
|
||||
|
||||
|
@ -393,7 +393,7 @@ OwnPtr<Messages::WindowServer::SetWindowIconBitmapResponse> ClientConnection::ha
|
|||
}
|
||||
|
||||
window.frame().invalidate_title_bar();
|
||||
WindowManager::the().tell_wm_listeners_window_icon_changed(window);
|
||||
WindowManager::the().tell_wms_window_icon_changed(window);
|
||||
return make<Messages::WindowServer::SetWindowIconBitmapResponse>();
|
||||
}
|
||||
|
||||
|
@ -722,49 +722,6 @@ OwnPtr<Messages::WindowServer::SetWindowAlphaHitThresholdResponse> ClientConnect
|
|||
return make<Messages::WindowServer::SetWindowAlphaHitThresholdResponse>();
|
||||
}
|
||||
|
||||
OwnPtr<Messages::WindowServer::WM_SetAppletAreaPositionResponse> ClientConnection::handle(const Messages::WindowServer::WM_SetAppletAreaPosition& message)
|
||||
{
|
||||
AppletManager::the().set_position(message.position());
|
||||
return make<Messages::WindowServer::WM_SetAppletAreaPositionResponse>();
|
||||
}
|
||||
|
||||
void ClientConnection::handle(const Messages::WindowServer::WM_SetActiveWindow& message)
|
||||
{
|
||||
auto* client = ClientConnection::from_client_id(message.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("WM_SetActiveWindow: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("WM_SetActiveWindow: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
WindowManager::the().minimize_windows(window, false);
|
||||
WindowManager::the().move_to_front_and_make_active(window);
|
||||
}
|
||||
|
||||
void ClientConnection::handle(const Messages::WindowServer::WM_PopupWindowMenu& message)
|
||||
{
|
||||
auto* client = ClientConnection::from_client_id(message.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("WM_PopupWindowMenu: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("WM_PopupWindowMenu: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
if (auto* modal_window = window.blocking_modal_window()) {
|
||||
modal_window->popup_window_menu(message.screen_position(), WindowMenuDefaultAction::BasedOnWindowState);
|
||||
} else {
|
||||
window.popup_window_menu(message.screen_position(), WindowMenuDefaultAction::BasedOnWindowState);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientConnection::handle(const Messages::WindowServer::StartWindowResize& request)
|
||||
{
|
||||
auto it = m_windows.find(request.window_id());
|
||||
|
@ -778,63 +735,11 @@ void ClientConnection::handle(const Messages::WindowServer::StartWindowResize& r
|
|||
WindowManager::the().start_window_resize(window, Screen::the().cursor_location(), MouseButton::Left);
|
||||
}
|
||||
|
||||
void ClientConnection::handle(const Messages::WindowServer::WM_StartWindowResize& request)
|
||||
{
|
||||
auto* client = ClientConnection::from_client_id(request.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("WM_StartWindowResize: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(request.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("WM_StartWindowResize: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
// FIXME: We are cheating a bit here by using the current cursor location and hard-coding the left button.
|
||||
// Maybe the client should be allowed to specify what initiated this request?
|
||||
WindowManager::the().start_window_resize(window, Screen::the().cursor_location(), MouseButton::Left);
|
||||
}
|
||||
|
||||
void ClientConnection::handle(const Messages::WindowServer::WM_SetWindowMinimized& message)
|
||||
{
|
||||
auto* client = ClientConnection::from_client_id(message.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("WM_SetWindowMinimized: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("WM_SetWindowMinimized: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
WindowManager::the().minimize_windows(window, message.minimized());
|
||||
}
|
||||
|
||||
OwnPtr<Messages::WindowServer::GreetResponse> ClientConnection::handle(const Messages::WindowServer::Greet&)
|
||||
{
|
||||
return make<Messages::WindowServer::GreetResponse>(Screen::the().rect(), Gfx::current_system_theme_buffer());
|
||||
}
|
||||
|
||||
void ClientConnection::handle(const Messages::WindowServer::WM_SetWindowTaskbarRect& message)
|
||||
{
|
||||
// Because the Taskbar (which should be the only user of this API) does not own the
|
||||
// window or the client id, there is a possibility that it may send this message for
|
||||
// a window or client that may have been destroyed already. This is not an error,
|
||||
// and we should not call did_misbehave() for either.
|
||||
auto* client = ClientConnection::from_client_id(message.client_id());
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end())
|
||||
return;
|
||||
|
||||
auto& window = *(*it).value;
|
||||
window.set_taskbar_rect(message.rect());
|
||||
}
|
||||
|
||||
OwnPtr<Messages::WindowServer::StartDragResponse> ClientConnection::handle(const Messages::WindowServer::StartDrag& message)
|
||||
{
|
||||
auto& wm = WindowManager::the();
|
||||
|
|
|
@ -45,6 +45,7 @@ class Compositor;
|
|||
class Window;
|
||||
class Menu;
|
||||
class Menubar;
|
||||
class WMClientConnection;
|
||||
|
||||
class ClientConnection final
|
||||
: public IPC::ClientConnection<WindowClientEndpoint, WindowServerEndpoint>
|
||||
|
@ -132,11 +133,6 @@ private:
|
|||
virtual OwnPtr<Messages::WindowServer::SetGlobalCursorTrackingResponse> handle(const Messages::WindowServer::SetGlobalCursorTracking&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::SetWindowOpacityResponse> handle(const Messages::WindowServer::SetWindowOpacity&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::SetWindowBackingStoreResponse> handle(const Messages::WindowServer::SetWindowBackingStore&) override;
|
||||
virtual void handle(const Messages::WindowServer::WM_SetActiveWindow&) override;
|
||||
virtual void handle(const Messages::WindowServer::WM_SetWindowMinimized&) override;
|
||||
virtual void handle(const Messages::WindowServer::WM_StartWindowResize&) override;
|
||||
virtual void handle(const Messages::WindowServer::WM_PopupWindowMenu&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::WM_SetAppletAreaPositionResponse> handle(const Messages::WindowServer::WM_SetAppletAreaPosition&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::SetWindowHasAlphaChannelResponse> handle(const Messages::WindowServer::SetWindowHasAlphaChannel&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::SetWindowAlphaHitThresholdResponse> handle(const Messages::WindowServer::SetWindowAlphaHitThreshold&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::MoveWindowToFrontResponse> handle(const Messages::WindowServer::MoveWindowToFront&) override;
|
||||
|
@ -152,7 +148,6 @@ private:
|
|||
virtual OwnPtr<Messages::WindowServer::PopupMenuResponse> handle(const Messages::WindowServer::PopupMenu&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::DismissMenuResponse> handle(const Messages::WindowServer::DismissMenu&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::SetWindowIconBitmapResponse> handle(const Messages::WindowServer::SetWindowIconBitmap&) override;
|
||||
virtual void handle(const Messages::WindowServer::WM_SetWindowTaskbarRect&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::StartDragResponse> handle(const Messages::WindowServer::StartDrag&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::SetSystemThemeResponse> handle(const Messages::WindowServer::SetSystemTheme&) override;
|
||||
virtual OwnPtr<Messages::WindowServer::GetSystemThemeResponse> handle(const Messages::WindowServer::GetSystemTheme&) override;
|
||||
|
@ -186,6 +181,9 @@ private:
|
|||
|
||||
bool m_has_display_link { false };
|
||||
bool m_unresponsive { false };
|
||||
|
||||
// Need this to get private client connection stuff
|
||||
friend WMClientConnection;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <WindowServer/Event.h>
|
||||
#include <WindowServer/EventLoop.h>
|
||||
#include <WindowServer/Screen.h>
|
||||
#include <WindowServer/WMClientConnection.h>
|
||||
#include <WindowServer/WindowManager.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -46,16 +47,19 @@
|
|||
namespace WindowServer {
|
||||
|
||||
EventLoop::EventLoop()
|
||||
: m_server(Core::LocalServer::construct())
|
||||
: m_window_server(Core::LocalServer::construct())
|
||||
, m_wm_server(Core::LocalServer::construct())
|
||||
{
|
||||
m_keyboard_fd = open("/dev/keyboard", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
m_mouse_fd = open("/dev/mouse", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
|
||||
bool ok = m_server->take_over_from_system_server();
|
||||
bool ok = m_window_server->take_over_from_system_server("/tmp/portal/window");
|
||||
VERIFY(ok);
|
||||
ok = m_wm_server->take_over_from_system_server("/tmp/portal/wm");
|
||||
VERIFY(ok);
|
||||
|
||||
m_server->on_ready_to_accept = [this] {
|
||||
auto client_socket = m_server->accept();
|
||||
m_window_server->on_ready_to_accept = [this] {
|
||||
auto client_socket = m_window_server->accept();
|
||||
if (!client_socket) {
|
||||
dbgln("WindowServer: accept failed.");
|
||||
return;
|
||||
|
@ -65,6 +69,17 @@ EventLoop::EventLoop()
|
|||
IPC::new_client_connection<ClientConnection>(client_socket.release_nonnull(), client_id);
|
||||
};
|
||||
|
||||
m_wm_server->on_ready_to_accept = [this] {
|
||||
auto client_socket = m_wm_server->accept();
|
||||
if (!client_socket) {
|
||||
dbgln("WindowServer: WM accept failed.");
|
||||
return;
|
||||
}
|
||||
static int s_next_wm_id = 0;
|
||||
int wm_id = ++s_next_wm_id;
|
||||
IPC::new_client_connection<WMClientConnection>(client_socket.release_nonnull(), wm_id);
|
||||
};
|
||||
|
||||
if (m_keyboard_fd >= 0) {
|
||||
m_keyboard_notifier = Core::Notifier::construct(m_keyboard_fd, Core::Notifier::Read);
|
||||
m_keyboard_notifier->on_ready_to_read = [this] { drain_keyboard(); };
|
||||
|
|
|
@ -51,7 +51,8 @@ private:
|
|||
RefPtr<Core::Notifier> m_keyboard_notifier;
|
||||
int m_mouse_fd { -1 };
|
||||
RefPtr<Core::Notifier> m_mouse_notifier;
|
||||
RefPtr<Core::LocalServer> m_server;
|
||||
RefPtr<Core::LocalServer> m_window_server;
|
||||
RefPtr<Core::LocalServer> m_wm_server;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
174
Userland/Services/WindowServer/WMClientConnection.cpp
Normal file
174
Userland/Services/WindowServer/WMClientConnection.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2021, the SerenityOS developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <WindowServer/AppletManager.h>
|
||||
#include <WindowServer/ClientConnection.h>
|
||||
#include <WindowServer/Screen.h>
|
||||
#include <WindowServer/WMClientConnection.h>
|
||||
|
||||
namespace WindowServer {
|
||||
|
||||
HashMap<int, NonnullRefPtr<WMClientConnection>> WMClientConnection::s_connections {};
|
||||
|
||||
WMClientConnection::WMClientConnection(NonnullRefPtr<Core::LocalSocket> client_socket, int client_id)
|
||||
: IPC::ClientConnection<WindowManagerClientEndpoint, WindowManagerServerEndpoint>(*this, move(client_socket), client_id)
|
||||
{
|
||||
s_connections.set(client_id, *this);
|
||||
}
|
||||
|
||||
WMClientConnection::~WMClientConnection()
|
||||
{
|
||||
// The WM has gone away, so take away the applet manager (cause there's nowhere
|
||||
// to draw it in).
|
||||
AppletManager::the().set_position({});
|
||||
}
|
||||
|
||||
void WMClientConnection::die()
|
||||
{
|
||||
deferred_invoke([this](auto&) {
|
||||
s_connections.remove(client_id());
|
||||
});
|
||||
}
|
||||
|
||||
OwnPtr<Messages::WindowManagerServer::SetAppletAreaPositionResponse> WMClientConnection::handle(const Messages::WindowManagerServer::SetAppletAreaPosition& message)
|
||||
{
|
||||
if (m_window_id < 0) {
|
||||
did_misbehave("SetAppletAreaPosition: WM didn't assign window as manager yet");
|
||||
// FIXME: return ok boolean?
|
||||
return make<Messages::WindowManagerServer::SetAppletAreaPositionResponse>();
|
||||
}
|
||||
|
||||
AppletManager::the().set_position(message.position());
|
||||
return make<Messages::WindowManagerServer::SetAppletAreaPositionResponse>();
|
||||
}
|
||||
|
||||
void WMClientConnection::handle(const Messages::WindowManagerServer::SetActiveWindow& message)
|
||||
{
|
||||
auto* client = WindowServer::ClientConnection::from_client_id(message.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("SetActiveWindow: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("SetActiveWindow: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
WindowManager::the().minimize_windows(window, false);
|
||||
WindowManager::the().move_to_front_and_make_active(window);
|
||||
}
|
||||
|
||||
void WMClientConnection::handle(const Messages::WindowManagerServer::PopupWindowMenu& message)
|
||||
{
|
||||
auto* client = WindowServer::ClientConnection::from_client_id(message.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("PopupWindowMenu: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("PopupWindowMenu: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
if (auto* modal_window = window.blocking_modal_window()) {
|
||||
modal_window->popup_window_menu(message.screen_position(), WindowMenuDefaultAction::BasedOnWindowState);
|
||||
} else {
|
||||
window.popup_window_menu(message.screen_position(), WindowMenuDefaultAction::BasedOnWindowState);
|
||||
}
|
||||
}
|
||||
|
||||
void WMClientConnection::handle(const Messages::WindowManagerServer::StartWindowResize& request)
|
||||
{
|
||||
auto* client = WindowServer::ClientConnection::from_client_id(request.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("WM_StartWindowResize: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(request.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("WM_StartWindowResize: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
// FIXME: We are cheating a bit here by using the current cursor location and hard-coding the left button.
|
||||
// Maybe the client should be allowed to specify what initiated this request?
|
||||
WindowManager::the().start_window_resize(window, Screen::the().cursor_location(), MouseButton::Left);
|
||||
}
|
||||
|
||||
void WMClientConnection::handle(const Messages::WindowManagerServer::SetWindowMinimized& message)
|
||||
{
|
||||
auto* client = WindowServer::ClientConnection::from_client_id(message.client_id());
|
||||
if (!client) {
|
||||
did_misbehave("WM_SetWindowMinimized: Bad client ID");
|
||||
return;
|
||||
}
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end()) {
|
||||
did_misbehave("WM_SetWindowMinimized: Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
WindowManager::the().minimize_windows(window, message.minimized());
|
||||
}
|
||||
|
||||
OwnPtr<Messages::WindowManagerServer::SetEventMaskResponse> WMClientConnection::handle(const Messages::WindowManagerServer::SetEventMask& message)
|
||||
{
|
||||
m_event_mask = message.event_mask();
|
||||
return make<Messages::WindowManagerServer::SetEventMaskResponse>();
|
||||
}
|
||||
|
||||
OwnPtr<Messages::WindowManagerServer::SetManagerWindowResponse> WMClientConnection::handle(const Messages::WindowManagerServer::SetManagerWindow& message)
|
||||
{
|
||||
m_window_id = message.window_id();
|
||||
|
||||
// Let the window manager know that we obtained a manager window, and should
|
||||
// receive information about other windows.
|
||||
WindowManager::the().greet_window_manager(*this);
|
||||
|
||||
return make<Messages::WindowManagerServer::SetManagerWindowResponse>();
|
||||
}
|
||||
|
||||
void WMClientConnection::handle(const Messages::WindowManagerServer::SetWindowTaskbarRect& message)
|
||||
{
|
||||
// Because the Taskbar (which should be the only user of this API) does not own the
|
||||
// window or the client id, there is a possibility that it may send this message for
|
||||
// a window or client that may have been destroyed already. This is not an error,
|
||||
// and we should not call did_misbehave() for either.
|
||||
auto* client = WindowServer::ClientConnection::from_client_id(message.client_id());
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
auto it = client->m_windows.find(message.window_id());
|
||||
if (it == client->m_windows.end())
|
||||
return;
|
||||
|
||||
auto& window = *(*it).value;
|
||||
window.set_taskbar_rect(message.rect());
|
||||
}
|
||||
|
||||
}
|
73
Userland/Services/WindowServer/WMClientConnection.h
Normal file
73
Userland/Services/WindowServer/WMClientConnection.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2021, the SerenityOS developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AK/NonnullRefPtr.h"
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibIPC/ClientConnection.h>
|
||||
#include <WindowServer/WindowManagerClientEndpoint.h>
|
||||
#include <WindowServer/WindowManagerServerEndpoint.h>
|
||||
|
||||
namespace WindowServer {
|
||||
|
||||
class WMClientConnection final
|
||||
: public IPC::ClientConnection<WindowManagerClientEndpoint, WindowManagerServerEndpoint>
|
||||
, public WindowManagerServerEndpoint {
|
||||
C_OBJECT(WMClientConnection)
|
||||
|
||||
public:
|
||||
~WMClientConnection() override;
|
||||
|
||||
virtual void handle(const Messages::WindowManagerServer::SetActiveWindow&) override;
|
||||
virtual void handle(const Messages::WindowManagerServer::SetWindowMinimized&) override;
|
||||
virtual void handle(const Messages::WindowManagerServer::StartWindowResize&) override;
|
||||
virtual void handle(const Messages::WindowManagerServer::PopupWindowMenu&) override;
|
||||
virtual void handle(const Messages::WindowManagerServer::SetWindowTaskbarRect&) override;
|
||||
virtual OwnPtr<Messages::WindowManagerServer::SetAppletAreaPositionResponse> handle(const Messages::WindowManagerServer::SetAppletAreaPosition&) override;
|
||||
virtual OwnPtr<Messages::WindowManagerServer::SetEventMaskResponse> handle(const Messages::WindowManagerServer::SetEventMask&) override;
|
||||
virtual OwnPtr<Messages::WindowManagerServer::SetManagerWindowResponse> handle(const Messages::WindowManagerServer::SetManagerWindow&) override;
|
||||
|
||||
unsigned event_mask() const { return m_event_mask; }
|
||||
int window_id() const { return m_window_id; }
|
||||
|
||||
private:
|
||||
explicit WMClientConnection(NonnullRefPtr<Core::LocalSocket> client_socket, int client_id);
|
||||
|
||||
// ^ClientConnection
|
||||
virtual void die() override;
|
||||
|
||||
// RefPtr<Core::Timer> m_ping_timer;
|
||||
static HashMap<int, NonnullRefPtr<WMClientConnection>> s_connections;
|
||||
unsigned m_event_mask { 0 };
|
||||
int m_window_id { -1 };
|
||||
|
||||
// WindowManager needs to access the window manager clients to notify
|
||||
// about events.
|
||||
friend class WindowManager;
|
||||
};
|
||||
|
||||
};
|
|
@ -113,12 +113,6 @@ Window::Window(ClientConnection& client, WindowType window_type, int window_id,
|
|||
, m_icon(default_window_icon())
|
||||
, m_frame(*this)
|
||||
{
|
||||
// FIXME: This should not be hard-coded here.
|
||||
if (m_type == WindowType::Taskbar) {
|
||||
m_wm_event_mask = WMEventMask::WindowStateChanges | WMEventMask::WindowRemovals | WMEventMask::WindowIconChanges;
|
||||
m_listens_to_wm_events = true;
|
||||
}
|
||||
|
||||
// Set default minimum size for Normal windows
|
||||
if (m_type == WindowType::Normal)
|
||||
m_minimum_size = s_default_normal_minimum_size;
|
||||
|
|
|
@ -100,9 +100,6 @@ public:
|
|||
void window_menu_activate_default();
|
||||
void request_close();
|
||||
|
||||
unsigned wm_event_mask() const { return m_wm_event_mask; }
|
||||
void set_wm_event_mask(unsigned mask) { m_wm_event_mask = mask; }
|
||||
|
||||
bool is_minimized() const { return m_minimized; }
|
||||
void set_minimized(bool);
|
||||
|
||||
|
@ -137,8 +134,6 @@ public:
|
|||
|
||||
Window* blocking_modal_window();
|
||||
|
||||
bool listens_to_wm_events() const { return m_listens_to_wm_events; }
|
||||
|
||||
ClientConnection* client() { return m_client; }
|
||||
const ClientConnection* client() const { return m_client; }
|
||||
|
||||
|
@ -381,7 +376,6 @@ private:
|
|||
bool m_frameless { false };
|
||||
bool m_resizable { false };
|
||||
Optional<Gfx::IntSize> m_resize_aspect_ratio {};
|
||||
bool m_listens_to_wm_events { false };
|
||||
bool m_minimized { false };
|
||||
bool m_maximized { false };
|
||||
bool m_fullscreen { false };
|
||||
|
@ -411,7 +405,6 @@ private:
|
|||
RefPtr<Cursor> m_cursor;
|
||||
RefPtr<Cursor> m_cursor_override;
|
||||
WindowFrame m_frame;
|
||||
unsigned m_wm_event_mask { 0 };
|
||||
Gfx::DisjointRectSet m_pending_paint_rects;
|
||||
Gfx::IntRect m_unmaximized_rect;
|
||||
Gfx::IntRect m_rect_in_applet_area;
|
||||
|
|
|
@ -23,12 +23,6 @@ endpoint WindowClient = 4
|
|||
|
||||
ScreenRectChanged(Gfx::IntRect rect) =|
|
||||
|
||||
WM_WindowRemoved(i32 wm_id, i32 client_id, i32 window_id) =|
|
||||
WM_WindowStateChanged(i32 wm_id, i32 client_id, i32 window_id, i32 parent_client_id, i32 parent_window_id, bool is_active, bool is_minimized, bool is_modal, bool is_frameless, i32 window_type, [UTF8] String title, Gfx::IntRect rect, i32 progress) =|
|
||||
WM_WindowIconBitmapChanged(i32 wm_id, i32 client_id, i32 window_id, Gfx::ShareableBitmap bitmap) =|
|
||||
WM_WindowRectChanged(i32 wm_id, i32 client_id, i32 window_id, Gfx::IntRect rect) =|
|
||||
WM_AppletAreaSizeChanged(i32 wm_id, Gfx::IntSize size) =|
|
||||
|
||||
AsyncSetWallpaperFinished(bool success) =|
|
||||
|
||||
DragAccepted() =|
|
||||
|
|
|
@ -209,21 +209,9 @@ void WindowManager::add_window(Window& window)
|
|||
|
||||
Compositor::the().invalidate_occlusions();
|
||||
|
||||
if (window.listens_to_wm_events()) {
|
||||
for_each_window([&](Window& other_window) {
|
||||
if (&window != &other_window) {
|
||||
tell_wm_listener_about_window(window, other_window);
|
||||
tell_wm_listener_about_window_icon(window, other_window);
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
if (auto* applet_area_window = AppletManager::the().window())
|
||||
tell_wm_listeners_applet_area_size_changed(applet_area_window->size());
|
||||
}
|
||||
|
||||
window.invalidate(true, true);
|
||||
|
||||
tell_wm_listeners_window_state_changed(window);
|
||||
tell_wms_window_state_changed(window);
|
||||
}
|
||||
|
||||
void WindowManager::move_to_front_and_make_active(Window& window)
|
||||
|
@ -295,71 +283,96 @@ void WindowManager::remove_window(Window& window)
|
|||
|
||||
Compositor::the().invalidate_occlusions();
|
||||
|
||||
for_each_window_listening_to_wm_events([&window](Window& listener) {
|
||||
if (!(listener.wm_event_mask() & WMEventMask::WindowRemovals))
|
||||
for_each_window_manager([&window](WMClientConnection& conn) {
|
||||
if (conn.window_id() < 0 || !(conn.event_mask() & WMEventMask::WindowRemovals))
|
||||
return IterationDecision::Continue;
|
||||
if (!window.is_internal() && !window.is_modal())
|
||||
listener.client()->post_message(Messages::WindowClient::WM_WindowRemoved(listener.window_id(), window.client_id(), window.window_id()));
|
||||
conn.post_message(Messages::WindowManagerClient::WindowRemoved(conn.window_id(), window.client_id(), window.window_id()));
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_listener_about_window(Window& listener, Window& window)
|
||||
void WindowManager::greet_window_manager(WMClientConnection& conn)
|
||||
{
|
||||
if (!(listener.wm_event_mask() & WMEventMask::WindowStateChanges))
|
||||
if (conn.window_id() < 0)
|
||||
return;
|
||||
|
||||
for_each_window([&](Window& other_window) {
|
||||
//if (conn.window_id() != other_window.window_id()) {
|
||||
tell_wm_about_window(conn, other_window);
|
||||
tell_wm_about_window_icon(conn, other_window);
|
||||
//}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
if (auto* applet_area_window = AppletManager::the().window())
|
||||
tell_wms_applet_area_size_changed(applet_area_window->size());
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_about_window(WMClientConnection& conn, Window& window)
|
||||
{
|
||||
if (conn.window_id() < 0)
|
||||
return;
|
||||
if (!(conn.event_mask() & WMEventMask::WindowStateChanges))
|
||||
return;
|
||||
if (window.is_internal())
|
||||
return;
|
||||
auto* parent = window.parent_window();
|
||||
listener.client()->post_message(Messages::WindowClient::WM_WindowStateChanged(listener.window_id(), window.client_id(), window.window_id(), parent ? parent->client_id() : -1, parent ? parent->window_id() : -1, window.is_active(), window.is_minimized(), window.is_modal_dont_unparent(), window.is_frameless(), (i32)window.type(), window.title(), window.rect(), window.progress()));
|
||||
conn.post_message(Messages::WindowManagerClient::WindowStateChanged(conn.window_id(), window.client_id(), window.window_id(), parent ? parent->client_id() : -1, parent ? parent->window_id() : -1, window.is_active(), window.is_minimized(), window.is_modal_dont_unparent(), window.is_frameless(), (i32)window.type(), window.title(), window.rect(), window.progress()));
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_listener_about_window_rect(Window& listener, Window& window)
|
||||
void WindowManager::tell_wm_about_window_rect(WMClientConnection& conn, Window& window)
|
||||
{
|
||||
if (!(listener.wm_event_mask() & WMEventMask::WindowRectChanges))
|
||||
if (conn.window_id() < 0)
|
||||
return;
|
||||
if (!(conn.event_mask() & WMEventMask::WindowRectChanges))
|
||||
return;
|
||||
if (window.is_internal())
|
||||
return;
|
||||
listener.client()->post_message(Messages::WindowClient::WM_WindowRectChanged(listener.window_id(), window.client_id(), window.window_id(), window.rect()));
|
||||
conn.post_message(Messages::WindowManagerClient::WindowRectChanged(conn.window_id(), window.client_id(), window.window_id(), window.rect()));
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_listener_about_window_icon(Window& listener, Window& window)
|
||||
void WindowManager::tell_wm_about_window_icon(WMClientConnection& conn, Window& window)
|
||||
{
|
||||
if (!(listener.wm_event_mask() & WMEventMask::WindowIconChanges))
|
||||
if (conn.window_id() < 0)
|
||||
return;
|
||||
if (!(conn.event_mask() & WMEventMask::WindowIconChanges))
|
||||
return;
|
||||
if (window.is_internal())
|
||||
return;
|
||||
listener.client()->post_message(Messages::WindowClient::WM_WindowIconBitmapChanged(listener.window_id(), window.client_id(), window.window_id(), window.icon().to_shareable_bitmap()));
|
||||
conn.post_message(Messages::WindowManagerClient::WindowIconBitmapChanged(conn.window_id(), window.client_id(), window.window_id(), window.icon().to_shareable_bitmap()));
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_listeners_window_state_changed(Window& window)
|
||||
void WindowManager::tell_wms_window_state_changed(Window& window)
|
||||
{
|
||||
for_each_window_listening_to_wm_events([&](Window& listener) {
|
||||
tell_wm_listener_about_window(listener, window);
|
||||
for_each_window_manager([&](WMClientConnection& conn) {
|
||||
tell_wm_about_window(conn, window);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_listeners_window_icon_changed(Window& window)
|
||||
void WindowManager::tell_wms_window_icon_changed(Window& window)
|
||||
{
|
||||
for_each_window_listening_to_wm_events([&](Window& listener) {
|
||||
tell_wm_listener_about_window_icon(listener, window);
|
||||
for_each_window_manager([&](WMClientConnection& conn) {
|
||||
tell_wm_about_window_icon(conn, window);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_listeners_window_rect_changed(Window& window)
|
||||
void WindowManager::tell_wms_window_rect_changed(Window& window)
|
||||
{
|
||||
for_each_window_listening_to_wm_events([&](Window& listener) {
|
||||
tell_wm_listener_about_window_rect(listener, window);
|
||||
for_each_window_manager([&](WMClientConnection& conn) {
|
||||
tell_wm_about_window_rect(conn, window);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void WindowManager::tell_wm_listeners_applet_area_size_changed(const Gfx::IntSize& size)
|
||||
void WindowManager::tell_wms_applet_area_size_changed(const Gfx::IntSize& size)
|
||||
{
|
||||
for_each_window_listening_to_wm_events([&](Window& listener) {
|
||||
listener.client()->post_message(Messages::WindowClient::WM_AppletAreaSizeChanged(listener.window_id(), size));
|
||||
for_each_window_manager([&](WMClientConnection& conn) {
|
||||
if (conn.window_id() < 0)
|
||||
return IterationDecision::Continue;
|
||||
|
||||
conn.post_message(Messages::WindowManagerClient::AppletAreaSizeChanged(conn.window_id(), size));
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
@ -379,7 +392,7 @@ void WindowManager::notify_title_changed(Window& window)
|
|||
if (m_switcher.is_visible())
|
||||
m_switcher.refresh();
|
||||
|
||||
tell_wm_listeners_window_state_changed(window);
|
||||
tell_wms_window_state_changed(window);
|
||||
}
|
||||
|
||||
void WindowManager::notify_modal_unparented(Window& window)
|
||||
|
@ -392,7 +405,7 @@ void WindowManager::notify_modal_unparented(Window& window)
|
|||
if (m_switcher.is_visible())
|
||||
m_switcher.refresh();
|
||||
|
||||
tell_wm_listeners_window_state_changed(window);
|
||||
tell_wms_window_state_changed(window);
|
||||
}
|
||||
|
||||
void WindowManager::notify_rect_changed(Window& window, const Gfx::IntRect& old_rect, const Gfx::IntRect& new_rect)
|
||||
|
@ -402,7 +415,7 @@ void WindowManager::notify_rect_changed(Window& window, const Gfx::IntRect& old_
|
|||
if (m_switcher.is_visible() && window.type() != WindowType::WindowSwitcher)
|
||||
m_switcher.refresh();
|
||||
|
||||
tell_wm_listeners_window_rect_changed(window);
|
||||
tell_wms_window_rect_changed(window);
|
||||
|
||||
if (window.type() == WindowType::Applet)
|
||||
AppletManager::the().relayout();
|
||||
|
@ -417,7 +430,7 @@ void WindowManager::notify_opacity_changed(Window&)
|
|||
|
||||
void WindowManager::notify_minimization_state_changed(Window& window)
|
||||
{
|
||||
tell_wm_listeners_window_state_changed(window);
|
||||
tell_wms_window_state_changed(window);
|
||||
|
||||
if (window.client())
|
||||
window.client()->post_message(Messages::WindowClient::WindowStateChanged(window.window_id(), window.is_minimized(), window.is_occluded()));
|
||||
|
@ -434,7 +447,7 @@ void WindowManager::notify_occlusion_state_changed(Window& window)
|
|||
|
||||
void WindowManager::notify_progress_changed(Window& window)
|
||||
{
|
||||
tell_wm_listeners_window_state_changed(window);
|
||||
tell_wms_window_state_changed(window);
|
||||
}
|
||||
|
||||
bool WindowManager::pick_new_active_window(Window* previous_active)
|
||||
|
@ -1360,14 +1373,14 @@ void WindowManager::set_active_window(Window* window, bool make_input)
|
|||
previously_active_window->invalidate(true, true);
|
||||
m_active_window = nullptr;
|
||||
m_active_input_tracking_window = nullptr;
|
||||
tell_wm_listeners_window_state_changed(*previously_active_window);
|
||||
tell_wms_window_state_changed(*previously_active_window);
|
||||
}
|
||||
|
||||
if (window) {
|
||||
m_active_window = *window;
|
||||
Core::EventLoop::current().post_event(*m_active_window, make<Event>(Event::WindowActivated));
|
||||
m_active_window->invalidate(true, true);
|
||||
tell_wm_listeners_window_state_changed(*m_active_window);
|
||||
tell_wms_window_state_changed(*m_active_window);
|
||||
}
|
||||
|
||||
// Window shapes may have changed (e.g. shadows for inactive/active windows)
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <WindowServer/Event.h>
|
||||
#include <WindowServer/MenuManager.h>
|
||||
#include <WindowServer/Menubar.h>
|
||||
#include <WindowServer/WMClientConnection.h>
|
||||
#include <WindowServer/Window.h>
|
||||
#include <WindowServer/WindowSwitcher.h>
|
||||
#include <WindowServer/WindowType.h>
|
||||
|
@ -169,10 +170,11 @@ public:
|
|||
void clear_resize_candidate();
|
||||
ResizeDirection resize_direction_of_window(const Window&);
|
||||
|
||||
void tell_wm_listeners_window_state_changed(Window&);
|
||||
void tell_wm_listeners_window_icon_changed(Window&);
|
||||
void tell_wm_listeners_window_rect_changed(Window&);
|
||||
void tell_wm_listeners_applet_area_size_changed(const Gfx::IntSize&);
|
||||
void greet_window_manager(WMClientConnection&);
|
||||
void tell_wms_window_state_changed(Window&);
|
||||
void tell_wms_window_icon_changed(Window&);
|
||||
void tell_wms_window_rect_changed(Window&);
|
||||
void tell_wms_applet_area_size_changed(const Gfx::IntSize&);
|
||||
|
||||
bool is_active_window_or_accessory(Window&) const;
|
||||
|
||||
|
@ -263,17 +265,18 @@ private:
|
|||
template<typename Callback>
|
||||
IterationDecision for_each_visible_window_from_back_to_front(Callback);
|
||||
template<typename Callback>
|
||||
void for_each_window_listening_to_wm_events(Callback);
|
||||
template<typename Callback>
|
||||
void for_each_window(Callback);
|
||||
template<typename Callback>
|
||||
IterationDecision for_each_window_of_type_from_front_to_back(WindowType, Callback, bool ignore_highlight = false);
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_window_manager(Callback);
|
||||
|
||||
virtual void event(Core::Event&) override;
|
||||
void paint_window_frame(const Window&);
|
||||
void tell_wm_listener_about_window(Window& listener, Window&);
|
||||
void tell_wm_listener_about_window_icon(Window& listener, Window&);
|
||||
void tell_wm_listener_about_window_rect(Window& listener, Window&);
|
||||
void tell_wm_about_window(WMClientConnection& conn, Window&);
|
||||
void tell_wm_about_window_icon(WMClientConnection& conn, Window&);
|
||||
void tell_wm_about_window_rect(WMClientConnection& conn, Window&);
|
||||
bool pick_new_active_window(Window*);
|
||||
|
||||
void do_move_to_front(Window&, bool, bool);
|
||||
|
@ -460,12 +463,13 @@ IterationDecision WindowManager::for_each_visible_window_from_front_to_back(Call
|
|||
}
|
||||
|
||||
template<typename Callback>
|
||||
void WindowManager::for_each_window_listening_to_wm_events(Callback callback)
|
||||
void WindowManager::for_each_window_manager(Callback callback)
|
||||
{
|
||||
for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) {
|
||||
if (!window->listens_to_wm_events())
|
||||
continue;
|
||||
if (callback(*window) == IterationDecision::Break)
|
||||
auto& connections = WMClientConnection::s_connections;
|
||||
|
||||
// FIXME: this isn't really ordered... does it need to be?
|
||||
for (auto it = connections.begin(); it != connections.end(); ++it) {
|
||||
if (callback(*it->value) == IterationDecision::Break)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
8
Userland/Services/WindowServer/WindowManagerClient.ipc
Normal file
8
Userland/Services/WindowServer/WindowManagerClient.ipc
Normal file
|
@ -0,0 +1,8 @@
|
|||
endpoint WindowManagerClient = 1872
|
||||
{
|
||||
WindowRemoved(i32 wm_id, i32 client_id, i32 window_id) =|
|
||||
WindowStateChanged(i32 wm_id, i32 client_id, i32 window_id, i32 parent_client_id, i32 parent_window_id, bool is_active, bool is_minimized, bool is_modal, bool is_frameless, i32 window_type, [UTF8] String title, Gfx::IntRect rect, i32 progress) =|
|
||||
WindowIconBitmapChanged(i32 wm_id, i32 client_id, i32 window_id, Gfx::ShareableBitmap bitmap) =|
|
||||
WindowRectChanged(i32 wm_id, i32 client_id, i32 window_id, Gfx::IntRect rect) =|
|
||||
AppletAreaSizeChanged(i32 wm_id, Gfx::IntSize size) =|
|
||||
}
|
12
Userland/Services/WindowServer/WindowManagerServer.ipc
Normal file
12
Userland/Services/WindowServer/WindowManagerServer.ipc
Normal file
|
@ -0,0 +1,12 @@
|
|||
endpoint WindowManagerServer = 1871
|
||||
{
|
||||
SetEventMask(u32 event_mask) => ()
|
||||
SetManagerWindow(i32 window_id) => ()
|
||||
|
||||
SetActiveWindow(i32 client_id, i32 window_id) =|
|
||||
SetWindowMinimized(i32 client_id, i32 window_id, bool minimized) =|
|
||||
StartWindowResize(i32 client_id, i32 window_id) =|
|
||||
PopupWindowMenu(i32 client_id, i32 window_id, Gfx::IntPoint screen_position) =|
|
||||
SetWindowTaskbarRect(i32 client_id, i32 window_id, Gfx::IntRect rect) =|
|
||||
SetAppletAreaPosition(Gfx::IntPoint position) => ()
|
||||
}
|
|
@ -78,13 +78,6 @@ endpoint WindowServer = 2
|
|||
|
||||
SetWindowBackingStore(i32 window_id, i32 bpp, i32 pitch, IPC::File anon_file, i32 serial, bool has_alpha_channel, Gfx::IntSize size, bool flush_immediately) => ()
|
||||
|
||||
WM_SetActiveWindow(i32 client_id, i32 window_id) =|
|
||||
WM_SetWindowMinimized(i32 client_id, i32 window_id, bool minimized) =|
|
||||
WM_StartWindowResize(i32 client_id, i32 window_id) =|
|
||||
WM_PopupWindowMenu(i32 client_id, i32 window_id, Gfx::IntPoint screen_position) =|
|
||||
WM_SetWindowTaskbarRect(i32 client_id, i32 window_id, Gfx::IntRect rect) =|
|
||||
WM_SetAppletAreaPosition(Gfx::IntPoint position) => ()
|
||||
|
||||
SetWindowHasAlphaChannel(i32 window_id, bool has_alpha_channel) => ()
|
||||
MoveWindowToFront(i32 window_id) => ()
|
||||
SetFullscreen(i32 window_id, bool fullscreen) => ()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue