* 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:
parent
af8899c4bf
commit
6c17d02551
@ -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
|
||||
|
@ -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 */
|
||||
|
21
headers/private/input/shared_cursor_area.h
Normal file
21
headers/private/input/shared_cursor_area.h
Normal 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 */
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 ;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user