diff --git a/src/servers/app/AppServer.cpp b/src/servers/app/AppServer.cpp index 430b322324..6440d8242d 100644 --- a/src/servers/app/AppServer.cpp +++ b/src/servers/app/AppServer.cpp @@ -2,8 +2,12 @@ * Copyright (c) 2001-2005, Haiku, Inc. * Distributed under the terms of the MIT license. * - * Author: DarkWyrm + * Authors: + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de */ + + #include #include #include @@ -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(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(&srvapp_id) < B_OK) + thread_id thread = -1; + if (msg.Read(&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; iCountItems();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; } diff --git a/src/servers/app/AppServer.h b/src/servers/app/AppServer.h index 7e1cf96222..ec09acbcb2 100644 --- a/src/servers/app/AppServer.h +++ b/src/servers/app/AppServer.h @@ -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; diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 9d8763eb0a..8c9289c114 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -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(); diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 70c4c59751..263820c1e1 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -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(fBitmapList->ItemAt(i)); - } - delete fBitmapList; - for (int32 i = 0; i < fPictureList->CountItems(); i++) { - delete static_cast(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(fBitmapList.ItemAt(i)); + } + + for (int32 i = 0; i < fPictureList.CountItems(); i++) { + delete static_cast(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(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()); 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(&frame); - reader.Read(&look); - reader.Read(&feel); - reader.Read(&flags); - reader.Read(&wkspaces); - reader.Read(&token); - reader.Read(&sendPort); - reader.Read(&looperPort); - if (reader.ReadString(&title) != B_OK) + receiver.Read(&frame); + receiver.Read(&look); + receiver.Read(&feel); + receiver.Read(&flags); + receiver.Read(&wkspaces); + receiver.Read(&token); + receiver.Read(&sendPort); + receiver.Read(&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; iCountItems(); 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); link.Read(&offset); link.Read(&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(win->GetWinBorder())->UpdateDecorator(); - win->Unlock(); + for (int32 i = 0; i < fWindowList.CountItems(); i++) { + ServerWindow *window = (ServerWindow*)fWindowList.ItemAt(i); + window->Lock(); + const_cast(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(bitmap->Token()); fLink.Attach(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(fBitmapList->ItemAt(i)); + for (int32 i = 0; i < fBitmapList.CountItems(); i++) { + ServerBitmap *bitmap = static_cast(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(fPictureList->ItemAt(i)); + for (int32 i = 0; i < fPictureList.CountItems(); i++) { + ServerPicture *picture = static_cast(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; } diff --git a/src/servers/app/ServerApp.h b/src/servers/app/ServerApp.h index 6efca8b697..942585d580 100644 --- a/src/servers/app/ServerApp.h +++ b/src/servers/app/ServerApp.h @@ -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 -// Adi Oanca -// Description: Server-side BApplication counterpart -// -//------------------------------------------------------------------------------ +/* + * Copyright 2001-2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm + * Adrian Oanca + * Stephan Aßmus + * Stefano Ceccherini (burton666@libero.it) + * Axel Dörfler, axeld@pinc-software.de + */ #ifndef _SERVERAPP_H_ #define _SERVERAPP_H_ + #include #include #include @@ -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; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 5beeaa84fd..251db4df61 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -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 -// Adi Oanca -// Stephan Aßmus -// Description: Shadow BWindow class -// -//------------------------------------------------------------------------------ +/* + * Copyright 2001-2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm + * Adrian Oanca + * Stephan Aßmus + * Stefano Ceccherini (burton666@libero.it) + * Axel Dörfler, axeld@pinc-software.de + */ + #include #include @@ -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); } diff --git a/src/servers/app/ServerWindow.h b/src/servers/app/ServerWindow.h index e46c69c4c4..4bbf499b40 100644 --- a/src/servers/app/ServerWindow.h +++ b/src/servers/app/ServerWindow.h @@ -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 -// Description: Shadow BWindow class -// -//------------------------------------------------------------------------------ +/* + * Copyright 2001-2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm + * Adrian Oanca + * Stephan Aßmus + * 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; diff --git a/src/servers/app/Workspace.cpp b/src/servers/app/Workspace.cpp index dcab2fa3f6..0bc3c16a07 100644 --- a/src/servers/app/Workspace.cpp +++ b/src/servers/app/Workspace.cpp @@ -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; }