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