1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078 |
- #include <LibC/SharedBuffer.h>
- #include <LibDraw/GraphicsBitmap.h>
- #include <SharedBuffer.h>
- #include <WindowServer/WSAPITypes.h>
- #include <WindowServer/WSClientConnection.h>
- #include <WindowServer/WSClipboard.h>
- #include <WindowServer/WSCompositor.h>
- #include <WindowServer/WSEventLoop.h>
- #include <WindowServer/WSMenu.h>
- #include <WindowServer/WSMenuBar.h>
- #include <WindowServer/WSMenuItem.h>
- #include <WindowServer/WSScreen.h>
- #include <WindowServer/WSWindow.h>
- #include <WindowServer/WSWindowManager.h>
- #include <WindowServer/WSWindowSwitcher.h>
- #include <errno.h>
- #include <stdio.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/uio.h>
- #include <unistd.h>
- HashMap<int, NonnullRefPtr<WSClientConnection>>* s_connections;
- void WSClientConnection::for_each_client(Function<void(WSClientConnection&)> callback)
- {
- if (!s_connections)
- return;
- for (auto& it : *s_connections) {
- callback(*it.value);
- }
- }
- WSClientConnection* WSClientConnection::from_client_id(int client_id)
- {
- if (!s_connections)
- return nullptr;
- auto it = s_connections->find(client_id);
- if (it == s_connections->end())
- return nullptr;
- return (*it).value.ptr();
- }
- WSClientConnection::WSClientConnection(CLocalSocket& client_socket, int client_id)
- : Connection(client_socket, client_id)
- {
- if (!s_connections)
- s_connections = new HashMap<int, NonnullRefPtr<WSClientConnection>>;
- s_connections->set(client_id, *this);
- }
- WSClientConnection::~WSClientConnection()
- {
- auto windows = move(m_windows);
- }
- void WSClientConnection::send_greeting()
- {
- WSAPI_ServerMessage message;
- message.type = WSAPI_ServerMessage::Type::Greeting;
- message.greeting.server_pid = getpid();
- message.greeting.your_client_id = client_id();
- message.greeting.screen_rect = WSScreen::the().rect();
- post_message(message);
- }
- void WSClientConnection::die()
- {
- s_connections->remove(client_id());
- }
- void WSClientConnection::post_error(const String& error_message)
- {
- dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", client_id(), error_message.characters());
- WSAPI_ServerMessage message;
- message.type = WSAPI_ServerMessage::Type::Error;
- ASSERT(error_message.length() < (ssize_t)sizeof(message.text));
- strcpy(message.text, error_message.characters());
- message.text_length = error_message.length();
- post_message(message);
- }
- void WSClientConnection::notify_about_new_screen_rect(const Rect& rect)
- {
- WSAPI_ServerMessage message;
- message.type = WSAPI_ServerMessage::Type::ScreenRectChanged;
- message.screen.rect = rect;
- post_message(message);
- }
- void WSClientConnection::notify_about_clipboard_contents_changed()
- {
- auto& clipboard = WSClipboard::the();
- WSAPI_ServerMessage message;
- message.type = WSAPI_ServerMessage::Type::ClipboardContentsChanged;
- message.clipboard.shared_buffer_id = -1;
- message.clipboard.contents_size = -1;
- ASSERT(clipboard.data_type().length() < (ssize_t)sizeof(message.text));
- strcpy(message.text, clipboard.data_type().characters());
- message.text_length = clipboard.data_type().length();
- post_message(message);
- }
- void WSClientConnection::event(CEvent& event)
- {
- if (static_cast<WSEvent&>(event).is_client_request()) {
- on_request(static_cast<const WSAPIClientRequest&>(event));
- return;
- }
- Connection::event(event);
- }
- static Vector<Rect, 32> get_rects(const WSAPI_ClientMessage& message, const ByteBuffer& extra_data)
- {
- Vector<Rect, 32> rects;
- if (message.rect_count > (int)(WSAPI_ClientMessage::max_inline_rect_count + extra_data.size() / sizeof(WSAPI_Rect))) {
- return {};
- }
- for (int i = 0; i < min(WSAPI_ClientMessage::max_inline_rect_count, message.rect_count); ++i)
- rects.append(message.rects[i]);
- if (!extra_data.is_empty()) {
- auto* extra_rects = reinterpret_cast<const WSAPI_Rect*>(extra_data.data());
- for (int i = 0; i < (int)(extra_data.size() / sizeof(WSAPI_Rect)); ++i)
- rects.append(extra_rects[i]);
- }
- return rects;
- }
- bool WSClientConnection::handle_message(const WSAPI_ClientMessage& message, const ByteBuffer&& extra_data)
- {
- switch (message.type) {
- case WSAPI_ClientMessage::Type::Greeting:
- set_client_pid(message.greeting.client_pid);
- break;
- case WSAPI_ClientMessage::Type::CreateMenubar:
- CEventLoop::current().post_event(*this, make<WSAPICreateMenubarRequest>(client_id()));
- break;
- case WSAPI_ClientMessage::Type::DestroyMenubar:
- CEventLoop::current().post_event(*this, make<WSAPIDestroyMenubarRequest>(client_id(), message.menu.menubar_id));
- break;
- case WSAPI_ClientMessage::Type::SetApplicationMenubar:
- CEventLoop::current().post_event(*this, make<WSAPISetApplicationMenubarRequest>(client_id(), message.menu.menubar_id));
- break;
- case WSAPI_ClientMessage::Type::AddMenuToMenubar:
- CEventLoop::current().post_event(*this, make<WSAPIAddMenuToMenubarRequest>(client_id(), message.menu.menubar_id, message.menu.menu_id));
- break;
- case WSAPI_ClientMessage::Type::CreateMenu:
- if (message.text_length > (int)sizeof(message.text)) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPICreateMenuRequest>(client_id(), String(message.text, message.text_length)));
- break;
- case WSAPI_ClientMessage::Type::PopupMenu:
- CEventLoop::current().post_event(*this, make<WSAPIPopupMenuRequest>(client_id(), message.menu.menu_id, message.menu.position));
- break;
- case WSAPI_ClientMessage::Type::DismissMenu:
- CEventLoop::current().post_event(*this, make<WSAPIDismissMenuRequest>(client_id(), message.menu.menu_id));
- break;
- case WSAPI_ClientMessage::Type::SetWindowIconBitmap:
- CEventLoop::current().post_event(*this, make<WSAPISetWindowIconBitmapRequest>(client_id(), message.window_id, message.window.icon_buffer_id, message.window.icon_size));
- break;
- case WSAPI_ClientMessage::Type::DestroyMenu:
- CEventLoop::current().post_event(*this, make<WSAPIDestroyMenuRequest>(client_id(), message.menu.menu_id));
- break;
- case WSAPI_ClientMessage::Type::AddMenuItem:
- if (message.text_length > (int)sizeof(message.text)) {
- did_misbehave();
- return false;
- }
- if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPIAddMenuItemRequest>(client_id(), message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked, message.menu.icon_buffer_id, message.menu.submenu_id));
- break;
- case WSAPI_ClientMessage::Type::UpdateMenuItem:
- if (message.text_length > (int)sizeof(message.text)) {
- did_misbehave();
- return false;
- }
- if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPIUpdateMenuItemRequest>(client_id(), message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked));
- break;
- case WSAPI_ClientMessage::Type::AddMenuSeparator:
- CEventLoop::current().post_event(*this, make<WSAPIAddMenuSeparatorRequest>(client_id(), message.menu.menu_id));
- break;
- case WSAPI_ClientMessage::Type::CreateWindow: {
- if (message.text_length > (int)sizeof(message.text)) {
- did_misbehave();
- return false;
- }
- auto ws_window_type = WSWindowType::Invalid;
- switch (message.window.type) {
- case WSAPI_WindowType::Normal:
- ws_window_type = WSWindowType::Normal;
- break;
- case WSAPI_WindowType::Menu:
- ws_window_type = WSWindowType::Menu;
- break;
- case WSAPI_WindowType::WindowSwitcher:
- ws_window_type = WSWindowType::WindowSwitcher;
- break;
- case WSAPI_WindowType::Taskbar:
- ws_window_type = WSWindowType::Taskbar;
- break;
- case WSAPI_WindowType::Tooltip:
- ws_window_type = WSWindowType::Tooltip;
- break;
- case WSAPI_WindowType::Menubar:
- ws_window_type = WSWindowType::Menubar;
- break;
- case WSAPI_WindowType::Invalid:
- default:
- dbgprintf("Unknown WSAPI_WindowType: %d\n", message.window.type);
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this,
- make<WSAPICreateWindowRequest>(client_id(),
- message.window.rect,
- String(message.text, message.text_length),
- message.window.has_alpha_channel,
- message.window.modal,
- message.window.resizable,
- message.window.fullscreen,
- message.window.show_titlebar,
- message.window.opacity,
- message.window.base_size,
- message.window.size_increment,
- ws_window_type,
- Color::from_rgba(message.window.background_color)));
- break;
- }
- case WSAPI_ClientMessage::Type::DestroyWindow:
- CEventLoop::current().post_event(*this, make<WSAPIDestroyWindowRequest>(client_id(), message.window_id));
- break;
- case WSAPI_ClientMessage::Type::SetWindowTitle:
- if (message.text_length > (int)sizeof(message.text)) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPISetWindowTitleRequest>(client_id(), message.window_id, String(message.text, message.text_length)));
- break;
- case WSAPI_ClientMessage::Type::GetWindowTitle:
- CEventLoop::current().post_event(*this, make<WSAPIGetWindowTitleRequest>(client_id(), message.window_id));
- break;
- case WSAPI_ClientMessage::Type::SetWindowRect:
- CEventLoop::current().post_event(*this, make<WSAPISetWindowRectRequest>(client_id(), message.window_id, message.window.rect));
- break;
- case WSAPI_ClientMessage::Type::GetWindowRect:
- CEventLoop::current().post_event(*this, make<WSAPIGetWindowRectRequest>(client_id(), message.window_id));
- break;
- case WSAPI_ClientMessage::Type::SetClipboardContents:
- if (message.text_length > (int)sizeof(message.text)) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPISetClipboardContentsRequest>(client_id(), message.clipboard.shared_buffer_id, message.clipboard.contents_size, String(message.text, message.text_length)));
- break;
- case WSAPI_ClientMessage::Type::GetClipboardContents:
- CEventLoop::current().post_event(*this, make<WSAPIGetClipboardContentsRequest>(client_id()));
- break;
- case WSAPI_ClientMessage::Type::InvalidateRect: {
- auto rects = get_rects(message, extra_data);
- if (rects.is_empty()) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPIInvalidateRectRequest>(client_id(), message.window_id, rects));
- break;
- }
- case WSAPI_ClientMessage::Type::DidFinishPainting: {
- auto rects = get_rects(message, extra_data);
- if (rects.is_empty()) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPIDidFinishPaintingNotification>(client_id(), message.window_id, rects));
- break;
- }
- case WSAPI_ClientMessage::Type::GetWindowBackingStore:
- CEventLoop::current().post_event(*this, make<WSAPIGetWindowBackingStoreRequest>(client_id(), message.window_id));
- break;
- case WSAPI_ClientMessage::Type::SetWindowBackingStore:
- CEventLoop::current().post_event(*this, make<WSAPISetWindowBackingStoreRequest>(client_id(), message.window_id, message.backing.shared_buffer_id, message.backing.size, message.backing.bpp, message.backing.pitch, message.backing.has_alpha_channel, message.backing.flush_immediately));
- break;
- case WSAPI_ClientMessage::Type::SetGlobalCursorTracking:
- CEventLoop::current().post_event(*this, make<WSAPISetGlobalCursorTrackingRequest>(client_id(), message.window_id, message.value));
- break;
- case WSAPI_ClientMessage::Type::SetWallpaper:
- if (message.text_length > (int)sizeof(message.text)) {
- did_misbehave();
- return false;
- }
- CEventLoop::current().post_event(*this, make<WSAPISetWallpaperRequest>(client_id(), String(message.text, message.text_length)));
- break;
- case WSAPI_ClientMessage::Type::GetWallpaper:
- CEventLoop::current().post_event(*this, make<WSAPIGetWallpaperRequest>(client_id()));
- break;
- case WSAPI_ClientMessage::Type::SetResolution:
- CEventLoop::current().post_event(*this, make<WSAPISetResolutionRequest>(client_id(), message.wm_conf.resolution.width, message.wm_conf.resolution.height));
- break;
- case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
- CEventLoop::current().post_event(*this, make<WSAPISetWindowOverrideCursorRequest>(client_id(), message.window_id, (WSStandardCursor)message.cursor.cursor));
- break;
- case WSAPI_ClientMessage::SetWindowHasAlphaChannel:
- CEventLoop::current().post_event(*this, make<WSAPISetWindowHasAlphaChannelRequest>(client_id(), message.window_id, message.value));
- break;
- case WSAPI_ClientMessage::Type::WM_SetActiveWindow:
- CEventLoop::current().post_event(*this, make<WSWMAPISetActiveWindowRequest>(client_id(), message.wm.client_id, message.wm.window_id));
- break;
- case WSAPI_ClientMessage::Type::WM_SetWindowMinimized:
- CEventLoop::current().post_event(*this, make<WSWMAPISetWindowMinimizedRequest>(client_id(), message.wm.client_id, message.wm.window_id, message.wm.minimized));
- break;
- case WSAPI_ClientMessage::Type::WM_StartWindowResize:
- CEventLoop::current().post_event(*this, make<WSWMAPIStartWindowResizeRequest>(client_id(), message.wm.client_id, message.wm.window_id));
- break;
- case WSAPI_ClientMessage::Type::WM_PopupWindowMenu:
- CEventLoop::current().post_event(*this, make<WSWMAPIPopupWindowMenuRequest>(client_id(), message.wm.client_id, message.wm.window_id, message.wm.position));
- break;
- case WSAPI_ClientMessage::Type::MoveWindowToFront:
- CEventLoop::current().post_event(*this, make<WSAPIMoveWindowToFrontRequest>(client_id(), message.window_id));
- break;
- case WSAPI_ClientMessage::Type::SetFullscreen:
- CEventLoop::current().post_event(*this, make<WSAPISetFullscreenRequest>(client_id(), message.window_id, message.value));
- break;
- default:
- break;
- }
- return true;
- }
- void WSClientConnection::handle_request(const WSAPICreateMenubarRequest&)
- {
- int menubar_id = m_next_menubar_id++;
- auto menubar = make<WSMenuBar>(*this, menubar_id);
- m_menubars.set(menubar_id, move(menubar));
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidCreateMenubar;
- response.menu.menubar_id = menubar_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIDestroyMenubarRequest& request)
- {
- int menubar_id = request.menubar_id();
- auto it = m_menubars.find(menubar_id);
- if (it == m_menubars.end()) {
- post_error("WSAPIDestroyMenubarRequest: Bad menubar ID");
- return;
- }
- auto& menubar = *(*it).value;
- WSWindowManager::the().close_menubar(menubar);
- m_menubars.remove(it);
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidDestroyMenubar;
- response.menu.menubar_id = menubar_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPICreateMenuRequest& request)
- {
- int menu_id = m_next_menu_id++;
- auto menu = WSMenu::construct(this, menu_id, request.text());
- m_menus.set(menu_id, move(menu));
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidCreateMenu;
- response.menu.menu_id = menu_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIDestroyMenuRequest& request)
- {
- int menu_id = static_cast<const WSAPIDestroyMenuRequest&>(request).menu_id();
- auto it = m_menus.find(menu_id);
- if (it == m_menus.end()) {
- post_error("WSAPIDestroyMenuRequest: Bad menu ID");
- return;
- }
- auto& menu = *(*it).value;
- menu.close();
- m_menus.remove(it);
- remove_child(menu);
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidDestroyMenu;
- response.menu.menu_id = menu_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetApplicationMenubarRequest& request)
- {
- int menubar_id = request.menubar_id();
- auto it = m_menubars.find(menubar_id);
- if (it == m_menubars.end()) {
- post_error("WSAPISetApplicationMenubarRequest: Bad menubar ID");
- return;
- }
- auto& menubar = *(*it).value;
- m_app_menubar = menubar.make_weak_ptr();
- WSWindowManager::the().notify_client_changed_app_menubar(*this);
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidSetApplicationMenubar;
- response.menu.menubar_id = menubar_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIAddMenuToMenubarRequest& request)
- {
- int menubar_id = request.menubar_id();
- int menu_id = request.menu_id();
- auto it = m_menubars.find(menubar_id);
- auto jt = m_menus.find(menu_id);
- if (it == m_menubars.end()) {
- post_error("WSAPIAddMenuToMenubarRequest: Bad menubar ID");
- return;
- }
- if (jt == m_menus.end()) {
- post_error("WSAPIAddMenuToMenubarRequest: Bad menu ID");
- return;
- }
- auto& menubar = *(*it).value;
- auto& menu = *(*jt).value;
- menubar.add_menu(menu);
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidAddMenuToMenubar;
- response.menu.menubar_id = menubar_id;
- response.menu.menu_id = menu_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIAddMenuItemRequest& request)
- {
- int menu_id = request.menu_id();
- unsigned identifier = request.identifier();
- auto it = m_menus.find(menu_id);
- if (it == m_menus.end()) {
- post_error("WSAPIAddMenuItemRequest: Bad menu ID");
- return;
- }
- auto& menu = *(*it).value;
- auto menu_item = make<WSMenuItem>(menu, identifier, request.text(), request.shortcut_text(), request.is_enabled(), request.is_checkable(), request.is_checked());
- if (request.icon_buffer_id() != -1) {
- auto icon_buffer = SharedBuffer::create_from_shared_buffer_id(request.icon_buffer_id());
- if (!icon_buffer) {
- did_misbehave();
- return;
- }
- // FIXME: Verify that the icon buffer can accomodate a 16x16 bitmap view.
- auto shared_icon = GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, icon_buffer.release_nonnull(), { 16, 16 });
- menu_item->set_icon(shared_icon);
- }
- menu_item->set_submenu_id(request.submenu_id());
- menu.add_item(move(menu_item));
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidAddMenuItem;
- response.menu.menu_id = menu_id;
- response.menu.identifier = identifier;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIPopupMenuRequest& request)
- {
- int menu_id = request.menu_id();
- auto position = request.position();
- auto it = m_menus.find(menu_id);
- if (it == m_menus.end()) {
- post_error("WSAPIPopupMenuRequest: Bad menu ID");
- return;
- }
- auto& menu = *(*it).value;
- menu.popup(position);
- }
- void WSClientConnection::handle_request(const WSAPIDismissMenuRequest& request)
- {
- int menu_id = request.menu_id();
- auto it = m_menus.find(menu_id);
- if (it == m_menus.end()) {
- post_error("WSAPIDismissMenuRequest: Bad menu ID");
- return;
- }
- auto& menu = *(*it).value;
- menu.close();
- }
- void WSClientConnection::handle_request(const WSAPIUpdateMenuItemRequest& request)
- {
- int menu_id = request.menu_id();
- unsigned identifier = request.identifier();
- auto it = m_menus.find(menu_id);
- if (it == m_menus.end()) {
- post_error("WSAPIUpdateMenuItemRequest: Bad menu ID");
- return;
- }
- auto& menu = *(*it).value;
- auto* menu_item = menu.item_with_identifier(request.identifier());
- if (!menu_item) {
- post_error("WSAPIUpdateMenuItemRequest: Bad menu item identifier");
- return;
- }
- menu_item->set_text(request.text());
- menu_item->set_shortcut_text(request.shortcut_text());
- menu_item->set_enabled(request.is_enabled());
- menu_item->set_checkable(request.is_checkable());
- if (request.is_checkable())
- menu_item->set_checked(request.is_checked());
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidUpdateMenuItem;
- response.menu.menu_id = menu_id;
- response.menu.identifier = identifier;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIAddMenuSeparatorRequest& request)
- {
- int menu_id = request.menu_id();
- auto it = m_menus.find(menu_id);
- if (it == m_menus.end()) {
- post_error("WSAPIAddMenuSeparatorRequest: Bad menu ID");
- return;
- }
- auto& menu = *(*it).value;
- menu.add_item(make<WSMenuItem>(menu, WSMenuItem::Separator));
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidAddMenuSeparator;
- response.menu.menu_id = menu_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIMoveWindowToFrontRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPIMoveWindowToFrontRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- WSWindowManager::the().move_to_front_and_make_active(window);
- }
- void WSClientConnection::handle_request(const WSAPISetFullscreenRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetFullscreenRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_fullscreen(request.fullscreen());
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidSetFullscreen;
- response.window_id = window_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetWindowOpacityRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetWindowOpacityRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_opacity(request.opacity());
- }
- void WSClientConnection::handle_request(const WSAPISetWallpaperRequest& request)
- {
- WSCompositor::the().set_wallpaper(request.wallpaper(), [&](bool success) {
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidSetWallpaper;
- response.value = success;
- post_message(response);
- });
- }
- void WSClientConnection::handle_request(const WSAPIGetWallpaperRequest&)
- {
- auto path = WSCompositor::the().wallpaper_path();
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidGetWallpaper;
- ASSERT(path.length() < (int)sizeof(response.text));
- memcpy(response.text, path.characters(), path.length() + 1);
- response.text_length = path.length();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetResolutionRequest& request)
- {
- WSWindowManager::the().set_resolution(request.resolution().width(), request.resolution().height());
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidSetResolution;
- response.value = true;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetWindowTitleRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetWindowTitleRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_title(request.title());
- }
- void WSClientConnection::handle_request(const WSAPIGetWindowTitleRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPIGetWindowTitleRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidGetWindowTitle;
- response.window_id = window.window_id();
- ASSERT(window.title().length() < (ssize_t)sizeof(response.text));
- strcpy(response.text, window.title().characters());
- response.text_length = window.title().length();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetWindowIconBitmapRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetWindowIconBitmapRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- auto icon_buffer = SharedBuffer::create_from_shared_buffer_id(request.icon_buffer_id());
- if (!icon_buffer) {
- window.set_default_icon();
- } else {
- window.set_icon(GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, *icon_buffer, request.icon_size()));
- }
- window.frame().invalidate_title_bar();
- WSWindowManager::the().tell_wm_listeners_window_icon_changed(window);
- }
- void WSClientConnection::handle_request(const WSAPISetWindowRectRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetWindowRectRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- if (window.is_fullscreen()) {
- dbgprintf("WSClientConnection: Ignoring SetWindowRect request for fullscreen window\n");
- return;
- }
- window.set_rect(request.rect());
- window.request_update(request.rect());
- }
- void WSClientConnection::handle_request(const WSAPIGetWindowRectRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPIGetWindowRectRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidGetWindowRect;
- response.window_id = window.window_id();
- response.window.rect = window.rect();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetClipboardContentsRequest& request)
- {
- auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
- if (!shared_buffer) {
- post_error("WSAPISetClipboardContentsRequest: Bad shared buffer ID");
- return;
- }
- WSClipboard::the().set_data(*shared_buffer, request.size(), request.data_type());
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidSetClipboardContents;
- response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIGetClipboardContentsRequest&)
- {
- auto& clipboard = WSClipboard::the();
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidGetClipboardContents;
- response.clipboard.shared_buffer_id = -1;
- response.clipboard.contents_size = 0;
- if (clipboard.size()) {
- // FIXME: Optimize case where an app is copy/pasting within itself.
- // We can just reuse the SharedBuffer then, since it will have the same peer PID.
- // It would be even nicer if a SharedBuffer could have an arbitrary number of clients..
- RefPtr<SharedBuffer> shared_buffer = SharedBuffer::create_with_size(clipboard.size());
- ASSERT(shared_buffer);
- memcpy(shared_buffer->data(), clipboard.data(), clipboard.size());
- shared_buffer->seal();
- shared_buffer->share_with(client_pid());
- response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
- response.clipboard.contents_size = clipboard.size();
- // FIXME: This is a workaround for the fact that SharedBuffers will go away if neither side is retaining them.
- // After we respond to GetClipboardContents, we have to wait for the client to ref the buffer on his side.
- m_last_sent_clipboard_content = move(shared_buffer);
- }
- ASSERT(clipboard.data_type().length() < (ssize_t)sizeof(response.text));
- if (!clipboard.data_type().is_null())
- strcpy(response.text, clipboard.data_type().characters());
- response.text_length = clipboard.data_type().length();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPICreateWindowRequest& request)
- {
- int window_id = m_next_window_id++;
- auto window = WSWindow::construct(*this, request.window_type(), window_id, request.is_modal(), request.is_resizable(), request.is_fullscreen());
- window->set_background_color(request.background_color());
- window->set_has_alpha_channel(request.has_alpha_channel());
- window->set_title(request.title());
- if (!request.is_fullscreen())
- window->set_rect(request.rect());
- window->set_show_titlebar(request.show_titlebar());
- window->set_opacity(request.opacity());
- window->set_size_increment(request.size_increment());
- window->set_base_size(request.base_size());
- window->invalidate();
- m_windows.set(window_id, move(window));
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidCreateWindow;
- response.window_id = window_id;
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPIDestroyWindowRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPIDestroyWindowRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- WSWindowManager::the().invalidate(window);
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidDestroyWindow;
- response.window_id = window.window_id();
- post_message(response);
- remove_child(window);
- ASSERT(it->value.ptr() == &window);
- m_windows.remove(window_id);
- }
- void WSClientConnection::post_paint_message(WSWindow& window)
- {
- auto rect_set = window.take_pending_paint_rects();
- if (window.is_minimized())
- return;
- WSAPI_ServerMessage message;
- message.type = WSAPI_ServerMessage::Type::Paint;
- message.window_id = window.window_id();
- auto& rects = rect_set.rects();
- message.rect_count = rects.size();
- for (int i = 0; i < min(WSAPI_ServerMessage::max_inline_rect_count, rects.size()); ++i)
- message.rects[i] = rects[i];
- message.paint.window_size = window.size();
- ByteBuffer extra_data;
- if (rects.size() > WSAPI_ServerMessage::max_inline_rect_count)
- extra_data = ByteBuffer::wrap(&rects[WSAPI_ServerMessage::max_inline_rect_count], (rects.size() - WSAPI_ServerMessage::max_inline_rect_count) * sizeof(WSAPI_Rect));
- post_message(message, extra_data);
- }
- void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPIInvalidateRectRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- for (int i = 0; i < request.rects().size(); ++i)
- window.request_update(request.rects()[i].intersected({ {}, window.size() }));
- }
- void WSClientConnection::handle_request(const WSAPIDidFinishPaintingNotification& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPIDidFinishPaintingNotification: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- for (auto& rect : request.rects())
- WSWindowManager::the().invalidate(window, rect);
- WSWindowSwitcher::the().refresh_if_needed();
- }
- void WSClientConnection::handle_request(const WSAPIGetWindowBackingStoreRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPIGetWindowBackingStoreRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- auto* backing_store = window.backing_store();
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidGetWindowBackingStore;
- response.window_id = window_id;
- response.backing.bpp = sizeof(RGBA32);
- response.backing.pitch = backing_store->pitch();
- response.backing.size = backing_store->size();
- response.backing.has_alpha_channel = backing_store->has_alpha_channel();
- response.backing.shared_buffer_id = backing_store->shared_buffer_id();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetWindowBackingStoreRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetWindowBackingStoreRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- if (window.last_backing_store() && window.last_backing_store()->shared_buffer_id() == request.shared_buffer_id()) {
- window.swap_backing_stores();
- } else {
- auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
- if (!shared_buffer)
- return;
- auto backing_store = GraphicsBitmap::create_with_shared_buffer(
- request.has_alpha_channel() ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
- *shared_buffer,
- request.size());
- window.set_backing_store(move(backing_store));
- }
- if (request.flush_immediately())
- window.invalidate();
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidSetWindowBackingStore;
- response.window_id = window_id;
- response.backing.shared_buffer_id = request.shared_buffer_id();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSAPISetGlobalCursorTrackingRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetGlobalCursorTrackingRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_global_cursor_tracking_enabled(request.value());
- }
- void WSClientConnection::handle_request(const WSAPISetWindowOverrideCursorRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetWindowOverrideCursorRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_override_cursor(WSCursor::create(request.cursor()));
- }
- void WSClientConnection::handle_request(const WSAPISetWindowHasAlphaChannelRequest& request)
- {
- int window_id = request.window_id();
- auto it = m_windows.find(window_id);
- if (it == m_windows.end()) {
- post_error("WSAPISetWindowHasAlphaChannelRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_has_alpha_channel(request.value());
- WSAPI_ServerMessage response;
- response.type = WSAPI_ServerMessage::Type::DidSetWindowHasAlphaChannel;
- response.window_id = window_id;
- response.value = request.value();
- post_message(response);
- }
- void WSClientConnection::handle_request(const WSWMAPISetActiveWindowRequest& request)
- {
- auto* client = WSClientConnection::from_client_id(request.target_client_id());
- if (!client) {
- post_error("WSWMAPISetActiveWindowRequest: Bad client ID");
- return;
- }
- auto it = client->m_windows.find(request.target_window_id());
- if (it == client->m_windows.end()) {
- post_error("WSWMAPISetActiveWindowRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_minimized(false);
- WSWindowManager::the().move_to_front_and_make_active(window);
- }
- void WSClientConnection::handle_request(const WSWMAPIPopupWindowMenuRequest& request)
- {
- auto* client = WSClientConnection::from_client_id(request.target_client_id());
- if (!client) {
- post_error("WSWMAPIPopupWindowMenuRequest: Bad client ID");
- return;
- }
- auto it = client->m_windows.find(request.target_window_id());
- if (it == client->m_windows.end()) {
- post_error("WSWMAPIPopupWindowMenuRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.popup_window_menu(request.position());
- }
- void WSClientConnection::handle_request(const WSWMAPIStartWindowResizeRequest& request)
- {
- auto* client = WSClientConnection::from_client_id(request.target_client_id());
- if (!client) {
- post_error("WSWMAPIStartWindowResizeRequest: Bad client ID");
- return;
- }
- auto it = client->m_windows.find(request.target_window_id());
- if (it == client->m_windows.end()) {
- post_error("WSWMAPIStartWindowResizeRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- // FIXME: We are cheating a bit here by using the current cursor location and hard-coding the left button.
- // Maybe the client should be allowed to specify what initiated this request?
- WSWindowManager::the().start_window_resize(window, WSScreen::the().cursor_location(), MouseButton::Left);
- }
- void WSClientConnection::handle_request(const WSWMAPISetWindowMinimizedRequest& request)
- {
- auto* client = WSClientConnection::from_client_id(request.target_client_id());
- if (!client) {
- post_error("WSWMAPISetWindowMinimizedRequest: Bad client ID");
- return;
- }
- auto it = client->m_windows.find(request.target_window_id());
- if (it == client->m_windows.end()) {
- post_error("WSWMAPISetWindowMinimizedRequest: Bad window ID");
- return;
- }
- auto& window = *(*it).value;
- window.set_minimized(request.is_minimized());
- }
- void WSClientConnection::on_request(const WSAPIClientRequest& request)
- {
- switch (request.type()) {
- case WSEvent::APICreateMenubarRequest:
- return handle_request(static_cast<const WSAPICreateMenubarRequest&>(request));
- case WSEvent::APIDestroyMenubarRequest:
- return handle_request(static_cast<const WSAPIDestroyMenubarRequest&>(request));
- case WSEvent::APICreateMenuRequest:
- return handle_request(static_cast<const WSAPICreateMenuRequest&>(request));
- case WSEvent::APIDestroyMenuRequest:
- return handle_request(static_cast<const WSAPIDestroyMenuRequest&>(request));
- case WSEvent::APISetApplicationMenubarRequest:
- return handle_request(static_cast<const WSAPISetApplicationMenubarRequest&>(request));
- case WSEvent::APIAddMenuToMenubarRequest:
- return handle_request(static_cast<const WSAPIAddMenuToMenubarRequest&>(request));
- case WSEvent::APIAddMenuItemRequest:
- return handle_request(static_cast<const WSAPIAddMenuItemRequest&>(request));
- case WSEvent::APIAddMenuSeparatorRequest:
- return handle_request(static_cast<const WSAPIAddMenuSeparatorRequest&>(request));
- case WSEvent::APIUpdateMenuItemRequest:
- return handle_request(static_cast<const WSAPIUpdateMenuItemRequest&>(request));
- case WSEvent::APISetWindowTitleRequest:
- return handle_request(static_cast<const WSAPISetWindowTitleRequest&>(request));
- case WSEvent::APIGetWindowTitleRequest:
- return handle_request(static_cast<const WSAPIGetWindowTitleRequest&>(request));
- case WSEvent::APISetWindowRectRequest:
- return handle_request(static_cast<const WSAPISetWindowRectRequest&>(request));
- case WSEvent::APIGetWindowRectRequest:
- return handle_request(static_cast<const WSAPIGetWindowRectRequest&>(request));
- case WSEvent::APISetWindowIconBitmapRequest:
- return handle_request(static_cast<const WSAPISetWindowIconBitmapRequest&>(request));
- case WSEvent::APISetClipboardContentsRequest:
- return handle_request(static_cast<const WSAPISetClipboardContentsRequest&>(request));
- case WSEvent::APIGetClipboardContentsRequest:
- return handle_request(static_cast<const WSAPIGetClipboardContentsRequest&>(request));
- case WSEvent::APICreateWindowRequest:
- return handle_request(static_cast<const WSAPICreateWindowRequest&>(request));
- case WSEvent::APIDestroyWindowRequest:
- return handle_request(static_cast<const WSAPIDestroyWindowRequest&>(request));
- case WSEvent::APIInvalidateRectRequest:
- return handle_request(static_cast<const WSAPIInvalidateRectRequest&>(request));
- case WSEvent::APIDidFinishPaintingNotification:
- return handle_request(static_cast<const WSAPIDidFinishPaintingNotification&>(request));
- case WSEvent::APIGetWindowBackingStoreRequest:
- return handle_request(static_cast<const WSAPIGetWindowBackingStoreRequest&>(request));
- case WSEvent::APISetGlobalCursorTrackingRequest:
- return handle_request(static_cast<const WSAPISetGlobalCursorTrackingRequest&>(request));
- case WSEvent::APISetWindowOpacityRequest:
- return handle_request(static_cast<const WSAPISetWindowOpacityRequest&>(request));
- case WSEvent::APISetWindowBackingStoreRequest:
- return handle_request(static_cast<const WSAPISetWindowBackingStoreRequest&>(request));
- case WSEvent::APISetWallpaperRequest:
- return handle_request(static_cast<const WSAPISetWallpaperRequest&>(request));
- case WSEvent::APIGetWallpaperRequest:
- return handle_request(static_cast<const WSAPIGetWallpaperRequest&>(request));
- case WSEvent::APISetResolutionRequest:
- return handle_request(static_cast<const WSAPISetResolutionRequest&>(request));
- case WSEvent::APISetWindowOverrideCursorRequest:
- return handle_request(static_cast<const WSAPISetWindowOverrideCursorRequest&>(request));
- case WSEvent::WMAPISetActiveWindowRequest:
- return handle_request(static_cast<const WSWMAPISetActiveWindowRequest&>(request));
- case WSEvent::WMAPISetWindowMinimizedRequest:
- return handle_request(static_cast<const WSWMAPISetWindowMinimizedRequest&>(request));
- case WSEvent::WMAPIStartWindowResizeRequest:
- return handle_request(static_cast<const WSWMAPIStartWindowResizeRequest&>(request));
- case WSEvent::WMAPIPopupWindowMenuRequest:
- return handle_request(static_cast<const WSWMAPIPopupWindowMenuRequest&>(request));
- case WSEvent::APIPopupMenuRequest:
- return handle_request(static_cast<const WSAPIPopupMenuRequest&>(request));
- case WSEvent::APIDismissMenuRequest:
- return handle_request(static_cast<const WSAPIDismissMenuRequest&>(request));
- case WSEvent::APISetWindowHasAlphaChannelRequest:
- return handle_request(static_cast<const WSAPISetWindowHasAlphaChannelRequest&>(request));
- case WSEvent::APIMoveWindowToFrontRequest:
- return handle_request(static_cast<const WSAPIMoveWindowToFrontRequest&>(request));
- case WSEvent::APISetFullscreenRequest:
- return handle_request(static_cast<const WSAPISetFullscreenRequest&>(request));
- default:
- break;
- }
- }
- bool WSClientConnection::is_showing_modal_window() const
- {
- for (auto& it : m_windows) {
- auto& window = *it.value;
- if (window.is_visible() && window.is_modal())
- return true;
- }
- return false;
- }
|