1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: Application.cpp 23 // Author: Erik Jaesler (erik@cgsoftware.com) 24 // Description: BApplication class is the center of the application 25 // universe. The global be_app and be_app_messenger 26 // variables are defined here as well. 27 //------------------------------------------------------------------------------ 28 29 // Standard Includes ----------------------------------------------------------- 30 #include <new> 31 #include <stdio.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 // System Includes ------------------------------------------------------------- 36 #include <AppFileInfo.h> 37 #include <Application.h> 38 #include <AppMisc.h> 39 #include <Cursor.h> 40 #include <Entry.h> 41 #include <File.h> 42 #include <Locker.h> 43 #include <Path.h> 44 #include <PropertyInfo.h> 45 #include <RegistrarDefs.h> 46 #include <Roster.h> 47 #include <RosterPrivate.h> 48 #include <Window.h> 49 50 // Project Includes ------------------------------------------------------------ 51 #include <LooperList.h> 52 #include <ObjectLocker.h> 53 #include <AppServerLink.h> 54 #include <ServerProtocol.h> 55 #include <PortLink.h> 56 #include <PortMessage.h> 57 58 // Local Includes -------------------------------------------------------------- 59 60 // Local Defines --------------------------------------------------------------- 61 62 // Uncomment this to run without the registrar - used only for app_server development! 63 #define RUN_WITHOUT_REGISTRAR 64 65 66 // Globals --------------------------------------------------------------------- 67 BApplication* be_app = NULL; 68 BMessenger be_app_messenger; 69 70 BResources* BApplication::_app_resources = NULL; 71 BLocker BApplication::_app_resources_lock("_app_resources_lock"); 72 73 property_info gApplicationPropInfo[] = 74 { 75 { 76 "Window", 77 {}, 78 {B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER}, 79 NULL, 0, 80 {}, 81 {}, 82 {} 83 }, 84 { 85 "Window", 86 {}, 87 {B_NAME_SPECIFIER}, 88 NULL, 1, 89 {}, 90 {}, 91 {} 92 }, 93 { 94 "Looper", 95 {}, 96 {B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER}, 97 NULL, 2, 98 {}, 99 {}, 100 {} 101 }, 102 { 103 "Looper", 104 {}, 105 {B_ID_SPECIFIER}, 106 NULL, 3, 107 {}, 108 {}, 109 {} 110 }, 111 { 112 "Looper", 113 {}, 114 {B_NAME_SPECIFIER}, 115 NULL, 4, 116 {}, 117 {}, 118 {} 119 }, 120 { 121 "Name", 122 {B_GET_PROPERTY}, 123 {B_DIRECT_SPECIFIER}, 124 NULL, 5, 125 {B_STRING_TYPE}, 126 {}, 127 {} 128 }, 129 { 130 "Window", 131 {B_COUNT_PROPERTIES}, 132 {B_DIRECT_SPECIFIER}, 133 NULL, 5, 134 {B_INT32_TYPE}, 135 {}, 136 {} 137 }, 138 { 139 "Loopers", 140 {B_GET_PROPERTY}, 141 {B_DIRECT_SPECIFIER}, 142 NULL, 5, 143 {B_MESSENGER_TYPE}, 144 {}, 145 {} 146 }, 147 { 148 "Windows", 149 {B_GET_PROPERTY}, 150 {B_DIRECT_SPECIFIER}, 151 NULL, 5, 152 {B_MESSENGER_TYPE}, 153 {}, 154 {} 155 }, 156 { 157 "Looper", 158 {B_COUNT_PROPERTIES}, 159 {B_DIRECT_SPECIFIER}, 160 NULL, 5, 161 {B_INT32_TYPE}, 162 {}, 163 {} 164 }, 165 {} 166 }; 167 168 // argc/argv 169 extern const int __libc_argc; 170 extern const char * const *__libc_argv; 171 172 class BMenuWindow : public BWindow 173 { 174 }; 175 //------------------------------------------------------------------------------ 176 177 // debugging 178 //#define DBG(x) x 179 #define DBG(x) 180 #define OUT printf 181 182 enum { 183 NOT_IMPLEMENTED = B_ERROR, 184 }; 185 186 // prototypes of helper functions 187 static const char* looper_name_for(const char *signature); 188 static status_t check_app_signature(const char *signature); 189 190 //------------------------------------------------------------------------------ 191 BApplication::BApplication(const char* signature) 192 : BLooper(looper_name_for(signature)), 193 fAppName(NULL), 194 fServerFrom(-1), 195 fServerTo(-1), 196 fServerHeap(NULL), 197 fPulseRate(500000), 198 fInitialWorkspace(0), 199 fDraggedMessage(NULL), 200 fPulseRunner(NULL), 201 fInitError(B_NO_INIT), 202 fReadyToRunCalled(false) 203 { 204 InitData(signature, NULL); 205 } 206 //------------------------------------------------------------------------------ 207 BApplication::BApplication(const char* signature, status_t* error) 208 : BLooper(looper_name_for(signature)), 209 fAppName(NULL), 210 fServerFrom(-1), 211 fServerTo(-1), 212 fServerHeap(NULL), 213 fPulseRate(500000), 214 fInitialWorkspace(0), 215 fDraggedMessage(NULL), 216 fPulseRunner(NULL), 217 fInitError(B_NO_INIT), 218 fReadyToRunCalled(false) 219 { 220 InitData(signature, error); 221 } 222 //------------------------------------------------------------------------------ 223 BApplication::~BApplication() 224 { 225 // unregister from the roster 226 BRoster::Private().RemoveApp(Team()); 227 // uninitialize be_app and be_app_messenger 228 be_app = NULL; 229 // R5 doesn't uninitialize be_app_messenger. 230 // be_app_messenger = BMessenger(); 231 } 232 //------------------------------------------------------------------------------ 233 BApplication::BApplication(BMessage* data) 234 : BLooper(looper_name_for(NULL)), 235 fAppName(NULL), 236 fServerFrom(-1), 237 fServerTo(-1), 238 fServerHeap(NULL), 239 fPulseRate(500000), 240 fInitialWorkspace(0), 241 fDraggedMessage(NULL), 242 fPulseRunner(NULL), 243 fInitError(B_NO_INIT), 244 fReadyToRunCalled(false) 245 { 246 } 247 //------------------------------------------------------------------------------ 248 BArchivable* BApplication::Instantiate(BMessage* data) 249 { 250 if (!validate_instantiation(data, "BApplication")) 251 { 252 return NULL; 253 } 254 255 return new BApplication(data); 256 } 257 //------------------------------------------------------------------------------ 258 status_t BApplication::Archive(BMessage* data, bool deep) const 259 { 260 return NOT_IMPLEMENTED; 261 } 262 //------------------------------------------------------------------------------ 263 status_t BApplication::InitCheck() const 264 { 265 return fInitError; 266 } 267 //------------------------------------------------------------------------------ 268 thread_id BApplication::Run() 269 { 270 AssertLocked(); 271 272 if (fRunCalled) 273 { 274 // Not allowed to call Run() more than once 275 // TODO: test 276 // find out what message is actually here 277 debugger(""); 278 } 279 280 // Note: We need a local variable too (for the return value), since 281 // fTaskID is cleared by Quit(). 282 thread_id thread = fTaskID = find_thread(NULL); 283 284 if (fMsgPort == B_NO_MORE_PORTS || fMsgPort == B_BAD_VALUE) 285 { 286 return fMsgPort; 287 } 288 289 fRunCalled = true; 290 291 run_task(); 292 293 return thread; 294 } 295 //------------------------------------------------------------------------------ 296 void BApplication::Quit() 297 { 298 bool unlock = false; 299 if (!IsLocked()) { 300 const char* name = Name(); 301 if (!name) 302 name = "no-name"; 303 printf("ERROR - you must Lock the application object before calling " 304 "Quit(), team=%ld, looper=%s\n", Team(), name); 305 unlock = true; 306 if (!Lock()) 307 return; 308 } 309 // Delete the object, if not running only. 310 if (!fRunCalled) { 311 delete this; 312 } else if (find_thread(NULL) != fTaskID) { 313 // We are not the looper thread. 314 // We push a _QUIT_ into the queue. 315 // TODO: When BLooper::AddMessage() is done, use that instead of 316 // PostMessage()??? This would overtake messages that are still at 317 // the port. 318 // NOTE: We must not unlock here -- otherwise we had to re-lock, which 319 // may not work. This is bad, since, if the port is full, it 320 // won't get emptier, as the looper thread needs to lock the object 321 // before dispatching messages. 322 while (PostMessage(_QUIT_, this) == B_WOULD_BLOCK) 323 snooze(10000); 324 } else { 325 // We are the looper thread. 326 // Just set fTerminating to true which makes us fall through the 327 // message dispatching loop and return from Run(). 328 fTerminating = true; 329 } 330 // If we had to lock the object, unlock now. 331 if (unlock) 332 Unlock(); 333 } 334 //------------------------------------------------------------------------------ 335 bool BApplication::QuitRequested() 336 { 337 // No windows -- nothing to do. 338 return BLooper::QuitRequested(); 339 } 340 //------------------------------------------------------------------------------ 341 void BApplication::Pulse() 342 { 343 } 344 //------------------------------------------------------------------------------ 345 void BApplication::ReadyToRun() 346 { 347 } 348 //------------------------------------------------------------------------------ 349 void BApplication::MessageReceived(BMessage* msg) 350 { 351 BLooper::MessageReceived(msg); 352 } 353 //------------------------------------------------------------------------------ 354 void BApplication::ArgvReceived(int32 argc, char** argv) 355 { 356 } 357 //------------------------------------------------------------------------------ 358 void BApplication::AppActivated(bool active) 359 { 360 } 361 //------------------------------------------------------------------------------ 362 void BApplication::RefsReceived(BMessage* a_message) 363 { 364 } 365 //------------------------------------------------------------------------------ 366 void BApplication::AboutRequested() 367 { 368 } 369 //------------------------------------------------------------------------------ 370 BHandler* BApplication::ResolveSpecifier(BMessage* msg, int32 index, 371 BMessage* specifier, int32 form, 372 const char* property) 373 { 374 return NULL; // not implemented 375 } 376 //------------------------------------------------------------------------------ 377 void BApplication::ShowCursor() 378 { 379 // Because we're just sending an opcode, we can skip the BSession and fake the protocol 380 int32 foo=AS_SHOW_CURSOR; 381 write_port(fServerTo,AS_SHOW_CURSOR,&foo,sizeof(int32)); 382 } 383 //------------------------------------------------------------------------------ 384 void BApplication::HideCursor() 385 { 386 // Because we're just sending an opcode, we can skip the BSession and fake the protocol 387 int32 foo=AS_HIDE_CURSOR; 388 write_port(fServerTo,AS_HIDE_CURSOR,&foo,sizeof(int32)); 389 } 390 //------------------------------------------------------------------------------ 391 void BApplication::ObscureCursor() 392 { 393 // Because we're just sending an opcode, we can skip the BSession and fake the protocol 394 int32 foo=AS_OBSCURE_CURSOR; 395 write_port(fServerTo,AS_OBSCURE_CURSOR,&foo,sizeof(int32)); 396 } 397 //------------------------------------------------------------------------------ 398 bool BApplication::IsCursorHidden() const 399 { 400 PortMessage msg; 401 402 BPrivate::BAppServerLink link; 403 link.SetOpCode(AS_QUERY_CURSOR_HIDDEN); 404 link.FlushWithReply(&msg); 405 return (msg.Code()==SERVER_TRUE)?true:false; 406 } 407 //------------------------------------------------------------------------------ 408 void BApplication::SetCursor(const void* cursor) 409 { 410 // BeBook sez: If you want to call SetCursor() without forcing an immediate 411 // sync of the Application Server, you have to use a BCursor. 412 // By deductive reasoning, this function forces a sync. =) 413 BCursor Cursor(cursor); 414 SetCursor(&Cursor, true); 415 } 416 //------------------------------------------------------------------------------ 417 void BApplication::SetCursor(const BCursor* cursor, bool sync) 418 { 419 BPrivate::BAppServerLink link; 420 PortMessage msg; 421 422 link.SetOpCode(AS_SET_CURSOR_BCURSOR); 423 link.Attach<bool>(sync); 424 link.Attach<int32>(cursor->m_serverToken); 425 if(sync) 426 link.FlushWithReply(&msg); 427 else 428 link.Flush(); 429 } 430 //------------------------------------------------------------------------------ 431 int32 BApplication::CountWindows() const 432 { 433 // BeBook sez: The windows list includes all windows explicitely created by 434 // the app ... but excludes private windows create by Be 435 // classes. 436 // I'm taking this to include private menu windows, thus the incl_menus 437 // param is false. 438 return count_windows(false); 439 } 440 //------------------------------------------------------------------------------ 441 BWindow* BApplication::WindowAt(int32 index) const 442 { 443 // BeBook sez: The windows list includes all windows explicitely created by 444 // the app ... but excludes private windows create by Be 445 // classes. 446 // I'm taking this to include private menu windows, thus the incl_menus 447 // param is false. 448 return window_at(index, false); 449 } 450 //------------------------------------------------------------------------------ 451 int32 BApplication::CountLoopers() const 452 { 453 using namespace BPrivate; 454 BObjectLocker<BLooperList> ListLock(gLooperList); 455 if (ListLock.IsLocked()) 456 { 457 return gLooperList.CountLoopers(); 458 } 459 460 return B_ERROR; // Some bad, non-specific thing has happened 461 } 462 //------------------------------------------------------------------------------ 463 BLooper* BApplication::LooperAt(int32 index) const 464 { 465 using namespace BPrivate; 466 BLooper* Looper = NULL; 467 BObjectLocker<BLooperList> ListLock(gLooperList); 468 if (ListLock.IsLocked()) 469 { 470 Looper = gLooperList.LooperAt(index); 471 } 472 473 return Looper; 474 } 475 //------------------------------------------------------------------------------ 476 bool BApplication::IsLaunching() const 477 { 478 return !fReadyToRunCalled; 479 } 480 //------------------------------------------------------------------------------ 481 status_t BApplication::GetAppInfo(app_info* info) const 482 { 483 return be_roster->GetRunningAppInfo(be_app->Team(), info); 484 } 485 //------------------------------------------------------------------------------ 486 BResources* BApplication::AppResources() 487 { 488 return NULL; // not implemented 489 } 490 //------------------------------------------------------------------------------ 491 void BApplication::DispatchMessage(BMessage* message, BHandler* handler) 492 { 493 switch (message->what) { 494 case B_ARGV_RECEIVED: 495 { 496 // build the argv vector 497 status_t error = B_OK; 498 int32 argc; 499 char **argv = NULL; 500 if (message->FindInt32("argc", &argc) == B_OK && argc > 0) { 501 argv = new char*[argc]; 502 for (int32 i = 0; error == B_OK && i < argc; i++) 503 argv[i] = NULL; 504 // copy the arguments 505 for (int32 i = 0; error == B_OK && i < argc; i++) { 506 const char *arg = NULL; 507 error = message->FindString("argv", i, &arg); 508 if (error == B_OK && arg) { 509 argv[i] = new(std::nothrow) char[strlen(arg) + 1]; 510 if (argv[i]) 511 strcpy(argv[i], arg); 512 else 513 error = B_NO_MEMORY; 514 } 515 } 516 } 517 // call the hook 518 if (error == B_OK) 519 ArgvReceived(argc, argv); 520 // cleanup 521 if (argv) { 522 for (int32 i = 0; i < argc; i++) 523 delete[] argv[i]; 524 delete[] argv; 525 } 526 break; 527 } 528 case B_REFS_RECEIVED: 529 RefsReceived(message); 530 break; 531 case B_READY_TO_RUN: 532 // TODO: Find out, whether to set fReadyToRunCalled before or 533 // after calling the hook. 534 ReadyToRun(); 535 fReadyToRunCalled = true; 536 break; 537 default: 538 BLooper::DispatchMessage(message, handler); 539 break; 540 } 541 } 542 //------------------------------------------------------------------------------ 543 void BApplication::SetPulseRate(bigtime_t rate) 544 { 545 fPulseRate = rate; 546 } 547 //------------------------------------------------------------------------------ 548 status_t BApplication::GetSupportedSuites(BMessage* data) 549 { 550 status_t err = B_OK; 551 if (!data) 552 { 553 err = B_BAD_VALUE; 554 } 555 556 if (!err) 557 { 558 err = data->AddString("Suites", "suite/vnd.Be-application"); 559 if (!err) 560 { 561 BPropertyInfo PropertyInfo(gApplicationPropInfo); 562 err = data->AddFlat("message", &PropertyInfo); 563 if (!err) 564 { 565 err = BHandler::GetSupportedSuites(data); 566 } 567 } 568 } 569 570 return err; 571 } 572 //------------------------------------------------------------------------------ 573 status_t BApplication::Perform(perform_code d, void* arg) 574 { 575 return NOT_IMPLEMENTED; 576 } 577 //------------------------------------------------------------------------------ 578 BApplication::BApplication(uint32 signature) 579 { 580 } 581 //------------------------------------------------------------------------------ 582 BApplication::BApplication(const BApplication& rhs) 583 { 584 } 585 //------------------------------------------------------------------------------ 586 BApplication& BApplication::operator=(const BApplication& rhs) 587 { 588 return *this; 589 } 590 //------------------------------------------------------------------------------ 591 void BApplication::_ReservedApplication1() 592 { 593 } 594 //------------------------------------------------------------------------------ 595 void BApplication::_ReservedApplication2() 596 { 597 } 598 //------------------------------------------------------------------------------ 599 void BApplication::_ReservedApplication3() 600 { 601 } 602 //------------------------------------------------------------------------------ 603 void BApplication::_ReservedApplication4() 604 { 605 } 606 //------------------------------------------------------------------------------ 607 void BApplication::_ReservedApplication5() 608 { 609 } 610 //------------------------------------------------------------------------------ 611 void BApplication::_ReservedApplication6() 612 { 613 } 614 //------------------------------------------------------------------------------ 615 void BApplication::_ReservedApplication7() 616 { 617 } 618 //------------------------------------------------------------------------------ 619 void BApplication::_ReservedApplication8() 620 { 621 } 622 //------------------------------------------------------------------------------ 623 bool BApplication::ScriptReceived(BMessage* msg, int32 index, BMessage* specifier, int32 form, const char* property) 624 { 625 return false; // not implemented 626 } 627 //------------------------------------------------------------------------------ 628 void BApplication::run_task() 629 { 630 task_looper(); 631 } 632 //------------------------------------------------------------------------------ 633 void BApplication::InitData(const char* signature, status_t* error) 634 { 635 // check whether there exists already an application 636 if (be_app) 637 debugger("2 BApplication objects were created. Only one is allowed."); 638 // check signature 639 fInitError = check_app_signature(signature); 640 fAppName = signature; 641 bool isRegistrar = (signature && !strcmp(signature, kRegistrarSignature)); 642 // get team and thread 643 team_id team = Team(); 644 thread_id thread = BPrivate::main_thread_for(team); 645 // get app executable ref 646 entry_ref ref; 647 if (fInitError == B_OK) 648 fInitError = BPrivate::get_app_ref(&ref); 649 // get the BAppFileInfo and extract the information we need 650 uint32 appFlags = B_REG_DEFAULT_APP_FLAGS; 651 if (fInitError == B_OK) { 652 BAppFileInfo fileInfo; 653 BFile file(&ref, B_READ_ONLY); 654 fInitError = fileInfo.SetTo(&file); 655 if (fInitError == B_OK) { 656 fileInfo.GetAppFlags(&appFlags); 657 char appFileSignature[B_MIME_TYPE_LENGTH + 1]; 658 // compare the file signature and the supplied signature 659 if (fileInfo.GetSignature(appFileSignature) == B_OK) { 660 if (strcmp(appFileSignature, signature) != 0) { 661 printf("Signature in rsrc doesn't match constructor arg. " 662 "(%s,%s)\n", signature, appFileSignature); 663 } 664 } 665 } 666 } 667 #ifndef RUN_WITHOUT_REGISTRAR 668 // check whether be_roster is valid 669 if (fInitError == B_OK && !isRegistrar 670 && !BRoster::Private().IsMessengerValid(false)) { 671 printf("FATAL: be_roster is not valid. Is the registrar running?\n"); 672 fInitError = B_NO_INIT; 673 } 674 675 // check whether or not we are pre-registered 676 bool preRegistered = false; 677 app_info appInfo; 678 if (fInitError == B_OK && !isRegistrar) { 679 preRegistered = BRoster::Private().IsAppPreRegistered(&ref, team, 680 &appInfo); 681 } 682 if (preRegistered) { 683 // we are pre-registered => the app info has been filled in 684 // Check whether we need to replace the looper port with a port 685 // created by the roster. 686 if (appInfo.port >= 0 && appInfo.port != fMsgPort) { 687 delete_port(fMsgPort); 688 fMsgPort = appInfo.port; 689 } else 690 appInfo.port = fMsgPort; 691 // check the signature and correct it, if necessary 692 if (strcmp(appInfo.signature, fAppName)) 693 BRoster::Private().SetSignature(team, fAppName); 694 // complete the registration 695 fInitError = BRoster::Private().CompleteRegistration(team, thread, 696 appInfo.port); 697 } else if (fInitError == B_OK) { 698 // not pre-registered -- try to register the application 699 team_id otherTeam = -1; 700 // the registrar must not register 701 if (!isRegistrar) { 702 fInitError = BRoster::Private().AddApplication(signature, &ref, 703 appFlags, team, thread, fMsgPort, true, NULL, &otherTeam); 704 } 705 if (fInitError == B_ALREADY_RUNNING) { 706 // An instance is already running and we asked for 707 // single/exclusive launch. Send our argv to the running app. 708 // Do that only, if the app is NOT B_ARGV_ONLY. 709 if (otherTeam >= 0 && __libc_argc > 1) { 710 app_info otherAppInfo; 711 if (be_roster->GetRunningAppInfo(otherTeam, &otherAppInfo) 712 == B_OK && !(otherAppInfo.flags & B_ARGV_ONLY)) { 713 // create an B_ARGV_RECEIVED message 714 BMessage argvMessage(B_ARGV_RECEIVED); 715 do_argv(&argvMessage); 716 // replace the first argv string with the path of the 717 // other application 718 BPath path; 719 if (path.SetTo(&otherAppInfo.ref) == B_OK) 720 argvMessage.ReplaceString("argv", 0, path.Path()); 721 // send the message 722 BMessenger(NULL, otherTeam).SendMessage(&argvMessage); 723 } 724 } 725 } else if (fInitError == B_OK) { 726 // the registrations was successful 727 // Create a B_ARGV_RECEIVED message and send it to ourselves. 728 // Do that even, if we are B_ARGV_ONLY. 729 // TODO: When BLooper::AddMessage() is done, use that instead of 730 // PostMessage(). 731 if (__libc_argc > 1) { 732 BMessage argvMessage(B_ARGV_RECEIVED); 733 do_argv(&argvMessage); 734 PostMessage(&argvMessage, this); 735 } 736 // send a B_READY_TO_RUN message as well 737 PostMessage(B_READY_TO_RUN, this); 738 } else if (fInitError > B_ERRORS_END) { 739 // Registrar internal errors shouldn't fall into the user's hands. 740 fInitError = B_ERROR; 741 } 742 } 743 #endif // ifdef RUN_WITHOUT_REGISTRAR 744 745 // Notify app_server that we exist 746 fServerFrom=find_port(SERVER_PORT_NAME); 747 if(fServerFrom!=B_NAME_NOT_FOUND) 748 { 749 // Create the port so that the app_server knows where to send messages 750 fServerTo=create_port(100,"a<fServerTo"); 751 if(fServerTo!=B_BAD_VALUE && fServerTo!=B_NO_MORE_PORTS) 752 { 753 // AS_CREATE_APP: 754 755 // Attach data: 756 // 1) port_id - receiver port of a regular app 757 // 2) int32 - handler ID token of the app 758 // 3) char * - signature of the regular app 759 PortLink link(fServerFrom); 760 PortMessage pmsg; 761 762 link.SetOpCode(AS_CREATE_APP); 763 link.Attach<port_id>(fServerTo); 764 link.Attach<port_id>(_get_object_token_(this)); 765 link.AttachString(signature); 766 link.FlushWithReply(&pmsg); 767 768 // Reply code: AS_CREATE_APP 769 // Reply data: 770 // 1) port_id server-side application port (fServerFrom value) 771 pmsg.Read<port_id>(&fServerFrom); 772 } 773 else 774 fInitError=fServerTo; 775 } 776 777 // init be_app and be_app_messenger 778 if (fInitError == B_OK) { 779 be_app = this; 780 be_app_messenger = BMessenger(NULL, this); 781 } 782 // set the BHandler's name 783 if (fInitError == B_OK) 784 SetName(ref.name); 785 // create meta MIME 786 if (fInitError == B_OK) { 787 BPath path; 788 if (path.SetTo(&ref) == B_OK) 789 create_app_meta_mime(path.Path(), false, true, false); 790 } 791 // Return the error or exit, if there was an error and no error variable 792 // has been supplied. 793 if (error) 794 *error = fInitError; 795 else if (fInitError != B_OK) 796 exit(0); 797 } 798 //------------------------------------------------------------------------------ 799 void BApplication::BeginRectTracking(BRect r, bool trackWhole) 800 { 801 BPrivate::BAppServerLink link; 802 link.Attach<int32>(AS_BEGIN_RECT_TRACKING); 803 link.Attach<BRect>(r); 804 link.Attach<int32>(trackWhole); 805 link.Flush(); 806 } 807 //------------------------------------------------------------------------------ 808 void BApplication::EndRectTracking() 809 { 810 int32 foo=AS_END_RECT_TRACKING; 811 write_port(fServerTo,AS_END_RECT_TRACKING,&foo,sizeof(int32)); 812 } 813 //------------------------------------------------------------------------------ 814 void BApplication::get_scs() 815 { 816 } 817 //------------------------------------------------------------------------------ 818 void BApplication::setup_server_heaps() 819 { 820 } 821 //------------------------------------------------------------------------------ 822 void* BApplication::rw_offs_to_ptr(uint32 offset) 823 { 824 return NULL; // not implemented 825 } 826 //------------------------------------------------------------------------------ 827 void* BApplication::ro_offs_to_ptr(uint32 offset) 828 { 829 return NULL; // not implemented 830 } 831 //------------------------------------------------------------------------------ 832 void* BApplication::global_ro_offs_to_ptr(uint32 offset) 833 { 834 return NULL; // not implemented 835 } 836 //------------------------------------------------------------------------------ 837 void BApplication::connect_to_app_server() 838 { 839 } 840 //------------------------------------------------------------------------------ 841 void BApplication::send_drag(BMessage* msg, int32 vs_token, BPoint offset, BRect drag_rect, BHandler* reply_to) 842 { 843 } 844 //------------------------------------------------------------------------------ 845 void BApplication::send_drag(BMessage* msg, int32 vs_token, BPoint offset, int32 bitmap_token, drawing_mode dragMode, BHandler* reply_to) 846 { 847 } 848 //------------------------------------------------------------------------------ 849 void BApplication::write_drag(_BSession_* session, BMessage* a_message) 850 { 851 } 852 //------------------------------------------------------------------------------ 853 bool BApplication::quit_all_windows(bool force) 854 { 855 return false; // not implemented 856 } 857 //------------------------------------------------------------------------------ 858 bool BApplication::window_quit_loop(bool, bool) 859 { 860 return false; // not implemented 861 } 862 //------------------------------------------------------------------------------ 863 void BApplication::do_argv(BMessage* message) 864 { 865 if (message) { 866 int32 argc = __libc_argc; 867 const char * const *argv = __libc_argv; 868 // add argc 869 message->AddInt32("argc", argc); 870 // add argv 871 for (int32 i = 0; i < argc; i++) 872 message->AddString("argv", argv[i]); 873 // add current working directory 874 char cwd[B_PATH_NAME_LENGTH + 1]; 875 if (getcwd(cwd, B_PATH_NAME_LENGTH + 1)) 876 message->AddString("cwd", cwd); 877 } 878 } 879 //------------------------------------------------------------------------------ 880 uint32 BApplication::InitialWorkspace() 881 { 882 return 0; // not implemented 883 } 884 //------------------------------------------------------------------------------ 885 int32 BApplication::count_windows(bool incl_menus) const 886 { 887 using namespace BPrivate; 888 889 // Windows are BLoopers, so we can just check each BLooper to see if it's 890 // a BWindow (or BMenuWindow) 891 int32 count = 0; 892 BObjectLocker<BLooperList> ListLock(gLooperList); 893 if (ListLock.IsLocked()) 894 { 895 BLooper* Looper = NULL; 896 for (int32 i = 0; i < gLooperList.CountLoopers(); ++i) 897 { 898 Looper = gLooperList.LooperAt(i); 899 if (dynamic_cast<BWindow*>(Looper)) 900 { 901 if (incl_menus || dynamic_cast<BMenuWindow*>(Looper) == NULL) 902 { 903 ++count; 904 } 905 } 906 } 907 } 908 909 return count; 910 } 911 //------------------------------------------------------------------------------ 912 BWindow* BApplication::window_at(uint32 index, bool incl_menus) const 913 { 914 using namespace BPrivate; 915 916 // Windows are BLoopers, so we can just check each BLooper to see if it's 917 // a BWindow (or BMenuWindow) 918 uint32 count = 0; 919 BWindow* Window = NULL; 920 BObjectLocker<BLooperList> ListLock(gLooperList); 921 if (ListLock.IsLocked()) 922 { 923 BLooper* Looper = NULL; 924 for (int32 i = 0; i < gLooperList.CountLoopers() && !Window; ++i) 925 { 926 Looper = gLooperList.LooperAt(i); 927 if (dynamic_cast<BWindow*>(Looper)) 928 { 929 if (incl_menus || dynamic_cast<BMenuWindow*>(Looper) == NULL) 930 { 931 if (count == index) 932 { 933 Window = dynamic_cast<BWindow*>(Looper); 934 } 935 else 936 { 937 ++count; 938 } 939 } 940 } 941 } 942 } 943 944 return Window; 945 } 946 //------------------------------------------------------------------------------ 947 status_t BApplication::get_window_list(BList* list, bool incl_menus) const 948 { 949 return NOT_IMPLEMENTED; 950 } 951 //------------------------------------------------------------------------------ 952 int32 BApplication::async_quit_entry(void* data) 953 { 954 return 0; // not implemented 955 } 956 //------------------------------------------------------------------------------ 957 958 // check_app_signature 959 /*! \brief Checks whether the supplied string is a valid application signature. 960 961 An error message is printed, if the string is no valid app signature. 962 963 \param signature The string to be checked. 964 \return 965 - \c B_OK: \a signature is a valid app signature. 966 - \c B_BAD_VALUE: \a signature is \c NULL or no valid app signature. 967 */ 968 static 969 status_t 970 check_app_signature(const char *signature) 971 { 972 bool isValid = false; 973 BMimeType type(signature); 974 if (type.IsValid() && !type.IsSupertypeOnly() 975 && BMimeType("application").Contains(&type)) { 976 isValid = true; 977 } 978 if (!isValid) { 979 printf("bad signature (%s), must begin with \"application/\" and " 980 "can't conflict with existing registered mime types inside " 981 "the \"application\" media type.\n", signature); 982 } 983 return (isValid ? B_OK : B_BAD_VALUE); 984 } 985 986 // looper_name_for 987 /*! \brief Returns the looper name for a given signature. 988 989 Normally this is "AppLooperPort", but in case of the registrar a 990 special name. 991 992 \return The looper name. 993 */ 994 static 995 const char* 996 looper_name_for(const char *signature) 997 { 998 if (signature && !strcmp(signature, kRegistrarSignature)) 999 return kRosterPortName; 1000 return "AppLooperPort"; 1001 } 1002 1003 1004 /* 1005 * $Log $ 1006 * 1007 * $Id $ 1008 * 1009 */ 1010 1011