2005-06-17 23:10:15 +04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2001-2005, Haiku, Inc.
|
|
|
|
* Distributed under the terms of the MIT license.
|
|
|
|
*
|
|
|
|
* Author: DarkWyrm <bpmagic@columbus.rr.com>
|
|
|
|
*/
|
2004-01-27 03:38:14 +03:00
|
|
|
#include <Accelerant.h>
|
2005-05-15 04:22:55 +04:00
|
|
|
#include <AppDefs.h>
|
|
|
|
#include <Directory.h>
|
2003-03-30 04:17:50 +04:00
|
|
|
#include <Entry.h>
|
2005-05-15 04:22:55 +04:00
|
|
|
#include <File.h>
|
|
|
|
#include <Message.h>
|
2003-10-09 03:18:30 +04:00
|
|
|
#include <Path.h>
|
2003-07-12 02:30:55 +04:00
|
|
|
#include <PortLink.h>
|
2005-05-15 04:22:55 +04:00
|
|
|
#include <StopWatch.h>
|
2005-06-17 02:30:50 +04:00
|
|
|
#include <RosterPrivate.h>
|
2003-08-31 21:38:34 +04:00
|
|
|
|
2005-05-15 04:22:55 +04:00
|
|
|
#include "BitmapManager.h"
|
2003-03-31 01:09:39 +04:00
|
|
|
#include "ColorSet.h"
|
2005-05-15 04:22:55 +04:00
|
|
|
#include "CursorManager.h"
|
2005-06-17 23:10:15 +04:00
|
|
|
#include "DecorManager.h"
|
2005-05-15 04:22:55 +04:00
|
|
|
#include "DefaultDecorator.h"
|
|
|
|
#include "Desktop.h"
|
2003-01-27 22:43:15 +03:00
|
|
|
#include "DisplayDriver.h"
|
2005-05-15 04:22:55 +04:00
|
|
|
#include "FontServer.h"
|
|
|
|
#include "RegistrarDefs.h"
|
|
|
|
#include "RGBColor.h"
|
|
|
|
#include "RootLayer.h"
|
2003-01-27 22:43:15 +03:00
|
|
|
#include "ServerApp.h"
|
2003-02-20 23:14:57 +03:00
|
|
|
#include "ServerCursor.h"
|
2003-01-27 22:43:15 +03:00
|
|
|
#include "ServerProtocol.h"
|
2003-02-07 15:53:57 +03:00
|
|
|
#include "ServerWindow.h"
|
2005-06-08 01:32:24 +04:00
|
|
|
#include "SystemPalette.h"
|
2003-03-30 04:17:50 +04:00
|
|
|
#include "Utils.h"
|
2005-05-15 04:22:55 +04:00
|
|
|
|
|
|
|
#include "AppServer.h"
|
|
|
|
|
2003-03-30 04:17:50 +04:00
|
|
|
//#define DEBUG_KEYHANDLING
|
2004-09-05 04:52:45 +04:00
|
|
|
//#define DEBUG_SERVER
|
2004-07-30 19:16:59 +04:00
|
|
|
|
2003-09-09 01:08:27 +04:00
|
|
|
#ifdef DEBUG_KEYHANDLING
|
|
|
|
# include <stdio.h>
|
2004-07-30 19:16:59 +04:00
|
|
|
# define KBTRACE(x) printf x
|
|
|
|
#else
|
|
|
|
# define KBTRACE(x) ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef DEBUG_SERVER
|
|
|
|
# include <stdio.h>
|
2003-09-09 01:08:27 +04:00
|
|
|
# define STRACE(x) printf x
|
|
|
|
#else
|
|
|
|
# define STRACE(x) ;
|
|
|
|
#endif
|
2004-01-20 01:18:37 +03:00
|
|
|
|
2003-02-15 18:28:22 +03:00
|
|
|
// Globals
|
2005-05-28 17:43:13 +04:00
|
|
|
Desktop *gDesktop;
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2005-05-27 17:36:05 +04:00
|
|
|
port_id gAppServerPort;
|
|
|
|
|
2005-06-17 23:10:15 +04:00
|
|
|
static AppServer *sAppServer;
|
2003-01-20 23:38:49 +03:00
|
|
|
|
2003-02-15 18:28:22 +03:00
|
|
|
//! Default background color for workspaces
|
2005-05-28 17:20:05 +04:00
|
|
|
//RGBColor workspace_default_color(51,102,160);
|
2003-02-24 00:40:44 +03:00
|
|
|
|
2003-03-31 01:09:39 +04:00
|
|
|
//! System-wide GUI color object
|
|
|
|
ColorSet gui_colorset;
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
/*!
|
|
|
|
\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.
|
|
|
|
*/
|
2005-03-29 23:49:55 +04:00
|
|
|
#if TEST_MODE
|
2005-04-20 00:44:09 +04:00
|
|
|
AppServer::AppServer(void) : BApplication (SERVER_SIGNATURE),
|
2003-03-23 23:52:37 +03:00
|
|
|
#else
|
2005-04-20 00:44:09 +04:00
|
|
|
AppServer::AppServer(void) :
|
2003-02-15 18:28:22 +03:00
|
|
|
#endif
|
2005-04-20 00:44:09 +04:00
|
|
|
fCursorSem(-1),
|
|
|
|
fCursorArea(-1)
|
2003-01-20 23:38:49 +03:00
|
|
|
{
|
2005-05-07 19:56:15 +04:00
|
|
|
fMessagePort = create_port(200, SERVER_PORT_NAME);
|
2005-04-17 16:26:16 +04:00
|
|
|
if (fMessagePort == B_NO_MORE_PORTS)
|
|
|
|
debugger("app_server could not create message port");
|
2005-05-27 17:36:05 +04:00
|
|
|
|
|
|
|
gAppServerPort = fMessagePort;
|
|
|
|
|
2005-04-17 16:26:16 +04:00
|
|
|
// 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");
|
2005-05-27 17:36:05 +04:00
|
|
|
|
|
|
|
fAppList = new BList();
|
|
|
|
fQuittingServer = false;
|
2005-05-28 17:43:13 +04:00
|
|
|
sAppServer = this;
|
2005-06-17 23:10:15 +04:00
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
// Create the font server and scan the proper directories.
|
2005-05-27 17:36:05 +04:00
|
|
|
fontserver = new FontServer;
|
2003-01-27 22:43:15 +03:00
|
|
|
fontserver->Lock();
|
2003-08-02 04:13:30 +04:00
|
|
|
|
|
|
|
// Used for testing purposes
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2004-08-29 19:01:44 +04:00
|
|
|
// TODO: Re-enable scanning of all font directories when server is actually put to use
|
2003-08-31 21:38:34 +04:00
|
|
|
fontserver->ScanDirectory("/boot/beos/etc/fonts/ttfonts/");
|
2003-01-27 22:43:15 +03:00
|
|
|
// fontserver->ScanDirectory("/boot/beos/etc/fonts/PS-Type1/");
|
2003-08-31 21:38:34 +04:00
|
|
|
// fontserver->ScanDirectory("/boot/home/config/fonts/ttfonts/");
|
|
|
|
// fontserver->ScanDirectory("/boot/home/config/fonts/psfonts/");
|
2003-01-27 22:43:15 +03:00
|
|
|
fontserver->SaveList();
|
|
|
|
|
2005-04-14 04:11:33 +04:00
|
|
|
if (!fontserver->SetSystemPlain(DEFAULT_PLAIN_FONT_FAMILY,
|
|
|
|
DEFAULT_PLAIN_FONT_STYLE,
|
|
|
|
DEFAULT_PLAIN_FONT_SIZE) &&
|
|
|
|
!fontserver->SetSystemPlain(FALLBACK_PLAIN_FONT_FAMILY,
|
|
|
|
DEFAULT_PLAIN_FONT_STYLE,
|
|
|
|
DEFAULT_PLAIN_FONT_SIZE)) {
|
|
|
|
printf("Couldn't set plain to %s (fallback: %s), %s %d pt\n",
|
2005-04-12 17:15:38 +04:00
|
|
|
DEFAULT_PLAIN_FONT_FAMILY,
|
2005-04-14 04:11:33 +04:00
|
|
|
FALLBACK_PLAIN_FONT_FAMILY,
|
2005-04-12 17:15:38 +04:00
|
|
|
DEFAULT_PLAIN_FONT_STYLE,
|
|
|
|
DEFAULT_PLAIN_FONT_SIZE);
|
|
|
|
}
|
|
|
|
|
2005-04-14 04:11:33 +04:00
|
|
|
if (!fontserver->SetSystemBold(DEFAULT_BOLD_FONT_FAMILY,
|
|
|
|
DEFAULT_BOLD_FONT_STYLE,
|
|
|
|
DEFAULT_BOLD_FONT_SIZE) &&
|
|
|
|
!fontserver->SetSystemBold(FALLBACK_BOLD_FONT_FAMILY,
|
|
|
|
DEFAULT_BOLD_FONT_STYLE,
|
|
|
|
DEFAULT_BOLD_FONT_SIZE)) {
|
|
|
|
printf("Couldn't set bold to %s (fallback: %s), %s %d pt\n",
|
2005-04-12 17:15:38 +04:00
|
|
|
DEFAULT_BOLD_FONT_FAMILY,
|
2005-04-14 04:11:33 +04:00
|
|
|
FALLBACK_BOLD_FONT_FAMILY,
|
2005-04-12 17:15:38 +04:00
|
|
|
DEFAULT_BOLD_FONT_STYLE,
|
|
|
|
DEFAULT_BOLD_FONT_SIZE);
|
|
|
|
}
|
|
|
|
|
2005-04-14 04:11:33 +04:00
|
|
|
if (!fontserver->SetSystemFixed(DEFAULT_FIXED_FONT_FAMILY,
|
|
|
|
DEFAULT_FIXED_FONT_STYLE,
|
|
|
|
DEFAULT_FIXED_FONT_SIZE) &&
|
|
|
|
!fontserver->SetSystemFixed(FALLBACK_FIXED_FONT_FAMILY,
|
|
|
|
DEFAULT_FIXED_FONT_STYLE,
|
|
|
|
DEFAULT_FIXED_FONT_SIZE)) {
|
|
|
|
printf("Couldn't set fixed to %s (fallback: %s), %s %d pt\n",
|
2005-04-12 17:15:38 +04:00
|
|
|
DEFAULT_FIXED_FONT_FAMILY,
|
2005-04-14 04:11:33 +04:00
|
|
|
FALLBACK_FIXED_FONT_FAMILY,
|
2005-04-12 17:15:38 +04:00
|
|
|
DEFAULT_FIXED_FONT_STYLE,
|
|
|
|
DEFAULT_FIXED_FONT_SIZE);
|
|
|
|
}
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
fontserver->Unlock();
|
2005-05-27 17:36:05 +04:00
|
|
|
|
2003-07-05 21:40:42 +04:00
|
|
|
// Load the GUI colors here and set the global set to the values contained therein. If this
|
|
|
|
// is not possible, set colors to the defaults
|
2005-06-15 21:20:17 +04:00
|
|
|
if (LoadColorSet(SERVER_SETTINGS_DIR COLOR_SETTINGS_NAME,&gui_colorset)!=B_OK)
|
2003-10-06 01:52:54 +04:00
|
|
|
gui_colorset.SetToDefaults();
|
2003-07-12 02:30:55 +04:00
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
// Set up the Desktop
|
2005-05-28 17:43:13 +04:00
|
|
|
gDesktop = new Desktop();
|
|
|
|
gDesktop->Init();
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2005-06-08 01:32:24 +04:00
|
|
|
// TODO: Maybe this is not the best place for this
|
|
|
|
InitializeColorMap();
|
|
|
|
|
2003-02-20 23:14:57 +03:00
|
|
|
// Create the bitmap allocator. Object declared in BitmapManager.cpp
|
2005-05-27 17:36:05 +04:00
|
|
|
bitmapmanager = new BitmapManager();
|
2003-02-20 23:14:57 +03:00
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
// This is necessary to mediate access between the Poller and app_server threads
|
2005-05-27 17:36:05 +04:00
|
|
|
fActiveAppLock = create_sem(1,"app_server_active_sem");
|
2003-01-27 22:43:15 +03:00
|
|
|
|
|
|
|
// This locker is for app_server and Picasso to vy for control of the ServerApp list
|
2005-05-27 17:36:05 +04:00
|
|
|
fAppListLock = create_sem(1,"app_server_applist_sem");
|
2003-01-27 22:43:15 +03:00
|
|
|
|
|
|
|
// Spawn our thread-monitoring thread
|
2005-05-27 17:36:05 +04:00
|
|
|
fPicassoThreadID = spawn_thread(PicassoThread, "picasso", B_NORMAL_PRIORITY, this);
|
2004-01-20 01:18:37 +03:00
|
|
|
if (fPicassoThreadID >= 0)
|
|
|
|
resume_thread(fPicassoThreadID);
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2005-04-17 16:26:16 +04:00
|
|
|
#if 0
|
2005-04-20 00:44:09 +04:00
|
|
|
LaunchCursorThread();
|
2005-04-17 16:26:16 +04:00
|
|
|
#endif
|
2003-01-20 23:38:49 +03:00
|
|
|
}
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
/*!
|
|
|
|
\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.
|
|
|
|
*/
|
2003-01-20 23:38:49 +03:00
|
|
|
AppServer::~AppServer(void)
|
|
|
|
{
|
2005-03-08 00:52:41 +03:00
|
|
|
debugger("We shouldn't be here! MainLoop()::B_QUIT_REQUESTED should see if we can exit the server.\n");
|
|
|
|
/*
|
2003-01-27 22:43:15 +03:00
|
|
|
ServerApp *tempapp;
|
|
|
|
int32 i;
|
2004-01-20 01:18:37 +03:00
|
|
|
acquire_sem(fAppListLock);
|
|
|
|
for(i=0;i<fAppList->CountItems();i++)
|
2003-01-27 22:43:15 +03:00
|
|
|
{
|
2004-01-20 01:18:37 +03:00
|
|
|
tempapp=(ServerApp *)fAppList->ItemAt(i);
|
2003-01-27 22:43:15 +03:00
|
|
|
if(tempapp!=NULL)
|
|
|
|
delete tempapp;
|
|
|
|
}
|
2004-01-20 01:18:37 +03:00
|
|
|
delete fAppList;
|
|
|
|
release_sem(fAppListLock);
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2003-02-20 23:14:57 +03:00
|
|
|
delete bitmapmanager;
|
|
|
|
|
2005-05-28 17:43:13 +04:00
|
|
|
delete gDesktop;
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
// 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.
|
2004-01-20 01:18:37 +03:00
|
|
|
kill_thread(fPicassoThreadID);
|
2005-04-20 00:44:09 +04:00
|
|
|
kill_thread(fCursorThreadID);
|
|
|
|
kill_thread(fISThreadID);
|
2003-01-27 22:43:15 +03:00
|
|
|
|
|
|
|
delete fontserver;
|
|
|
|
|
|
|
|
make_decorator=NULL;
|
2005-03-08 00:52:41 +03:00
|
|
|
*/
|
2003-01-20 23:38:49 +03:00
|
|
|
}
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
/*!
|
|
|
|
\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
|
|
|
|
*/
|
2005-05-27 14:57:25 +04:00
|
|
|
int32
|
|
|
|
AppServer::PicassoThread(void *data)
|
2003-01-20 23:38:49 +03:00
|
|
|
{
|
2005-06-08 08:01:59 +04:00
|
|
|
for (;;) {
|
|
|
|
acquire_sem(sAppServer->fAppListLock);
|
|
|
|
for (int32 i = 0;;) {
|
|
|
|
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i++);
|
|
|
|
if (!app)
|
2005-01-17 00:35:02 +03:00
|
|
|
break;
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
app->PingTarget();
|
|
|
|
}
|
2005-06-08 08:01:59 +04:00
|
|
|
release_sem(sAppServer->fAppListLock);
|
2003-01-27 22:43:15 +03:00
|
|
|
// we do this every other second so as not to suck *too* many CPU cycles
|
2005-03-04 02:21:36 +03:00
|
|
|
snooze(1000000);
|
2003-01-27 22:43:15 +03:00
|
|
|
}
|
2003-01-20 23:38:49 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-04-20 00:44:09 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Starts Input Server
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
AppServer::LaunchInputServer()
|
|
|
|
{
|
|
|
|
// We are supposed to start the input_server, but it's a BApplication
|
|
|
|
// that depends on the registrar running, which is started after app_server
|
|
|
|
// so we wait on roster thread to launch the input server
|
|
|
|
|
|
|
|
fISThreadID = B_ERROR;
|
|
|
|
|
2005-06-17 02:30:50 +04:00
|
|
|
while (!BRoster::Private().IsMessengerValid(false) && !fQuittingServer) {
|
2005-04-20 00:44:09 +04:00
|
|
|
snooze(250000);
|
2005-06-17 02:30:50 +04:00
|
|
|
BRoster::Private::DeleteBeRoster();
|
|
|
|
BRoster::Private::InitBeRoster();
|
2005-04-20 00:44:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fQuittingServer)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// we use an area for cursor data communication with input_server
|
|
|
|
// area id and sem id are sent to the input_server
|
|
|
|
|
|
|
|
if (fCursorArea < B_OK)
|
|
|
|
fCursorArea = create_area("isCursor", (void**) &fCursorAddr, B_ANY_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
|
|
|
|
if (fCursorSem < B_OK)
|
2005-05-15 04:22:55 +04:00
|
|
|
fCursorSem = create_sem(0, "isSem");
|
2005-04-20 00:44:09 +04:00
|
|
|
|
|
|
|
int32 arg_c = 1;
|
|
|
|
char **arg_v = (char **)malloc(sizeof(char *) * (arg_c + 1));
|
2005-04-28 14:10:52 +04:00
|
|
|
#if TEST_MODE
|
|
|
|
arg_v[0] = strdup("/boot/home/svnhaiku/trunk/distro/x86.R1/beos/system/servers/input_server");
|
|
|
|
#else
|
|
|
|
arg_v[0] = strdup("/system/servers/input_server");
|
|
|
|
#endif
|
2005-04-20 00:44:09 +04:00
|
|
|
arg_v[1] = NULL;
|
|
|
|
fISThreadID = load_image(arg_c, (const char**)arg_v, (const char **)environ);
|
|
|
|
free(arg_v[0]);
|
|
|
|
|
|
|
|
int32 tmpbuf[2] = {fCursorSem, fCursorArea};
|
2005-05-15 04:22:55 +04:00
|
|
|
int32 code = 0;
|
|
|
|
send_data(fISThreadID, code, (void *)tmpbuf, sizeof(tmpbuf));
|
2005-04-20 00:44:09 +04:00
|
|
|
|
|
|
|
resume_thread(fISThreadID);
|
|
|
|
setpgid(fISThreadID, 0);
|
|
|
|
|
|
|
|
// we receive
|
|
|
|
|
|
|
|
thread_id sender;
|
2005-05-15 04:22:55 +04:00
|
|
|
code = receive_data(&sender, (void *)tmpbuf, sizeof(tmpbuf));
|
|
|
|
fISASPort = tmpbuf[0];
|
|
|
|
fISPort = tmpbuf[1];
|
2005-04-20 00:44:09 +04:00
|
|
|
|
|
|
|
// if at any time, one of these ports is error prone, it might mean input_server is gone
|
|
|
|
// then relaunch input_server
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Starts the Cursor Thread
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
AppServer::LaunchCursorThread()
|
|
|
|
{
|
|
|
|
// Spawn our cursor thread
|
2005-05-15 04:22:55 +04:00
|
|
|
fCursorThreadID = spawn_thread(CursorThread, "CursorThreadOfTheDeath", B_REAL_TIME_DISPLAY_PRIORITY - 1, this);
|
2005-04-20 00:44:09 +04:00
|
|
|
if (fCursorThreadID >= 0)
|
2005-05-15 04:22:55 +04:00
|
|
|
resume_thread(fCursorThreadID);
|
2005-04-20 00:44:09 +04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief The Cursor Thread task
|
|
|
|
*/
|
|
|
|
int32
|
|
|
|
AppServer::CursorThread(void* data)
|
|
|
|
{
|
|
|
|
AppServer *app = (AppServer *)data;
|
|
|
|
|
|
|
|
BPoint p;
|
2005-04-28 14:10:52 +04:00
|
|
|
|
|
|
|
app->LaunchInputServer();
|
2005-04-20 00:44:09 +04:00
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
while (acquire_sem(app->fCursorSem) == B_OK) {
|
|
|
|
|
2005-05-15 04:22:55 +04:00
|
|
|
p.y = *app->fCursorAddr & 0x7fff;
|
2005-04-30 19:00:10 +04:00
|
|
|
p.x = *app->fCursorAddr >> 15 & 0x7fff;
|
2005-04-20 00:44:09 +04:00
|
|
|
|
2005-05-28 17:43:13 +04:00
|
|
|
gDesktop->GetDisplayDriver()->MoveCursorTo(p.x, p.y);
|
2005-04-30 19:00:10 +04:00
|
|
|
STRACE(("CursorThread : %f, %f\n", p.x, p.y));
|
2005-04-20 00:44:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
snooze(100000);
|
|
|
|
|
|
|
|
} while (!app->fQuittingServer);
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 18:28:22 +03:00
|
|
|
/*!
|
|
|
|
\brief The call that starts it all...
|
|
|
|
\return Always 0
|
|
|
|
*/
|
2005-05-27 14:57:25 +04:00
|
|
|
thread_id
|
|
|
|
AppServer::Run(void)
|
2003-01-20 23:38:49 +03:00
|
|
|
{
|
2003-01-27 22:43:15 +03:00
|
|
|
MainLoop();
|
2005-03-25 23:39:43 +03:00
|
|
|
kill_thread(fPicassoThreadID);
|
2003-02-15 18:28:22 +03:00
|
|
|
return 0;
|
2003-01-20 23:38:49 +03:00
|
|
|
}
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
|
|
|
|
//! Main message-monitoring loop for the regular message port - no input messages!
|
2005-05-27 14:57:25 +04:00
|
|
|
void
|
|
|
|
AppServer::MainLoop(void)
|
2003-01-20 23:38:49 +03:00
|
|
|
{
|
2005-06-15 01:28:56 +04:00
|
|
|
BPrivate::PortLink pmsg(-1, fMessagePort);
|
2005-06-08 04:36:26 +04:00
|
|
|
|
|
|
|
while (1) {
|
2004-07-30 19:16:59 +04:00
|
|
|
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
|
|
|
|
|
2005-06-08 04:36:26 +04:00
|
|
|
int32 code;
|
2005-06-08 08:01:59 +04:00
|
|
|
status_t err = pmsg.GetNextMessage(code);
|
2005-06-08 04:36:26 +04:00
|
|
|
if (err < B_OK) {
|
2005-06-08 17:24:40 +04:00
|
|
|
STRACE(("MainLoop:pmsg.GetNextMessage() failed\n"));
|
2004-07-30 19:16:59 +04:00
|
|
|
continue;
|
|
|
|
}
|
2005-06-08 04:36:26 +04:00
|
|
|
|
|
|
|
switch (code) {
|
2004-07-30 19:16:59 +04:00
|
|
|
case B_QUIT_REQUESTED:
|
|
|
|
case AS_CREATE_APP:
|
|
|
|
case AS_DELETE_APP:
|
|
|
|
case AS_UPDATED_CLIENT_FONTLIST:
|
|
|
|
case AS_QUERY_FONTS_CHANGED:
|
|
|
|
case AS_SET_UI_COLORS:
|
|
|
|
case AS_GET_UI_COLOR:
|
|
|
|
case AS_SET_DECORATOR:
|
|
|
|
case AS_GET_DECORATOR:
|
|
|
|
case AS_R5_SET_DECORATOR:
|
2005-06-08 08:01:59 +04:00
|
|
|
DispatchMessage(code, pmsg);
|
2004-07-30 19:16:59 +04:00
|
|
|
break;
|
|
|
|
default:
|
2003-01-27 22:43:15 +03:00
|
|
|
{
|
2005-06-08 08:01:59 +04:00
|
|
|
STRACE(("Server::MainLoop received unexpected code %ld (offset %ld)\n",
|
|
|
|
code, code - SERVER_TRUE));
|
2004-07-30 19:16:59 +04:00
|
|
|
break;
|
2003-01-27 22:43:15 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-01-20 23:38:49 +03:00
|
|
|
}
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
/*!
|
|
|
|
\brief Message handling function for all messages sent to the app_server
|
|
|
|
\param code ID of the message sent
|
2004-07-30 19:16:59 +04:00
|
|
|
\param buffer Attachment buffer for the message.
|
2003-01-27 22:43:15 +03:00
|
|
|
|
|
|
|
*/
|
2005-05-26 19:06:31 +04:00
|
|
|
void
|
2005-06-15 01:28:56 +04:00
|
|
|
AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
2003-01-20 23:38:49 +03:00
|
|
|
{
|
2005-05-26 19:06:31 +04:00
|
|
|
switch (code) {
|
2003-02-24 18:47:06 +03:00
|
|
|
case AS_CREATE_APP:
|
2003-01-27 22:43:15 +03:00
|
|
|
{
|
|
|
|
// Create the ServerApp to node monitor a new BApplication
|
|
|
|
|
|
|
|
// Attached data:
|
2003-10-04 04:56:43 +04:00
|
|
|
// 1) port_id - receiver port of a regular app
|
2004-01-13 03:56:36 +03:00
|
|
|
// 2) port_id - client looper port - for send messages to the client
|
|
|
|
// 2) team_id - app's team ID
|
|
|
|
// 3) int32 - handler token of the regular app
|
|
|
|
// 4) char * - signature of the regular app
|
2003-01-27 22:43:15 +03:00
|
|
|
|
|
|
|
// Find the necessary data
|
2005-05-26 19:06:31 +04:00
|
|
|
team_id clientTeamID = -1;
|
|
|
|
port_id clientLooperPort = -1;
|
2005-06-08 08:01:59 +04:00
|
|
|
port_id clientReplyPort = -1;
|
2005-05-26 19:06:31 +04:00
|
|
|
int32 htoken = B_NULL_TOKEN;
|
2005-06-08 08:01:59 +04:00
|
|
|
char *appSignature = NULL;
|
2004-07-30 19:16:59 +04:00
|
|
|
|
2005-06-08 08:01:59 +04:00
|
|
|
msg.Read<port_id>(&clientReplyPort);
|
2004-07-30 19:16:59 +04:00
|
|
|
msg.Read<port_id>(&clientLooperPort);
|
|
|
|
msg.Read<team_id>(&clientTeamID);
|
|
|
|
msg.Read<int32>(&htoken);
|
2005-06-08 08:01:59 +04:00
|
|
|
if (msg.ReadString(&appSignature) != B_OK)
|
|
|
|
break;
|
2005-05-26 19:06:31 +04:00
|
|
|
|
2005-06-08 08:01:59 +04:00
|
|
|
port_id serverListen = create_port(DEFAULT_MONITOR_PORT_SIZE, appSignature);
|
|
|
|
if (serverListen < B_OK) {
|
2003-02-14 04:53:53 +03:00
|
|
|
printf("No more ports left. Time to crash. Have a nice day! :)\n");
|
2003-01-27 22:43:15 +03:00
|
|
|
break;
|
|
|
|
}
|
2005-06-08 08:01:59 +04:00
|
|
|
|
2005-05-26 19:06:31 +04:00
|
|
|
// we let the application own the port, so that we get aware when it's gone
|
2005-06-08 08:01:59 +04:00
|
|
|
if (set_port_owner(serverListen, clientTeamID) < B_OK) {
|
|
|
|
delete_port(serverListen);
|
2005-05-26 19:06:31 +04:00
|
|
|
printf("Could not transfer port ownership to client %ld!\n", clientTeamID);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the ServerApp subthread for this app
|
|
|
|
acquire_sem(fAppListLock);
|
|
|
|
|
2005-06-08 08:01:59 +04:00
|
|
|
ServerApp *app = new ServerApp(clientReplyPort, serverListen, clientLooperPort,
|
|
|
|
clientTeamID, htoken, appSignature);
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2004-07-30 19:16:59 +04:00
|
|
|
// add the new ServerApp to the known list of ServerApps
|
2005-05-26 19:06:31 +04:00
|
|
|
fAppList->AddItem(app);
|
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
release_sem(fAppListLock);
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2005-06-15 01:28:56 +04:00
|
|
|
BPrivate::PortLink replylink(clientReplyPort);
|
2004-08-22 04:27:15 +04:00
|
|
|
replylink.StartMessage(SERVER_TRUE);
|
2005-06-08 08:01:59 +04:00
|
|
|
replylink.Attach<int32>(serverListen);
|
2003-10-04 04:56:43 +04:00
|
|
|
replylink.Flush();
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2004-07-30 19:16:59 +04:00
|
|
|
// This is necessary because BPortLink::ReadString allocates memory
|
2005-06-08 08:01:59 +04:00
|
|
|
free(appSignature);
|
2003-01-27 22:43:15 +03:00
|
|
|
break;
|
|
|
|
}
|
2003-02-24 18:47:06 +03:00
|
|
|
case AS_DELETE_APP:
|
2003-01-27 22:43:15 +03:00
|
|
|
{
|
|
|
|
// Delete a ServerApp. Received only from the respective ServerApp when a
|
|
|
|
// BApplication asks it to quit.
|
2005-05-26 19:06:31 +04:00
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
// Attached Data:
|
|
|
|
// 1) thread_id - thread ID of the ServerApp to be deleted
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2005-05-26 19:06:31 +04:00
|
|
|
int32 i = 0, appnum = fAppList->CountItems();
|
|
|
|
ServerApp *srvapp = NULL;
|
|
|
|
thread_id srvapp_id = -1;
|
|
|
|
|
|
|
|
if (msg.Read<thread_id>(&srvapp_id) < B_OK)
|
2004-07-30 19:16:59 +04:00
|
|
|
break;
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
acquire_sem(fAppListLock);
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
// Run through the list of apps and nuke the proper one
|
2005-05-26 19:06:31 +04:00
|
|
|
for (i = 0; i < appnum; i++) {
|
|
|
|
srvapp = (ServerApp *)fAppList->ItemAt(i);
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2005-06-15 01:28:56 +04:00
|
|
|
if (srvapp != NULL && srvapp->MonitorThreadID() == srvapp_id) {
|
|
|
|
srvapp = (ServerApp *)fAppList->RemoveItem(i);
|
|
|
|
if (srvapp) {
|
2003-01-27 22:43:15 +03:00
|
|
|
delete srvapp;
|
2005-06-15 01:28:56 +04:00
|
|
|
srvapp = NULL;
|
2003-01-27 22:43:15 +03:00
|
|
|
}
|
|
|
|
break; // jump out of our for() loop
|
|
|
|
}
|
|
|
|
}
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
release_sem(fAppListLock);
|
2003-01-27 22:43:15 +03:00
|
|
|
break;
|
|
|
|
}
|
2003-02-24 18:47:06 +03:00
|
|
|
case AS_UPDATED_CLIENT_FONTLIST:
|
2003-01-27 22:43:15 +03:00
|
|
|
{
|
|
|
|
// received when the client-side global font list has been
|
|
|
|
// refreshed
|
|
|
|
fontserver->Lock();
|
|
|
|
fontserver->FontsUpdated();
|
|
|
|
fontserver->Unlock();
|
|
|
|
break;
|
|
|
|
}
|
2003-02-24 18:47:06 +03:00
|
|
|
case AS_QUERY_FONTS_CHANGED:
|
2003-01-27 22:43:15 +03:00
|
|
|
{
|
|
|
|
// Client application is asking if the font list has changed since
|
|
|
|
// the last client-side refresh
|
|
|
|
|
|
|
|
// Attached data:
|
|
|
|
// 1) port_id reply port
|
|
|
|
|
|
|
|
fontserver->Lock();
|
|
|
|
bool needs_update=fontserver->FontsNeedUpdated();
|
|
|
|
fontserver->Unlock();
|
|
|
|
|
2004-07-30 19:16:59 +04:00
|
|
|
// Seeing how the client merely wants an answer, we'll skip the BPortLink
|
2003-10-04 04:56:43 +04:00
|
|
|
// and all its overhead and just write the code to port.
|
|
|
|
port_id replyport;
|
2004-07-30 19:16:59 +04:00
|
|
|
if (msg.Read<port_id>(&replyport) < B_OK)
|
|
|
|
break;
|
2005-06-15 01:28:56 +04:00
|
|
|
BPrivate::PortLink replylink(replyport);
|
2004-07-30 19:16:59 +04:00
|
|
|
replylink.StartMessage(needs_update ? SERVER_TRUE : SERVER_FALSE);
|
|
|
|
replylink.Flush();
|
2003-01-27 22:43:15 +03:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case B_QUIT_REQUESTED:
|
|
|
|
{
|
2005-04-14 04:11:33 +04:00
|
|
|
#if TEST_MODE
|
2003-01-27 22:43:15 +03:00
|
|
|
// Attached Data:
|
|
|
|
// none
|
|
|
|
|
|
|
|
// We've been asked to quit, so (for now) broadcast to all
|
|
|
|
// test apps to quit. This situation will occur only when the server
|
|
|
|
// is compiled as a regular Be application.
|
2005-03-08 00:52:41 +03:00
|
|
|
|
2005-06-17 23:10:15 +04:00
|
|
|
BroadcastToAllApps(AS_QUIT_APP);
|
2003-01-27 22:43:15 +03:00
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
// we have to wait until *all* threads have finished!
|
2005-06-08 05:40:22 +04:00
|
|
|
ServerApp *app;
|
2004-01-20 01:18:37 +03:00
|
|
|
acquire_sem(fAppListLock);
|
|
|
|
thread_info tinfo;
|
2005-06-08 05:40:22 +04:00
|
|
|
for (int32 i = 0; i < fAppList->CountItems(); i++) {
|
|
|
|
app = (ServerApp*)fAppList->ItemAt(i);
|
|
|
|
if (!app)
|
2004-01-20 01:18:37 +03:00
|
|
|
continue;
|
2005-06-08 05:40:22 +04:00
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
// Instead of calling wait_for_thread, we will wait a bit, check for the
|
|
|
|
// thread_id. We will only wait so long, because then the app is probably crashed
|
|
|
|
// or hung. Seeing that being the case, we'll kill its BApp team and fake the
|
|
|
|
// quit message
|
2005-06-08 05:40:22 +04:00
|
|
|
if (get_thread_info(app->MonitorThreadID(), &tinfo)==B_OK) {
|
|
|
|
bool killteam = true;
|
|
|
|
|
|
|
|
for (int32 j = 0; j < 5; j++) {
|
2005-03-04 02:21:36 +03:00
|
|
|
snooze(500000); // wait half a second for it to quit
|
2005-06-08 05:40:22 +04:00
|
|
|
if (get_thread_info(app->MonitorThreadID(), &tinfo) != B_OK) {
|
|
|
|
killteam = false;
|
2004-01-20 01:18:37 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-06-08 05:40:22 +04:00
|
|
|
|
|
|
|
if (killteam) {
|
2004-01-20 01:18:37 +03:00
|
|
|
kill_team(app->ClientTeamID());
|
|
|
|
app->PostMessage(B_QUIT_REQUESTED);
|
|
|
|
}
|
|
|
|
}
|
2004-01-13 03:56:36 +03:00
|
|
|
}
|
2005-03-04 02:21:36 +03:00
|
|
|
|
|
|
|
kill_thread(fPicassoThreadID);
|
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
release_sem(fAppListLock);
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2005-05-28 17:43:13 +04:00
|
|
|
delete gDesktop;
|
2005-03-08 00:52:41 +03:00
|
|
|
delete fAppList;
|
|
|
|
delete bitmapmanager;
|
|
|
|
delete fontserver;
|
2004-01-17 21:37:57 +03:00
|
|
|
|
|
|
|
// we are now clear to exit
|
2005-06-08 05:40:22 +04:00
|
|
|
exit_thread(0);
|
2005-03-29 19:39:08 +04:00
|
|
|
#endif
|
2003-01-27 22:43:15 +03:00
|
|
|
break;
|
|
|
|
}
|
2003-07-24 23:38:24 +04:00
|
|
|
case AS_SET_SYSCURSOR_DEFAULTS:
|
|
|
|
{
|
2005-01-19 20:55:50 +03:00
|
|
|
// although this isn't pretty, ATM we only have RootLayer.
|
|
|
|
// this messages should be handled somewhere into a RootLayer
|
|
|
|
// specific area - this set is intended for a RootLayer.
|
2005-05-28 17:43:13 +04:00
|
|
|
gDesktop->ActiveRootLayer()->GetCursorManager().SetDefaults();
|
2003-07-24 23:38:24 +04:00
|
|
|
break;
|
|
|
|
}
|
2003-01-27 22:43:15 +03:00
|
|
|
default:
|
|
|
|
// we should never get here.
|
|
|
|
break;
|
|
|
|
}
|
2003-01-20 23:38:49 +03:00
|
|
|
}
|
|
|
|
|
2003-02-04 03:20:15 +03:00
|
|
|
/*!
|
|
|
|
\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.
|
|
|
|
*/
|
2005-05-27 14:57:25 +04:00
|
|
|
ServerApp *
|
|
|
|
AppServer::FindApp(const char *sig)
|
2003-02-04 03:20:15 +03:00
|
|
|
{
|
2005-06-15 01:28:56 +04:00
|
|
|
if (!sig)
|
2003-02-04 03:20:15 +03:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ServerApp *foundapp=NULL;
|
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
acquire_sem(fAppListLock);
|
2003-02-04 03:20:15 +03:00
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
for(int32 i=0; i<fAppList->CountItems();i++)
|
2003-02-04 03:20:15 +03:00
|
|
|
{
|
2004-01-20 01:18:37 +03:00
|
|
|
foundapp=(ServerApp*)fAppList->ItemAt(i);
|
2005-05-07 19:56:15 +04:00
|
|
|
if(foundapp && foundapp->Title() == sig)
|
2003-02-04 03:20:15 +03:00
|
|
|
{
|
2004-01-20 01:18:37 +03:00
|
|
|
release_sem(fAppListLock);
|
2003-02-04 03:20:15 +03:00
|
|
|
return foundapp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-20 01:18:37 +03:00
|
|
|
release_sem(fAppListLock);
|
2003-02-04 03:20:15 +03:00
|
|
|
|
|
|
|
// couldn't find a match
|
|
|
|
return NULL;
|
2003-01-20 23:38:49 +03:00
|
|
|
}
|
|
|
|
|
2003-02-14 04:53:53 +03:00
|
|
|
/*!
|
2005-06-17 23:10:15 +04:00
|
|
|
\brief Send a quick (no attachments) message to all applications
|
2003-02-14 14:04:01 +03:00
|
|
|
|
2005-06-17 23:10:15 +04:00
|
|
|
Quite useful for notification for things like server shutdown, system
|
|
|
|
color changes, etc.
|
2003-02-14 04:53:53 +03:00
|
|
|
*/
|
2005-06-17 23:10:15 +04:00
|
|
|
void
|
|
|
|
BroadcastToAllApps(const int32 &code)
|
2003-02-12 04:11:55 +03:00
|
|
|
{
|
2005-06-17 23:10:15 +04:00
|
|
|
acquire_sem(sAppServer->fAppListLock);
|
|
|
|
|
|
|
|
for (int32 i = 0; i < sAppServer->fAppList->CountItems(); i++) {
|
|
|
|
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i);
|
|
|
|
|
|
|
|
if (!app)
|
|
|
|
{ printf("PANIC in Broadcast()\n"); continue; }
|
|
|
|
app->PostMessage(code);
|
|
|
|
}
|
|
|
|
|
|
|
|
release_sem(sAppServer->fAppListLock);
|
2003-02-12 04:11:55 +03:00
|
|
|
}
|
|
|
|
|
2005-06-17 23:10:15 +04:00
|
|
|
// #pragma mark -
|
|
|
|
|
2003-01-27 22:43:15 +03:00
|
|
|
/*!
|
|
|
|
\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.
|
|
|
|
*/
|
2005-05-27 14:57:25 +04:00
|
|
|
int
|
|
|
|
main(int argc, char** argv)
|
2003-01-20 23:38:49 +03:00
|
|
|
{
|
|
|
|
// There can be only one....
|
2005-05-27 17:36:05 +04:00
|
|
|
if (find_port(SERVER_PORT_NAME) >= B_OK)
|
2003-01-20 23:38:49 +03:00
|
|
|
return -1;
|
|
|
|
|
2005-03-13 20:07:40 +03:00
|
|
|
srand(real_time_clock_usecs());
|
2005-05-27 14:57:25 +04:00
|
|
|
AppServer app_server;
|
2004-01-13 03:56:36 +03:00
|
|
|
app_server.Run();
|
2003-01-20 23:38:49 +03:00
|
|
|
return 0;
|
|
|
|
}
|