* 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
This commit is contained in:
Axel Dörfler 2005-11-15 19:59:53 +00:00
parent af8899c4bf
commit 6c17d02551
13 changed files with 345 additions and 217 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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 <SupportDefs.h>
struct shared_cursor {
uint32 pos;
int32 read;
};
#endif /* SHARED_CURSOR_AREA_H */

View File

@ -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

View File

@ -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<Desktop> fDesktops;
BLocker fDesktopLock;
port_id fISASPort;
port_id fISPort;
};
extern BitmapManager *gBitmapManager;

View File

@ -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

View File

@ -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;

View File

@ -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 ;

View File

@ -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();

View File

@ -31,6 +31,8 @@
#include <ServerProtocol.h>
#include <FontPrivate.h>
#include <InputServerTypes.h>
#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<int32>(&bitmapToken);
receiver.Read<BRect>(&frame);
receiver.Read<uint32>(&look);
receiver.Read<uint32>(&feel);
receiver.Read<uint32>(&flags);
receiver.Read<uint32>(&workspaces);
receiver.Read<int32>(&token);
receiver.Read<port_id>(&clientReplyPort);
receiver.Read<port_id>(&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<bool>(&hasKeyboard);
link.Read<bool>(&hasMouse);
port_id port;
link.Read<int32>(&port);
sem_id sem;
if (link.Read<int32>(&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<int32>(&bitmapToken);
link.Read<BRect>(&frame);
link.Read<uint32>(&look);
link.Read<uint32>(&feel);
link.Read<uint32>(&flags);
link.Read<uint32>(&workspaces);
link.Read<int32>(&token);
link.Read<port_id>(&clientReplyPort);
link.Read<port_id>(&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_id>(&team);

View File

@ -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

View File

@ -9,6 +9,8 @@
#include "kb_mouse_driver.h"
#include "MethodReplicant.h"
#include <AppServerLink.h>
#include <Autolock.h>
#include <Deskbar.h>
#include <Directory.h>
@ -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<bool>(true);
link.Attach<bool>(true);
link.Attach<int32>(fAppServerPort);
link.Attach<int32>(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.

View File

@ -12,6 +12,8 @@
#include "KeyboardSettings.h"
#include "MouseSettings.h"
#include "shared_cursor_area.h"
#include <Application.h>
#include <Debug.h>
#include <FindDirectory.h>
@ -30,20 +32,9 @@
#include <unistd.h>
#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