Rewrote how the app_server and ServerApp's quit. As a side effect, the server
can now quit instantly. AppServer must no longer call ServerApp's destructor once it's running - it now has to call Quit() in this case. The ServerApp is now destructed in its own thread. Some cleanup (like renaming ServerApp::MonitorThreadID() to Thread()). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13238 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
014ddc8724
commit
fcb006dcf5
@ -2,8 +2,12 @@
|
||||
* Copyright (c) 2001-2005, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
|
||||
|
||||
#include <Accelerant.h>
|
||||
#include <AppDefs.h>
|
||||
#include <Directory.h>
|
||||
@ -52,6 +56,10 @@
|
||||
# define STRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
static const uint32 kMsgShutdownServer = 'shuT';
|
||||
|
||||
|
||||
// Globals
|
||||
Desktop *gDesktop;
|
||||
|
||||
@ -92,10 +100,9 @@ AppServer::AppServer(void) :
|
||||
if (fServerInputPort == B_NO_MORE_PORTS)
|
||||
debugger("app_server could not create input port");
|
||||
|
||||
fAppList = new BList();
|
||||
fQuittingServer = false;
|
||||
fQuitting = false;
|
||||
sAppServer = this;
|
||||
|
||||
|
||||
// Create the font server and scan the proper directories.
|
||||
fontserver = new FontServer;
|
||||
fontserver->Lock();
|
||||
@ -228,19 +235,25 @@ AppServer::~AppServer(void)
|
||||
int32
|
||||
AppServer::PicassoThread(void *data)
|
||||
{
|
||||
for (;;) {
|
||||
while (!sAppServer->fQuitting) {
|
||||
acquire_sem(sAppServer->fAppListLock);
|
||||
for (int32 i = 0;;) {
|
||||
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i++);
|
||||
ServerApp *app = (ServerApp *)sAppServer->fAppList.ItemAt(i++);
|
||||
if (!app)
|
||||
break;
|
||||
|
||||
app->PingTarget();
|
||||
}
|
||||
release_sem(sAppServer->fAppListLock);
|
||||
// we do this every other second so as not to suck *too* many CPU cycles
|
||||
release_sem(sAppServer->fAppListLock);
|
||||
// we do this every second so as not to suck *too* many CPU cycles
|
||||
snooze(1000000);
|
||||
}
|
||||
|
||||
// app_server is about to quit
|
||||
// wait some more, and then make sure it'll shutdown everything
|
||||
snooze(2000000);
|
||||
sAppServer->PostMessage(kMsgShutdownServer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -257,13 +270,13 @@ AppServer::LaunchInputServer()
|
||||
|
||||
fISThreadID = B_ERROR;
|
||||
|
||||
while (!BRoster::Private().IsMessengerValid(false) && !fQuittingServer) {
|
||||
while (!BRoster::Private().IsMessengerValid(false) && !fQuitting) {
|
||||
snooze(250000);
|
||||
BRoster::Private::DeleteBeRoster();
|
||||
BRoster::Private::InitBeRoster();
|
||||
}
|
||||
|
||||
if (fQuittingServer)
|
||||
if (fQuitting)
|
||||
return;
|
||||
|
||||
// we use an area for cursor data communication with input_server
|
||||
@ -323,18 +336,15 @@ AppServer::LaunchCursorThread()
|
||||
int32
|
||||
AppServer::CursorThread(void* data)
|
||||
{
|
||||
AppServer *app = (AppServer *)data;
|
||||
AppServer *server = (AppServer *)data;
|
||||
|
||||
BPoint p;
|
||||
|
||||
app->LaunchInputServer();
|
||||
server->LaunchInputServer();
|
||||
|
||||
do {
|
||||
|
||||
while (acquire_sem(app->fCursorSem) == B_OK) {
|
||||
|
||||
p.y = *app->fCursorAddr & 0x7fff;
|
||||
p.x = *app->fCursorAddr >> 15 & 0x7fff;
|
||||
while (acquire_sem(server->fCursorSem) == B_OK) {
|
||||
BPoint p;
|
||||
p.y = *server->fCursorAddr & 0x7fff;
|
||||
p.x = *server->fCursorAddr >> 15 & 0x7fff;
|
||||
|
||||
gDesktop->GetDisplayDriver()->MoveCursorTo(p.x, p.y);
|
||||
STRACE(("CursorThread : %f, %f\n", p.x, p.y));
|
||||
@ -342,12 +352,25 @@ AppServer::CursorThread(void* data)
|
||||
|
||||
snooze(100000);
|
||||
|
||||
} while (!app->fQuittingServer);
|
||||
} while (!server->fQuitting);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Send a message to the AppServer with no attachments
|
||||
\param code ID code of the message to post
|
||||
*/
|
||||
void
|
||||
AppServer::PostMessage(int32 code)
|
||||
{
|
||||
BPrivate::LinkSender link(fMessagePort);
|
||||
link.StartMessage(code);
|
||||
link.Flush();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief The call that starts it all...
|
||||
\return Always 0
|
||||
@ -365,38 +388,19 @@ AppServer::Run(void)
|
||||
void
|
||||
AppServer::MainLoop(void)
|
||||
{
|
||||
BPrivate::PortLink pmsg(-1, fMessagePort);
|
||||
BPrivate::PortLink link(-1, fMessagePort);
|
||||
|
||||
while (1) {
|
||||
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
|
||||
|
||||
int32 code;
|
||||
status_t err = pmsg.GetNextMessage(code);
|
||||
status_t err = link.GetNextMessage(code);
|
||||
if (err < B_OK) {
|
||||
STRACE(("MainLoop:pmsg.GetNextMessage() failed\n"));
|
||||
STRACE(("MainLoop:link.GetNextMessage() failed\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
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:
|
||||
DispatchMessage(code, pmsg);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
STRACE(("Server::MainLoop received unexpected code %ld (offset %ld)\n",
|
||||
code, code - SERVER_TRUE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
DispatchMessage(code, link);
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,7 +417,7 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||
case AS_CREATE_APP:
|
||||
{
|
||||
// Create the ServerApp to node monitor a new BApplication
|
||||
|
||||
|
||||
// Attached data:
|
||||
// 1) port_id - receiver port of a regular app
|
||||
// 2) port_id - client looper port - for send messages to the client
|
||||
@ -435,39 +439,29 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||
if (msg.ReadString(&appSignature) != B_OK)
|
||||
break;
|
||||
|
||||
port_id serverListen = create_port(DEFAULT_MONITOR_PORT_SIZE, appSignature);
|
||||
if (serverListen < B_OK) {
|
||||
printf("No more ports left. Time to crash. Have a nice day! :)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// we let the application own the port, so that we get aware when it's gone
|
||||
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,
|
||||
ServerApp *app = new ServerApp(clientReplyPort, clientLooperPort,
|
||||
clientTeamID, htoken, appSignature);
|
||||
if (app->InitCheck() == B_OK
|
||||
&& app->Run()) {
|
||||
// add the new ServerApp to the known list of ServerApps
|
||||
acquire_sem(fAppListLock);
|
||||
fAppList.AddItem(app);
|
||||
release_sem(fAppListLock);
|
||||
} else {
|
||||
delete app;
|
||||
|
||||
// add the new ServerApp to the known list of ServerApps
|
||||
fAppList->AddItem(app);
|
||||
|
||||
release_sem(fAppListLock);
|
||||
|
||||
BPrivate::PortLink replylink(clientReplyPort);
|
||||
replylink.StartMessage(SERVER_TRUE);
|
||||
replylink.Attach<int32>(serverListen);
|
||||
replylink.Flush();
|
||||
// if everything went well, ServerApp::Run() will notify
|
||||
// the client - but since it didn't, we do it here
|
||||
BPrivate::LinkSender reply(clientReplyPort);
|
||||
reply.StartMessage(SERVER_FALSE);
|
||||
reply.Flush();
|
||||
}
|
||||
|
||||
// This is necessary because BPortLink::ReadString allocates memory
|
||||
free(appSignature);
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_DELETE_APP:
|
||||
{
|
||||
// Delete a ServerApp. Received only from the respective ServerApp when a
|
||||
@ -476,41 +470,45 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||
// Attached Data:
|
||||
// 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)
|
||||
thread_id thread = -1;
|
||||
if (msg.Read<thread_id>(&thread) < B_OK)
|
||||
break;
|
||||
|
||||
acquire_sem(fAppListLock);
|
||||
|
||||
// Run through the list of apps and nuke the proper one
|
||||
for (i = 0; i < appnum; i++) {
|
||||
srvapp = (ServerApp *)fAppList->ItemAt(i);
|
||||
|
||||
if (srvapp != NULL && srvapp->MonitorThreadID() == srvapp_id) {
|
||||
srvapp = (ServerApp *)fAppList->RemoveItem(i);
|
||||
if (srvapp) {
|
||||
delete srvapp;
|
||||
srvapp = NULL;
|
||||
}
|
||||
break; // jump out of our for() loop
|
||||
int32 count = fAppList.CountItems();
|
||||
ServerApp *removeApp = NULL;
|
||||
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
ServerApp *app = (ServerApp *)fAppList.ItemAt(i);
|
||||
|
||||
if (app != NULL && app->Thread() == thread) {
|
||||
fAppList.RemoveItem(i);
|
||||
removeApp = app;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
release_sem(fAppListLock);
|
||||
|
||||
if (removeApp != NULL)
|
||||
removeApp->Quit();
|
||||
|
||||
if (fQuitting && count <= 1)
|
||||
PostMessage(kMsgShutdownServer);
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_UPDATED_CLIENT_FONTLIST:
|
||||
{
|
||||
// received when the client-side global font list has been
|
||||
// refreshed
|
||||
fontserver->Lock();
|
||||
fontserver->FontsUpdated();
|
||||
fontserver->Unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_QUERY_FONTS_CHANGED:
|
||||
{
|
||||
// Client application is asking if the font list has changed since
|
||||
@ -531,50 +529,34 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||
BPrivate::PortLink replylink(replyport);
|
||||
replylink.StartMessage(needs_update ? SERVER_TRUE : SERVER_FALSE);
|
||||
replylink.Flush();
|
||||
|
||||
break;
|
||||
}
|
||||
case B_QUIT_REQUESTED:
|
||||
{
|
||||
|
||||
#if TEST_MODE
|
||||
// Attached Data:
|
||||
// none
|
||||
|
||||
case B_QUIT_REQUESTED:
|
||||
// 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.
|
||||
|
||||
fQuitting = true;
|
||||
BroadcastToAllApps(AS_QUIT_APP);
|
||||
|
||||
// we have to wait until *all* threads have finished!
|
||||
ServerApp *app;
|
||||
// We now need to process the remaining AS_DELETE_APP messages and
|
||||
// wait for the kMsgShutdownServer message.
|
||||
// If an application does not quit as asked, the picasso thread
|
||||
// will send us this message in 2-3 seconds.
|
||||
break;
|
||||
|
||||
case kMsgShutdownServer:
|
||||
// let's kill all remaining applications
|
||||
|
||||
acquire_sem(fAppListLock);
|
||||
thread_info tinfo;
|
||||
for (int32 i = 0; i < fAppList->CountItems(); i++) {
|
||||
app = (ServerApp*)fAppList->ItemAt(i);
|
||||
if (!app)
|
||||
continue;
|
||||
|
||||
// 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
|
||||
if (get_thread_info(app->MonitorThreadID(), &tinfo)==B_OK) {
|
||||
bool killteam = true;
|
||||
for (int32 i = 0; i < fAppList.CountItems(); i++) {
|
||||
ServerApp *app = (ServerApp*)fAppList.ItemAt(i);
|
||||
|
||||
for (int32 j = 0; j < 5; j++) {
|
||||
snooze(500000); // wait half a second for it to quit
|
||||
if (get_thread_info(app->MonitorThreadID(), &tinfo) != B_OK) {
|
||||
killteam = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (killteam) {
|
||||
kill_team(app->ClientTeamID());
|
||||
app->PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
}
|
||||
kill_thread(app->Thread());
|
||||
kill_team(app->ClientTeam());
|
||||
}
|
||||
|
||||
kill_thread(fPicassoThreadID);
|
||||
@ -582,15 +564,14 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||
release_sem(fAppListLock);
|
||||
|
||||
delete gDesktop;
|
||||
delete fAppList;
|
||||
delete bitmapmanager;
|
||||
delete fontserver;
|
||||
|
||||
// we are now clear to exit
|
||||
exit_thread(0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case AS_SET_SYSCURSOR_DEFAULTS:
|
||||
{
|
||||
// although this isn't pretty, ATM we only have RootLayer.
|
||||
@ -599,8 +580,10 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||
gDesktop->ActiveRootLayer()->GetCursorManager().SetDefaults();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// we should never get here.
|
||||
STRACE(("Server::MainLoop received unexpected code %ld (offset %ld)\n",
|
||||
code, code - SERVER_TRUE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -614,31 +597,31 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
|
||||
while it does its searching.
|
||||
*/
|
||||
ServerApp *
|
||||
AppServer::FindApp(const char *sig)
|
||||
AppServer::FindApp(const char *signature)
|
||||
{
|
||||
if (!sig)
|
||||
if (!signature)
|
||||
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;
|
||||
ServerApp *foundApp = NULL;
|
||||
for (int32 i = 0; i < fAppList.CountItems(); i++) {
|
||||
ServerApp *app = (ServerApp*)fAppList.ItemAt(i);
|
||||
if (app && !strcasecmp(app->Signature(), signature)) {
|
||||
foundApp = app;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
release_sem(fAppListLock);
|
||||
|
||||
// couldn't find a match
|
||||
return NULL;
|
||||
|
||||
return foundApp;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/*!
|
||||
\brief Send a quick (no attachments) message to all applications
|
||||
|
||||
@ -650,18 +633,19 @@ BroadcastToAllApps(const int32 &code)
|
||||
{
|
||||
acquire_sem(sAppServer->fAppListLock);
|
||||
|
||||
for (int32 i = 0; i < sAppServer->fAppList->CountItems(); i++) {
|
||||
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i);
|
||||
for (int32 i = 0; i < sAppServer->fAppList.CountItems(); i++) {
|
||||
ServerApp *app = (ServerApp *)sAppServer->fAppList.ItemAt(i);
|
||||
|
||||
if (!app)
|
||||
{ printf("PANIC in Broadcast()\n"); continue; }
|
||||
if (!app) {
|
||||
printf("PANIC in Broadcast()\n");
|
||||
continue;
|
||||
}
|
||||
app->PostMessage(code);
|
||||
}
|
||||
|
||||
release_sem(sAppServer->fAppListLock);
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
/*!
|
||||
\brief Entry function to run the entire server
|
||||
@ -677,7 +661,9 @@ main(int argc, char** argv)
|
||||
return -1;
|
||||
|
||||
srand(real_time_clock_usecs());
|
||||
AppServer app_server;
|
||||
app_server.Run();
|
||||
|
||||
AppServer server;
|
||||
server.Run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ public:
|
||||
static int32 PicassoThread(void *data);
|
||||
thread_id Run(void);
|
||||
void MainLoop(void);
|
||||
|
||||
|
||||
void PostMessage(int32 code);
|
||||
void DispatchMessage(int32 code, BPrivate::PortLink &link);
|
||||
ServerApp* FindApp(const char *sig);
|
||||
|
||||
@ -64,10 +65,10 @@ private:
|
||||
|
||||
port_id fMessagePort;
|
||||
port_id fServerInputPort;
|
||||
|
||||
volatile bool fQuittingServer;
|
||||
|
||||
BList *fAppList;
|
||||
|
||||
volatile bool fQuitting;
|
||||
|
||||
BList fAppList;
|
||||
thread_id fPicassoThreadID;
|
||||
|
||||
thread_id fISThreadID;
|
||||
|
@ -268,7 +268,7 @@ Desktop::AddWinBorder(WinBorder *winBorder)
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
wb = (WinBorder *)fWinBorderList.ItemAt(i);
|
||||
|
||||
if (wb->App()->ClientTeamID() == winBorder->App()->ClientTeamID()
|
||||
if (wb->App()->ClientTeam() == winBorder->App()->ClientTeam()
|
||||
&& wb->Feel() == feelToLookFor) {
|
||||
// R2: RootLayer comparison is needed.
|
||||
feel == B_NORMAL_WINDOW_FEEL ?
|
||||
@ -322,7 +322,7 @@ Desktop::RemoveWinBorder(WinBorder *winBorder)
|
||||
wb = (WinBorder*)fWinBorderList.ItemAt(i);
|
||||
|
||||
if (wb->Feel() == B_NORMAL_WINDOW_FEEL
|
||||
&& wb->App()->ClientTeamID() == winBorder->App()->ClientTeamID()) {
|
||||
&& wb->App()->ClientTeam() == winBorder->App()->ClientTeam()) {
|
||||
// R2: RootLayer comparison is needed. We'll see.
|
||||
wb->fSubWindowList.RemoveItem(winBorder);
|
||||
}
|
||||
@ -368,7 +368,7 @@ Desktop::AddWinBorderToSubset(WinBorder *winBorder, WinBorder *toWinBorder)
|
||||
if ((winBorder->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL
|
||||
|| winBorder->Feel() == B_MODAL_SUBSET_WINDOW_FEEL)
|
||||
&& toWinBorder->Feel() == B_NORMAL_WINDOW_FEEL
|
||||
&& toWinBorder->App()->ClientTeamID() == winBorder->App()->ClientTeamID()
|
||||
&& toWinBorder->App()->ClientTeam() == winBorder->App()->ClientTeam()
|
||||
&& !toWinBorder->fSubWindowList.HasItem(winBorder)) {
|
||||
// add to normal_window's list
|
||||
toWinBorder->fSubWindowList.AddWinBorder(winBorder);
|
||||
@ -442,7 +442,7 @@ Desktop::FindWinBorderByServerWindowTokenAndTeamID(int32 token, team_id teamID)
|
||||
Lock();
|
||||
for (int32 i = 0; (wb = (WinBorder *)fWinBorderList.ItemAt(i)); i++) {
|
||||
if (wb->Window()->ClientToken() == token
|
||||
&& wb->Window()->ClientTeamID() == teamID)
|
||||
&& wb->Window()->ClientTeam() == teamID)
|
||||
break;
|
||||
}
|
||||
Unlock();
|
||||
|
@ -63,6 +63,10 @@
|
||||
# define FTRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
static const uint32 kMsgAppQuit = 'appQ';
|
||||
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
\param sendport port ID for the BApplication which will receive the ServerApp's messages
|
||||
@ -70,21 +74,17 @@
|
||||
\param fSignature NULL-terminated string which contains the BApplication's
|
||||
MIME fSignature.
|
||||
*/
|
||||
ServerApp::ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort,
|
||||
team_id clientTeamID, int32 handlerID, const char* signature)
|
||||
ServerApp::ServerApp(port_id clientReplyPort, port_id clientLooperPort,
|
||||
team_id clientTeam, int32 handlerID, const char* signature)
|
||||
:
|
||||
fClientAppPort(sendport),
|
||||
fMessagePort(rcvport),
|
||||
fLockSem(-1),
|
||||
fClientReplyPort(clientReplyPort),
|
||||
fMessagePort(-1),
|
||||
fClientLooperPort(clientLooperPort),
|
||||
fSignature(signature),
|
||||
fMonitorThreadID(-1),
|
||||
fClientTeamID(clientTeamID),
|
||||
fLink(fClientAppPort, fMessagePort),
|
||||
fSWindowList(new BList()),
|
||||
fBitmapList(new BList()),
|
||||
fPictureList(new BList()),
|
||||
fThread(-1),
|
||||
fClientTeam(clientTeam),
|
||||
fAppCursor(NULL),
|
||||
fLockSem(create_sem(1, "ServerApp sem")),
|
||||
fCursorHidden(false),
|
||||
fIsActive(false),
|
||||
//fHandlerToken(handlerID),
|
||||
@ -92,7 +92,25 @@ ServerApp::ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort
|
||||
fQuitting(false)
|
||||
{
|
||||
if (fSignature == "")
|
||||
fSignature = "application/x-vnd.NULL-application-signature";
|
||||
fSignature = "application/no-signature";
|
||||
|
||||
fLockSem = create_sem(1, Signature());
|
||||
if (fLockSem < B_OK)
|
||||
return;
|
||||
|
||||
fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, Signature());
|
||||
if (fMessagePort < B_OK)
|
||||
return;
|
||||
|
||||
fLink.SetSenderPort(fClientReplyPort);
|
||||
fLink.SetReceiverPort(fMessagePort);
|
||||
|
||||
// we let the application own the port, so that we get aware when it's gone
|
||||
if (set_port_owner(fMessagePort, clientTeam) < B_OK) {
|
||||
delete_port(fMessagePort);
|
||||
fMessagePort = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// although this isn't pretty, ATM we have only one RootLayer.
|
||||
// there should be a way that this ServerApp be attached to a particular
|
||||
@ -102,13 +120,11 @@ ServerApp::ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort
|
||||
|
||||
if (defaultCursor) {
|
||||
fAppCursor = new ServerCursor(defaultCursor);
|
||||
fAppCursor->SetOwningTeam(fClientTeamID);
|
||||
fAppCursor->SetOwningTeam(fClientTeam);
|
||||
}
|
||||
|
||||
Run();
|
||||
|
||||
STRACE(("ServerApp %s:\n", fSignature.String()));
|
||||
STRACE(("\tBApp port: %ld\n", fClientAppPort));
|
||||
STRACE(("\tBApp port: %ld\n", fClientReplyPort));
|
||||
STRACE(("\tReceiver port: %ld\n", fMessagePort));
|
||||
}
|
||||
|
||||
@ -117,67 +133,119 @@ ServerApp::ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort
|
||||
ServerApp::~ServerApp(void)
|
||||
{
|
||||
STRACE(("*ServerApp %s:~ServerApp()\n",fSignature.String()));
|
||||
|
||||
fQuitting = true;
|
||||
|
||||
for (int32 i = 0; i< fBitmapList->CountItems(); i++) {
|
||||
delete static_cast<ServerBitmap *>(fBitmapList->ItemAt(i));
|
||||
}
|
||||
delete fBitmapList;
|
||||
|
||||
for (int32 i = 0; i < fPictureList->CountItems(); i++) {
|
||||
delete static_cast<ServerPicture *>(fPictureList->ItemAt(i));
|
||||
if (!fQuitting)
|
||||
CRITICAL("ServerApp: destructor called after Run()!\n");
|
||||
|
||||
// first, make sure our monitor thread doesn't
|
||||
for (int32 i = 0; i < fBitmapList.CountItems(); i++) {
|
||||
delete static_cast<ServerBitmap *>(fBitmapList.ItemAt(i));
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < fPictureList.CountItems(); i++) {
|
||||
delete static_cast<ServerPicture *>(fPictureList.ItemAt(i));
|
||||
}
|
||||
delete fPictureList;
|
||||
|
||||
// This shouldn't be necessary -- all cursors owned by the app
|
||||
// should be cleaned up by RemoveAppCursors
|
||||
// if(fAppCursor)
|
||||
// delete fAppCursor;
|
||||
// delete fAppCursor;
|
||||
|
||||
// although this isn't pretty, ATM we have only one RootLayer.
|
||||
// there should be a way that this ServerApp be attached to a particular
|
||||
// RootLayer to know which RootLayer's cursor to modify.
|
||||
gDesktop->ActiveRootLayer()->GetCursorManager().RemoveAppCursors(fClientTeamID);
|
||||
gDesktop->ActiveRootLayer()->GetCursorManager().RemoveAppCursors(fClientTeam);
|
||||
delete_sem(fLockSem);
|
||||
|
||||
STRACE(("#ServerApp %s:~ServerApp()\n", fSignature.String()));
|
||||
|
||||
// TODO: Is this the right place for this ?
|
||||
// From what I've understood, this is the port created by
|
||||
// the BApplication (?), but if I delete it in there, GetNextMessage()
|
||||
// in the MonitorApp thread never returns. Cleanup.
|
||||
delete_port(fMessagePort);
|
||||
|
||||
status_t dummyStatus;
|
||||
wait_for_thread(fMonitorThreadID, &dummyStatus);
|
||||
|
||||
delete fSharedMem;
|
||||
|
||||
STRACE(("ServerApp %s::~ServerApp(): Exiting\n", fSignature.String()));
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Checks if the application was initialized correctly
|
||||
*/
|
||||
status_t
|
||||
ServerApp::InitCheck()
|
||||
{
|
||||
if (fMessagePort < B_OK)
|
||||
return fMessagePort;
|
||||
|
||||
if (fClientReplyPort < B_OK)
|
||||
return fClientReplyPort;
|
||||
|
||||
if (fLockSem < B_OK)
|
||||
return fLockSem;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Starts the ServerApp monitoring for messages
|
||||
\return false if the application couldn't start, true if everything went OK.
|
||||
*/
|
||||
bool
|
||||
ServerApp::Run(void)
|
||||
ServerApp::Run()
|
||||
{
|
||||
fQuitting = false;
|
||||
|
||||
// Unlike a BApplication, a ServerApp is *supposed* to return immediately
|
||||
// when its Run() function is called.
|
||||
fMonitorThreadID = spawn_thread(MonitorApp, fSignature.String(), B_NORMAL_PRIORITY, this);
|
||||
if (fMonitorThreadID < B_OK)
|
||||
fThread = spawn_thread(_message_thread, fSignature.String(), B_NORMAL_PRIORITY, this);
|
||||
if (fThread < B_OK)
|
||||
return false;
|
||||
|
||||
return resume_thread(fMonitorThreadID) == B_OK;
|
||||
// Let's tell the client how to talk with us
|
||||
fLink.StartMessage(SERVER_TRUE);
|
||||
fLink.Attach<int32>(fMessagePort);
|
||||
fLink.Flush();
|
||||
|
||||
if (resume_thread(fThread) != B_OK) {
|
||||
fQuitting = true;
|
||||
kill_thread(fThread);
|
||||
fThread = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief This quits the application and deletes it. You're not supposed
|
||||
to call its destructor directly.
|
||||
|
||||
At the point you're calling this method, the application should already
|
||||
be removed from the application list.
|
||||
*/
|
||||
void
|
||||
ServerApp::Quit()
|
||||
{
|
||||
if (fThread < B_OK) {
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
// execute application deletion in the message looper thread
|
||||
|
||||
fQuitting = true;
|
||||
|
||||
BPrivate::LinkSender link(fMessagePort);
|
||||
link.StartMessage(kMsgAppQuit);
|
||||
link.Flush();
|
||||
|
||||
send_data(fThread, 'QUIT', NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Pings the target app to make sure it's still working
|
||||
\return true if target is still "alive" and false if "He's dead, Jim."
|
||||
"But that's impossible..."
|
||||
|
||||
|
||||
This function is called by the app_server thread to ensure that
|
||||
the target app still exists. We do this not by sending a message
|
||||
but by calling get_port_info. We don't want to send ping messages
|
||||
@ -187,13 +255,13 @@ ServerApp::Run(void)
|
||||
tell the app_server to delete the respective ServerApp.
|
||||
*/
|
||||
bool
|
||||
ServerApp::PingTarget(void)
|
||||
ServerApp::PingTarget()
|
||||
{
|
||||
team_info tinfo;
|
||||
if (get_team_info(fClientTeamID, &tinfo) == B_BAD_TEAM_ID) {
|
||||
team_info info;
|
||||
if (get_team_info(fClientTeam, &info) != B_OK) {
|
||||
BPrivate::LinkSender link(gAppServerPort);
|
||||
link.StartMessage(AS_DELETE_APP);
|
||||
link.Attach(&fMonitorThreadID, sizeof(thread_id));
|
||||
link.Attach(&fThread, sizeof(thread_id));
|
||||
link.Flush();
|
||||
return false;
|
||||
}
|
||||
@ -260,34 +328,50 @@ ServerApp::SetAppCursor(void)
|
||||
/*!
|
||||
\brief The thread function ServerApps use to monitor messages
|
||||
\param data Pointer to the thread's ServerApp object
|
||||
\return Throwaway value - always 0
|
||||
*/
|
||||
int32
|
||||
ServerApp::MonitorApp(void *data)
|
||||
ServerApp::_message_thread(void *_app)
|
||||
{
|
||||
ServerApp *app = (ServerApp *)_app;
|
||||
|
||||
app->_MessageLooper();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief The thread function ServerApps use to monitor messages
|
||||
*/
|
||||
void
|
||||
ServerApp::_MessageLooper()
|
||||
{
|
||||
// Message-dispatching loop for the ServerApp
|
||||
|
||||
ServerApp *app = (ServerApp *)data;
|
||||
BPrivate::LinkReceiver &reader = app->fLink.Receiver();
|
||||
BPrivate::LinkReceiver &receiver = fLink.Receiver();
|
||||
|
||||
int32 code;
|
||||
status_t err = B_OK;
|
||||
|
||||
while (!app->fQuitting) {
|
||||
STRACE(("info: ServerApp::MonitorApp listening on port %ld.\n", app->fMessagePort));
|
||||
err = reader.GetNextMessage(code, B_INFINITE_TIMEOUT);
|
||||
if (err < B_OK) {
|
||||
STRACE(("ServerApp::MonitorApp(): GetNextMessage returned %s\n", strerror(err)));
|
||||
while (!fQuitting) {
|
||||
STRACE(("info: ServerApp::_MessageLooper() listening on port %ld.\n", fMessagePort));
|
||||
err = receiver.GetNextMessage(code, B_INFINITE_TIMEOUT);
|
||||
if (err < B_OK || code == B_QUIT_REQUESTED) {
|
||||
STRACE(("ServerApp: application seems to be gone...\n"));
|
||||
|
||||
// ToDo: this should kill the app, but it doesn't work
|
||||
// Tell the app_server to quit us
|
||||
BPrivate::LinkSender link(gAppServerPort);
|
||||
link.StartMessage(AS_DELETE_APP);
|
||||
link.Attach(&app->fMonitorThreadID, sizeof(thread_id));
|
||||
link.Attach<thread_id>(Thread());
|
||||
link.Flush();
|
||||
break;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case kMsgAppQuit:
|
||||
// we receive this from our destructor on quit
|
||||
fQuitting = true;
|
||||
break;
|
||||
|
||||
case AS_CREATE_WINDOW:
|
||||
{
|
||||
// Create the ServerWindow to node monitor a new OBWindow
|
||||
@ -312,22 +396,21 @@ ServerApp::MonitorApp(void *data)
|
||||
port_id looperPort = -1;
|
||||
char *title = NULL;
|
||||
|
||||
reader.Read<BRect>(&frame);
|
||||
reader.Read<uint32>(&look);
|
||||
reader.Read<uint32>(&feel);
|
||||
reader.Read<uint32>(&flags);
|
||||
reader.Read<uint32>(&wkspaces);
|
||||
reader.Read<int32>(&token);
|
||||
reader.Read<port_id>(&sendPort);
|
||||
reader.Read<port_id>(&looperPort);
|
||||
if (reader.ReadString(&title) != B_OK)
|
||||
receiver.Read<BRect>(&frame);
|
||||
receiver.Read<uint32>(&look);
|
||||
receiver.Read<uint32>(&feel);
|
||||
receiver.Read<uint32>(&flags);
|
||||
receiver.Read<uint32>(&wkspaces);
|
||||
receiver.Read<int32>(&token);
|
||||
receiver.Read<port_id>(&sendPort);
|
||||
receiver.Read<port_id>(&looperPort);
|
||||
if (receiver.ReadString(&title) != B_OK)
|
||||
break;
|
||||
|
||||
STRACE(("ServerApp %s: Got 'New Window' message, trying to do smething...\n",app->fSignature.String()));
|
||||
STRACE(("ServerApp %s: Got 'New Window' message, trying to do smething...\n", Signature()));
|
||||
|
||||
// ServerWindow constructor will reply with port_id of a newly created port
|
||||
ServerWindow *sw = NULL;
|
||||
sw = new ServerWindow(title, app, sendPort, looperPort, token);
|
||||
ServerWindow *sw = new ServerWindow(title, this, sendPort, looperPort, token);
|
||||
sw->Init(frame, look, feel, flags, wkspaces);
|
||||
|
||||
STRACE(("\nServerApp %s: New Window %s (%.1f,%.1f,%.1f,%.1f)\n",
|
||||
@ -337,46 +420,38 @@ ServerApp::MonitorApp(void *data)
|
||||
free(title);
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_QUIT_APP:
|
||||
{
|
||||
// This message is received only when the app_server is asked to shut down in
|
||||
// test/debug mode. Of course, if we are testing while using AccelerantDriver, we do
|
||||
// NOT want to shut down client applications. The server can be quit o in this fashion
|
||||
// through the driver's interface, such as closing the ViewDriver's window.
|
||||
|
||||
STRACE(("ServerApp %s:Server shutdown notification received\n",
|
||||
app->fSignature.String()));
|
||||
|
||||
STRACE(("ServerApp %s:Server shutdown notification received\n", Signature()));
|
||||
|
||||
// If we are using the real, accelerated version of the
|
||||
// DisplayDriver, we do NOT want the user to be able shut down
|
||||
// the server. The results would NOT be pretty
|
||||
#if TEST_MODE
|
||||
BMessage pleaseQuit(B_QUIT_REQUESTED);
|
||||
app->SendMessageToClient(&pleaseQuit);
|
||||
SendMessageToClient(&pleaseQuit);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case B_QUIT_REQUESTED:
|
||||
{
|
||||
STRACE(("ServerApp %s: B_QUIT_REQUESTED\n",app->fSignature.String()));
|
||||
// Our BApplication sent us this message when it quit.
|
||||
// We need to ask the app_server to delete ourself.
|
||||
BPrivate::LinkSender sender(gAppServerPort);
|
||||
sender.StartMessage(AS_DELETE_APP);
|
||||
sender.Attach(&app->fMonitorThreadID, sizeof(thread_id));
|
||||
sender.Flush();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
STRACE(("ServerApp %s: Got a Message to dispatch\n", app->fSignature.String()));
|
||||
app->DispatchMessage(code, reader);
|
||||
STRACE(("ServerApp %s: Got a Message to dispatch\n", Signature()));
|
||||
_DispatchMessage(code, receiver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
// Quit() will send us a message; we're handling the exiting procedure
|
||||
thread_id sender;
|
||||
receive_data(&sender, NULL, 0);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +465,7 @@ ServerApp::MonitorApp(void *data)
|
||||
matter of casting and incrementing an index variable to access them.
|
||||
*/
|
||||
void
|
||||
ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
{
|
||||
LayerData ld;
|
||||
|
||||
@ -404,9 +479,8 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
ServerWindow *win;
|
||||
BMessage msg(_COLORS_UPDATED);
|
||||
|
||||
for(int32 i=0; i<fSWindowList->CountItems(); i++)
|
||||
{
|
||||
win=(ServerWindow*)fSWindowList->ItemAt(i);
|
||||
for(int32 i = 0; i < fWindowList.CountItems(); i++) {
|
||||
win=(ServerWindow*)fWindowList.ItemAt(i);
|
||||
win->GetWinBorder()->UpdateColors();
|
||||
win->SendMessageToClient(AS_UPDATE_COLORS, msg);
|
||||
}
|
||||
@ -444,25 +518,24 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
size_t msgsize;
|
||||
area_info ai;
|
||||
int8 *msgpointer;
|
||||
|
||||
|
||||
link.Read<area_id>(&area);
|
||||
link.Read<size_t>(&offset);
|
||||
link.Read<size_t>(&msgsize);
|
||||
|
||||
|
||||
// Part sanity check, part get base pointer :)
|
||||
if (get_area_info(area, &ai) < B_OK)
|
||||
break;
|
||||
|
||||
|
||||
msgpointer = (int8*)ai.address + offset;
|
||||
|
||||
|
||||
RAMLinkMsgReader mlink(msgpointer);
|
||||
DispatchMessage(mlink.Code(), mlink);
|
||||
|
||||
_DispatchMessage(mlink.Code(), mlink);
|
||||
|
||||
// This is a very special case in the sense that when ServerMemIO is used for this
|
||||
// purpose, it will be set to NOT automatically free the memory which it had
|
||||
// requested. This is the server's job once the message has been dispatched.
|
||||
fSharedMem->ReleaseBuffer(msgpointer);
|
||||
|
||||
break;
|
||||
}
|
||||
case AS_ACQUIRE_SERVERMEM:
|
||||
@ -536,14 +609,11 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
{
|
||||
STRACE(("ServerApp %s: Received decorator update notification\n",fSignature.String()));
|
||||
|
||||
ServerWindow *win;
|
||||
|
||||
for(int32 i = 0; i < fSWindowList->CountItems(); i++)
|
||||
{
|
||||
win = (ServerWindow*)fSWindowList->ItemAt(i);
|
||||
win->Lock();
|
||||
const_cast<WinBorder *>(win->GetWinBorder())->UpdateDecorator();
|
||||
win->Unlock();
|
||||
for (int32 i = 0; i < fWindowList.CountItems(); i++) {
|
||||
ServerWindow *window = (ServerWindow*)fWindowList.ItemAt(i);
|
||||
window->Lock();
|
||||
const_cast<WinBorder *>(window->GetWinBorder())->UpdateDecorator();
|
||||
window->Unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -652,7 +722,7 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
fSignature.String(), frame.Width(), frame.Height()));
|
||||
|
||||
if (bitmap) {
|
||||
fBitmapList->AddItem(bitmap);
|
||||
fBitmapList.AddItem(bitmap);
|
||||
fLink.StartMessage(SERVER_TRUE);
|
||||
fLink.Attach<int32>(bitmap->Token());
|
||||
fLink.Attach<int32>(bitmap->Area());
|
||||
@ -683,7 +753,7 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
if (bitmap) {
|
||||
STRACE(("ServerApp %s: Deleting Bitmap %ld\n", fSignature.String(), id));
|
||||
|
||||
fBitmapList->RemoveItem(bitmap);
|
||||
fBitmapList.RemoveItem(bitmap);
|
||||
bitmapmanager->DeleteBitmap(bitmap);
|
||||
fLink.StartMessage(SERVER_TRUE);
|
||||
} else
|
||||
@ -814,7 +884,7 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
gDesktop->ActiveRootLayer()->GetCursorManager().DeleteCursor(fAppCursor->ID());
|
||||
|
||||
fAppCursor = new ServerCursor(cdata);
|
||||
fAppCursor->SetOwningTeam(fClientTeamID);
|
||||
fAppCursor->SetOwningTeam(fClientTeam);
|
||||
fAppCursor->SetAppSignature(fSignature.String());
|
||||
gDesktop->ActiveRootLayer()->GetCursorManager().AddCursor(fAppCursor);
|
||||
// although this isn't pretty, ATM we have only one RootLayer.
|
||||
@ -862,7 +932,7 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
link.Read(cursorData, sizeof(cursorData));
|
||||
|
||||
fAppCursor = new ServerCursor(cursorData);
|
||||
fAppCursor->SetOwningTeam(fClientTeamID);
|
||||
fAppCursor->SetOwningTeam(fClientTeam);
|
||||
fAppCursor->SetAppSignature(fSignature.String());
|
||||
// although this isn't pretty, ATM we have only one RootLayer.
|
||||
// there should be a way that this ServerApp be attached to a particular
|
||||
@ -1849,7 +1919,7 @@ ServerApp::DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
int32
|
||||
ServerApp::CountBitmaps() const
|
||||
{
|
||||
return fBitmapList ? fBitmapList->CountItems() : 0;
|
||||
return fBitmapList.CountItems();
|
||||
}
|
||||
|
||||
|
||||
@ -1861,13 +1931,12 @@ ServerApp::CountBitmaps() const
|
||||
ServerBitmap *
|
||||
ServerApp::FindBitmap(int32 token) const
|
||||
{
|
||||
ServerBitmap *bitmap;
|
||||
for (int32 i = 0; i < fBitmapList->CountItems(); i++) {
|
||||
bitmap = static_cast<ServerBitmap *>(fBitmapList->ItemAt(i));
|
||||
for (int32 i = 0; i < fBitmapList.CountItems(); i++) {
|
||||
ServerBitmap *bitmap = static_cast<ServerBitmap *>(fBitmapList.ItemAt(i));
|
||||
if (bitmap && bitmap->Token() == token)
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1875,16 +1944,15 @@ ServerApp::FindBitmap(int32 token) const
|
||||
int32
|
||||
ServerApp::CountPictures() const
|
||||
{
|
||||
return fPictureList ? fPictureList->CountItems() : 0;
|
||||
return fPictureList.CountItems();
|
||||
}
|
||||
|
||||
|
||||
ServerPicture *
|
||||
ServerApp::FindPicture(int32 token) const
|
||||
{
|
||||
ServerPicture *picture;
|
||||
for (int32 i = 0; i < fPictureList->CountItems(); i++) {
|
||||
picture = static_cast<ServerPicture *>(fPictureList->ItemAt(i));
|
||||
for (int32 i = 0; i < fPictureList.CountItems(); i++) {
|
||||
ServerPicture *picture = static_cast<ServerPicture *>(fPictureList.ItemAt(i));
|
||||
if (picture && picture->GetToken() == token)
|
||||
return picture;
|
||||
}
|
||||
@ -1894,15 +1962,15 @@ ServerApp::FindPicture(int32 token) const
|
||||
|
||||
|
||||
team_id
|
||||
ServerApp::ClientTeamID() const
|
||||
ServerApp::ClientTeam() const
|
||||
{
|
||||
return fClientTeamID;
|
||||
return fClientTeam;
|
||||
}
|
||||
|
||||
|
||||
thread_id
|
||||
ServerApp::MonitorThreadID() const
|
||||
ServerApp::Thread() const
|
||||
{
|
||||
return fMonitorThreadID;
|
||||
return fThread;
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: ServerApp.h
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Adi Oanca <adioanca@myrealbox.com>
|
||||
// Description: Server-side BApplication counterpart
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright 2001-2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Adrian Oanca <adioanca@cotty.iren.ro>
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Stefano Ceccherini (burton666@libero.it)
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
#ifndef _SERVERAPP_H_
|
||||
#define _SERVERAPP_H_
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
#include <PortLink.h>
|
||||
@ -52,11 +37,14 @@ namespace BPrivate {
|
||||
*/
|
||||
class ServerApp {
|
||||
public:
|
||||
ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort,
|
||||
ServerApp(port_id clientAppPort, port_id clientLooperPort,
|
||||
team_id clientTeamID, int32 handlerID, const char* signature);
|
||||
virtual ~ServerApp(void);
|
||||
|
||||
bool Run(void);
|
||||
~ServerApp();
|
||||
|
||||
status_t InitCheck();
|
||||
bool Run();
|
||||
|
||||
void Quit();
|
||||
/*
|
||||
TODO: These aren't even implemented...
|
||||
void Lock(void);
|
||||
@ -69,19 +57,19 @@ public:
|
||||
*/
|
||||
bool IsActive(void) const { return fIsActive; }
|
||||
void Activate(bool value);
|
||||
|
||||
|
||||
bool PingTarget(void);
|
||||
|
||||
|
||||
void PostMessage(int32 code);
|
||||
void SendMessageToClient( const BMessage* msg ) const;
|
||||
|
||||
|
||||
void SetAppCursor(void);
|
||||
|
||||
team_id ClientTeamID() const;
|
||||
thread_id MonitorThreadID() const;
|
||||
|
||||
const char *Title() const { return fSignature.String(); }
|
||||
|
||||
|
||||
team_id ClientTeam() const;
|
||||
thread_id Thread() const;
|
||||
|
||||
const char *Signature() const { return fSignature.String(); }
|
||||
|
||||
int32 CountBitmaps() const;
|
||||
ServerBitmap *FindBitmap(int32 token) const;
|
||||
|
||||
@ -93,12 +81,16 @@ public:
|
||||
SubWindowList fAppSubWindowList;
|
||||
|
||||
private:
|
||||
void DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
|
||||
void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
|
||||
void _MessageLooper();
|
||||
|
||||
static int32 MonitorApp(void *data);
|
||||
static int32 _message_thread(void *data);
|
||||
|
||||
// TODO: Not used.
|
||||
sem_id fLockSem;
|
||||
|
||||
// our BApplication's event port
|
||||
port_id fClientAppPort;
|
||||
port_id fClientReplyPort;
|
||||
// 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
|
||||
@ -109,23 +101,20 @@ private:
|
||||
|
||||
BString fSignature;
|
||||
|
||||
thread_id fMonitorThreadID;
|
||||
team_id fClientTeamID;
|
||||
thread_id fThread;
|
||||
team_id fClientTeam;
|
||||
|
||||
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,
|
||||
*fPictureList;
|
||||
|
||||
BList fWindowList;
|
||||
BList fBitmapList;
|
||||
BList fPictureList;
|
||||
|
||||
ServerCursor *fAppCursor;
|
||||
|
||||
// TODO: Not used.
|
||||
sem_id fLockSem;
|
||||
|
||||
|
||||
bool fCursorHidden;
|
||||
bool fIsActive;
|
||||
|
||||
|
@ -1,31 +1,15 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: ServerWindow.cpp
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Adi Oanca <adioanca@cotty.iren.ro>
|
||||
// Stephan Aßmus <superstippi@gmx.de>
|
||||
// Description: Shadow BWindow class
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright 2001-2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Adrian Oanca <adioanca@cotty.iren.ro>
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Stefano Ceccherini (burton666@libero.it)
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
|
||||
|
||||
#include <AppDefs.h>
|
||||
#include <Rect.h>
|
||||
@ -75,7 +59,6 @@
|
||||
# define DTRACE(x) ;
|
||||
#endif
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
@ -83,11 +66,11 @@
|
||||
Does a lot of stuff to set up for the window - new decorator, new winborder, spawn a
|
||||
monitor thread.
|
||||
*/
|
||||
ServerWindow::ServerWindow(const char *string, ServerApp *winapp,
|
||||
port_id winport, port_id looperPort, int32 handlerID)
|
||||
: fServerApp(winapp),
|
||||
// fClientWinPort is the port to which the app awaits messages from the server
|
||||
fClientWinPort(winport),
|
||||
ServerWindow::ServerWindow(const char *string, ServerApp *app,
|
||||
port_id clientPort, port_id looperPort, int32 handlerID)
|
||||
:
|
||||
fServerApp(app),
|
||||
fClientReplyPort(clientPort),
|
||||
fClientLooperPort(looperPort),
|
||||
fClientViewsWithInvalidCoords(B_VIEW_RESIZED),
|
||||
fHandlerToken(handlerID)
|
||||
@ -100,14 +83,14 @@ ServerWindow::ServerWindow(const char *string, ServerApp *winapp,
|
||||
} else
|
||||
strcpy(fName, "Unnamed Window");
|
||||
|
||||
fClientTeamID = winapp->ClientTeamID();
|
||||
fClientTeam = app->ClientTeam();
|
||||
fWinBorder = NULL;
|
||||
fCurrentLayer = NULL;
|
||||
|
||||
// fMessagePort is the port to which the app sends messages for the server
|
||||
fMessagePort = create_port(30, fName);
|
||||
|
||||
fMsgSender = new BPrivate::LinkSender(fClientWinPort);
|
||||
fMsgSender = new BPrivate::LinkSender(fClientReplyPort);
|
||||
fMsgReceiver = new BPrivate::LinkReceiver(fMessagePort);
|
||||
|
||||
// Send a reply to our window - it is expecting fMessagePort port.
|
||||
@ -124,15 +107,15 @@ ServerWindow::Init(BRect frame, uint32 wlook,
|
||||
uint32 wfeel, uint32 wflags, uint32 wwksindex)
|
||||
{
|
||||
char name[60];
|
||||
snprintf(name, sizeof(name), "%ld: %s", fClientTeamID, fName);
|
||||
snprintf(name, sizeof(name), "%ld: %s", fClientTeam, fName);
|
||||
|
||||
fWinBorder = new WinBorder(frame, name, wlook, wfeel, wflags,
|
||||
wwksindex, this, gDesktop->GetDisplayDriver());
|
||||
|
||||
// Spawn our message-monitoring thread
|
||||
fMonitorThreadID = spawn_thread(MonitorWin, fName, B_NORMAL_PRIORITY, this);
|
||||
if (fMonitorThreadID >= B_OK)
|
||||
resume_thread(fMonitorThreadID);
|
||||
fThread = spawn_thread(MonitorWin, fName, B_NORMAL_PRIORITY, this);
|
||||
if (fThread >= B_OK)
|
||||
resume_thread(fThread);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,29 +1,14 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: ServerWindow.h
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Description: Shadow BWindow class
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright 2001-2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Adrian Oanca <adioanca@cotty.iren.ro>
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Stefano Ceccherini (burton666@libero.it)
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
#ifndef _SERVERWIN_H_
|
||||
#define _SERVERWIN_H_
|
||||
|
||||
@ -103,16 +88,16 @@ public:
|
||||
{ return fClientViewsWithInvalidCoords; };
|
||||
|
||||
// to who we belong. who do we own. our title.
|
||||
inline ServerApp* App(void) const { return fServerApp; }
|
||||
inline const WinBorder* GetWinBorder(void) const { return fWinBorder; }
|
||||
inline const char* Title(void) const { return fName; }
|
||||
inline ServerApp* App() const { return fServerApp; }
|
||||
inline const WinBorder* GetWinBorder() const { return fWinBorder; }
|
||||
inline const char* Title() const { return fName; }
|
||||
|
||||
// related thread/team_id(s).
|
||||
inline team_id ClientTeamID(void) const { return fClientTeamID; }
|
||||
inline thread_id ThreadID(void) const { return fMonitorThreadID;}
|
||||
inline team_id ClientTeam() const { return fClientTeam; }
|
||||
inline thread_id Thread() const { return fThread; }
|
||||
|
||||
// server "private" - try not to use.
|
||||
inline int32 ClientToken(void) const { return fHandlerToken; }
|
||||
inline int32 ClientToken() const { return fHandlerToken; }
|
||||
|
||||
// ToDo: public??
|
||||
SubWindowList fSubWindowList;
|
||||
@ -143,15 +128,15 @@ private:
|
||||
bool inverse,
|
||||
BPoint where);
|
||||
char fName[50];
|
||||
|
||||
|
||||
ServerApp* fServerApp;
|
||||
WinBorder* fWinBorder;
|
||||
|
||||
team_id fClientTeamID;
|
||||
thread_id fMonitorThreadID;
|
||||
|
||||
|
||||
team_id fClientTeam;
|
||||
thread_id fThread;
|
||||
|
||||
port_id fMessagePort;
|
||||
port_id fClientWinPort;
|
||||
port_id fClientReplyPort;
|
||||
port_id fClientLooperPort;
|
||||
|
||||
BPrivate::LinkReceiver* fMsgReceiver;
|
||||
|
@ -369,41 +369,35 @@ STRACE(("Wks(%ld)::MoveToBack(%s) \n", fID, newLast? newLast->GetName(): "NULL")
|
||||
return false;
|
||||
|
||||
// this is a modal app
|
||||
if (newLast->App()->fAppSubWindowList.HasItem(newLast))
|
||||
{
|
||||
ListData *before;
|
||||
if (newLast->App()->fAppSubWindowList.HasItem(newLast)) {
|
||||
ListData* before;
|
||||
|
||||
// remove now to properly place later
|
||||
RemoveItem(newLastItem);
|
||||
|
||||
while (cursor)
|
||||
{
|
||||
while (cursor) {
|
||||
if (!cursor->layerPtr->IsHidden()
|
||||
&& cursor->layerPtr->Level() > B_SYSTEM_LAST
|
||||
&& cursor->layerPtr->App()->ClientTeamID() == newLast->App()->ClientTeamID())
|
||||
{
|
||||
&& cursor->layerPtr->App()->ClientTeam() == newLast->App()->ClientTeam())
|
||||
break;
|
||||
}
|
||||
|
||||
cursor = cursor->upperItem;
|
||||
}
|
||||
|
||||
|
||||
if (cursor)
|
||||
before = cursor->lowerItem;
|
||||
else
|
||||
before = fTopItem;
|
||||
|
||||
InsertItem(newLastItem, before);
|
||||
}
|
||||
// this is a modal subset
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// this is a modal subset
|
||||
// this subset modal is visible, it means its main window must be visible. search for it.
|
||||
ListData *mainWindowItem, *before;
|
||||
int32 indexThis = 0, indexCursor;
|
||||
|
||||
// search by going deep
|
||||
while(cursor)
|
||||
{
|
||||
while (cursor) {
|
||||
if (cursor->layerPtr->Level() == B_NORMAL && !cursor->layerPtr->IsHidden()
|
||||
&& (indexThis = cursor->layerPtr->fSubWindowList.IndexOf(newLast)) >= 0)
|
||||
break;
|
||||
@ -416,14 +410,13 @@ STRACE(("Wks(%ld)::MoveToBack(%s) \n", fID, newLast? newLast->GetName(): "NULL")
|
||||
RemoveItem(newLastItem);
|
||||
|
||||
// good. found our main window. now go up and properly place.
|
||||
mainWindowItem = cursor;
|
||||
before = cursor->lowerItem;
|
||||
mainWindowItem = cursor;
|
||||
before = cursor->lowerItem;
|
||||
|
||||
cursor = cursor->lowerItem;
|
||||
while(cursor)
|
||||
{
|
||||
cursor = cursor->lowerItem;
|
||||
while (cursor) {
|
||||
if (cursor->layerPtr->Level() == B_MODAL_APP && !cursor->layerPtr->IsHidden()
|
||||
&& cursor->layerPtr->App()->ClientTeamID() == newLast->App()->ClientTeamID())
|
||||
&& cursor->layerPtr->App()->ClientTeam() == newLast->App()->ClientTeam())
|
||||
{
|
||||
indexCursor = mainWindowItem->layerPtr->fSubWindowList.IndexOf(cursor->layerPtr);
|
||||
if (indexCursor >= 0)
|
||||
@ -810,7 +803,7 @@ STRACE(("W(%ld)::ShowWinBorder(%s) \n", fID, winBorder? winBorder->GetName(): "N
|
||||
// take only application's modals
|
||||
tempList.AddList(&winBorder->App()->fAppSubWindowList);
|
||||
if (fFrontItem
|
||||
&& fFrontItem->layerPtr->App()->ClientTeamID() == winBorder->App()->ClientTeamID())
|
||||
&& fFrontItem->layerPtr->App()->ClientTeam() == winBorder->App()->ClientTeam())
|
||||
userBusy = false;
|
||||
}
|
||||
// SUBSET modal
|
||||
@ -1217,47 +1210,46 @@ void Workspace::PrintItem(ListData *item) const
|
||||
/*
|
||||
Insert item in the top-bottom direction.
|
||||
*/
|
||||
void Workspace::InsertItem(ListData *item, ListData *before)
|
||||
void
|
||||
Workspace::InsertItem(ListData *item, ListData *before)
|
||||
{
|
||||
// insert before one other item;
|
||||
if(before)
|
||||
{
|
||||
if(before->upperItem)
|
||||
before->upperItem->lowerItem = item;
|
||||
item->upperItem = before->upperItem;
|
||||
item->lowerItem = before;
|
||||
before->upperItem = item;
|
||||
if (before) {
|
||||
if (before->upperItem)
|
||||
before->upperItem->lowerItem = item;
|
||||
|
||||
if(fTopItem == before)
|
||||
item->upperItem = before->upperItem;
|
||||
item->lowerItem = before;
|
||||
before->upperItem = item;
|
||||
|
||||
if (fTopItem == before)
|
||||
fTopItem = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// insert item at the end.
|
||||
item->upperItem = fBottomItem;
|
||||
if(fBottomItem)
|
||||
item->upperItem = fBottomItem;
|
||||
if (fBottomItem)
|
||||
fBottomItem->lowerItem = item;
|
||||
|
||||
fBottomItem = item;
|
||||
fBottomItem = item;
|
||||
|
||||
if(!fTopItem)
|
||||
fTopItem = item;
|
||||
if (!fTopItem)
|
||||
fTopItem = item;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
void Workspace::RemoveItem(ListData *item)
|
||||
void
|
||||
Workspace::RemoveItem(ListData *item)
|
||||
{
|
||||
if(!item)
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if(fBottomItem == item)
|
||||
if (fBottomItem == item)
|
||||
fBottomItem = item->upperItem;
|
||||
else
|
||||
item->lowerItem->upperItem = item->upperItem;
|
||||
|
||||
if(fTopItem == item)
|
||||
if (fTopItem == item)
|
||||
fTopItem = item->lowerItem;
|
||||
else
|
||||
item->upperItem->lowerItem = item->lowerItem;
|
||||
@ -1267,23 +1259,22 @@ void Workspace::RemoveItem(ListData *item)
|
||||
item->upperItem = NULL;
|
||||
item->lowerItem = NULL;
|
||||
|
||||
if(fFocusItem == item)
|
||||
if (fFocusItem == item)
|
||||
fFocusItem = NULL;
|
||||
|
||||
if(fFrontItem == item)
|
||||
if (fFrontItem == item)
|
||||
fFrontItem = NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
ListData *Workspace::HasItem(const ListData *item, int32 *index) const
|
||||
ListData*
|
||||
Workspace::HasItem(const ListData *item, int32 *index) const
|
||||
{
|
||||
int32 idx = 0;
|
||||
ListData *itemX;
|
||||
int32 idx = 0;
|
||||
ListData* itemX;
|
||||
|
||||
for (itemX = fBottomItem; itemX != NULL; itemX = itemX->upperItem)
|
||||
{
|
||||
if(item == itemX)
|
||||
for (itemX = fBottomItem; itemX != NULL; itemX = itemX->upperItem) {
|
||||
if (item == itemX)
|
||||
break;
|
||||
|
||||
idx++;
|
||||
@ -1295,16 +1286,15 @@ ListData *Workspace::HasItem(const ListData *item, int32 *index) const
|
||||
return itemX;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
ListData* Workspace::HasItem(const WinBorder *layer, int32 *index) const
|
||||
ListData*
|
||||
Workspace::HasItem(const WinBorder *layer, int32 *index) const
|
||||
{
|
||||
int32 idx = 0;
|
||||
ListData *itemX;
|
||||
|
||||
for (itemX = fBottomItem; itemX != NULL; itemX = itemX->upperItem)
|
||||
{
|
||||
if(layer == itemX->layerPtr)
|
||||
for (itemX = fBottomItem; itemX != NULL; itemX = itemX->upperItem) {
|
||||
if (layer == itemX->layerPtr)
|
||||
break;
|
||||
|
||||
idx++;
|
||||
@ -1316,62 +1306,58 @@ ListData* Workspace::HasItem(const WinBorder *layer, int32 *index) const
|
||||
return itemX;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/*!
|
||||
\brief Returns the index of the specified item starting from the back-most window.
|
||||
*/
|
||||
int32 Workspace::IndexOf(const ListData *item) const
|
||||
int32
|
||||
Workspace::IndexOf(const ListData *item) const
|
||||
{
|
||||
if (!item)
|
||||
return -1;
|
||||
|
||||
int32 index = 0;
|
||||
for (ListData *itemX = fTopItem; itemX != NULL; itemX = itemX->lowerItem)
|
||||
{
|
||||
if(itemX->layerPtr == item->layerPtr)
|
||||
int32 index = 0;
|
||||
for (ListData *itemX = fTopItem; itemX != NULL; itemX = itemX->lowerItem) {
|
||||
if (itemX->layerPtr == item->layerPtr)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline
|
||||
bool Workspace::placeToBack(ListData *newLast)
|
||||
{
|
||||
int32 level = newLast->layerPtr->Level();
|
||||
ListData *cursor = newLast->upperItem;
|
||||
|
||||
switch(level)
|
||||
{
|
||||
inline bool
|
||||
Workspace::placeToBack(ListData *newLast)
|
||||
{
|
||||
int32 level = newLast->layerPtr->Level();
|
||||
ListData* cursor = newLast->upperItem;
|
||||
|
||||
switch (level) {
|
||||
case B_FLOATING_ALL:
|
||||
case B_FLOATING_APP:
|
||||
{
|
||||
int32 count = 0;
|
||||
while (cursor && cursor->layerPtr->Level() == level)
|
||||
{
|
||||
int32 count = 0;
|
||||
while (cursor && cursor->layerPtr->Level() == level) {
|
||||
if (!cursor->layerPtr->IsHidden())
|
||||
count++;
|
||||
cursor = cursor->upperItem;
|
||||
cursor = cursor->upperItem;
|
||||
}
|
||||
|
||||
// we're already the last floating window
|
||||
if (count == 0)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
bool changeFocus = false;
|
||||
else {
|
||||
bool changeFocus = false;
|
||||
|
||||
if (fFocusItem == newLast)
|
||||
changeFocus = true;
|
||||
|
||||
if (changeFocus)
|
||||
{
|
||||
ListData *cursor = newLast->upperItem;
|
||||
while ( cursor
|
||||
&& ( cursor->layerPtr->IsHidden()
|
||||
|| cursor->layerPtr->WindowFlags() & B_AVOID_FOCUS)
|
||||
&& cursor->layerPtr->Level() == level)
|
||||
{
|
||||
if (changeFocus) {
|
||||
ListData* cursor = newLast->upperItem;
|
||||
while (cursor
|
||||
&& (cursor->layerPtr->IsHidden()
|
||||
|| cursor->layerPtr->WindowFlags() & B_AVOID_FOCUS)
|
||||
&& cursor->layerPtr->Level() == level) {
|
||||
cursor = cursor->upperItem;
|
||||
}
|
||||
|
||||
@ -1386,24 +1372,21 @@ bool Workspace::placeToBack(ListData *newLast)
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case B_NORMAL:
|
||||
{
|
||||
int32 count = 0;
|
||||
int32 cursorLevel;
|
||||
while(cursor)
|
||||
{
|
||||
int32 count = 0;
|
||||
int32 cursorLevel;
|
||||
while (cursor) {
|
||||
cursorLevel = cursor->layerPtr->Level();
|
||||
if (cursorLevel == B_MODAL_APP)
|
||||
cursorLevel = B_NORMAL;
|
||||
|
||||
if (cursorLevel < level)
|
||||
{
|
||||
if (cursorLevel < level) {
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
count++;
|
||||
cursor = cursor->upperItem;
|
||||
}
|
||||
@ -1412,16 +1395,15 @@ bool Workspace::placeToBack(ListData *newLast)
|
||||
// we're already the last normal window
|
||||
if (count == 0)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
else {
|
||||
RemoveItem(newLast);
|
||||
InsertItem(newLast, cursor? cursor->lowerItem: fTopItem);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1429,7 +1411,8 @@ bool Workspace::placeToBack(ListData *newLast)
|
||||
/*!
|
||||
\brief Based on it's WinBorder type, places this item in front as it is possible.
|
||||
*/
|
||||
void Workspace::placeInFront(ListData *item, const bool userBusy)
|
||||
void
|
||||
Workspace::placeInFront(ListData *item, const bool userBusy)
|
||||
{
|
||||
if (!item)
|
||||
return;
|
||||
@ -1483,11 +1466,10 @@ void Workspace::placeInFront(ListData *item, const bool userBusy)
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool Workspace::removeAndPlaceBefore(ListData *item, ListData *beforeItem)
|
||||
inline bool
|
||||
Workspace::removeAndPlaceBefore(ListData *item, ListData *beforeItem)
|
||||
{
|
||||
if (item && item != beforeItem)
|
||||
{
|
||||
if (item && item != beforeItem) {
|
||||
RemoveItem(item);
|
||||
// insert into proper place.
|
||||
InsertItem(item, beforeItem);
|
||||
@ -1501,40 +1483,39 @@ bool Workspace::removeAndPlaceBefore(ListData *item, ListData *beforeItem)
|
||||
specified WinBorder in Workspace's list an remove it.
|
||||
\resolution: private
|
||||
*/
|
||||
inline
|
||||
bool Workspace::removeAndPlaceBefore(const WinBorder *wb, ListData *beforeItem)
|
||||
inline bool
|
||||
Workspace::removeAndPlaceBefore(const WinBorder *wb, ListData *beforeItem)
|
||||
{
|
||||
return removeAndPlaceBefore(HasItem(wb), beforeItem);
|
||||
}
|
||||
|
||||
inline
|
||||
WinBorder* Workspace::searchANormalWindow(WinBorder *wb) const
|
||||
{
|
||||
ListData *listItem = fBottomItem;
|
||||
while (listItem)
|
||||
{
|
||||
if (listItem->layerPtr->Level() == B_NORMAL && !listItem->layerPtr->IsHidden()
|
||||
&& listItem->layerPtr->App()->ClientTeamID() == wb->App()->ClientTeamID())
|
||||
return listItem->layerPtr;
|
||||
|
||||
listItem = listItem->upperItem;
|
||||
inline WinBorder*
|
||||
Workspace::searchANormalWindow(WinBorder *wb) const
|
||||
{
|
||||
ListData* listItem = fBottomItem;
|
||||
while (listItem) {
|
||||
if (listItem->layerPtr->Level() == B_NORMAL && !listItem->layerPtr->IsHidden()
|
||||
&& listItem->layerPtr->App()->ClientTeam() == wb->App()->ClientTeam())
|
||||
return listItem->layerPtr;
|
||||
|
||||
listItem = listItem->upperItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
WinBorder* Workspace::searchFirstMainWindow(WinBorder *wb) const
|
||||
inline WinBorder*
|
||||
Workspace::searchFirstMainWindow(WinBorder *wb) const
|
||||
{
|
||||
ListData *listItem = fBottomItem;
|
||||
while (listItem)
|
||||
{
|
||||
ListData* listItem = fBottomItem;
|
||||
while (listItem) {
|
||||
if (listItem->layerPtr->Level() == B_NORMAL && !listItem->layerPtr->IsHidden()
|
||||
&& listItem->layerPtr->App()->ClientTeamID() == wb->App()->ClientTeamID()
|
||||
&& listItem->layerPtr->App()->ClientTeam() == wb->App()->ClientTeam()
|
||||
&& listItem->layerPtr->fSubWindowList.HasItem(wb))
|
||||
return listItem->layerPtr;
|
||||
return listItem->layerPtr;
|
||||
|
||||
listItem = listItem->upperItem;
|
||||
listItem = listItem->upperItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user