With the recent changes to the communication mechanism, fake_app_server
did not work anymore, and thus, the safemode with the current Bootscript did not work. It now does again. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13192 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -24,34 +24,32 @@
|
|||||||
// Description: main manager object for the app_server
|
// Description: main manager object for the app_server
|
||||||
//
|
//
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#include <AppDefs.h>
|
|
||||||
#include <Accelerant.h>
|
#include <Accelerant.h>
|
||||||
#include <Entry.h>
|
#include <AppDefs.h>
|
||||||
#include <Path.h>
|
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <PortLink.h>
|
#include <Entry.h>
|
||||||
|
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include "AppServer.h"
|
#include <Path.h>
|
||||||
#include "ServerProtocol.h"
|
#include <PortLink.h>
|
||||||
#include "ServerApp.h"
|
#include <StopWatch.h>
|
||||||
#include <TokenSpace.h>
|
|
||||||
#if 0
|
#include "BitmapManager.h"
|
||||||
#include "ColorSet.h"
|
#include "ColorSet.h"
|
||||||
#include "DisplayDriver.h"
|
#include "DisplayDriver.h"
|
||||||
#include "ServerCursor.h"
|
|
||||||
#include "ServerWindow.h"
|
|
||||||
#include "DefaultDecorator.h"
|
|
||||||
#include "RGBColor.h"
|
|
||||||
#include "BitmapManager.h"
|
|
||||||
#include "CursorManager.h"
|
|
||||||
#include "Utils.h"
|
|
||||||
#include "FontServer.h"
|
#include "FontServer.h"
|
||||||
#include "Desktop.h"
|
#include "RegistrarDefs.h"
|
||||||
#include "RootLayer.h"
|
#include "RGBColor.h"
|
||||||
#endif
|
#include "ServerApp.h"
|
||||||
#include <StopWatch.h>
|
#include "ServerCursor.h"
|
||||||
|
#include "ServerProtocol.h"
|
||||||
|
#include "SystemPalette.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
#include "AppServer.h"
|
||||||
|
|
||||||
|
//#define DEBUG_KEYHANDLING
|
||||||
|
//#define DEBUG_SERVER
|
||||||
|
|
||||||
#ifdef DEBUG_KEYHANDLING
|
#ifdef DEBUG_KEYHANDLING
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
@@ -60,63 +58,133 @@
|
|||||||
# define KBTRACE(x) ;
|
# define KBTRACE(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define DEBUG_SERVER
|
|
||||||
#ifdef DEBUG_SERVER
|
#ifdef DEBUG_SERVER
|
||||||
# define DEBUG 1
|
# include <stdio.h>
|
||||||
# include <Debug.h>
|
# define STRACE(x) printf x
|
||||||
# define STRACE(x) _sPrintf x
|
|
||||||
#else
|
#else
|
||||||
# define STRACE(x) ;
|
# define STRACE(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Globals
|
// Globals
|
||||||
|
|
||||||
|
port_id gAppServerPort;
|
||||||
|
|
||||||
|
//! Used to access the app_server from new_decorator
|
||||||
|
static AppServer *sAppServer = NULL;
|
||||||
|
|
||||||
|
//! Default background color for workspaces
|
||||||
|
//RGBColor workspace_default_color(51,102,160);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Constructor
|
||||||
|
|
||||||
|
This loads the default fonts, allocates all the major global variables, spawns the main housekeeping
|
||||||
|
threads, loads user preferences for the UI and decorator, and allocates various locks.
|
||||||
|
*/
|
||||||
AppServer::AppServer(void)
|
AppServer::AppServer(void)
|
||||||
|
:
|
||||||
|
fCursorSem(-1),
|
||||||
|
fCursorArea(-1)
|
||||||
{
|
{
|
||||||
fMessagePort = create_port(200, SERVER_PORT_NAME);
|
fMessagePort = create_port(200, SERVER_PORT_NAME);
|
||||||
|
if (fMessagePort == B_NO_MORE_PORTS)
|
||||||
|
debugger("app_server could not create message port");
|
||||||
|
|
||||||
fAppList = new BList(0);
|
gAppServerPort = fMessagePort;
|
||||||
fQuittingServer= false;
|
|
||||||
|
// 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_NO_MORE_PORTS)
|
||||||
|
debugger("app_server could not create input port");
|
||||||
|
|
||||||
|
fAppList = new BList();
|
||||||
|
fQuittingServer = false;
|
||||||
|
make_decorator = NULL;
|
||||||
|
|
||||||
|
// We need this in order for new_decorator to be able to instantiate new decorators
|
||||||
|
sAppServer = this;
|
||||||
|
|
||||||
// This is necessary to mediate access between the Poller and app_server threads
|
// This is necessary to mediate access between the Poller and app_server threads
|
||||||
fActiveAppLock= create_sem(1,"app_server_active_sem");
|
fActiveAppLock = create_sem(1,"app_server_active_sem");
|
||||||
|
|
||||||
// This locker is for app_server and Picasso to vy for control of the ServerApp list
|
// This locker is for app_server and Picasso to vy for control of the ServerApp list
|
||||||
fAppListLock= create_sem(1,"app_server_applist_sem");
|
fAppListLock = create_sem(1,"app_server_applist_sem");
|
||||||
|
|
||||||
|
// This locker is to mediate access to the make_decorator pointer
|
||||||
|
fDecoratorLock = create_sem(1,"app_server_decor_sem");
|
||||||
|
|
||||||
// Spawn our thread-monitoring thread
|
// Spawn our thread-monitoring thread
|
||||||
fPicassoThreadID= spawn_thread(PicassoThread,"picasso", B_NORMAL_PRIORITY, this);
|
fPicassoThreadID = spawn_thread(PicassoThread, "picasso", B_NORMAL_PRIORITY, this);
|
||||||
if (fPicassoThreadID >= 0)
|
if (fPicassoThreadID >= 0)
|
||||||
resume_thread(fPicassoThreadID);
|
resume_thread(fPicassoThreadID);
|
||||||
|
|
||||||
|
fDecoratorName ="Default";
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LaunchCursorThread();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Destructor
|
||||||
|
|
||||||
|
Reached only when the server is asked to shut down in Test mode. Kills all apps, shuts down the
|
||||||
|
desktop, kills the housekeeping threads, etc.
|
||||||
|
*/
|
||||||
AppServer::~AppServer(void)
|
AppServer::~AppServer(void)
|
||||||
{
|
{
|
||||||
|
debugger("We shouldn't be here! MainLoop()::B_QUIT_REQUESTED should see if we can exit the server.\n");
|
||||||
|
/*
|
||||||
|
ServerApp *tempapp;
|
||||||
|
int32 i;
|
||||||
|
acquire_sem(fAppListLock);
|
||||||
|
for(i=0;i<fAppList->CountItems();i++)
|
||||||
|
{
|
||||||
|
tempapp=(ServerApp *)fAppList->ItemAt(i);
|
||||||
|
if(tempapp!=NULL)
|
||||||
|
delete tempapp;
|
||||||
|
}
|
||||||
|
delete fAppList;
|
||||||
|
release_sem(fAppListLock);
|
||||||
|
|
||||||
|
delete bitmapmanager;
|
||||||
|
|
||||||
|
delete gDesktop;
|
||||||
|
|
||||||
|
// If these threads are still running, kill them - after this, if exit_poller
|
||||||
|
// is deleted, who knows what will happen... These things will just return an
|
||||||
|
// error and fail if the threads have already exited.
|
||||||
|
kill_thread(fPicassoThreadID);
|
||||||
|
kill_thread(fCursorThreadID);
|
||||||
|
kill_thread(fISThreadID);
|
||||||
|
|
||||||
|
delete fontserver;
|
||||||
|
|
||||||
|
make_decorator=NULL;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Thread function for watching for dead apps
|
||||||
|
\param data Pointer to the app_server to which the thread belongs
|
||||||
|
\return Throwaway value - always 0
|
||||||
|
*/
|
||||||
int32
|
int32
|
||||||
AppServer::PicassoThread(void *data)
|
AppServer::PicassoThread(void *data)
|
||||||
{
|
{
|
||||||
int32 i;
|
for (;;) {
|
||||||
AppServer *appserver=(AppServer*)data;
|
acquire_sem(sAppServer->fAppListLock);
|
||||||
ServerApp *app;
|
for (int32 i = 0;;) {
|
||||||
for(;;)
|
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i++);
|
||||||
{
|
if (!app)
|
||||||
i = 0;
|
|
||||||
#if 1
|
|
||||||
acquire_sem(appserver->fAppListLock);
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
app=(ServerApp*)appserver->fAppList->ItemAt(i++);
|
|
||||||
if(!app)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
app->PingTarget();
|
app->PingTarget();
|
||||||
}
|
}
|
||||||
release_sem(appserver->fAppListLock);
|
release_sem(sAppServer->fAppListLock);
|
||||||
#endif
|
|
||||||
// we do this every other second so as not to suck *too* many CPU cycles
|
// we do this every other second so as not to suck *too* many CPU cycles
|
||||||
snooze(1000000);
|
snooze(1000000);
|
||||||
}
|
}
|
||||||
@@ -124,6 +192,28 @@ AppServer::PicassoThread(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Starts Input Server
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
AppServer::LaunchInputServer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Starts the Cursor Thread
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
AppServer::LaunchCursorThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief The call that starts it all...
|
||||||
|
\return Always 0
|
||||||
|
*/
|
||||||
thread_id
|
thread_id
|
||||||
AppServer::Run(void)
|
AppServer::Run(void)
|
||||||
{
|
{
|
||||||
@@ -137,23 +227,19 @@ AppServer::Run(void)
|
|||||||
void
|
void
|
||||||
AppServer::MainLoop(void)
|
AppServer::MainLoop(void)
|
||||||
{
|
{
|
||||||
BPrivate::PortLink pmsg(-1,fMessagePort);
|
BPrivate::PortLink pmsg(-1, fMessagePort);
|
||||||
int32 code=0;
|
|
||||||
status_t err=B_OK;
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
|
|
||||||
err=pmsg.GetNextMessage(code);
|
|
||||||
|
|
||||||
if(err<B_OK)
|
while (1) {
|
||||||
{
|
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
|
||||||
STRACE(("MainLoop:pmsg.GetNextMessage failed\n"));
|
|
||||||
|
int32 code;
|
||||||
|
status_t err = pmsg.GetNextMessage(code);
|
||||||
|
if (err < B_OK) {
|
||||||
|
STRACE(("MainLoop:pmsg.GetNextMessage() failed\n"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(code)
|
switch (code) {
|
||||||
{
|
|
||||||
case B_QUIT_REQUESTED:
|
case B_QUIT_REQUESTED:
|
||||||
case AS_CREATE_APP:
|
case AS_CREATE_APP:
|
||||||
case AS_DELETE_APP:
|
case AS_DELETE_APP:
|
||||||
@@ -164,25 +250,114 @@ AppServer::MainLoop(void)
|
|||||||
case AS_SET_DECORATOR:
|
case AS_SET_DECORATOR:
|
||||||
case AS_GET_DECORATOR:
|
case AS_GET_DECORATOR:
|
||||||
case AS_R5_SET_DECORATOR:
|
case AS_R5_SET_DECORATOR:
|
||||||
DispatchMessage(code,pmsg);
|
DispatchMessage(code, pmsg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
STRACE(("Server::MainLoop received unexpected code %ld(offset %ld)\n",
|
STRACE(("Server::MainLoop received unexpected code %ld (offset %ld)\n",
|
||||||
code,code-SERVER_TRUE));
|
code, code - SERVER_TRUE));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Loads the specified decorator and sets the system's decorator to it.
|
||||||
|
\param path Path to the decorator to load
|
||||||
|
\return True if successful, false if not.
|
||||||
|
|
||||||
|
If the server cannot load the specified decorator, nothing changes. Passing a
|
||||||
|
NULL string to this function sets the decorator to the internal one.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
AppServer::LoadDecorator(const char *path)
|
||||||
|
{
|
||||||
|
// Loads a window decorator based on the supplied path and forces a decorator update.
|
||||||
|
// If it cannot load the specified decorator, it will retain the current one and
|
||||||
|
// return false. Note that passing a NULL string to this function sets the decorator
|
||||||
|
// to the internal one.
|
||||||
|
|
||||||
|
// passing the string "Default" will set the window decorator to the app_server's
|
||||||
|
// internal one
|
||||||
|
if(!path)
|
||||||
|
{
|
||||||
|
make_decorator= NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_decorator *pcreatefunc= NULL;
|
||||||
|
status_t stat;
|
||||||
|
image_id addon;
|
||||||
|
|
||||||
|
addon = load_add_on(path);
|
||||||
|
if (addon < B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// As of now, we do nothing with decorator versions, but the possibility exists
|
||||||
|
// that the API will change even though I cannot forsee any reason to do so. If
|
||||||
|
// we *did* do anything with decorator versions, the assignment to a global would
|
||||||
|
// go here.
|
||||||
|
|
||||||
|
// Get the instantiation function
|
||||||
|
stat = get_image_symbol(addon, "instantiate_decorator",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void**)&pcreatefunc);
|
||||||
|
if (stat != B_OK) {
|
||||||
|
unload_add_on(addon);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPath temppath(path);
|
||||||
|
fDecoratorName=temppath.Leaf();
|
||||||
|
|
||||||
|
acquire_sem(fDecoratorLock);
|
||||||
|
make_decorator=pcreatefunc;
|
||||||
|
fDecoratorID=addon;
|
||||||
|
release_sem(fDecoratorLock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Loads decorator settings on disk or the default if settings are invalid
|
||||||
|
void
|
||||||
|
AppServer::InitDecorators(void)
|
||||||
|
{
|
||||||
|
BMessage settings;
|
||||||
|
|
||||||
|
BDirectory dir;
|
||||||
|
if (dir.SetTo(SERVER_SETTINGS_DIR) == B_ENTRY_NOT_FOUND)
|
||||||
|
create_directory(SERVER_SETTINGS_DIR, 0777);
|
||||||
|
|
||||||
|
BString path(SERVER_SETTINGS_DIR);
|
||||||
|
path += "DecoratorSettings";
|
||||||
|
BFile file(path.String(), B_READ_ONLY);
|
||||||
|
|
||||||
|
if (file.InitCheck() == B_OK
|
||||||
|
&& settings.Unflatten(&file) == B_OK) {
|
||||||
|
BString itemtext;
|
||||||
|
if (settings.FindString("decorator", &itemtext) == B_OK) {
|
||||||
|
path.SetTo(DECORATORS_DIR);
|
||||||
|
path += itemtext;
|
||||||
|
if (LoadDecorator(path.String()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We got this far, so something must have gone wrong. We set make_decorator
|
||||||
|
// to NULL so that the decorator allocation routine knows to utilize the included
|
||||||
|
// default decorator instead of an addon.
|
||||||
|
make_decorator = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Message handling function for all messages sent to the app_server
|
||||||
|
\param code ID of the message sent
|
||||||
|
\param buffer Attachment buffer for the message.
|
||||||
|
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||||
{
|
{
|
||||||
switch(code)
|
switch (code) {
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
case AS_CREATE_APP:
|
case AS_CREATE_APP:
|
||||||
{
|
{
|
||||||
// Create the ServerApp to node monitor a new BApplication
|
// Create the ServerApp to node monitor a new BApplication
|
||||||
@@ -195,81 +370,78 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
|||||||
// 4) char * - signature of the regular app
|
// 4) char * - signature of the regular app
|
||||||
|
|
||||||
// Find the necessary data
|
// Find the necessary data
|
||||||
team_id clientTeamID=-1;
|
team_id clientTeamID = -1;
|
||||||
port_id clientLooperPort=-1;
|
port_id clientLooperPort = -1;
|
||||||
port_id app_port=-1;
|
port_id clientReplyPort = -1;
|
||||||
int32 htoken=B_NULL_TOKEN;
|
int32 htoken = B_NULL_TOKEN;
|
||||||
char *app_signature=NULL;
|
char *appSignature = NULL;
|
||||||
|
|
||||||
msg.Read<port_id>(&app_port);
|
msg.Read<port_id>(&clientReplyPort);
|
||||||
msg.Read<port_id>(&clientLooperPort);
|
msg.Read<port_id>(&clientLooperPort);
|
||||||
msg.Read<team_id>(&clientTeamID);
|
msg.Read<team_id>(&clientTeamID);
|
||||||
msg.Read<int32>(&htoken);
|
msg.Read<int32>(&htoken);
|
||||||
msg.ReadString(&app_signature);
|
if (msg.ReadString(&appSignature) != B_OK)
|
||||||
|
break;
|
||||||
// Create the ServerApp subthread for this app
|
|
||||||
acquire_sem(fAppListLock);
|
port_id serverListen = create_port(DEFAULT_MONITOR_PORT_SIZE, appSignature);
|
||||||
|
if (serverListen < B_OK) {
|
||||||
port_id server_listen=create_port(DEFAULT_MONITOR_PORT_SIZE, app_signature);
|
|
||||||
if(server_listen<B_OK)
|
|
||||||
{
|
|
||||||
release_sem(fAppListLock);
|
|
||||||
printf("No more ports left. Time to crash. Have a nice day! :)\n");
|
printf("No more ports left. Time to crash. Have a nice day! :)\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ServerApp *newapp=NULL;
|
|
||||||
newapp= new ServerApp(app_port,server_listen, clientLooperPort, clientTeamID,
|
// we let the application own the port, so that we get aware when it's gone
|
||||||
htoken, app_signature);
|
if (set_port_owner(serverListen, clientTeamID) < B_OK) {
|
||||||
|
delete_port(serverListen);
|
||||||
|
printf("Could not transfer port ownership to client %ld!\n", clientTeamID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the ServerApp subthread for this app
|
||||||
|
acquire_sem(fAppListLock);
|
||||||
|
|
||||||
|
ServerApp *app = new ServerApp(clientReplyPort, serverListen, clientLooperPort,
|
||||||
|
clientTeamID, htoken, appSignature);
|
||||||
|
|
||||||
// add the new ServerApp to the known list of ServerApps
|
// add the new ServerApp to the known list of ServerApps
|
||||||
fAppList->AddItem(newapp);
|
fAppList->AddItem(app);
|
||||||
|
|
||||||
release_sem(fAppListLock);
|
release_sem(fAppListLock);
|
||||||
|
|
||||||
BPrivate::PortLink replylink(app_port);
|
BPrivate::PortLink replylink(clientReplyPort);
|
||||||
replylink.StartMessage(SERVER_TRUE);
|
replylink.StartMessage(SERVER_TRUE);
|
||||||
replylink.Attach<int32>(newapp->fMessagePort);
|
replylink.Attach<int32>(serverListen);
|
||||||
replylink.Flush();
|
replylink.Flush();
|
||||||
|
|
||||||
// This is necessary because BPrivate::PortLink::ReadString allocates memory
|
// This is necessary because BPortLink::ReadString allocates memory
|
||||||
if(app_signature)
|
free(appSignature);
|
||||||
free(app_signature);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_DELETE_APP:
|
case AS_DELETE_APP:
|
||||||
{
|
{
|
||||||
// Delete a ServerApp. Received only from the respective ServerApp when a
|
// Delete a ServerApp. Received only from the respective ServerApp when a
|
||||||
// BApplication asks it to quit.
|
// BApplication asks it to quit.
|
||||||
|
|
||||||
// Attached Data:
|
// Attached Data:
|
||||||
// 1) thread_id - thread ID of the ServerApp to be deleted
|
// 1) thread_id - thread ID of the ServerApp to be deleted
|
||||||
|
|
||||||
int32 i=0,
|
|
||||||
appnum=fAppList->CountItems();
|
|
||||||
|
|
||||||
ServerApp *srvapp=NULL;
|
|
||||||
thread_id srvapp_id=-1;
|
|
||||||
|
|
||||||
if(msg.Read<thread_id>(&srvapp_id)<B_OK)
|
int32 i = 0, appnum = fAppList->CountItems();
|
||||||
|
ServerApp *srvapp = NULL;
|
||||||
|
thread_id srvapp_id = -1;
|
||||||
|
|
||||||
|
if (msg.Read<thread_id>(&srvapp_id) < B_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
acquire_sem(fAppListLock);
|
acquire_sem(fAppListLock);
|
||||||
|
|
||||||
// Run through the list of apps and nuke the proper one
|
// Run through the list of apps and nuke the proper one
|
||||||
for(i= 0; i < appnum; i++)
|
for (i = 0; i < appnum; i++) {
|
||||||
{
|
srvapp = (ServerApp *)fAppList->ItemAt(i);
|
||||||
srvapp=(ServerApp *)fAppList->ItemAt(i);
|
|
||||||
|
|
||||||
if(srvapp != NULL && srvapp->fMonitorThreadID== srvapp_id)
|
if (srvapp != NULL && srvapp->MonitorThreadID() == srvapp_id) {
|
||||||
{
|
srvapp = (ServerApp *)fAppList->RemoveItem(i);
|
||||||
srvapp=(ServerApp *)fAppList->RemoveItem(i);
|
if (srvapp) {
|
||||||
if(srvapp)
|
|
||||||
{
|
|
||||||
status_t temp;
|
|
||||||
wait_for_thread(srvapp_id, &temp);
|
|
||||||
delete srvapp;
|
delete srvapp;
|
||||||
srvapp= NULL;
|
srvapp = NULL;
|
||||||
}
|
}
|
||||||
break; // jump out of our for() loop
|
break; // jump out of our for() loop
|
||||||
}
|
}
|
||||||
@@ -278,53 +450,94 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
|||||||
release_sem(fAppListLock);
|
release_sem(fAppListLock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
case B_QUIT_REQUESTED:
|
||||||
case AS_QUERY_FONTS_CHANGED:
|
|
||||||
{
|
{
|
||||||
// Seeing how the client merely wants an answer, we'll skip the BPrivate::PortLink
|
|
||||||
// and all its overhead and just write the code to port.
|
|
||||||
port_id replyport;
|
|
||||||
if (msg.Read<port_id>(&replyport) < B_OK)
|
|
||||||
break;
|
|
||||||
BPrivate::PortLink replylink(replyport);
|
|
||||||
replylink.StartMessage(SERVER_FALSE);
|
|
||||||
replylink.Flush();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_GET_DECORATOR:
|
|
||||||
{
|
|
||||||
// Attached Data:
|
|
||||||
// 1) port_id reply port
|
|
||||||
|
|
||||||
port_id replyport=-1;
|
|
||||||
if(msg.Read<port_id>(&replyport)<B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BPrivate::PortLink replylink(replyport);
|
|
||||||
replylink.StartMessage(AS_GET_DECORATOR);
|
|
||||||
replylink.AttachString("none");
|
|
||||||
replylink.Flush();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AS_UPDATED_CLIENT_FONTLIST:
|
|
||||||
case AS_SET_UI_COLORS:
|
|
||||||
case AS_SET_DECORATOR:
|
|
||||||
case AS_R5_SET_DECORATOR:
|
|
||||||
case AS_SET_SYSCURSOR_DEFAULTS:
|
case AS_SET_SYSCURSOR_DEFAULTS:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
|
// we should never get here.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Send a quick (no attachments) message to all applications
|
||||||
|
|
||||||
|
Quite useful for notification for things like server shutdown, system
|
||||||
|
color changes, etc.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
AppServer::Broadcast(int32 code)
|
||||||
|
{
|
||||||
|
acquire_sem(fAppListLock);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fAppList->CountItems(); i++) {
|
||||||
|
ServerApp *app = (ServerApp *)fAppList->ItemAt(i);
|
||||||
|
|
||||||
|
if (!app)
|
||||||
|
{ printf("PANIC in AppServer::Broadcast()\n"); continue; }
|
||||||
|
app->PostMessage(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
release_sem(fAppListLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Finds the application with the given signature
|
||||||
|
\param sig MIME signature of the application to find
|
||||||
|
\return the corresponding ServerApp or NULL if not found
|
||||||
|
|
||||||
|
This call should be made only when necessary because it locks the app list
|
||||||
|
while it does its searching.
|
||||||
|
*/
|
||||||
|
ServerApp *
|
||||||
|
AppServer::FindApp(const char *sig)
|
||||||
|
{
|
||||||
|
if (!sig)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ServerApp *foundapp=NULL;
|
||||||
|
|
||||||
|
acquire_sem(fAppListLock);
|
||||||
|
|
||||||
|
for(int32 i=0; i<fAppList->CountItems();i++)
|
||||||
|
{
|
||||||
|
foundapp=(ServerApp*)fAppList->ItemAt(i);
|
||||||
|
if(foundapp && foundapp->Title() == sig)
|
||||||
|
{
|
||||||
|
release_sem(fAppListLock);
|
||||||
|
return foundapp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
release_sem(fAppListLock);
|
||||||
|
|
||||||
|
// couldn't find a match
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Entry function to run the entire server
|
||||||
|
\param argc Number of command-line arguments present
|
||||||
|
\param argv String array of the command-line arguments
|
||||||
|
\return -1 if the app_server is already running, 0 if everything's OK.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
// There can be only one....
|
// There can be only one....
|
||||||
if (find_port(SERVER_PORT_NAME) != B_NAME_NOT_FOUND)
|
if (find_port(SERVER_PORT_NAME) >= B_OK)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
srand(real_time_clock_usecs());
|
||||||
AppServer app_server;
|
AppServer app_server;
|
||||||
app_server.Run();
|
app_server.Run();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
#ifndef _OPENBEOS_APP_SERVER_H_
|
/*
|
||||||
#define _OPENBEOS_APP_SERVER_H_
|
* Copyright (c) 2001-2005, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Author: DarkWyrm <[email protected]>
|
||||||
|
*/
|
||||||
|
#ifndef _HAIKU_APP_SERVER_H_
|
||||||
|
#define _HAIKU_APP_SERVER_H_
|
||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
@@ -21,6 +27,15 @@ namespace BPrivate {
|
|||||||
class PortLink;
|
class PortLink;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class AppServer AppServer.h
|
||||||
|
\brief main manager object for the app_server
|
||||||
|
|
||||||
|
File for the main app_server thread. This particular thread monitors for
|
||||||
|
application start and quit messages. It also starts the housekeeping threads
|
||||||
|
and initializes most of the server's globals.
|
||||||
|
*/
|
||||||
|
|
||||||
class AppServer {
|
class AppServer {
|
||||||
public:
|
public:
|
||||||
AppServer(void);
|
AppServer(void);
|
||||||
@@ -31,18 +46,58 @@ public:
|
|||||||
thread_id Run(void);
|
thread_id Run(void);
|
||||||
void MainLoop(void);
|
void MainLoop(void);
|
||||||
|
|
||||||
|
bool LoadDecorator(const char *path);
|
||||||
|
void InitDecorators(void);
|
||||||
|
|
||||||
void DispatchMessage(int32 code, BPrivate::PortLink &link);
|
void DispatchMessage(int32 code, BPrivate::PortLink &link);
|
||||||
|
void Broadcast(int32 code);
|
||||||
|
|
||||||
|
ServerApp* FindApp(const char *sig);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void LaunchCursorThread();
|
||||||
|
void LaunchInputServer();
|
||||||
|
|
||||||
|
friend Decorator* new_decorator(BRect rect, const char *title,
|
||||||
|
int32 wlook, int32 wfeel, int32 wflags, DisplayDriver *ddriver);
|
||||||
|
|
||||||
|
// global function pointer
|
||||||
|
create_decorator *make_decorator;
|
||||||
|
|
||||||
port_id fMessagePort;
|
port_id fMessagePort;
|
||||||
bool fQuittingServer;
|
port_id fServerInputPort;
|
||||||
|
|
||||||
|
image_id fDecoratorID;
|
||||||
|
|
||||||
|
BString fDecoratorName;
|
||||||
|
|
||||||
|
volatile bool fQuittingServer;
|
||||||
|
|
||||||
BList *fAppList;
|
BList *fAppList;
|
||||||
thread_id fPicassoThreadID;
|
thread_id fPicassoThreadID;
|
||||||
|
|
||||||
|
thread_id fISThreadID;
|
||||||
|
thread_id fCursorThreadID;
|
||||||
|
sem_id fCursorSem;
|
||||||
|
area_id fCursorArea;
|
||||||
|
uint32 *fCursorAddr;
|
||||||
|
|
||||||
|
port_id fISASPort;
|
||||||
|
port_id fISPort;
|
||||||
|
|
||||||
sem_id fActiveAppLock, fAppListLock;
|
sem_id fActiveAppLock,
|
||||||
|
fAppListLock,
|
||||||
|
fDecoratorLock;
|
||||||
|
|
||||||
|
DisplayDriver *fDriver;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern AppServer *app_server;
|
Decorator *new_decorator(BRect rect, const char *title, int32 wlook, int32 wfeel,
|
||||||
|
int32 wflags, DisplayDriver *ddriver);
|
||||||
|
|
||||||
#endif
|
extern BitmapManager *bitmapmanager;
|
||||||
|
extern ColorSet gui_colorset;
|
||||||
|
extern AppServer *app_server;
|
||||||
|
extern port_id gAppServerPort;
|
||||||
|
|
||||||
|
#endif /* _HAIKU_APP_SERVER_H_ */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -30,17 +30,15 @@
|
|||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <LinkMsgReader.h>
|
#include <PortLink.h>
|
||||||
#include <LinkMsgSender.h>
|
|
||||||
//#include "FMWList.h"
|
|
||||||
|
|
||||||
class AppServer;
|
class AreaPool;
|
||||||
class BMessage;
|
class BMessage;
|
||||||
class BList;
|
class BList;
|
||||||
class DisplayDriver;
|
class DisplayDriver;
|
||||||
|
class ServerPicture;
|
||||||
class ServerCursor;
|
class ServerCursor;
|
||||||
class ServerBitmap;
|
class ServerBitmap;
|
||||||
class AreaPool;
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
class PortLink;
|
class PortLink;
|
||||||
@@ -50,64 +48,91 @@ namespace BPrivate {
|
|||||||
\class ServerApp ServerApp.h
|
\class ServerApp ServerApp.h
|
||||||
\brief Counterpart to BApplication within the app_server
|
\brief Counterpart to BApplication within the app_server
|
||||||
*/
|
*/
|
||||||
class ServerApp
|
class ServerApp {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort,
|
ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort,
|
||||||
team_id clientTeamID, int32 handlerID, char *signature);
|
team_id clientTeamID, int32 handlerID, const char* signature);
|
||||||
virtual ~ServerApp(void);
|
virtual ~ServerApp(void);
|
||||||
|
|
||||||
bool Run(void);
|
bool Run(void);
|
||||||
static int32 MonitorApp(void *data);
|
/*
|
||||||
|
TODO: These aren't even implemented...
|
||||||
void Lock(void);
|
void Lock(void);
|
||||||
void Unlock(void);
|
void Unlock(void);
|
||||||
bool IsLocked(void);
|
bool IsLocked(void);
|
||||||
|
*/
|
||||||
/*!
|
/*!
|
||||||
\brief Determines whether the application is the active one
|
\brief Determines whether the application is the active one
|
||||||
\return true if active, false if not.
|
\return true if active, false if not.
|
||||||
*/
|
*/
|
||||||
bool IsActive(void) const { return fIsActive; }
|
bool IsActive(void) const { return fIsActive; }
|
||||||
|
|
||||||
void Activate(bool value);
|
void Activate(bool value);
|
||||||
|
|
||||||
bool PingTarget(void);
|
bool PingTarget(void);
|
||||||
|
|
||||||
void PostMessage(int32 code);
|
void PostMessage(int32 code);
|
||||||
|
|
||||||
void SendMessageToClient( const BMessage* msg ) const;
|
void SendMessageToClient( const BMessage* msg ) const;
|
||||||
|
|
||||||
void SetAppCursor(void);
|
void SetAppCursor(void);
|
||||||
|
|
||||||
team_id ClientTeamID();
|
team_id ClientTeamID() const;
|
||||||
|
thread_id MonitorThreadID() const;
|
||||||
|
|
||||||
const char * Title() const { return fSignature.String(); }
|
const char *Title() const { return fSignature.String(); }
|
||||||
protected:
|
|
||||||
friend class AppServer;
|
|
||||||
friend class ServerWindow;
|
|
||||||
|
|
||||||
void DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
|
int32 CountBitmaps() const;
|
||||||
|
ServerBitmap *FindBitmap(int32 token) const;
|
||||||
|
|
||||||
port_id fClientAppPort,
|
int32 CountPictures() const;
|
||||||
fMessagePort,
|
ServerPicture *FindPicture(int32 token) const;
|
||||||
// TODO: find out why there is both the app port and the looper port. Do
|
|
||||||
// we really need both?
|
|
||||||
fClientLooperPort;
|
|
||||||
|
|
||||||
BString fSignature;
|
|
||||||
thread_id fMonitorThreadID;
|
|
||||||
|
|
||||||
team_id fClientTeamID;
|
|
||||||
|
|
||||||
BPrivate::LinkReceiver *fMsgReader;
|
|
||||||
BPrivate::LinkSender *fMsgSender;
|
|
||||||
|
|
||||||
/* BList *fSWindowList,
|
AreaPool *AppAreaPool() { return fSharedMem; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
|
||||||
|
|
||||||
|
static int32 MonitorApp(void *data);
|
||||||
|
|
||||||
|
// our BApplication's event port
|
||||||
|
port_id fClientAppPort;
|
||||||
|
// port we receive messages from our BApplication
|
||||||
|
port_id fMessagePort;
|
||||||
|
// TODO: find out why there is both the app port and the looper port. Do
|
||||||
|
// we really need both? Actually, we aren't using any of these ports,
|
||||||
|
// as BAppServerLink/BPortlink's messages always contain the reply port
|
||||||
|
// To send a message to the client, write a BMessage to this port
|
||||||
|
port_id fClientLooperPort;
|
||||||
|
|
||||||
|
BString fSignature;
|
||||||
|
|
||||||
|
thread_id fMonitorThreadID;
|
||||||
|
team_id fClientTeamID;
|
||||||
|
|
||||||
|
BPrivate::PortLink fLink;
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - Are really Bitmaps and Pictures stored per application and not globally ?
|
||||||
|
// - As we reference these stuff by token, what about putting them in hash tables ?
|
||||||
|
BList *fSWindowList,
|
||||||
*fBitmapList,
|
*fBitmapList,
|
||||||
*fPictureList;
|
*fPictureList;
|
||||||
*/ sem_id fLockSem;
|
|
||||||
|
ServerCursor *fAppCursor;
|
||||||
|
|
||||||
|
// TODO: Not used.
|
||||||
|
sem_id fLockSem;
|
||||||
|
|
||||||
bool fCursorHidden;
|
bool fCursorHidden;
|
||||||
bool fIsActive;
|
bool fIsActive;
|
||||||
int32 fHandlerToken;
|
|
||||||
|
// token ID of the BApplication's BHandler object.
|
||||||
|
// Used for BMessage target specification
|
||||||
|
// TODO: Is it still needed ? We aren't using it.
|
||||||
|
//int32 fHandlerToken;
|
||||||
|
|
||||||
AreaPool *fSharedMem;
|
AreaPool *fSharedMem;
|
||||||
|
|
||||||
|
bool fQuitting;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // _SERVERAPP_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user