From 6c17d025516c9c1a271394f8ef618d842e68c716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 15 Nov 2005 19:59:53 +0000 Subject: [PATCH] * Introduced a new handshake between input_server and app_server, and some temporary handling code in the app_server. * RootLayer no longer creates the input_server messaging port - this is now the responsibility of the input_server. * Moved AS_CREATE_[OFFSCREEN_]WINDOW from ServerApp::_MessageLooper() to _DispatchMessage(). * The RootLayer thread is now started as soon as the input_server is there. * removed or disabled any input_server stuff in the AppServer class. * removed old message commmands to the app_server. * Removed the R5_CURSOR_COMM and HAIKU_APPSERVER_COMM definitions: the input_server is now automatically built correctly depending on the target. * InputServer::EventLoop() plays now safe and checks for error conditions. * InputServer::EnqueueDeviceMessage() seems to leak memory, added TODO about this. * InputServer event loop messaging uses ports for inner-app communication - why? * The InputServer event loop thread is no longer killed on exit, it just quits when its port is gone. * Minor cleanup in input_server. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14949 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/app/ServerProtocol.h | 7 +- headers/private/input/InputServerTypes.h | 14 ++ headers/private/input/shared_cursor_area.h | 21 ++ src/servers/app/AppServer.cpp | 22 +-- src/servers/app/AppServer.h | 13 -- src/servers/app/Desktop.cpp | 17 +- src/servers/app/Desktop.h | 4 + src/servers/app/Jamfile | 2 +- src/servers/app/RootLayer.cpp | 31 ++- src/servers/app/ServerApp.cpp | 205 +++++++++++--------- src/servers/app/drawing/ViewHWInterface.cpp | 2 +- src/servers/input/InputServer.cpp | 186 +++++++++++++----- src/servers/input/InputServer.h | 38 ++-- 13 files changed, 345 insertions(+), 217 deletions(-) create mode 100644 headers/private/input/shared_cursor_area.h diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index 6da84426d1..24d630cd81 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -25,11 +25,8 @@ enum { SERVER_TRUE = B_OK, SERVER_FALSE = B_ERROR, - AS_SERVER_BMESSAGE = 1, - AS_SERVER_AREALINK, - AS_SERVER_SESSION, - AS_SERVER_PORTLINK, - AS_CLIENT_DEAD, + AS_REGISTER_INPUT_SERVER = 1, + AS_ACQUIRED_INPUT_STREAM, AS_GET_DESKTOP, // Desktop definitions diff --git a/headers/private/input/InputServerTypes.h b/headers/private/input/InputServerTypes.h index fc79b01f6e..814fa775f9 100644 --- a/headers/private/input/InputServerTypes.h +++ b/headers/private/input/InputServerTypes.h @@ -1,3 +1,11 @@ +/* + * Copyright 2001-2005, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef INPUT_SERVER_TYPES_H +#define INPUT_SERVER_TYPES_H + + #define IS_GET_MOUSE_TYPE 'Igmt' #define IS_SET_MOUSE_TYPE 'Ismt' #define IS_GET_MOUSE_ACCELERATION 'Igma' @@ -31,6 +39,10 @@ #define IS_CONTROL_DEVICES 'Icnd' #define SYSTEM_SHUTTING_DOWN 'SSDn' +// app_server communication +#define IS_ACQUIRE_INPUT 'Iaqi' +#define IS_RELEASE_INPUT 'Irli' + // Method Replicant #define IS_SET_METHOD 'MRsm' #define IS_METHOD_REGISTER 'MRmr' @@ -40,3 +52,5 @@ #define IS_UPDATE_METHOD 'MRu!' #define IS_ADD_METHOD 'MRa!' #define IS_REMOVE_METHOD 'MRr!' + +#endif /* INPUT_SERVER_TYPES_H */ diff --git a/headers/private/input/shared_cursor_area.h b/headers/private/input/shared_cursor_area.h new file mode 100644 index 0000000000..7893e94f7f --- /dev/null +++ b/headers/private/input/shared_cursor_area.h @@ -0,0 +1,21 @@ +/* + * Copyright 2005, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef SHARED_CURSOR_AREA_H +#define SHARED_CURSOR_AREA_H + + +#include + + +struct shared_cursor { + uint32 pos; + int32 read; +}; + + +#endif /* SHARED_CURSOR_AREA_H */ diff --git a/src/servers/app/AppServer.cpp b/src/servers/app/AppServer.cpp index 4b10721523..a81f522f9d 100644 --- a/src/servers/app/AppServer.cpp +++ b/src/servers/app/AppServer.cpp @@ -83,30 +83,14 @@ ColorSet gGUIColorSet; AppServer::AppServer() : MessageLooper("app_server"), fMessagePort(-1), - fServerInputPort(-1), - fISThreadID(-1), - fCursorThreadID(-1), - fCursorSem(-1), - fCursorArea(-1), - fCursorAddr(NULL), fDesktops(), - fDesktopLock("AppServerDesktopLock"), - fISASPort(-1), - fISPort(-1) + fDesktopLock("AppServerDesktopLock") { fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, SERVER_PORT_NAME); if (fMessagePort < B_OK) debugger("app_server could not create message port"); fLink.SetReceiverPort(fMessagePort); - gAppServerPort = fMessagePort; - - // Create the input port. The input_server will send it's messages here. - // TODO: If we want multiple user support we would need an individual - // port for each user and do the following for each RootLayer. - fServerInputPort = create_port(200, SERVER_INPUT_PORT); - if (fServerInputPort < B_OK) - debugger("app_server could not create input port"); sAppServer = this; @@ -164,6 +148,7 @@ AppServer::RunLooper() } +#if 0 /*! \brief Starts Input Server */ @@ -237,6 +222,7 @@ AppServer::_LaunchCursorThread() } + /*! \brief The Cursor Thread task */ @@ -262,6 +248,7 @@ AppServer::_CursorThread(void* data) return B_OK; } +#endif /*! @@ -364,7 +351,6 @@ AppServer::_DispatchMessage(int32 code, BPrivate::LinkReceiver& msg) wait_for_thread(thread, &status); } - kill_thread(fCursorThreadID); delete this; // we are now clear to exit diff --git a/src/servers/app/AppServer.h b/src/servers/app/AppServer.h index 2116279476..22f331e8f3 100644 --- a/src/servers/app/AppServer.h +++ b/src/servers/app/AppServer.h @@ -46,26 +46,13 @@ class AppServer : public MessageLooper { Desktop* _CreateDesktop(uid_t userID); Desktop* _FindDesktop(uid_t userID); - void _LaunchCursorThread(); void _LaunchInputServer(); - static int32 _CursorThread(void *data); - private: port_id fMessagePort; - port_id fServerInputPort; - - thread_id fISThreadID; - thread_id fCursorThreadID; - sem_id fCursorSem; - area_id fCursorArea; - uint32 *fCursorAddr; BObjectList fDesktops; BLocker fDesktopLock; - - port_id fISASPort; - port_id fISPort; }; extern BitmapManager *gBitmapManager; diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 20d8e9c72f..220085b728 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -102,9 +102,12 @@ Desktop::Init() // TODO: add user identity to the name char name[32]; sprintf(name, "RootLayer %d", 1); - fRootLayer = new RootLayer(name, 4, this, GetDrawingEngine()); - fRootLayer->RunThread(); + +#if TEST_MODE + RegisterInputServer(find_port(SERVER_INPUT_PORT)); + // this is where the ViewHWInterface will send its input events to +#endif // take care of setting the default cursor ServerCursor *cursor = fCursorManager.GetCursor(B_CURSOR_DEFAULT); @@ -339,6 +342,16 @@ Desktop::_ActivateApp(team_id team) } +void +Desktop::RegisterInputServer(port_id port) +{ + fInputPort = port; + fRootLayer->RunThread(); + + fVirtualScreen.HWInterface()->SetCursorVisible(true); +} + + /*! \brief Send a quick (no attachments) message to all applications diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 6d3aa485a8..7628c84bb1 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -49,6 +49,9 @@ class Desktop : public MessageLooper, public ScreenOwner { uid_t UserID() const { return fUserID; } virtual port_id MessagePort() const { return fMessagePort; } + void RegisterInputServer(port_id port); + port_id InputServerPort() { return fInputPort; } + void BroadcastToAllApps(int32 code); // Methods for multiple monitors. @@ -101,6 +104,7 @@ class Desktop : public MessageLooper, public ScreenOwner { ::VirtualScreen fVirtualScreen; DesktopSettings::Private* fSettings; port_id fMessagePort; + port_id fInputPort; BLocker fAppListLock; BList fAppList; diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index 10c1a62925..095d16e3a5 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -3,7 +3,7 @@ SubDir HAIKU_TOP src servers app ; AddResources app_server : app_server.rdef ; UseLibraryHeaders png zlib ; -UsePrivateHeaders app interface shared [ FDirName servers app ] ; +UsePrivateHeaders app input interface shared [ FDirName servers app ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; UseFreeTypeHeaders ; diff --git a/src/servers/app/RootLayer.cpp b/src/servers/app/RootLayer.cpp index 8d675d8e4d..95dac1f2a1 100644 --- a/src/servers/app/RootLayer.cpp +++ b/src/servers/app/RootLayer.cpp @@ -130,15 +130,15 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount, // Spawn our working thread fThreadID = spawn_thread(WorkingThread, name, B_DISPLAY_PRIORITY, this); - fListenPort = find_port(SERVER_INPUT_PORT); - if (fListenPort == B_NAME_NOT_FOUND) { - fListenPort = -1; - } #if ON_SCREEN_DEBUGGING_INFO DebugInfoManager::Default()->SetRootLayer(this); #endif fFrame = desktop->VirtualScreen().Frame(); + + // RootLayer starts with valid visible regions + fFullVisible.Set(Bounds()); + fVisible.Set(Bounds()); } @@ -194,12 +194,10 @@ RootLayer::WorkingThread(void *data) { RootLayer *oneRootLayer = (RootLayer*)data; - // first make sure we are actualy visible oneRootLayer->Lock(); + oneRootLayer->fListenPort = oneRootLayer->fDesktop->InputServerPort(); - // RootLayer starts with valid visible regions - oneRootLayer->fFullVisible.Set(oneRootLayer->Bounds()); - oneRootLayer->fVisible.Set(oneRootLayer->Bounds()); + // first make sure we are actualy visible oneRootLayer->MarkForRebuild(oneRootLayer->Bounds()); oneRootLayer->MarkForRedraw(oneRootLayer->Bounds()); @@ -208,12 +206,10 @@ RootLayer::WorkingThread(void *data) oneRootLayer->TriggerRedraw(); oneRootLayer->Unlock(); - + STRACE(("info: RootLayer(%s)::WorkingThread listening on port %ld.\n", oneRootLayer->Name(), oneRootLayer->fListenPort)); - while(!oneRootLayer->fQuiting) { - + while (!oneRootLayer->fQuiting) { BMessage *msg = oneRootLayer->ReadMessageFromPort(B_INFINITE_TIMEOUT); - if (msg) oneRootLayer->fQueue.AddMessage(msg); @@ -228,12 +224,11 @@ RootLayer::WorkingThread(void *data) bool dispatchNextMessage = true; while(dispatchNextMessage && !oneRootLayer->fQuiting) { BMessage *currentMessage = oneRootLayer->fQueue.NextMessage(); - + if (!currentMessage) // no more messages dispatchNextMessage = false; else { - oneRootLayer->Lock(); switch (currentMessage->what) { @@ -245,7 +240,7 @@ RootLayer::WorkingThread(void *data) case B_MOUSE_MOVED: case B_MOUSE_WHEEL_CHANGED: oneRootLayer->MouseEventHandler(currentMessage); - break; + break; case B_KEY_DOWN: case B_KEY_UP: @@ -253,15 +248,15 @@ RootLayer::WorkingThread(void *data) case B_UNMAPPED_KEY_UP: case B_MODIFIERS_CHANGED: oneRootLayer->KeyboardEventHandler(currentMessage); - break; + break; case B_QUIT_REQUESTED: exit_thread(0); - break; + break; default: printf("RootLayer(%s)::WorkingThread received unexpected code %lx\n", oneRootLayer->Name(), msg->what); - break; + break; } oneRootLayer->Unlock(); diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 11f073b548..ead3bfddfc 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include "AppServer.h" #include "BGet++.h" #include "BitmapManager.h" @@ -354,98 +356,6 @@ ServerApp::_MessageLooper() fQuitting = true; break; - case AS_CREATE_WINDOW: - case AS_CREATE_OFFSCREEN_WINDOW: - { - // Create a ServerWindow/OffscreenServerWindow - - // Attached data: - // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) - // 2) BRect window frame - // 3) uint32 window look - // 4) uint32 window feel - // 5) uint32 window flags - // 6) uint32 workspace index - // 7) int32 BHandler token of the window - // 8) port_id window's reply port - // 9) port_id window's looper port - // 10) const char * title - - BRect frame; - int32 bitmapToken; - uint32 look; - uint32 feel; - uint32 flags; - uint32 workspaces; - int32 token = B_NULL_TOKEN; - port_id clientReplyPort = -1; - port_id looperPort = -1; - char *title = NULL; - - if (code == AS_CREATE_OFFSCREEN_WINDOW) - receiver.Read(&bitmapToken); - - receiver.Read(&frame); - receiver.Read(&look); - receiver.Read(&feel); - receiver.Read(&flags); - receiver.Read(&workspaces); - receiver.Read(&token); - receiver.Read(&clientReplyPort); - receiver.Read(&looperPort); - if (receiver.ReadString(&title) != B_OK) - break; - - if (!frame.IsValid()) { - // make sure we pass a valid rectangle to ServerWindow - frame.right = frame.left + 1; - frame.bottom = frame.top + 1; - } - - status_t status = B_ERROR; - ServerWindow *window = NULL; - - if (code == AS_CREATE_OFFSCREEN_WINDOW) { - ServerBitmap* bitmap = FindBitmap(bitmapToken); - - if (bitmap != NULL) { - window = new OffscreenServerWindow(title, this, clientReplyPort, - looperPort, token, bitmap); - } - } else { - window = new ServerWindow(title, this, clientReplyPort, looperPort, token); - STRACE(("\nServerApp %s: New Window %s (%.1f,%.1f,%.1f,%.1f)\n", - fSignature(), title, frame.left, frame.top, frame.right, frame.bottom)); - } - - free(title); - - // NOTE: the reply to the client is handled in ServerWindow::Run() - if (window != NULL) { - status = window->Init(frame, look, feel, flags, workspaces); - if (status == B_OK && !window->Run()) - status = B_ERROR; - - // add the window to the list - if (status == B_OK && fWindowListLock.Lock()) { - status = fWindowList.AddItem(window) ? B_OK : B_NO_MEMORY; - fWindowListLock.Unlock(); - } - - if (status < B_OK) - delete window; - } - - // if sucessful, ServerWindow::Run() will already have replied - if (status < B_OK) { - // window creation failed, we need to notify the client - BPrivate::LinkSender reply(clientReplyPort); - reply.StartMessage(status); - reply.Flush(); - } - break; - } - case AS_QUIT_APP: { // This message is received only when the app_server is asked to shut down in @@ -497,6 +407,117 @@ void ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) { switch (code) { + case AS_REGISTER_INPUT_SERVER: + { + BMessage message(IS_ACQUIRE_INPUT); + SendMessageToClient(&message); + break; + } + case AS_ACQUIRED_INPUT_STREAM: + { + bool hasKeyboard, hasMouse; + link.Read(&hasKeyboard); + link.Read(&hasMouse); + + port_id port; + link.Read(&port); + sem_id sem; + if (link.Read(&sem) == B_OK) + fDesktop->RegisterInputServer(port); + break; + } + case AS_CREATE_WINDOW: + case AS_CREATE_OFFSCREEN_WINDOW: + { + // Create a ServerWindow/OffscreenServerWindow + + // Attached data: + // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) + // 2) BRect window frame + // 3) uint32 window look + // 4) uint32 window feel + // 5) uint32 window flags + // 6) uint32 workspace index + // 7) int32 BHandler token of the window + // 8) port_id window's reply port + // 9) port_id window's looper port + // 10) const char * title + + BRect frame; + int32 bitmapToken; + uint32 look; + uint32 feel; + uint32 flags; + uint32 workspaces; + int32 token = B_NULL_TOKEN; + port_id clientReplyPort = -1; + port_id looperPort = -1; + char *title = NULL; + + if (code == AS_CREATE_OFFSCREEN_WINDOW) + link.Read(&bitmapToken); + + link.Read(&frame); + link.Read(&look); + link.Read(&feel); + link.Read(&flags); + link.Read(&workspaces); + link.Read(&token); + link.Read(&clientReplyPort); + link.Read(&looperPort); + if (link.ReadString(&title) != B_OK) + break; + + if (!frame.IsValid()) { + // make sure we pass a valid rectangle to ServerWindow + frame.right = frame.left + 1; + frame.bottom = frame.top + 1; + } + + status_t status = B_ERROR; + ServerWindow *window = NULL; + + if (code == AS_CREATE_OFFSCREEN_WINDOW) { + ServerBitmap* bitmap = FindBitmap(bitmapToken); + + if (bitmap != NULL) { + window = new OffscreenServerWindow(title, this, clientReplyPort, + looperPort, token, bitmap); + } + } else { + window = new ServerWindow(title, this, clientReplyPort, looperPort, token); + STRACE(("\nServerApp %s: New Window %s (%.1f,%.1f,%.1f,%.1f)\n", + fSignature(), title, frame.left, frame.top, frame.right, frame.bottom)); + } + + free(title); + + // NOTE: the reply to the client is handled in ServerWindow::Run() + if (window != NULL) { + status = window->Init(frame, look, feel, flags, workspaces); + if (status == B_OK && !window->Run()) + status = B_ERROR; + + // add the window to the list + if (status == B_OK && fWindowListLock.Lock()) { + status = fWindowList.AddItem(window) ? B_OK : B_NO_MEMORY; + fWindowListLock.Unlock(); + } + + if (status < B_OK) + delete window; + } + + // if sucessful, ServerWindow::Run() will already have replied + if (status < B_OK) { + // window creation failed, we need to notify the client + BPrivate::LinkSender reply(clientReplyPort); + reply.StartMessage(status); + reply.Flush(); + } + break; + } + case AS_GET_WINDOW_LIST: team_id team; link.Read(&team); diff --git a/src/servers/app/drawing/ViewHWInterface.cpp b/src/servers/app/drawing/ViewHWInterface.cpp index 06a54eaee8..bdb66d9607 100644 --- a/src/servers/app/drawing/ViewHWInterface.cpp +++ b/src/servers/app/drawing/ViewHWInterface.cpp @@ -162,7 +162,7 @@ CardView::CardView(BRect bounds) SetViewColor(B_TRANSPARENT_32_BIT); #ifndef INPUTSERVER_TEST_MODE - fInputPort = find_port(SERVER_INPUT_PORT); + fInputPort = create_port(200, SERVER_INPUT_PORT); #else fInputPort = create_port(100, "ViewInputDevice"); #endif diff --git a/src/servers/input/InputServer.cpp b/src/servers/input/InputServer.cpp index 9e6685da47..1a1badd878 100644 --- a/src/servers/input/InputServer.cpp +++ b/src/servers/input/InputServer.cpp @@ -9,6 +9,8 @@ #include "kb_mouse_driver.h" #include "MethodReplicant.h" +#include + #include #include #include @@ -139,7 +141,10 @@ InputServer::InputServer() fChars(NULL), fScreen(B_MAIN_SCREEN_ID), fBLWindow(NULL), - fIMAware(false) + fIMAware(false), + fCursorSem(-1), + fAppServerPort(-1), + fCursorArea(-1) { #if DEBUG == 2 if (sLogFile == NULL) @@ -168,7 +173,7 @@ InputServer::InputServer() gDeviceManager.LoadState(); -#ifdef R5_CURSOR_COMM +#ifndef HAIKU_TARGET_PLATFORM_HAIKU if (has_data(find_thread(NULL))) { PRINT(("HasData == YES\n")); int32 buffer[2]; @@ -183,28 +188,24 @@ InputServer::InputServer() fCursorSem = buffer[0]; area_id appArea = buffer[1]; - fCloneArea = clone_area("isClone", (void**)&fAppBuffer, B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, appArea); - if (fCloneArea < B_OK) { + fCursorArea = clone_area("isClone", (void**)&fCursorBuffer, + B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, appArea); + if (fCursorArea < B_OK) { PRINTERR(("clone_area error : %s\n", strerror(fCloneArea))); } - fAsPort = create_port(100, "is_as"); + fAppServerPort = create_port(100, "is_as"); - PRINT(("is_as port :%ld\n", fAsPort)); + PRINT(("is_as port :%ld\n", fAppServerPort)); buffer[1] = fEventLooperPort; - buffer[0] = fAsPort; + buffer[0] = fAppServerPort; status_t err; if ((err = send_data(appThreadId, 0, buffer, sizeof(buffer)))!=B_OK) PRINTERR(("error when send_data %s\n", strerror(err))); } #endif -#ifdef HAIKU_APPSERVER_COMM - fAsPort = find_port(SERVER_INPUT_PORT); - if (fAsPort == B_NAME_NOT_FOUND) - PRINTERR(("input_server couldn't find app_server's input port\n")); -#endif _InitKeyboardMouseStates(); @@ -221,13 +222,8 @@ InputServer::~InputServer() CALLED(); fAddOnManager->Lock(); fAddOnManager->Quit(); - -#ifdef R5_CURSOR_COMM - delete_port(fAsPort); - fAsPort = -1; - fAppBuffer = NULL; - delete_area(fCloneArea); -#endif // R5_CURSOR_COMM + + _ReleaseInput(NULL); #if DEBUG == 2 fclose(sLogFile); @@ -264,8 +260,8 @@ InputServer::_InitKeyboardMouseStates() fFrame = BRect(0, 0, 800, 600); fMousePos = BPoint(fFrame.right / 2, fFrame.bottom / 2); - if (LoadKeymap() != B_OK) - LoadSystemKeymap(); + if (_LoadKeymap() != B_OK) + _LoadSystemKeymap(); BMessage *msg = new BMessage(B_MOUSE_MOVED); HandleSetMousePosition(msg, msg); @@ -275,7 +271,7 @@ InputServer::_InitKeyboardMouseStates() status_t -InputServer::LoadKeymap() +InputServer::_LoadKeymap() { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path)!=B_OK) @@ -316,7 +312,7 @@ InputServer::LoadKeymap() status_t -InputServer::LoadSystemKeymap() +InputServer::_LoadSystemKeymap() { delete[] fChars; fKeys = sSystemKeymap; @@ -381,8 +377,8 @@ InputServer::QuitRequested() fAddOnManager->SaveState(); gDeviceManager.SaveState(); - kill_thread(fISPortThread); delete_port(fEventLooperPort); + // the event looper thread will exit after this fEventLooperPort = -1; return true; } @@ -392,6 +388,75 @@ void InputServer::ReadyToRun() { CALLED(); + + // say hello to the app_server + + BPrivate::AppServerLink link; + link.StartMessage(AS_REGISTER_INPUT_SERVER); + link.Flush(); +} + + +status_t +InputServer::_AcquireInput(BMessage& message, BMessage& reply) +{ + // TODO: it currently just gets everything we have + area_id area; + if (message.FindInt32("cursor_area", &area) == B_OK) { + // try to clone the area + fCursorBuffer = NULL; + + fCursorSem = create_sem(0, "cursor semaphore"); + if (fCursorSem >= B_OK) { + fCursorArea = clone_area("input server cursor", (void**)&fCursorBuffer, + B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area); + } + } + + fAppServerPort = create_port(200, "input server target"); + if (fAppServerPort < B_OK) { + _ReleaseInput(&message); + return fAppServerPort; + } + + // TODO: would be nice if we could just reply to this message... +#if 0 + reply.AddBool("has_keyboard", true); + reply.AddBool("has_mouse", true); + reply.AddInt32("event port", fAppServerPort); + + if (fCursorBuffer != NULL) { + // cursor shared buffer is supported + reply.AddInt32("cursor semaphore", fCursorSem); + } +#else + BPrivate::AppServerLink link; + link.StartMessage(AS_ACQUIRED_INPUT_STREAM); + link.Attach(true); + link.Attach(true); + link.Attach(fAppServerPort); + link.Attach(fCursorSem); + link.Flush(); +#endif + return B_OK; +} + + +void +InputServer::_ReleaseInput(BMessage* /*message*/) +{ + if (fCursorBuffer != NULL) { + fCursorBuffer = NULL; +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + delete_sem(fCursorSem); +#endif + delete_area(fCursorArea); + + fCursorSem = -1; + fCursorArea = -1; + } + + delete_port(fAppServerPort); } @@ -483,6 +548,14 @@ InputServer::MessageReceived(BMessage* message) status = HandleFocusUnfocusIMAwareView(message, &reply); break; + // app_server communication + case IS_ACQUIRE_INPUT: + _AcquireInput(*message, reply); + return; + case IS_RELEASE_INPUT: + _ReleaseInput(message); + return; + // device looper related case IS_FIND_DEVICES: case IS_WATCH_DEVICES: @@ -494,6 +567,7 @@ InputServer::MessageReceived(BMessage* message) case IS_METHOD_REGISTER: fAddOnManager->PostMessage(message); return; + case B_SOME_APP_LAUNCHED: { const char *signature; @@ -686,7 +760,7 @@ InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply) status_t -InputServer::HandleSetMousePosition(BMessage *message, BMessage *outbound) +InputServer::HandleSetMousePosition(BMessage* message, BMessage* outbound) { CALLED(); @@ -719,18 +793,24 @@ InputServer::HandleSetMousePosition(BMessage *message, BMessage *outbound) outbound->AddInt32("modifiers", fKeyInfo.modifiers); PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y)); } -#ifdef R5_CURSOR_COMM - if (fAppBuffer) { - fAppBuffer[0] = (0x3 << 30L) + + if (fCursorBuffer) { +#ifndef HAIKU_TARGET_PLATFORM_HAIKU + fCursorBuffer[0] = (0x3 << 30L) | ((uint32)fMousePos.x & 0x7fff) << 15 | ((uint32)fMousePos.y & 0x7fff); - PRINT(("released cursorSem with value : %08lx\n", fAppBuffer[0])); + PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0])); release_sem(fCursorSem); - } +#else + atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL + | ((uint32)fMousePos.y & 0xffff)); + if (atomic_or(&fCursorBuffer->read, 1) == 0) + release_sem_etc(fCursorSem, 0, B_RELEASE_ALL); #endif + } break; - + // some Key Down and up codes .. case B_KEY_DOWN: case B_KEY_UP: @@ -833,8 +913,8 @@ InputServer::HandleGetSetKeyMap(BMessage* message, BMessage* reply) return status; } - if (LoadKeymap() != B_OK) - LoadSystemKeymap(); + if (_LoadKeymap() != B_OK) + _LoadSystemKeymap(); BMessage msg(IS_CONTROL_DEVICES); msg.AddInt32("type", B_KEYBOARD_DEVICE); @@ -873,6 +953,9 @@ InputServer::EnqueueDeviceMessage(BMessage* message) { CALLED(); + // TODO: message is not deleted??? + // TODO: why use ports for in-house messaging??? + ssize_t length = message->FlattenedSize(); char buffer[length]; status_t err; @@ -980,23 +1063,31 @@ status_t InputServer::EventLoop() { CALLED(); - fEventLooperPort = create_port(100, "haiku_is_event_port"); + fEventLooperPort = create_port(100, "input server event loop"); if (fEventLooperPort < 0) { PRINTERR(("InputServer: create_port error: (0x%x) %s\n", fEventLooperPort, strerror(fEventLooperPort))); - } + return fEventLooperPort; + } - fISPortThread = spawn_thread(ISPortWatcher, "_input_server_event_loop_", + thread_id thread = spawn_thread(_PortWatcher, "_input_server_event_loop_", B_REAL_TIME_DISPLAY_PRIORITY + 3, this); - resume_thread(fISPortThread); - return 0; + if (thread < B_OK || resume_thread(thread) < B_OK) { + if (thread >= B_OK) + kill_thread(thread); + delete_port(fEventLooperPort); + fEventLooperPort = -1; + return thread < B_OK ? thread : B_ERROR; + } + + return B_OK; } bool InputServer::EventLoopRunning() { - return fEventLooperPort > -1; + return fEventLooperPort >= B_OK; } @@ -1070,8 +1161,8 @@ InputServer::DispatchEvent(BMessage* message) if ((err = message->Flatten(buffer,length)) < B_OK) return err; - if (fAsPort > 0) - write_port(fAsPort, 0, buffer, length); + if (fAppServerPort > 0) + write_port(fAppServerPort, 0, buffer, length); return B_OK; } @@ -1481,21 +1572,26 @@ InputServer::SafeMode() int32 -InputServer::ISPortWatcher(void* arg) +InputServer::_PortWatcher(void* arg) { InputServer* self = (InputServer*)arg; - self->WatchPort(); + self->_WatchPort(); return B_OK; } void -InputServer::WatchPort() +InputServer::_WatchPort() { while (true) { // Block until we find the size of the next message ssize_t length = port_buffer_size(fEventLooperPort); + if (length < B_OK) { + PRINT("[Event Looper] port gone, exiting.\n"); + return; + } + PRINT(("[Event Looper] BMessage Size = %lu\n", length)); char buffer[length]; @@ -1522,7 +1618,7 @@ InputServer::WatchPort() PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err))); delete event; continue; - } + } // This is where the message should be processed. diff --git a/src/servers/input/InputServer.h b/src/servers/input/InputServer.h index 7d71e00391..49c64c4498 100644 --- a/src/servers/input/InputServer.h +++ b/src/servers/input/InputServer.h @@ -12,6 +12,8 @@ #include "KeyboardSettings.h" #include "MouseSettings.h" +#include "shared_cursor_area.h" + #include #include #include @@ -30,20 +32,9 @@ #include -#define HAIKU_APPSERVER_COMM -#define R5_CURSOR_COMM - // define this when R5 cursor communication should be used -//#define APPSERVER_R5_COMM - // define this when R5 app_server communication should be used - #define INPUTSERVER_SIGNATURE "application/x-vnd.Be-input_server" // use this when target should replace R5 input_server -#ifdef APPSERVER_R5_COMM - #define R5_CURSOR_COMM - #undef HAIKU_APPSERVER_COMM -#endif - class InputDeviceListItem { public: InputDeviceListItem(BInputServerDevice& serverDevice, input_device_ref& device); @@ -185,13 +176,16 @@ class InputServer : public BApplication { private: typedef BApplication _inherited; - status_t LoadKeymap(); - status_t LoadSystemKeymap(); + status_t _LoadKeymap(); + status_t _LoadSystemKeymap(); void _InitKeyboardMouseStates(); - void WatchPort(); + status_t _AcquireInput(BMessage& message, BMessage& reply); + void _ReleaseInput(BMessage* message); - static int32 ISPortWatcher(void *arg); + void _WatchPort(); + + static int32 _PortWatcher(void *arg); // static bool doStartStopDevice(void*, void*); InputDeviceListItem* _FindInputDeviceListItem(BInputServerDevice& device); @@ -205,7 +199,6 @@ class InputServer : public BApplication { BList fInputDeviceList; BLocker fInputDeviceListLocker; - KeyboardSettings fKeyboardSettings; MouseSettings fMouseSettings; @@ -216,7 +209,6 @@ class InputServer : public BApplication { uint32 fCharsSize; // current keymap char count port_id fEventLooperPort; - thread_id fISPortThread; AddOnManager* fAddOnManager; @@ -230,12 +222,14 @@ class InputServer : public BApplication { const BMessenger* fReplicantMessenger; BottomlineWindow* fBLWindow; bool fIMAware; - -#ifdef R5_CURSOR_COMM + sem_id fCursorSem; - port_id fAsPort; - area_id fCloneArea; - uint32* fAppBuffer; + port_id fAppServerPort; + area_id fCursorArea; +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + shared_cursor* fCursorBuffer; +#else + uint32* fCursorBuffer; #endif #if DEBUG == 2