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/WSMenuBar.o \
 | ||||||
|     ../WindowServer/WSMenu.o \
 |     ../WindowServer/WSMenu.o \
 | ||||||
|     ../WindowServer/WSMenuItem.o \
 |     ../WindowServer/WSMenuItem.o \
 | ||||||
|  |     ../WindowServer/WSClientConnection.o \
 | ||||||
|     ../WindowServer/main.o |     ../WindowServer/main.o | ||||||
| 
 | 
 | ||||||
| AK_OBJS = \
 | AK_OBJS = \
 | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ void Process::destroy_all_windows() | ||||||
| { | { | ||||||
|     if (!WSMessageLoop::the().running()) |     if (!WSMessageLoop::the().running()) | ||||||
|         return; |         return; | ||||||
|  |     dbgprintf("Sending death notification for client_id %d\n", gui_client_id()); | ||||||
|     WSMessageLoop::the().notify_client_died(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 Font; | ||||||
| class Process; | class Process; | ||||||
| 
 | 
 | ||||||
| class WSMenu { | class WSMenu : public Weakable<WSMenu> { | ||||||
| public: | public: | ||||||
|     WSMenu(Process&, int menu_id, String&& name); |     WSMenu(Process&, int menu_id, String&& name); | ||||||
|     ~WSMenu(); |     ~WSMenu(); | ||||||
|  |  | ||||||
|  | @ -2,11 +2,12 @@ | ||||||
| 
 | 
 | ||||||
| #include "WSMenu.h" | #include "WSMenu.h" | ||||||
| #include <AK/Vector.h> | #include <AK/Vector.h> | ||||||
|  | #include <AK/Weakable.h> | ||||||
| #include <AK/WeakPtr.h> | #include <AK/WeakPtr.h> | ||||||
| 
 | 
 | ||||||
| class Process; | class Process; | ||||||
| 
 | 
 | ||||||
| class WSMenuBar { | class WSMenuBar : public Weakable<WSMenuBar> { | ||||||
| public: | public: | ||||||
|     WSMenuBar(int menubar_id, Process&); |     WSMenuBar(int menubar_id, Process&); | ||||||
|     ~WSMenuBar(); |     ~WSMenuBar(); | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| #include "WSMessageReceiver.h" | #include "WSMessageReceiver.h" | ||||||
| #include "WSWindowManager.h" | #include "WSWindowManager.h" | ||||||
| #include "WSScreen.h" | #include "WSScreen.h" | ||||||
|  | #include <WindowServer/WSClientConnection.h> | ||||||
| #include "PS2MouseDevice.h" | #include "PS2MouseDevice.h" | ||||||
| #include <Kernel/Keyboard.h> | #include <Kernel/Keyboard.h> | ||||||
| #include <AK/Bitmap.h> | #include <AK/Bitmap.h> | ||||||
|  | @ -267,7 +268,10 @@ void WSMessageLoop::drain_keyboard() | ||||||
| void WSMessageLoop::notify_client_died(int client_id) | void WSMessageLoop::notify_client_died(int client_id) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     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) | 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(); |         Scheduler::yield(); | ||||||
| 
 | 
 | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|  | 
 | ||||||
|  |     WSClientConnection* client = WSClientConnection::ensure_for_client_id(client_id); | ||||||
|  | 
 | ||||||
|     ASSERT(size == sizeof(GUI_ClientMessage)); |     ASSERT(size == sizeof(GUI_ClientMessage)); | ||||||
|     auto& message = *reinterpret_cast<const GUI_ClientMessage*>(data); |     auto& message = *reinterpret_cast<const GUI_ClientMessage*>(data); | ||||||
|     switch (message.type) { |     switch (message.type) { | ||||||
|     case GUI_ClientMessage::Type::CreateMenubar: |     case GUI_ClientMessage::Type::CreateMenubar: | ||||||
|         post_message(&WSWindowManager::the(), make<WSAPICreateMenubarRequest>(client_id)); |         post_message(client, make<WSAPICreateMenubarRequest>(client_id)); | ||||||
|         break; |         break; | ||||||
|     case GUI_ClientMessage::Type::DestroyMenubar: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::SetApplicationMenubar: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::AddMenuToMenubar: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::CreateMenu: |     case GUI_ClientMessage::Type::CreateMenu: | ||||||
|         ASSERT(message.text_length < sizeof(message.text)); |         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; |         break; | ||||||
|     case GUI_ClientMessage::Type::DestroyMenu: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::AddMenuItem: |     case GUI_ClientMessage::Type::AddMenuItem: | ||||||
|         ASSERT(message.text_length < sizeof(message.text)); |         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; |         break; | ||||||
|     case GUI_ClientMessage::Type::CreateWindow: |     case GUI_ClientMessage::Type::CreateWindow: | ||||||
|         ASSERT(message.text_length < sizeof(message.text)); |         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; |         break; | ||||||
|     case GUI_ClientMessage::Type::DestroyWindow: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::SetWindowTitle: |     case GUI_ClientMessage::Type::SetWindowTitle: | ||||||
|         ASSERT(message.text_length < sizeof(message.text)); |         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; |         break; | ||||||
|     case GUI_ClientMessage::Type::GetWindowTitle: |     case GUI_ClientMessage::Type::GetWindowTitle: | ||||||
|         ASSERT(message.text_length < sizeof(message.text)); |         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; |         break; | ||||||
|     case GUI_ClientMessage::Type::SetWindowRect: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::GetWindowRect: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::InvalidateRect: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::DidFinishPainting: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::GetWindowBackingStore: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::ReleaseWindowBackingStore: |     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; |         break; | ||||||
|     case GUI_ClientMessage::Type::SetGlobalCursorTracking: |     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; |         break; | ||||||
|     } |     } | ||||||
|     server_process().request_wakeup(); |     server_process().request_wakeup(); | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| #include "WSMessage.h" | #include "WSMessage.h" | ||||||
| #include "WSMessageLoop.h" | #include "WSMessageLoop.h" | ||||||
| #include "Process.h" | #include "Process.h" | ||||||
|  | #include <WindowServer/WSClientConnection.h> | ||||||
| 
 | 
 | ||||||
| WSWindow::WSWindow(WSMenu& menu) | WSWindow::WSWindow(WSMenu& menu) | ||||||
|     : m_lock("WSWindow (menu)") |     : m_lock("WSWindow (menu)") | ||||||
|  | @ -12,12 +13,11 @@ WSWindow::WSWindow(WSMenu& menu) | ||||||
|     WSWindowManager::the().add_window(*this); |     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_lock("WSWindow (normal)") | ||||||
|  |     , m_client_id(client_id) | ||||||
|     , m_type(WSWindowType::Normal) |     , m_type(WSWindowType::Normal) | ||||||
|     , m_process(&process) |  | ||||||
|     , m_window_id(window_id) |     , m_window_id(window_id) | ||||||
|     , m_pid(process.pid()) |  | ||||||
| { | { | ||||||
|     WSWindowManager::the().add_window(*this); |     WSWindowManager::the().add_window(*this); | ||||||
| } | } | ||||||
|  | @ -44,15 +44,21 @@ void WSWindow::set_rect(const Rect& rect) | ||||||
|     Rect old_rect; |     Rect old_rect; | ||||||
|     { |     { | ||||||
|         WSWindowLocker locker(*this); |         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; |             return; | ||||||
|         if (m_rect == rect) |         if (m_rect == rect) | ||||||
|             return; |             return; | ||||||
|         old_rect = m_rect; |         old_rect = m_rect; | ||||||
|         m_rect = rect; |         m_rect = rect; | ||||||
|         if (!m_backing || old_rect.size() != rect.size()) { |         if (!m_backing || old_rect.size() != rect.size()) { | ||||||
|             if (m_process) |             if (process) | ||||||
|                 m_backing = GraphicsBitmap::create(*m_process, m_rect.size()); |                 m_backing = GraphicsBitmap::create(*process, m_rect.size()); | ||||||
|             if (m_menu) |             if (m_menu) | ||||||
|                 m_backing = GraphicsBitmap::create_kernel_only(m_rect.size()); |                 m_backing = GraphicsBitmap::create_kernel_only(m_rect.size()); | ||||||
|         } |         } | ||||||
|  | @ -135,19 +141,15 @@ void WSWindow::on_message(WSMessage& message) | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|         WSWindowLocker window_locker(*this); |         WSWindowLocker window_locker(*this); | ||||||
|         if (!m_process) |         if (auto* client = WSClientConnection::from_client_id(m_client_id)) { | ||||||
|             return; |             if (auto* process = client->process()) { | ||||||
|         LOCKER(m_process->gui_events_lock()); |                 LOCKER(process->gui_events_lock()); | ||||||
|         m_process->gui_events().append(move(gui_event)); |                 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) | void WSWindow::set_global_cursor_tracking_enabled(bool enabled) | ||||||
| { | { | ||||||
|     dbgprintf("WSWindow{%p} global_cursor_tracking <- %u\n", enabled); |     dbgprintf("WSWindow{%p} global_cursor_tracking <- %u\n", enabled); | ||||||
|  |  | ||||||
|  | @ -6,21 +6,19 @@ | ||||||
| #include <AK/InlineLinkedList.h> | #include <AK/InlineLinkedList.h> | ||||||
| #include <AK/Lock.h> | #include <AK/Lock.h> | ||||||
| #include <AK/Badge.h> | #include <AK/Badge.h> | ||||||
| #include <Kernel/Process.h> |  | ||||||
| #include "WSMessageReceiver.h" | #include "WSMessageReceiver.h" | ||||||
| #include <WindowServer/WSWindowType.h> | #include <WindowServer/WSWindowType.h> | ||||||
| 
 | 
 | ||||||
| class Process; |  | ||||||
| class WSMenu; | class WSMenu; | ||||||
| 
 | 
 | ||||||
| class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> { | class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> { | ||||||
|     friend class WSWindowLocker; |     friend class WSWindowLocker; | ||||||
| public: | public: | ||||||
|     WSWindow(Process&, int window_id); |     WSWindow(int client_id, int window_id); | ||||||
|     explicit WSWindow(WSMenu&); |     explicit WSWindow(WSMenu&); | ||||||
|     virtual ~WSWindow() override; |     virtual ~WSWindow() override; | ||||||
| 
 | 
 | ||||||
|     const Process* process() const { return m_process; } |     int client_id() const { return m_client_id; } | ||||||
| 
 | 
 | ||||||
|     WSWindowType type() const { return m_type; } |     WSWindowType type() const { return m_type; } | ||||||
|     int window_id() const { return m_window_id; } |     int window_id() const { return m_window_id; } | ||||||
|  | @ -59,13 +57,9 @@ public: | ||||||
| 
 | 
 | ||||||
|     GraphicsBitmap* backing() { return m_backing.ptr(); } |     GraphicsBitmap* backing() { return m_backing.ptr(); } | ||||||
| 
 | 
 | ||||||
|     pid_t pid() const { return m_pid; } |  | ||||||
| 
 |  | ||||||
|     void set_global_cursor_tracking_enabled(bool); |     void set_global_cursor_tracking_enabled(bool); | ||||||
|     bool global_cursor_tracking() const { return m_global_cursor_tracking_enabled; } |     bool global_cursor_tracking() const { return m_global_cursor_tracking_enabled; } | ||||||
| 
 | 
 | ||||||
|     void notify_process_died(Badge<Process>); |  | ||||||
| 
 |  | ||||||
|     // For InlineLinkedList.
 |     // For InlineLinkedList.
 | ||||||
|     // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
 |     // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
 | ||||||
|     WSWindow* m_next { nullptr }; |     WSWindow* m_next { nullptr }; | ||||||
|  | @ -73,6 +67,7 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Lock m_lock; |     Lock m_lock; | ||||||
|  |     int m_client_id { 0 }; | ||||||
|     String m_title; |     String m_title; | ||||||
|     Rect m_rect; |     Rect m_rect; | ||||||
|     WSWindowType m_type { WSWindowType::Normal }; |     WSWindowType m_type { WSWindowType::Normal }; | ||||||
|  | @ -83,9 +78,7 @@ private: | ||||||
|     WSMenu* m_menu { nullptr }; |     WSMenu* m_menu { nullptr }; | ||||||
| 
 | 
 | ||||||
|     RetainPtr<GraphicsBitmap> m_backing; |     RetainPtr<GraphicsBitmap> m_backing; | ||||||
|     Process* m_process { nullptr }; |  | ||||||
|     int m_window_id { -1 }; |     int m_window_id { -1 }; | ||||||
|     pid_t m_pid { -1 }; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class WSWindowLocker { | class WSWindowLocker { | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
| #include "WSMenu.h" | #include "WSMenu.h" | ||||||
| #include "WSMenuBar.h" | #include "WSMenuBar.h" | ||||||
| #include "WSMenuItem.h" | #include "WSMenuItem.h" | ||||||
|  | #include <WindowServer/WSClientConnection.h> | ||||||
| #include <Kernel/RTC.h> | #include <Kernel/RTC.h> | ||||||
| 
 | 
 | ||||||
| //#define DEBUG_COUNTERS
 | //#define DEBUG_COUNTERS
 | ||||||
|  | @ -239,7 +240,10 @@ int WSWindowManager::menubar_menu_margin() const | ||||||
| void WSWindowManager::set_current_menubar(WSMenuBar* menubar) | void WSWindowManager::set_current_menubar(WSMenuBar* menubar) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     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); |     dbgprintf("[WM] Current menubar is now %p\n", menubar); | ||||||
|     Point next_menu_location { menubar_menu_margin() / 2, 3 }; |     Point next_menu_location { menubar_menu_margin() / 2, 3 }; | ||||||
|     for_each_active_menubar_menu([&] (WSMenu& menu) { |     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_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 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 (should_open_menu) { | ||||||
|         if (m_current_menu == &menu) |         if (current_menu() == &menu) | ||||||
|             return; |             return; | ||||||
|         close_current_menu(); |         close_current_menu(); | ||||||
|         if (!menu.is_empty()) { |         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.move_to({ menu.rect_in_menubar().x(), menu.rect_in_menubar().bottom() }); | ||||||
|             menu_window.set_visible(true); |             menu_window.set_visible(true); | ||||||
|         } |         } | ||||||
|         m_current_menu = &menu; |         m_current_menu = menu.make_weak_ptr(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left) { |     if (event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left) { | ||||||
|  | @ -422,7 +426,7 @@ void WSWindowManager::close_current_menu() | ||||||
|     m_current_menu = nullptr; |     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) { |     for_each_active_menubar_menu([&] (WSMenu& menu) { | ||||||
|         if (menu.rect_in_menubar().contains(event.position())) { |         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())) { |     if (menubar_rect().contains(event.position())) { | ||||||
|         handle_menubar_mouse_event(*m_current_menubar, event); |         handle_menubar_mouse_event(event); | ||||||
|         return; |         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); |     m_back_painter->draw_line({ 0, menubar_rect().bottom() }, { menubar_rect().right(), menubar_rect().bottom() }, Color::White); | ||||||
|     for_each_active_menubar_menu([&] (WSMenu& menu) { |     for_each_active_menubar_menu([&] (WSMenu& menu) { | ||||||
|         Color text_color = Color::Black; |         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()); |             m_back_painter->fill_rect(menu.rect_in_menubar(), menu_selection_color()); | ||||||
|             text_color = Color::White; |             text_color = Color::White; | ||||||
|         } |         } | ||||||
|  | @ -733,284 +737,6 @@ void WSWindowManager::on_message(WSMessage& message) | ||||||
|         compose(); |         compose(); | ||||||
|         return; |         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) | 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)); |         WSMessageLoop::the().post_message(m_active_window.ptr(), make<WSMessage>(WSMessage::WindowActivated)); | ||||||
|         invalidate(*m_active_window); |         invalidate(*m_active_window); | ||||||
| 
 | 
 | ||||||
|         ASSERT(window->process()); |         int client_id = window->client_id(); | ||||||
|         auto it = m_app_menubars.find(window->process()->gui_client_id()); |         auto* client = WSClientConnection::from_client_id(client_id); | ||||||
|         if (it != m_app_menubars.end()) { |         ASSERT(client); | ||||||
|             auto* menubar = (*it).value; |         set_current_menubar(client->app_menubar()); | ||||||
|             if (menubar != m_current_menubar) |  | ||||||
|                 set_current_menubar(menubar); |  | ||||||
|         } else { |  | ||||||
|             set_current_menubar(nullptr); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1119,44 +840,27 @@ void WSWindowManager::flush(const Rect& a_rect) | ||||||
| void WSWindowManager::close_menu(WSMenu& menu) | void WSWindowManager::close_menu(WSMenu& menu) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     if (m_current_menu == &menu) |     if (current_menu() == &menu) | ||||||
|         close_current_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 | int WSWindowManager::active_client_id() const | ||||||
| { | { | ||||||
|     if (m_active_window) |     if (m_active_window) | ||||||
|         return m_active_window->process()->gui_client_id(); |         return m_active_window->client_id(); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::destroy_all_menus(Process& process) | void WSWindowManager::notify_client_changed_app_menubar(WSClientConnection& client) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     if (active_client_id() == client.client_id()) | ||||||
|     Vector<int> menu_ids; |         set_current_menubar(client.app_menubar()); | ||||||
|     bool should_close_current_menu = false; |     invalidate(); | ||||||
|     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()); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ class WSMenuBar; | ||||||
| class WSMouseEvent; | class WSMouseEvent; | ||||||
| class WSClientWantsToPaintMessage; | class WSClientWantsToPaintMessage; | ||||||
| class WSWindow; | class WSWindow; | ||||||
|  | class WSClientConnection; | ||||||
| class CharacterBitmap; | class CharacterBitmap; | ||||||
| class GraphicsBitmap; | class GraphicsBitmap; | ||||||
| 
 | 
 | ||||||
|  | @ -31,6 +32,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     void notify_title_changed(WSWindow&); |     void notify_title_changed(WSWindow&); | ||||||
|     void notify_rect_changed(WSWindow&, const Rect& oldRect, const Rect& newRect); |     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(); } |     WSWindow* active_window() { return m_active_window.ptr(); } | ||||||
|     int active_client_id() const; |     int active_client_id() const; | ||||||
|  | @ -42,9 +44,9 @@ public: | ||||||
|     void draw_menubar(); |     void draw_menubar(); | ||||||
| 
 | 
 | ||||||
|     Rect menubar_rect() const; |     Rect menubar_rect() const; | ||||||
|     WSMenuBar* current_menubar() { return m_current_menubar; } |     WSMenuBar* current_menubar() { return m_current_menubar.ptr(); } | ||||||
|     void set_current_menubar(WSMenuBar*); |     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 set_current_menu(WSMenu*); | ||||||
| 
 | 
 | ||||||
|     void invalidate(const WSWindow&); |     void invalidate(const WSWindow&); | ||||||
|  | @ -57,6 +59,7 @@ public: | ||||||
|     const Font& font() const { return *m_font; } |     const Font& font() const { return *m_font; } | ||||||
| 
 | 
 | ||||||
|     void close_menu(WSMenu&); |     void close_menu(WSMenu&); | ||||||
|  |     void close_menubar(WSMenuBar&); | ||||||
|     Color menu_selection_color() const { return m_menu_selection_color; } |     Color menu_selection_color() const { return m_menu_selection_color; } | ||||||
|     int menubar_menu_margin() const; |     int menubar_menu_margin() const; | ||||||
| 
 | 
 | ||||||
|  | @ -70,7 +73,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     void process_mouse_event(WSMouseEvent&); |     void process_mouse_event(WSMouseEvent&); | ||||||
|     void handle_menu_mouse_event(WSMenu&, 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_titlebar_mouse_event(WSWindow&, WSMouseEvent&); | ||||||
|     void handle_close_button_mouse_event(WSWindow&, WSMouseEvent&); |     void handle_close_button_mouse_event(WSWindow&, WSMouseEvent&); | ||||||
|     void handle_client_request(WSAPIClientRequest&); |     void handle_client_request(WSAPIClientRequest&); | ||||||
|  | @ -145,15 +148,8 @@ private: | ||||||
|     Lockable<bool> m_flash_flush; |     Lockable<bool> m_flash_flush; | ||||||
|     bool m_buffers_are_flipped { false }; |     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; |     OwnPtr<WSMenu> m_system_menu; | ||||||
|     Color m_menu_selection_color; |     Color m_menu_selection_color; | ||||||
|     WSMenuBar* m_current_menubar { nullptr }; |     WeakPtr<WSMenuBar> m_current_menubar; | ||||||
|     WSMenu* m_current_menu { nullptr }; |     WeakPtr<WSMenu> m_current_menu; | ||||||
|     HashMap<int, OwnPtr<WSMenuBar>> m_menubars; |  | ||||||
|     HashMap<int, OwnPtr<WSMenu>> m_menus; |  | ||||||
|     HashMap<int, WSMenuBar*> m_app_menubars; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling