mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	WindowServer: Add WSClientConnection class to manage an individual client.
This makes both object lifetimes and object ID's a lot easier to understand.
This commit is contained in:
		
							parent
							
								
									f529b845ec
								
							
						
					
					
						commit
						aa7947c889
					
				
					 11 changed files with 452 additions and 383 deletions
				
			
		|  | @ -66,6 +66,7 @@ WINDOWSERVER_OBJS = \ | |||
|     ../WindowServer/WSMenuBar.o \
 | ||||
|     ../WindowServer/WSMenu.o \
 | ||||
|     ../WindowServer/WSMenuItem.o \
 | ||||
|     ../WindowServer/WSClientConnection.o \
 | ||||
|     ../WindowServer/main.o | ||||
| 
 | ||||
| AK_OBJS = \
 | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ void Process::destroy_all_windows() | |||
| { | ||||
|     if (!WSMessageLoop::the().running()) | ||||
|         return; | ||||
|     dbgprintf("Sending death notification for client_id %d\n", gui_client_id()); | ||||
|     WSMessageLoop::the().notify_client_died(gui_client_id()); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										316
									
								
								WindowServer/WSClientConnection.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								WindowServer/WSClientConnection.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,316 @@ | |||
| #include <WindowServer/WSClientConnection.h> | ||||
| #include <WindowServer/WSMessageLoop.h> | ||||
| #include <WindowServer/WSMenuBar.h> | ||||
| #include <WindowServer/WSMenu.h> | ||||
| #include <WindowServer/WSMenuItem.h> | ||||
| #include <WindowServer/WSWindow.h> | ||||
| #include <WindowServer/WSWindowManager.h> | ||||
| #include <Kernel/GUITypes.h> | ||||
| #include <Kernel/MemoryManager.h> | ||||
| 
 | ||||
| Lockable<HashMap<int, WSClientConnection*>>* s_connections; | ||||
| 
 | ||||
| 
 | ||||
| WSClientConnection* WSClientConnection::from_client_id(int client_id) | ||||
| { | ||||
|     if (!s_connections) | ||||
|         return nullptr; | ||||
|     LOCKER(s_connections->lock()); | ||||
|     auto it = s_connections->resource().find(client_id); | ||||
|     if (it == s_connections->resource().end()) | ||||
|         return nullptr; | ||||
|     return (*it).value; | ||||
| } | ||||
| 
 | ||||
| WSClientConnection* WSClientConnection::ensure_for_client_id(int client_id) | ||||
| { | ||||
|     if (auto* client = from_client_id(client_id)) | ||||
|         return client; | ||||
|     return new WSClientConnection(client_id); | ||||
| } | ||||
| 
 | ||||
| WSClientConnection::WSClientConnection(int client_id) | ||||
|     : m_client_id(client_id) | ||||
| { | ||||
|     if (!s_connections) | ||||
|         s_connections = new Lockable<HashMap<int, WSClientConnection*>>; | ||||
|     LOCKER(s_connections->lock()); | ||||
|     s_connections->resource().set(client_id, this); | ||||
| 
 | ||||
|     m_process = ((Process*)m_client_id)->make_weak_ptr(); | ||||
| } | ||||
| 
 | ||||
| WSClientConnection::~WSClientConnection() | ||||
| { | ||||
|     LOCKER(s_connections->lock()); | ||||
|     s_connections->resource().remove(m_client_id); | ||||
| } | ||||
| 
 | ||||
| void WSClientConnection::on_message(WSMessage& message) | ||||
| { | ||||
|     if (message.is_client_request()) { | ||||
|         handle_client_request(static_cast<WSAPIClientRequest&>(message)); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (message.type() == WSMessage::WM_ClientDisconnected) { | ||||
|         int client_id = static_cast<WSClientDisconnectedNotification&>(message).client_id(); | ||||
|         dbgprintf("WSClientConnection: Client disconnected: %d\n", client_id); | ||||
|         delete this; | ||||
|         return; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void WSClientConnection::handle_client_request(WSAPIClientRequest& request) | ||||
| { | ||||
|     switch (request.type()) { | ||||
|     case WSMessage::APICreateMenubarRequest: { | ||||
|         int menubar_id = m_next_menubar_id++; | ||||
|         auto menubar = make<WSMenuBar>(menubar_id, *WSMessageLoop::process_from_client_id(request.client_id())); | ||||
|         m_menubars.set(menubar_id, move(menubar)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidCreateMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDestroyMenubarRequest: { | ||||
|         int menubar_id = static_cast<WSAPIDestroyMenubarRequest&>(request).menubar_id(); | ||||
|         auto it = m_menubars.find(menubar_id); | ||||
|         if (it == m_menubars.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|             // FIXME: Send an error.
 | ||||
|             return; | ||||
|         } | ||||
|         auto& menubar = *(*it).value; | ||||
|         WSWindowManager::the().close_menubar(menubar); | ||||
|         m_menubars.remove(it); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidDestroyMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APICreateMenuRequest: { | ||||
|         int menu_id = m_next_menu_id++; | ||||
|         auto menu = make<WSMenu>(*WSMessageLoop::process_from_client_id(request.client_id()), menu_id, static_cast<WSAPICreateMenuRequest&>(request).text()); | ||||
|         m_menus.set(menu_id, move(menu)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidCreateMenu; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDestroyMenuRequest: { | ||||
|         int menu_id = static_cast<WSAPIDestroyMenuRequest&>(request).menu_id(); | ||||
|         auto it = m_menus.find(menu_id); | ||||
|         if (it == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|             // FIXME: Send an error.
 | ||||
|             return; | ||||
|         } | ||||
|         auto& menu = *(*it).value; | ||||
|         WSWindowManager::the().close_menu(menu); | ||||
|         m_menus.remove(it); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidDestroyMenu; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APISetApplicationMenubarRequest: { | ||||
|         int menubar_id = static_cast<WSAPISetApplicationMenubarRequest&>(request).menubar_id(); | ||||
|         auto it = m_menubars.find(menubar_id); | ||||
|         if (it == m_menubars.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|             // FIXME: Send an error.
 | ||||
|             return; | ||||
|         } | ||||
|         auto& menubar = *(*it).value; | ||||
|         m_app_menubar = menubar.make_weak_ptr(); | ||||
|         WSWindowManager::the().notify_client_changed_app_menubar(*this); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidSetApplicationMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIAddMenuToMenubarRequest: { | ||||
|         int menubar_id = static_cast<WSAPIAddMenuToMenubarRequest&>(request).menubar_id(); | ||||
|         int menu_id = static_cast<WSAPIAddMenuToMenubarRequest&>(request).menu_id(); | ||||
|         auto it = m_menubars.find(menubar_id); | ||||
|         auto jt = m_menus.find(menu_id); | ||||
|         if (it == m_menubars.end() || jt == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& menubar = *(*it).value; | ||||
|         auto& menu = *(*jt).value; | ||||
|         menubar.add_menu(&menu); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidAddMenuToMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIAddMenuItemRequest: { | ||||
|         int menu_id = static_cast<WSAPIAddMenuItemRequest&>(request).menu_id(); | ||||
|         unsigned identifier = static_cast<WSAPIAddMenuItemRequest&>(request).identifier(); | ||||
|         String text = static_cast<WSAPIAddMenuItemRequest&>(request).text(); | ||||
|         auto it = m_menus.find(menu_id); | ||||
|         if (it == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& menu = *(*it).value; | ||||
|         menu.add_item(make<WSMenuItem>(identifier, move(text))); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidAddMenuItem; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         response.menu.identifier = identifier; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIAddMenuSeparatorRequest: { | ||||
|         int menu_id = static_cast<WSAPIAddMenuSeparatorRequest&>(request).menu_id(); | ||||
|         auto it = m_menus.find(menu_id); | ||||
|         if (it == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& menu = *(*it).value; | ||||
|         menu.add_item(make<WSMenuItem>(WSMenuItem::Separator)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidAddMenuSeparator; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APISetWindowTitleRequest: { | ||||
|         int window_id = static_cast<WSAPISetWindowTitleRequest&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         window.set_title(static_cast<WSAPISetWindowTitleRequest&>(request).title()); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIGetWindowTitleRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowTitleRequest&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidGetWindowTitle; | ||||
|         response.window_id = window.window_id(); | ||||
|         ASSERT(window.title().length() < sizeof(response.text)); | ||||
|         strcpy(response.text, window.title().characters()); | ||||
|         response.text_length = window.title().length(); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APISetWindowRectRequest: { | ||||
|         int window_id = static_cast<WSAPISetWindowRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         window.set_rect(static_cast<WSAPISetWindowRectRequest&>(request).rect()); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIGetWindowRectRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidGetWindowRect; | ||||
|         response.window_id = window.window_id(); | ||||
|         response.window.rect = window.rect(); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APICreateWindowRequest: { | ||||
|         int window_id = m_next_window_id++; | ||||
|         auto window = make<WSWindow>(request.client_id(), window_id); | ||||
|         window->set_title(static_cast<WSAPICreateWindowRequest&>(request).title()); | ||||
|         window->set_rect(static_cast<WSAPICreateWindowRequest&>(request).rect()); | ||||
|         m_windows.set(window_id, move(window)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidCreateWindow; | ||||
|         response.window_id = window_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDestroyWindowRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         WSWindowManager::the().invalidate(window); | ||||
|         m_windows.remove(it); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIInvalidateRectRequest: { | ||||
|         int window_id = static_cast<WSAPIInvalidateRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::Paint; | ||||
|         response.window_id = window_id; | ||||
|         response.paint.rect = static_cast<WSAPIInvalidateRectRequest&>(request).rect(); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDidFinishPaintingNotification: { | ||||
|         int window_id = static_cast<WSAPIDidFinishPaintingNotification&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         WSWindowManager::the().invalidate(window, static_cast<WSAPIDidFinishPaintingNotification&>(request).rect()); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIGetWindowBackingStoreRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowBackingStoreRequest&>(request).window_id(); | ||||
|         auto it = m_windows.find(window_id); | ||||
|         if (it == m_windows.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         auto* backing_store = window.backing(); | ||||
| 
 | ||||
|         // FIXME: It shouldn't work this way!
 | ||||
|         backing_store->retain(); | ||||
| 
 | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidGetWindowBackingStore; | ||||
|         response.window_id = window_id; | ||||
|         response.backing.backing_store_id = backing_store; | ||||
|         response.backing.bpp = sizeof(RGBA32); | ||||
|         response.backing.pitch = backing_store->pitch(); | ||||
|         response.backing.size = backing_store->size(); | ||||
|         response.backing.pixels = reinterpret_cast<RGBA32*>(backing_store->client_region()->laddr().as_ptr()); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIReleaseWindowBackingStoreRequest: { | ||||
|         int backing_store_id = static_cast<WSAPIReleaseWindowBackingStoreRequest&>(request).backing_store_id(); | ||||
|         // FIXME: It shouldn't work this way!
 | ||||
|         auto* backing_store = (GraphicsBitmap*)backing_store_id; | ||||
|         backing_store->release(); | ||||
|         break; | ||||
|     } | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										48
									
								
								WindowServer/WSClientConnection.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								WindowServer/WSClientConnection.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <AK/HashMap.h> | ||||
| #include <AK/OwnPtr.h> | ||||
| #include <AK/WeakPtr.h> | ||||
| #include <WindowServer/WSMessageReceiver.h> | ||||
| 
 | ||||
| class WSWindow; | ||||
| class WSMenu; | ||||
| class WSMenuBar; | ||||
| class WSAPIClientRequest; | ||||
| 
 | ||||
| // FIXME: Remove.
 | ||||
| class Process; | ||||
| 
 | ||||
| class WSClientConnection final : public WSMessageReceiver { | ||||
| public: | ||||
|     explicit WSClientConnection(int client_id); | ||||
|     virtual ~WSClientConnection() override; | ||||
| 
 | ||||
|     static WSClientConnection* from_client_id(int client_id); | ||||
|     static WSClientConnection* ensure_for_client_id(int client_id); | ||||
| 
 | ||||
|     // FIXME: Remove.
 | ||||
|     Process* process() { return m_process.ptr(); } | ||||
| 
 | ||||
|     int client_id() const { return m_client_id; } | ||||
|     WSMenuBar* app_menubar() { return m_app_menubar.ptr(); } | ||||
| 
 | ||||
| private: | ||||
|     virtual void on_message(WSMessage&) override; | ||||
| 
 | ||||
|     void handle_client_request(WSAPIClientRequest&); | ||||
| 
 | ||||
|     int m_client_id { 0 }; | ||||
| 
 | ||||
|     HashMap<int, OwnPtr<WSWindow>> m_windows; | ||||
|     HashMap<int, OwnPtr<WSMenuBar>> m_menubars; | ||||
|     HashMap<int, OwnPtr<WSMenu>> m_menus; | ||||
|     WeakPtr<WSMenuBar> m_app_menubar; | ||||
| 
 | ||||
|     int m_next_menubar_id { 10000 }; | ||||
|     int m_next_menu_id { 20000 }; | ||||
|     int m_next_window_id { 1982 }; | ||||
| 
 | ||||
|     // FIXME: Remove.
 | ||||
|     WeakPtr<Process> m_process; | ||||
| }; | ||||
|  | @ -12,7 +12,7 @@ class WSWindow; | |||
| class Font; | ||||
| class Process; | ||||
| 
 | ||||
| class WSMenu { | ||||
| class WSMenu : public Weakable<WSMenu> { | ||||
| public: | ||||
|     WSMenu(Process&, int menu_id, String&& name); | ||||
|     ~WSMenu(); | ||||
|  |  | |||
|  | @ -2,11 +2,12 @@ | |||
| 
 | ||||
| #include "WSMenu.h" | ||||
| #include <AK/Vector.h> | ||||
| #include <AK/Weakable.h> | ||||
| #include <AK/WeakPtr.h> | ||||
| 
 | ||||
| class Process; | ||||
| 
 | ||||
| class WSMenuBar { | ||||
| class WSMenuBar : public Weakable<WSMenuBar> { | ||||
| public: | ||||
|     WSMenuBar(int menubar_id, Process&); | ||||
|     ~WSMenuBar(); | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| #include "WSMessageReceiver.h" | ||||
| #include "WSWindowManager.h" | ||||
| #include "WSScreen.h" | ||||
| #include <WindowServer/WSClientConnection.h> | ||||
| #include "PS2MouseDevice.h" | ||||
| #include <Kernel/Keyboard.h> | ||||
| #include <AK/Bitmap.h> | ||||
|  | @ -267,7 +268,10 @@ void WSMessageLoop::drain_keyboard() | |||
| void WSMessageLoop::notify_client_died(int client_id) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     post_message(&WSWindowManager::the(), make<WSClientDisconnectedNotification>(client_id)); | ||||
|     auto* client = WSClientConnection::from_client_id(client_id); | ||||
|     if (!client) | ||||
|         return; | ||||
|     post_message(client, make<WSClientDisconnectedNotification>(client_id)); | ||||
| } | ||||
| 
 | ||||
| ssize_t WSMessageLoop::on_receive_from_client(int client_id, const byte* data, size_t size) | ||||
|  | @ -277,67 +281,70 @@ ssize_t WSMessageLoop::on_receive_from_client(int client_id, const byte* data, s | |||
|         Scheduler::yield(); | ||||
| 
 | ||||
|     LOCKER(m_lock); | ||||
| 
 | ||||
|     WSClientConnection* client = WSClientConnection::ensure_for_client_id(client_id); | ||||
| 
 | ||||
|     ASSERT(size == sizeof(GUI_ClientMessage)); | ||||
|     auto& message = *reinterpret_cast<const GUI_ClientMessage*>(data); | ||||
|     switch (message.type) { | ||||
|     case GUI_ClientMessage::Type::CreateMenubar: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPICreateMenubarRequest>(client_id)); | ||||
|         post_message(client, make<WSAPICreateMenubarRequest>(client_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::DestroyMenubar: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIDestroyMenubarRequest>(client_id, message.menu.menubar_id)); | ||||
|         post_message(client, make<WSAPIDestroyMenubarRequest>(client_id, message.menu.menubar_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::SetApplicationMenubar: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPISetApplicationMenubarRequest>(client_id, message.menu.menubar_id)); | ||||
|         post_message(client, make<WSAPISetApplicationMenubarRequest>(client_id, message.menu.menubar_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::AddMenuToMenubar: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIAddMenuToMenubarRequest>(client_id, message.menu.menubar_id, message.menu.menu_id)); | ||||
|         post_message(client, make<WSAPIAddMenuToMenubarRequest>(client_id, message.menu.menubar_id, message.menu.menu_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::CreateMenu: | ||||
|         ASSERT(message.text_length < sizeof(message.text)); | ||||
|         post_message(&WSWindowManager::the(), make<WSAPICreateMenuRequest>(client_id, String(message.text, message.text_length))); | ||||
|         post_message(client, make<WSAPICreateMenuRequest>(client_id, String(message.text, message.text_length))); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::DestroyMenu: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIDestroyMenuRequest>(client_id, message.menu.menu_id)); | ||||
|         post_message(client, make<WSAPIDestroyMenuRequest>(client_id, message.menu.menu_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::AddMenuItem: | ||||
|         ASSERT(message.text_length < sizeof(message.text)); | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length))); | ||||
|         post_message(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length))); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::CreateWindow: | ||||
|         ASSERT(message.text_length < sizeof(message.text)); | ||||
|         post_message(&WSWindowManager::the(), make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length))); | ||||
|         post_message(client, make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length))); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::DestroyWindow: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIDestroyWindowRequest>(client_id, message.window_id)); | ||||
|         post_message(client, make<WSAPIDestroyWindowRequest>(client_id, message.window_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::SetWindowTitle: | ||||
|         ASSERT(message.text_length < sizeof(message.text)); | ||||
|         post_message(&WSWindowManager::the(), make<WSAPISetWindowTitleRequest>(client_id, message.window_id, String(message.text, message.text_length))); | ||||
|         post_message(client, make<WSAPISetWindowTitleRequest>(client_id, message.window_id, String(message.text, message.text_length))); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::GetWindowTitle: | ||||
|         ASSERT(message.text_length < sizeof(message.text)); | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIGetWindowTitleRequest>(client_id, message.window_id)); | ||||
|         post_message(client, make<WSAPIGetWindowTitleRequest>(client_id, message.window_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::SetWindowRect: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPISetWindowRectRequest>(client_id, message.window_id, message.window.rect)); | ||||
|         post_message(client, make<WSAPISetWindowRectRequest>(client_id, message.window_id, message.window.rect)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::GetWindowRect: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIGetWindowRectRequest>(client_id, message.window_id)); | ||||
|         post_message(client, make<WSAPIGetWindowRectRequest>(client_id, message.window_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::InvalidateRect: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIInvalidateRectRequest>(client_id, message.window_id, message.window.rect)); | ||||
|         post_message(client, make<WSAPIInvalidateRectRequest>(client_id, message.window_id, message.window.rect)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::DidFinishPainting: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, message.window.rect)); | ||||
|         post_message(client, make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, message.window.rect)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::GetWindowBackingStore: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIGetWindowBackingStoreRequest>(client_id, message.window_id)); | ||||
|         post_message(client, make<WSAPIGetWindowBackingStoreRequest>(client_id, message.window_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::ReleaseWindowBackingStore: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPIReleaseWindowBackingStoreRequest>(client_id, (int)message.backing.backing_store_id)); | ||||
|         post_message(client, make<WSAPIReleaseWindowBackingStoreRequest>(client_id, (int)message.backing.backing_store_id)); | ||||
|         break; | ||||
|     case GUI_ClientMessage::Type::SetGlobalCursorTracking: | ||||
|         post_message(&WSWindowManager::the(), make<WSAPISetGlobalCursorTrackingRequest>(client_id, message.value)); | ||||
|         post_message(client, make<WSAPISetGlobalCursorTrackingRequest>(client_id, message.value)); | ||||
|         break; | ||||
|     } | ||||
|     server_process().request_wakeup(); | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| #include "WSMessage.h" | ||||
| #include "WSMessageLoop.h" | ||||
| #include "Process.h" | ||||
| #include <WindowServer/WSClientConnection.h> | ||||
| 
 | ||||
| WSWindow::WSWindow(WSMenu& menu) | ||||
|     : m_lock("WSWindow (menu)") | ||||
|  | @ -12,12 +13,11 @@ WSWindow::WSWindow(WSMenu& menu) | |||
|     WSWindowManager::the().add_window(*this); | ||||
| } | ||||
| 
 | ||||
| WSWindow::WSWindow(Process& process, int window_id) | ||||
| WSWindow::WSWindow(int client_id, int window_id) | ||||
|     : m_lock("WSWindow (normal)") | ||||
|     , m_client_id(client_id) | ||||
|     , m_type(WSWindowType::Normal) | ||||
|     , m_process(&process) | ||||
|     , m_window_id(window_id) | ||||
|     , m_pid(process.pid()) | ||||
| { | ||||
|     WSWindowManager::the().add_window(*this); | ||||
| } | ||||
|  | @ -44,15 +44,21 @@ void WSWindow::set_rect(const Rect& rect) | |||
|     Rect old_rect; | ||||
|     { | ||||
|         WSWindowLocker locker(*this); | ||||
|         if (!m_process && !m_menu) | ||||
| 
 | ||||
|         Process* process = nullptr; | ||||
|         auto* client = WSClientConnection::from_client_id(m_client_id); | ||||
|         if (client) | ||||
|             process = client->process(); | ||||
| 
 | ||||
|         if (!process && !m_menu) | ||||
|             return; | ||||
|         if (m_rect == rect) | ||||
|             return; | ||||
|         old_rect = m_rect; | ||||
|         m_rect = rect; | ||||
|         if (!m_backing || old_rect.size() != rect.size()) { | ||||
|             if (m_process) | ||||
|                 m_backing = GraphicsBitmap::create(*m_process, m_rect.size()); | ||||
|             if (process) | ||||
|                 m_backing = GraphicsBitmap::create(*process, m_rect.size()); | ||||
|             if (m_menu) | ||||
|                 m_backing = GraphicsBitmap::create_kernel_only(m_rect.size()); | ||||
|         } | ||||
|  | @ -135,17 +141,13 @@ void WSWindow::on_message(WSMessage& message) | |||
| 
 | ||||
|     { | ||||
|         WSWindowLocker window_locker(*this); | ||||
|         if (!m_process) | ||||
|             return; | ||||
|         LOCKER(m_process->gui_events_lock()); | ||||
|         m_process->gui_events().append(move(gui_event)); | ||||
|         if (auto* client = WSClientConnection::from_client_id(m_client_id)) { | ||||
|             if (auto* process = client->process()) { | ||||
|                 LOCKER(process->gui_events_lock()); | ||||
|                 process->gui_events().append(move(gui_event)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void WSWindow::notify_process_died(Badge<Process>) | ||||
| { | ||||
|     WSWindowLocker locker(*this); | ||||
|     m_process = nullptr; | ||||
| } | ||||
| 
 | ||||
| void WSWindow::set_global_cursor_tracking_enabled(bool enabled) | ||||
|  |  | |||
|  | @ -6,21 +6,19 @@ | |||
| #include <AK/InlineLinkedList.h> | ||||
| #include <AK/Lock.h> | ||||
| #include <AK/Badge.h> | ||||
| #include <Kernel/Process.h> | ||||
| #include "WSMessageReceiver.h" | ||||
| #include <WindowServer/WSWindowType.h> | ||||
| 
 | ||||
| class Process; | ||||
| class WSMenu; | ||||
| 
 | ||||
| class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> { | ||||
|     friend class WSWindowLocker; | ||||
| public: | ||||
|     WSWindow(Process&, int window_id); | ||||
|     WSWindow(int client_id, int window_id); | ||||
|     explicit WSWindow(WSMenu&); | ||||
|     virtual ~WSWindow() override; | ||||
| 
 | ||||
|     const Process* process() const { return m_process; } | ||||
|     int client_id() const { return m_client_id; } | ||||
| 
 | ||||
|     WSWindowType type() const { return m_type; } | ||||
|     int window_id() const { return m_window_id; } | ||||
|  | @ -59,13 +57,9 @@ public: | |||
| 
 | ||||
|     GraphicsBitmap* backing() { return m_backing.ptr(); } | ||||
| 
 | ||||
|     pid_t pid() const { return m_pid; } | ||||
| 
 | ||||
|     void set_global_cursor_tracking_enabled(bool); | ||||
|     bool global_cursor_tracking() const { return m_global_cursor_tracking_enabled; } | ||||
| 
 | ||||
|     void notify_process_died(Badge<Process>); | ||||
| 
 | ||||
|     // For InlineLinkedList.
 | ||||
|     // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
 | ||||
|     WSWindow* m_next { nullptr }; | ||||
|  | @ -73,6 +67,7 @@ public: | |||
| 
 | ||||
| private: | ||||
|     Lock m_lock; | ||||
|     int m_client_id { 0 }; | ||||
|     String m_title; | ||||
|     Rect m_rect; | ||||
|     WSWindowType m_type { WSWindowType::Normal }; | ||||
|  | @ -83,9 +78,7 @@ private: | |||
|     WSMenu* m_menu { nullptr }; | ||||
| 
 | ||||
|     RetainPtr<GraphicsBitmap> m_backing; | ||||
|     Process* m_process { nullptr }; | ||||
|     int m_window_id { -1 }; | ||||
|     pid_t m_pid { -1 }; | ||||
| }; | ||||
| 
 | ||||
| class WSWindowLocker { | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "WSMenu.h" | ||||
| #include "WSMenuBar.h" | ||||
| #include "WSMenuItem.h" | ||||
| #include <WindowServer/WSClientConnection.h> | ||||
| #include <Kernel/RTC.h> | ||||
| 
 | ||||
| //#define DEBUG_COUNTERS
 | ||||
|  | @ -239,7 +240,10 @@ int WSWindowManager::menubar_menu_margin() const | |||
| void WSWindowManager::set_current_menubar(WSMenuBar* menubar) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     m_current_menubar = menubar; | ||||
|     if (menubar) | ||||
|         m_current_menubar = menubar->make_weak_ptr(); | ||||
|     else | ||||
|         m_current_menubar = nullptr; | ||||
|     dbgprintf("[WM] Current menubar is now %p\n", menubar); | ||||
|     Point next_menu_location { menubar_menu_margin() / 2, 3 }; | ||||
|     for_each_active_menubar_menu([&] (WSMenu& menu) { | ||||
|  | @ -395,10 +399,10 @@ void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, WSMouseEvent& event) | |||
| { | ||||
|     bool is_hover_with_any_menu_open = event.type() == WSMouseEvent::MouseMove && m_current_menu; | ||||
|     bool is_mousedown_with_left_button = event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left; | ||||
|     bool should_open_menu = &menu != m_current_menu && (is_hover_with_any_menu_open || is_mousedown_with_left_button); | ||||
|     bool should_open_menu = &menu != current_menu() && (is_hover_with_any_menu_open || is_mousedown_with_left_button); | ||||
| 
 | ||||
|     if (should_open_menu) { | ||||
|         if (m_current_menu == &menu) | ||||
|         if (current_menu() == &menu) | ||||
|             return; | ||||
|         close_current_menu(); | ||||
|         if (!menu.is_empty()) { | ||||
|  | @ -406,7 +410,7 @@ void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, WSMouseEvent& event) | |||
|             menu_window.move_to({ menu.rect_in_menubar().x(), menu.rect_in_menubar().bottom() }); | ||||
|             menu_window.set_visible(true); | ||||
|         } | ||||
|         m_current_menu = &menu; | ||||
|         m_current_menu = menu.make_weak_ptr(); | ||||
|         return; | ||||
|     } | ||||
|     if (event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left) { | ||||
|  | @ -422,7 +426,7 @@ void WSWindowManager::close_current_menu() | |||
|     m_current_menu = nullptr; | ||||
| } | ||||
| 
 | ||||
| void WSWindowManager::handle_menubar_mouse_event(WSMenuBar&, WSMouseEvent& event) | ||||
| void WSWindowManager::handle_menubar_mouse_event(WSMouseEvent& event) | ||||
| { | ||||
|     for_each_active_menubar_menu([&] (WSMenu& menu) { | ||||
|         if (menu.rect_in_menubar().contains(event.position())) { | ||||
|  | @ -499,7 +503,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event) | |||
|     } | ||||
| 
 | ||||
|     if (menubar_rect().contains(event.position())) { | ||||
|         handle_menubar_mouse_event(*m_current_menubar, event); | ||||
|         handle_menubar_mouse_event(event); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -684,7 +688,7 @@ void WSWindowManager::draw_menubar() | |||
|     m_back_painter->draw_line({ 0, menubar_rect().bottom() }, { menubar_rect().right(), menubar_rect().bottom() }, Color::White); | ||||
|     for_each_active_menubar_menu([&] (WSMenu& menu) { | ||||
|         Color text_color = Color::Black; | ||||
|         if (&menu == m_current_menu) { | ||||
|         if (&menu == current_menu()) { | ||||
|             m_back_painter->fill_rect(menu.rect_in_menubar(), menu_selection_color()); | ||||
|             text_color = Color::White; | ||||
|         } | ||||
|  | @ -733,284 +737,6 @@ void WSWindowManager::on_message(WSMessage& message) | |||
|         compose(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (message.is_client_request()) { | ||||
|         handle_client_request(static_cast<WSAPIClientRequest&>(message)); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (message.type() == WSMessage::WM_ClientDisconnected) { | ||||
|         int client_id = static_cast<WSClientDisconnectedNotification&>(message).client_id(); | ||||
|         dbgprintf("[WM] Client disconnected: %d\n", client_id); | ||||
| 
 | ||||
|         destroy_all_menus(*WSMessageLoop::process_from_client_id(client_id)); | ||||
|         Vector<int> windows_belonging_to_client; | ||||
|         for (auto& it : m_windows_by_id) { | ||||
|             if (it.value->process()->gui_client_id() == client_id) | ||||
|                 windows_belonging_to_client.append(it.value->window_id()); | ||||
|         } | ||||
|         for (int window_id : windows_belonging_to_client) { | ||||
|             m_windows_by_id.remove(window_id); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void WSWindowManager::handle_client_request(WSAPIClientRequest& request) | ||||
| { | ||||
|     switch (request.type()) { | ||||
|     case WSMessage::APICreateMenubarRequest: { | ||||
|         int menubar_id = m_next_menubar_id++; | ||||
|         auto menubar = make<WSMenuBar>(menubar_id, *WSMessageLoop::process_from_client_id(request.client_id())); | ||||
|         m_menubars.set(menubar_id, move(menubar)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidCreateMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDestroyMenubarRequest: { | ||||
|         int menubar_id = static_cast<WSAPIDestroyMenubarRequest&>(request).menubar_id(); | ||||
|         auto it = m_menubars.find(menubar_id); | ||||
|         if (it == m_menubars.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|             // FIXME: Send an error.
 | ||||
|             return; | ||||
|         } | ||||
|         auto& menubar = *(*it).value; | ||||
|         if (&menubar == m_current_menubar) | ||||
|             set_current_menubar(nullptr); | ||||
|         m_menubars.remove(it); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidDestroyMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APICreateMenuRequest: { | ||||
|         int menu_id = m_next_menu_id++; | ||||
|         auto menu = make<WSMenu>(*WSMessageLoop::process_from_client_id(request.client_id()), menu_id, static_cast<WSAPICreateMenuRequest&>(request).text()); | ||||
|         m_menus.set(menu_id, move(menu)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidCreateMenu; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDestroyMenuRequest: { | ||||
|         int menu_id = static_cast<WSAPIDestroyMenuRequest&>(request).menu_id(); | ||||
|         auto it = m_menus.find(menu_id); | ||||
|         if (it == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|             // FIXME: Send an error.
 | ||||
|             return; | ||||
|         } | ||||
|         auto& menu = *(*it).value; | ||||
|         close_menu(menu); | ||||
|         m_menus.remove(it); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidDestroyMenu; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APISetApplicationMenubarRequest: { | ||||
|         int menubar_id = static_cast<WSAPISetApplicationMenubarRequest&>(request).menubar_id(); | ||||
|         auto it = m_menubars.find(menubar_id); | ||||
|         if (it == m_menubars.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|             // FIXME: Send an error.
 | ||||
|             return; | ||||
|         } | ||||
|         auto& menubar = *(*it).value; | ||||
|         m_app_menubars.set(request.client_id(), &menubar); | ||||
|         if (active_client_id() == request.client_id()) | ||||
|             set_current_menubar(&menubar); | ||||
|         invalidate(); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidSetApplicationMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIAddMenuToMenubarRequest: { | ||||
|         int menubar_id = static_cast<WSAPIAddMenuToMenubarRequest&>(request).menubar_id(); | ||||
|         int menu_id = static_cast<WSAPIAddMenuToMenubarRequest&>(request).menu_id(); | ||||
|         auto it = m_menubars.find(menubar_id); | ||||
|         auto jt = m_menus.find(menu_id); | ||||
|         if (it == m_menubars.end() || jt == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& menubar = *(*it).value; | ||||
|         auto& menu = *(*jt).value; | ||||
|         menubar.add_menu(&menu); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidAddMenuToMenubar; | ||||
|         response.menu.menubar_id = menubar_id; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIAddMenuItemRequest: { | ||||
|         int menu_id = static_cast<WSAPIAddMenuItemRequest&>(request).menu_id(); | ||||
|         unsigned identifier = static_cast<WSAPIAddMenuItemRequest&>(request).identifier(); | ||||
|         String text = static_cast<WSAPIAddMenuItemRequest&>(request).text(); | ||||
|         auto it = m_menus.find(menu_id); | ||||
|         if (it == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& menu = *(*it).value; | ||||
|         menu.add_item(make<WSMenuItem>(identifier, move(text))); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidAddMenuItem; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         response.menu.identifier = identifier; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIAddMenuSeparatorRequest: { | ||||
|         int menu_id = static_cast<WSAPIAddMenuSeparatorRequest&>(request).menu_id(); | ||||
|         auto it = m_menus.find(menu_id); | ||||
|         if (it == m_menus.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& menu = *(*it).value; | ||||
|         menu.add_item(make<WSMenuItem>(WSMenuItem::Separator)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidAddMenuSeparator; | ||||
|         response.menu.menu_id = menu_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APISetWindowTitleRequest: { | ||||
|         int window_id = static_cast<WSAPISetWindowTitleRequest&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         window.set_title(static_cast<WSAPISetWindowTitleRequest&>(request).title()); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIGetWindowTitleRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowTitleRequest&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidGetWindowTitle; | ||||
|         response.window_id = window.window_id(); | ||||
|         ASSERT(window.title().length() < sizeof(response.text)); | ||||
|         strcpy(response.text, window.title().characters()); | ||||
|         response.text_length = window.title().length(); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APISetWindowRectRequest: { | ||||
|         int window_id = static_cast<WSAPISetWindowRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         window.set_rect(static_cast<WSAPISetWindowRectRequest&>(request).rect()); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIGetWindowRectRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidGetWindowRect; | ||||
|         response.window_id = window.window_id(); | ||||
|         response.window.rect = window.rect(); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APICreateWindowRequest: { | ||||
|         int window_id = m_next_window_id++; | ||||
|         auto window = make<WSWindow>(*WSMessageLoop::process_from_client_id(request.client_id()), window_id); | ||||
|         window->set_title(static_cast<WSAPICreateWindowRequest&>(request).title()); | ||||
|         window->set_rect(static_cast<WSAPICreateWindowRequest&>(request).rect()); | ||||
|         m_windows_by_id.set(window_id, move(window)); | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidCreateWindow; | ||||
|         response.window_id = window_id; | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDestroyWindowRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         invalidate(window); | ||||
|         m_windows_by_id.remove(it); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIInvalidateRectRequest: { | ||||
|         int window_id = static_cast<WSAPIInvalidateRectRequest&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::Paint; | ||||
|         response.window_id = window_id; | ||||
|         response.paint.rect = static_cast<WSAPIInvalidateRectRequest&>(request).rect(); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIDidFinishPaintingNotification: { | ||||
|         int window_id = static_cast<WSAPIDidFinishPaintingNotification&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         invalidate(window, static_cast<WSAPIDidFinishPaintingNotification&>(request).rect()); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIGetWindowBackingStoreRequest: { | ||||
|         int window_id = static_cast<WSAPIGetWindowBackingStoreRequest&>(request).window_id(); | ||||
|         auto it = m_windows_by_id.find(window_id); | ||||
|         if (it == m_windows_by_id.end()) { | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|         auto& window = *(*it).value; | ||||
|         auto* backing_store = window.backing(); | ||||
| 
 | ||||
|         // FIXME: It shouldn't work this way!
 | ||||
|         backing_store->retain(); | ||||
| 
 | ||||
|         GUI_ServerMessage response; | ||||
|         response.type = GUI_ServerMessage::Type::DidGetWindowBackingStore; | ||||
|         response.window_id = window_id; | ||||
|         response.backing.backing_store_id = backing_store; | ||||
|         response.backing.bpp = sizeof(RGBA32); | ||||
|         response.backing.pitch = backing_store->pitch(); | ||||
|         response.backing.size = backing_store->size(); | ||||
|         response.backing.pixels = reinterpret_cast<RGBA32*>(backing_store->client_region()->laddr().as_ptr()); | ||||
|         WSMessageLoop::the().post_message_to_client(request.client_id(), response); | ||||
|         break; | ||||
|     } | ||||
|     case WSMessage::APIReleaseWindowBackingStoreRequest: { | ||||
|         int backing_store_id = static_cast<WSAPIReleaseWindowBackingStoreRequest&>(request).backing_store_id(); | ||||
|         // FIXME: It shouldn't work this way!
 | ||||
|         auto* backing_store = (GraphicsBitmap*)backing_store_id; | ||||
|         backing_store->release(); | ||||
|         break; | ||||
|     } | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void WSWindowManager::set_active_window(WSWindow* window) | ||||
|  | @ -1028,15 +754,10 @@ void WSWindowManager::set_active_window(WSWindow* window) | |||
|         WSMessageLoop::the().post_message(m_active_window.ptr(), make<WSMessage>(WSMessage::WindowActivated)); | ||||
|         invalidate(*m_active_window); | ||||
| 
 | ||||
|         ASSERT(window->process()); | ||||
|         auto it = m_app_menubars.find(window->process()->gui_client_id()); | ||||
|         if (it != m_app_menubars.end()) { | ||||
|             auto* menubar = (*it).value; | ||||
|             if (menubar != m_current_menubar) | ||||
|                 set_current_menubar(menubar); | ||||
|         } else { | ||||
|             set_current_menubar(nullptr); | ||||
|         } | ||||
|         int client_id = window->client_id(); | ||||
|         auto* client = WSClientConnection::from_client_id(client_id); | ||||
|         ASSERT(client); | ||||
|         set_current_menubar(client->app_menubar()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1119,44 +840,27 @@ void WSWindowManager::flush(const Rect& a_rect) | |||
| void WSWindowManager::close_menu(WSMenu& menu) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     if (m_current_menu == &menu) | ||||
|     if (current_menu() == &menu) | ||||
|         close_current_menu(); | ||||
| } | ||||
| 
 | ||||
| void WSWindowManager::close_menubar(WSMenuBar& menubar) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     if (current_menubar() == &menubar) | ||||
|         set_current_menubar(nullptr); | ||||
| } | ||||
| 
 | ||||
| int WSWindowManager::active_client_id() const | ||||
| { | ||||
|     if (m_active_window) | ||||
|         return m_active_window->process()->gui_client_id(); | ||||
|         return m_active_window->client_id(); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void WSWindowManager::destroy_all_menus(Process& process) | ||||
| void WSWindowManager::notify_client_changed_app_menubar(WSClientConnection& client) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     Vector<int> menu_ids; | ||||
|     bool should_close_current_menu = false; | ||||
|     for (auto& it : m_menus) { | ||||
|         if (it.value->process() == &process) | ||||
|             menu_ids.append(it.value->menu_id()); | ||||
|         if (m_current_menu == it.value.ptr()) | ||||
|             should_close_current_menu = true; | ||||
|     } | ||||
|     if (should_close_current_menu) | ||||
|         close_current_menu(); | ||||
|     for (int menu_id : menu_ids) | ||||
|         m_menus.remove(menu_id); | ||||
| 
 | ||||
|     Vector<int> menubar_ids; | ||||
|     bool should_close_current_menubar = false; | ||||
|     for (auto& it : m_menubars) { | ||||
|         if (it.value->process() == &process) | ||||
|             menubar_ids.append(it.value->menubar_id()); | ||||
|         if (m_current_menubar == it.value.ptr()) | ||||
|             should_close_current_menubar = true; | ||||
|     } | ||||
|     if (should_close_current_menubar) | ||||
|         set_current_menubar(nullptr); | ||||
|     for (int menubar_id : menubar_ids) | ||||
|         m_menubars.remove(menubar_id); | ||||
|     m_app_menubars.remove(process.gui_client_id()); | ||||
|     if (active_client_id() == client.client_id()) | ||||
|         set_current_menubar(client.app_menubar()); | ||||
|     invalidate(); | ||||
| } | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ class WSMenuBar; | |||
| class WSMouseEvent; | ||||
| class WSClientWantsToPaintMessage; | ||||
| class WSWindow; | ||||
| class WSClientConnection; | ||||
| class CharacterBitmap; | ||||
| class GraphicsBitmap; | ||||
| 
 | ||||
|  | @ -31,6 +32,7 @@ public: | |||
| 
 | ||||
|     void notify_title_changed(WSWindow&); | ||||
|     void notify_rect_changed(WSWindow&, const Rect& oldRect, const Rect& newRect); | ||||
|     void notify_client_changed_app_menubar(WSClientConnection&); | ||||
| 
 | ||||
|     WSWindow* active_window() { return m_active_window.ptr(); } | ||||
|     int active_client_id() const; | ||||
|  | @ -42,9 +44,9 @@ public: | |||
|     void draw_menubar(); | ||||
| 
 | ||||
|     Rect menubar_rect() const; | ||||
|     WSMenuBar* current_menubar() { return m_current_menubar; } | ||||
|     WSMenuBar* current_menubar() { return m_current_menubar.ptr(); } | ||||
|     void set_current_menubar(WSMenuBar*); | ||||
|     WSMenu* current_menu() { return m_current_menu; } | ||||
|     WSMenu* current_menu() { return m_current_menu.ptr(); } | ||||
|     void set_current_menu(WSMenu*); | ||||
| 
 | ||||
|     void invalidate(const WSWindow&); | ||||
|  | @ -57,6 +59,7 @@ public: | |||
|     const Font& font() const { return *m_font; } | ||||
| 
 | ||||
|     void close_menu(WSMenu&); | ||||
|     void close_menubar(WSMenuBar&); | ||||
|     Color menu_selection_color() const { return m_menu_selection_color; } | ||||
|     int menubar_menu_margin() const; | ||||
| 
 | ||||
|  | @ -70,7 +73,7 @@ private: | |||
| 
 | ||||
|     void process_mouse_event(WSMouseEvent&); | ||||
|     void handle_menu_mouse_event(WSMenu&, WSMouseEvent&); | ||||
|     void handle_menubar_mouse_event(WSMenuBar&, WSMouseEvent&); | ||||
|     void handle_menubar_mouse_event(WSMouseEvent&); | ||||
|     void handle_titlebar_mouse_event(WSWindow&, WSMouseEvent&); | ||||
|     void handle_close_button_mouse_event(WSWindow&, WSMouseEvent&); | ||||
|     void handle_client_request(WSAPIClientRequest&); | ||||
|  | @ -145,15 +148,8 @@ private: | |||
|     Lockable<bool> m_flash_flush; | ||||
|     bool m_buffers_are_flipped { false }; | ||||
| 
 | ||||
|     int m_next_menubar_id { 100 }; | ||||
|     int m_next_menu_id { 100 }; | ||||
|     int m_next_window_id { 1982 }; | ||||
| 
 | ||||
|     OwnPtr<WSMenu> m_system_menu; | ||||
|     Color m_menu_selection_color; | ||||
|     WSMenuBar* m_current_menubar { nullptr }; | ||||
|     WSMenu* m_current_menu { nullptr }; | ||||
|     HashMap<int, OwnPtr<WSMenuBar>> m_menubars; | ||||
|     HashMap<int, OwnPtr<WSMenu>> m_menus; | ||||
|     HashMap<int, WSMenuBar*> m_app_menubars; | ||||
|     WeakPtr<WSMenuBar> m_current_menubar; | ||||
|     WeakPtr<WSMenu> m_current_menu; | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling