1 /* 2 * Copyright 2001-2009, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * Adrian Oanca <adioanca@cotty.iren.ro> 8 * Stephan Aßmus <superstippi@gmx.de> 9 * Stefano Ceccherini (burton666@libero.it) 10 * Axel Dörfler, axeld@pinc-software.de 11 * Jérôme Duval, jerome.duval@free.fr 12 * Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk> 13 * Philippe Saint-Pierre, stpere@gmail.com 14 */ 15 16 17 /*! \class ServerApp ServerApp.h 18 \brief Counterpart to BApplication within the app_server 19 */ 20 21 22 #include "ServerApp.h" 23 24 #include <new> 25 #include <stdio.h> 26 #include <string.h> 27 #include <syslog.h> 28 29 #include <AppDefs.h> 30 #include <Autolock.h> 31 #include <Debug.h> 32 #include <List.h> 33 #include <ScrollBar.h> 34 #include <Shape.h> 35 #include <String.h> 36 37 #include <FontPrivate.h> 38 #include <MessengerPrivate.h> 39 #include <PrivateScreen.h> 40 #include <RosterPrivate.h> 41 #include <ServerProtocol.h> 42 #include <WindowPrivate.h> 43 44 #include "AppServer.h" 45 #include "BitmapManager.h" 46 #include "CursorManager.h" 47 #include "CursorSet.h" 48 #include "Desktop.h" 49 #include "DecorManager.h" 50 #include "DrawingEngine.h" 51 #include "EventStream.h" 52 #include "FontManager.h" 53 #include "HWInterface.h" 54 #include "InputManager.h" 55 #include "OffscreenServerWindow.h" 56 #include "Screen.h" 57 #include "ServerBitmap.h" 58 #include "ServerConfig.h" 59 #include "ServerCursor.h" 60 #include "ServerPicture.h" 61 #include "ServerTokenSpace.h" 62 #include "ServerWindow.h" 63 #include "SystemPalette.h" 64 #include "Window.h" 65 66 67 //#define DEBUG_SERVERAPP 68 #ifdef DEBUG_SERVERAPP 69 # define STRACE(x) debug_printf x 70 #else 71 # define STRACE(x) ; 72 #endif 73 74 //#define DEBUG_SERVERAPP_FONT 75 #ifdef DEBUG_SERVERAPP_FONT 76 # define FTRACE(x) debug_printf x 77 #else 78 # define FTRACE(x) ; 79 #endif 80 81 using std::nothrow; 82 83 static const uint32 kMsgUpdateShowAllDraggers = '_adg'; 84 static const uint32 kMsgAppQuit = 'appQ'; 85 86 87 ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort, 88 port_id clientLooperPort, team_id clientTeam, 89 int32 clientToken, const char* signature) 90 : 91 MessageLooper("application"), 92 93 fMessagePort(-1), 94 fClientReplyPort(clientReplyPort), 95 fDesktop(desktop), 96 fSignature(signature), 97 fClientTeam(clientTeam), 98 fWindowListLock("window list"), 99 fTemporaryDisplayModeChange(0), 100 fMapLocker("server app maps"), 101 fAppCursor(NULL), 102 fViewCursor(NULL), 103 fCursorHideLevel(0), 104 fIsActive(false), 105 fMemoryAllocator(this) 106 { 107 if (fSignature == "") 108 fSignature = "application/no-signature"; 109 110 char name[B_OS_NAME_LENGTH]; 111 snprintf(name, sizeof(name), "a<%ld:%s", clientTeam, SignatureLeaf()); 112 113 fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name); 114 if (fMessagePort < B_OK) 115 return; 116 117 fLink.SetSenderPort(fClientReplyPort); 118 fLink.SetReceiverPort(fMessagePort); 119 fLink.SetTargetTeam(clientTeam); 120 121 // we let the application own the port, so that we get aware when it's gone 122 if (set_port_owner(fMessagePort, clientTeam) < B_OK) { 123 delete_port(fMessagePort); 124 fMessagePort = -1; 125 return; 126 } 127 128 BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam, 129 clientLooperPort, clientToken); 130 131 fInitialWorkspace = desktop->CurrentWorkspace(); 132 // TODO: this should probably be retrieved when the app is loaded! 133 134 // record the current system wide fonts.. 135 desktop->LockSingleWindow(); 136 DesktopSettings settings(desktop); 137 settings.GetDefaultPlainFont(fPlainFont); 138 settings.GetDefaultBoldFont(fBoldFont); 139 settings.GetDefaultFixedFont(fFixedFont); 140 desktop->UnlockSingleWindow(); 141 142 STRACE(("ServerApp %s:\n", Signature())); 143 STRACE(("\tBApp port: %ld\n", fClientReplyPort)); 144 STRACE(("\tReceiver port: %ld\n", fMessagePort)); 145 } 146 147 148 ServerApp::~ServerApp() 149 { 150 STRACE(("*ServerApp %s:~ServerApp()\n", Signature())); 151 ASSERT(fQuitting); 152 153 // quit all server windows 154 155 fWindowListLock.Lock(); 156 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 157 ServerWindow* window = fWindowList.ItemAt(i); 158 window->Quit(); 159 } 160 fWindowListLock.Unlock(); 161 162 // wait for the windows to quit 163 snooze(20000); 164 165 fDesktop->RevertScreenModes(fTemporaryDisplayModeChange); 166 167 fWindowListLock.Lock(); 168 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 169 ServerWindow* window = fWindowList.ItemAt(i); 170 171 // A window could have been removed in the mean time 172 // (if those 20 milli seconds from above weren't enough) 173 if (window == NULL) 174 continue; 175 176 sem_id deathSemaphore = window->DeathSemaphore(); 177 fWindowListLock.Unlock(); 178 179 // wait 3 seconds for our window to quit - that's quite a long 180 // time, but killing it might have desastrous effects 181 if (MessageLooper::WaitForQuit(deathSemaphore, 3000000) != B_OK) { 182 // This really shouldn't happen, as it shows we're buggy 183 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 184 syslog(LOG_ERR, "ServerApp %s: ServerWindow doesn't respond!\n", 185 Signature()); 186 #else 187 debugger("ServerWindow doesn't respond!\n"); 188 #endif 189 } 190 fWindowListLock.Lock(); 191 } 192 193 fMapLocker.Lock(); 194 195 while (!fBitmapMap.empty()) 196 _DeleteBitmap(fBitmapMap.begin()->second); 197 198 while (!fPictureMap.empty()) 199 RemovePicture(fPictureMap.begin()->second); 200 201 fDesktop->GetCursorManager().DeleteCursors(fClientTeam); 202 203 STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature())); 204 } 205 206 207 /*! \brief Checks if the application was initialized correctly 208 */ 209 status_t 210 ServerApp::InitCheck() 211 { 212 if (fMessagePort < B_OK) 213 return fMessagePort; 214 215 if (fClientReplyPort < B_OK) 216 return fClientReplyPort; 217 218 if (fWindowListLock.Sem() < B_OK) 219 return fWindowListLock.Sem(); 220 221 return B_OK; 222 } 223 224 225 /*! \brief This quits the application and deletes it. You're not supposed 226 to call its destructor directly. 227 228 At the point you're calling this method, the application should already 229 be removed from the application list. 230 */ 231 void 232 ServerApp::Quit(sem_id shutdownSemaphore) 233 { 234 if (fThread < B_OK) { 235 delete this; 236 return; 237 } 238 239 // execute application deletion in the message looper thread 240 241 fQuitting = true; 242 PostMessage(kMsgAppQuit); 243 244 send_data(fThread, 'QUIT', &shutdownSemaphore, sizeof(sem_id)); 245 } 246 247 248 /*! \brief Sets the ServerApp's active status 249 \param value The new status of the ServerApp. 250 251 This changes an internal flag and also sets the current cursor to the one 252 specified by the application 253 */ 254 void 255 ServerApp::Activate(bool value) 256 { 257 if (fIsActive == value) 258 return; 259 260 fIsActive = value; 261 262 if (fIsActive) { 263 // notify registrar about the active app 264 BRoster::Private roster; 265 roster.UpdateActiveApp(ClientTeam()); 266 267 if (_HasWindowUnderMouse()) { 268 // Set the cursor to the application cursor, if any 269 fDesktop->SetCursor(CurrentCursor()); 270 } 271 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); 272 } 273 } 274 275 276 /*! \brief Send a message to the ServerApp's BApplication 277 \param message The message to send 278 */ 279 void 280 ServerApp::SendMessageToClient(BMessage* message) const 281 { 282 status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL, 283 100000); 284 if (status != B_OK) { 285 syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(), 286 strerror(status)); 287 } 288 } 289 290 291 void 292 ServerApp::SetCurrentCursor(ServerCursor* cursor) 293 { 294 if (fViewCursor != cursor) { 295 if (fViewCursor) 296 fViewCursor->ReleaseReference(); 297 298 fViewCursor = cursor; 299 300 if (fViewCursor) 301 fViewCursor->AcquireReference(); 302 } 303 304 fDesktop->SetCursor(CurrentCursor()); 305 } 306 307 308 ServerCursor* 309 ServerApp::CurrentCursor() const 310 { 311 if (fViewCursor != NULL) 312 return fViewCursor; 313 314 return fAppCursor; 315 } 316 317 318 bool 319 ServerApp::AddWindow(ServerWindow* window) 320 { 321 BAutolock locker(fWindowListLock); 322 323 return fWindowList.AddItem(window); 324 } 325 326 327 void 328 ServerApp::RemoveWindow(ServerWindow* window) 329 { 330 BAutolock locker(fWindowListLock); 331 332 fWindowList.RemoveItem(window); 333 } 334 335 336 bool 337 ServerApp::InWorkspace(int32 index) const 338 { 339 BAutolock locker(fWindowListLock); 340 341 // we could cache this, but then we'd have to recompute the cached 342 // value everytime a window has closed or changed workspaces 343 344 // TODO: support initial application workspace! 345 346 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 347 ServerWindow* serverWindow = fWindowList.ItemAt(i); 348 349 const Window* window = serverWindow->Window(); 350 if (window == NULL || window->IsOffscreenWindow()) 351 continue; 352 353 // only normal and unhidden windows count 354 355 if (window->IsNormal() && !window->IsHidden() 356 && window->InWorkspace(index)) 357 return true; 358 } 359 360 return false; 361 } 362 363 364 uint32 365 ServerApp::Workspaces() const 366 { 367 uint32 workspaces = 0; 368 369 BAutolock locker(fWindowListLock); 370 371 // we could cache this, but then we'd have to recompute the cached 372 // value everytime a window has closed or changed workspaces 373 374 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 375 ServerWindow* serverWindow = fWindowList.ItemAt(i); 376 377 const Window* window = serverWindow->Window(); 378 if (window == NULL || window->IsOffscreenWindow()) 379 continue; 380 381 // only normal and unhidden windows count 382 383 if (window->IsNormal() && !window->IsHidden()) 384 workspaces |= window->Workspaces(); 385 } 386 387 // TODO: add initial application workspace! 388 return workspaces; 389 } 390 391 392 /*! \brief Acquires a reference of the desired bitmap, if available. 393 \param token ID token of the bitmap to find 394 \return The bitmap having that ID or NULL if not found 395 */ 396 ServerBitmap* 397 ServerApp::GetBitmap(int32 token) const 398 { 399 if (token < 1) 400 return NULL; 401 402 BAutolock _(fMapLocker); 403 404 ServerBitmap* bitmap = _FindBitmap(token); 405 if (bitmap == NULL) 406 return NULL; 407 408 bitmap->AcquireReference(); 409 410 return bitmap; 411 } 412 413 414 ServerPicture* 415 ServerApp::CreatePicture(const ServerPicture* original) 416 { 417 ServerPicture* picture; 418 if (original != NULL) 419 picture = new(std::nothrow) ServerPicture(*original); 420 else 421 picture = new(std::nothrow) ServerPicture(); 422 423 if (picture != NULL && !picture->SetOwner(this)) 424 picture->ReleaseReference(); 425 426 return picture; 427 } 428 429 430 ServerPicture* 431 ServerApp::GetPicture(int32 token) const 432 { 433 if (token < 1) 434 return NULL; 435 436 BAutolock _(fMapLocker); 437 438 ServerPicture* picture = _FindPicture(token); 439 if (picture == NULL) 440 return NULL; 441 442 picture->AcquireReference(); 443 444 return picture; 445 } 446 447 448 bool 449 ServerApp::AddPicture(ServerPicture* picture) 450 { 451 BAutolock _(fMapLocker); 452 453 try { 454 fPictureMap.insert(std::make_pair(picture->Token(), picture)); 455 } catch (std::bad_alloc& exception) { 456 return false; 457 } 458 459 return true; 460 } 461 462 463 void 464 ServerApp::RemovePicture(ServerPicture* picture) 465 { 466 BAutolock _(fMapLocker); 467 468 fPictureMap.erase(picture->Token()); 469 picture->ReleaseReference(); 470 } 471 472 473 // #pragma mark - private methods 474 475 476 void 477 ServerApp::_GetLooperName(char* name, size_t length) 478 { 479 snprintf(name, length, "a:%ld:%s", ClientTeam(), SignatureLeaf()); 480 } 481 482 483 /*! \brief Handler function for BApplication API messages 484 \param code Identifier code for the message. Equivalent to BMessage::what 485 \param buffer Any attachments 486 487 Note that the buffer's exact format is determined by the particular message. 488 All attachments are placed in the buffer via a PortLink, so it will be a 489 matter of casting and incrementing an index variable to access them. 490 */ 491 void 492 ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) 493 { 494 switch (code) { 495 case AS_REGISTER_INPUT_SERVER: 496 { 497 EventStream* stream 498 = new(std::nothrow) InputServerStream(fHandlerMessenger); 499 if (stream != NULL 500 && (!stream->IsValid() || !gInputManager->AddStream(stream))) { 501 delete stream; 502 break; 503 } 504 505 // TODO: this should be done using notifications (so that an 506 // abandoned stream will get noticed directly) 507 if (fDesktop->EventDispatcher().InitCheck() != B_OK) 508 fDesktop->EventDispatcher().SetTo(gInputManager->GetStream()); 509 break; 510 } 511 512 case AS_APP_CRASHED: 513 // Allow the debugger to show its window: if needed, remove any 514 // kWindowScreenFeels from the windows of this application 515 if (fDesktop->LockAllWindows()) { 516 if (fWindowListLock.Lock()) { 517 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 518 ServerWindow* serverWindow = fWindowList.ItemAt(i); 519 520 Window* window = serverWindow->Window(); 521 if (window == NULL || window->IsOffscreenWindow()) 522 continue; 523 524 if (window->Feel() == kWindowScreenFeel) 525 fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL); 526 } 527 528 fWindowListLock.Unlock(); 529 } 530 fDesktop->UnlockAllWindows(); 531 } 532 break; 533 534 case AS_CREATE_WINDOW: 535 case AS_CREATE_OFFSCREEN_WINDOW: 536 { 537 port_id clientReplyPort = -1; 538 status_t status = _CreateWindow(code, link, clientReplyPort); 539 540 // if sucessful, ServerWindow::Run() will already have replied 541 if (status < B_OK) { 542 // window creation failed, we need to notify the client 543 BPrivate::LinkSender reply(clientReplyPort); 544 reply.StartMessage(status); 545 reply.Flush(); 546 } 547 break; 548 } 549 550 case AS_GET_WINDOW_LIST: 551 { 552 team_id team; 553 if (link.Read<team_id>(&team) == B_OK) 554 fDesktop->WriteWindowList(team, fLink.Sender()); 555 break; 556 } 557 558 case AS_GET_WINDOW_INFO: 559 { 560 int32 serverToken; 561 if (link.Read<int32>(&serverToken) == B_OK) 562 fDesktop->WriteWindowInfo(serverToken, fLink.Sender()); 563 break; 564 } 565 566 case AS_GET_WINDOW_ORDER: 567 { 568 int32 workspace; 569 if (link.Read<int32>(&workspace) == B_OK) 570 fDesktop->WriteWindowOrder(workspace, fLink.Sender()); 571 break; 572 } 573 574 case AS_GET_APPLICATION_ORDER: 575 { 576 int32 workspace; 577 if (link.Read<int32>(&workspace) == B_OK) 578 fDesktop->WriteApplicationOrder(workspace, fLink.Sender()); 579 break; 580 } 581 582 case AS_MINIMIZE_TEAM: 583 { 584 team_id team; 585 if (link.Read<team_id>(&team) == B_OK) 586 fDesktop->MinimizeApplication(team); 587 break; 588 } 589 590 case AS_BRING_TEAM_TO_FRONT: 591 { 592 team_id team; 593 if (link.Read<team_id>(&team) == B_OK) 594 fDesktop->BringApplicationToFront(team); 595 break; 596 } 597 598 case AS_WINDOW_ACTION: 599 { 600 int32 token; 601 int32 action; 602 603 link.Read<int32>(&token); 604 if (link.Read<int32>(&action) != B_OK) 605 break; 606 607 fDesktop->WindowAction(token, action); 608 break; 609 } 610 611 // Decorator commands 612 613 case AS_SET_DECORATOR: 614 { 615 // Attached Data: 616 // int32 the index of the decorator to use 617 618 int32 index; 619 link.Read<int32>(&index); 620 if (gDecorManager.SetDecorator(index)) 621 fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR); 622 break; 623 } 624 case AS_COUNT_DECORATORS: 625 { 626 fLink.StartMessage(B_OK); 627 fLink.Attach<int32>(gDecorManager.CountDecorators()); 628 fLink.Flush(); 629 break; 630 } 631 case AS_GET_DECORATOR: 632 { 633 fLink.StartMessage(B_OK); 634 fLink.Attach<int32>(gDecorManager.GetDecorator()); 635 fLink.Flush(); 636 break; 637 } 638 case AS_GET_DECORATOR_NAME: 639 { 640 int32 index; 641 link.Read<int32>(&index); 642 643 BString str(gDecorManager.GetDecoratorName(index)); 644 if (str.CountChars() > 0) { 645 fLink.StartMessage(B_OK); 646 fLink.AttachString(str.String()); 647 } else 648 fLink.StartMessage(B_ERROR); 649 650 fLink.Flush(); 651 break; 652 } 653 case AS_R5_SET_DECORATOR: 654 { 655 // Sort of supports Tracker's nifty Easter Egg. It was easy to do 656 // and it's kind of neat, so why not? 657 658 // Attached Data: 659 // int32 value of the decorator to use 660 // 0: BeOS 661 // 1: Amiga 662 // 2: Windows 663 // 3: MacOS 664 665 int32 decindex = 0; 666 link.Read<int32>(&decindex); 667 668 if (gDecorManager.SetR5Decorator(decindex)) 669 fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR); 670 671 break; 672 } 673 case AS_CREATE_BITMAP: 674 { 675 STRACE(("ServerApp %s: Received BBitmap creation request\n", 676 Signature())); 677 678 // Allocate a bitmap for an application 679 680 // Attached Data: 681 // 1) BRect bounds 682 // 2) color_space space 683 // 3) int32 bitmap_flags 684 // 4) int32 bytes_per_row 685 // 5) int32 screen_id 686 687 // Reply Data: 688 // 1) int32 server token 689 // 2) area_id id of the area in which the bitmap data resides 690 // 3) int32 area pointer offset used to calculate fBasePtr 691 692 // First, let's attempt to allocate the bitmap 693 ServerBitmap* bitmap = NULL; 694 uint8 allocationFlags = kAllocator; 695 696 BRect frame; 697 color_space colorSpace; 698 uint32 flags; 699 int32 bytesPerRow; 700 int32 screenID; 701 702 link.Read<BRect>(&frame); 703 link.Read<color_space>(&colorSpace); 704 link.Read<uint32>(&flags); 705 link.Read<int32>(&bytesPerRow); 706 if (link.Read<int32>(&screenID) == B_OK) { 707 // TODO: choose the right HWInterface with regards to the 708 // screenID 709 bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator, 710 *fDesktop->HWInterface(), frame, colorSpace, flags, 711 bytesPerRow, screenID, &allocationFlags); 712 } 713 714 STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n", 715 Signature(), frame.Width() + 1, frame.Height() + 1)); 716 717 if (bitmap != NULL && _AddBitmap(bitmap)) { 718 fLink.StartMessage(B_OK); 719 fLink.Attach<int32>(bitmap->Token()); 720 fLink.Attach<uint8>(allocationFlags); 721 722 fLink.Attach<area_id>( 723 fMemoryAllocator.Area(bitmap->AllocationCookie())); 724 fLink.Attach<int32>( 725 fMemoryAllocator.AreaOffset(bitmap->AllocationCookie())); 726 727 if ((allocationFlags & kFramebuffer) != 0) 728 fLink.Attach<int32>(bitmap->BytesPerRow()); 729 } else { 730 if (bitmap != NULL) 731 bitmap->ReleaseReference(); 732 733 fLink.StartMessage(B_NO_MEMORY); 734 } 735 736 fLink.Flush(); 737 break; 738 } 739 case AS_DELETE_BITMAP: 740 { 741 STRACE(("ServerApp %s: received BBitmap delete request\n", 742 Signature())); 743 744 // Attached Data: 745 // 1) int32 token 746 int32 token; 747 link.Read<int32>(&token); 748 749 fMapLocker.Lock(); 750 751 ServerBitmap* bitmap = _FindBitmap(token); 752 if (bitmap != NULL) { 753 STRACE(("ServerApp %s: Deleting Bitmap %ld\n", Signature(), 754 token)); 755 756 _DeleteBitmap(bitmap); 757 } 758 759 fMapLocker.Unlock(); 760 break; 761 } 762 case AS_GET_BITMAP_OVERLAY_RESTRICTIONS: 763 { 764 overlay_restrictions restrictions; 765 status_t status = B_ERROR; 766 767 int32 token; 768 if (link.Read<int32>(&token) != B_OK) 769 break; 770 771 ServerBitmap* bitmap = GetBitmap(token); 772 if (bitmap != NULL) { 773 STRACE(("ServerApp %s: Get overlay restrictions for bitmap " 774 "%ld\n", Signature(), token)); 775 776 status = fDesktop->HWInterface()->GetOverlayRestrictions( 777 bitmap->Overlay(), &restrictions); 778 779 bitmap->ReleaseReference(); 780 } 781 782 fLink.StartMessage(status); 783 if (status == B_OK) 784 fLink.Attach(&restrictions, sizeof(overlay_restrictions)); 785 786 fLink.Flush(); 787 break; 788 } 789 case AS_GET_BITMAP_SUPPORT_FLAGS: 790 { 791 uint32 colorSpace; 792 if (link.Read<uint32>(&colorSpace) != B_OK) 793 break; 794 795 bool overlay = fDesktop->HWInterface()->CheckOverlayRestrictions( 796 64, 64, (color_space)colorSpace); 797 uint32 flags = overlay ? B_BITMAPS_SUPPORT_OVERLAY : 0; 798 799 fLink.StartMessage(B_OK); 800 fLink.Attach<int32>(flags); 801 fLink.Flush(); 802 break; 803 } 804 805 // Picture ops 806 807 case AS_CREATE_PICTURE: 808 { 809 // TODO: Maybe rename this to AS_UPLOAD_PICTURE ? 810 STRACE(("ServerApp %s: Create Picture\n", Signature())); 811 status_t status = B_NO_MEMORY; 812 813 ServerPicture* picture = CreatePicture(); 814 if (picture != NULL) { 815 int32 subPicturesCount = 0; 816 link.Read<int32>(&subPicturesCount); 817 for (int32 i = 0; i < subPicturesCount; i++) { 818 int32 token = -1; 819 link.Read<int32>(&token); 820 821 // TODO: do we actually need another reference here? 822 if (ServerPicture* subPicture = GetPicture(token)) 823 picture->NestPicture(subPicture); 824 } 825 status = picture->ImportData(link); 826 } 827 if (status == B_OK) { 828 fLink.StartMessage(B_OK); 829 fLink.Attach<int32>(picture->Token()); 830 } else 831 fLink.StartMessage(status); 832 833 fLink.Flush(); 834 break; 835 } 836 837 case AS_DELETE_PICTURE: 838 { 839 STRACE(("ServerApp %s: Delete Picture\n", Signature())); 840 int32 token; 841 if (link.Read<int32>(&token) == B_OK) { 842 BAutolock _(fMapLocker); 843 844 ServerPicture* picture = _FindPicture(token); 845 if (picture != NULL) 846 RemovePicture(picture); 847 } 848 break; 849 } 850 851 case AS_CLONE_PICTURE: 852 { 853 STRACE(("ServerApp %s: Clone Picture\n", Signature())); 854 int32 token; 855 ServerPicture* original = NULL; 856 if (link.Read<int32>(&token) == B_OK) 857 original = GetPicture(token); 858 859 if (original != NULL) { 860 ServerPicture* cloned = CreatePicture(original); 861 if (cloned != NULL) { 862 fLink.StartMessage(B_OK); 863 fLink.Attach<int32>(cloned->Token()); 864 } else 865 fLink.StartMessage(B_NO_MEMORY); 866 867 original->ReleaseReference(); 868 } else 869 fLink.StartMessage(B_BAD_VALUE); 870 871 fLink.Flush(); 872 break; 873 } 874 875 case AS_DOWNLOAD_PICTURE: 876 { 877 STRACE(("ServerApp %s: Download Picture\n", Signature())); 878 int32 token; 879 link.Read<int32>(&token); 880 ServerPicture* picture = GetPicture(token); 881 if (picture != NULL) { 882 picture->ExportData(fLink); 883 // ExportData() calls StartMessage() already 884 picture->ReleaseReference(); 885 } else 886 fLink.StartMessage(B_ERROR); 887 888 fLink.Flush(); 889 break; 890 } 891 892 case AS_CURRENT_WORKSPACE: 893 STRACE(("ServerApp %s: get current workspace\n", Signature())); 894 895 if (fDesktop->LockSingleWindow()) { 896 fLink.StartMessage(B_OK); 897 fLink.Attach<int32>(fDesktop->CurrentWorkspace()); 898 fDesktop->UnlockSingleWindow(); 899 } else 900 fLink.StartMessage(B_ERROR); 901 902 fLink.Flush(); 903 break; 904 905 case AS_ACTIVATE_WORKSPACE: 906 { 907 STRACE(("ServerApp %s: activate workspace\n", Signature())); 908 909 // TODO: See above 910 int32 index; 911 link.Read<int32>(&index); 912 913 fDesktop->SetWorkspace(index); 914 break; 915 } 916 917 case AS_SET_WORKSPACE_LAYOUT: 918 { 919 int32 newColumns; 920 int32 newRows; 921 if (link.Read<int32>(&newColumns) == B_OK 922 && link.Read<int32>(&newRows) == B_OK) 923 fDesktop->SetWorkspacesLayout(newColumns, newRows); 924 break; 925 } 926 927 case AS_GET_WORKSPACE_LAYOUT: 928 { 929 if (fDesktop->LockSingleWindow()) { 930 DesktopSettings settings(fDesktop); 931 932 fLink.StartMessage(B_OK); 933 fLink.Attach<int32>(settings.WorkspacesColumns()); 934 fLink.Attach<int32>(settings.WorkspacesRows()); 935 936 fDesktop->UnlockSingleWindow(); 937 } else 938 fLink.StartMessage(B_ERROR); 939 940 fLink.Flush(); 941 break; 942 } 943 944 case AS_IDLE_TIME: 945 STRACE(("ServerApp %s: idle time\n", Signature())); 946 947 fLink.StartMessage(B_OK); 948 fLink.Attach<bigtime_t>(fDesktop->EventDispatcher().IdleTime()); 949 fLink.Flush(); 950 break; 951 952 case AS_SHOW_CURSOR: 953 { 954 STRACE(("ServerApp %s: Show Cursor\n", Signature())); 955 fCursorHideLevel--; 956 if (fCursorHideLevel < 0) 957 fCursorHideLevel = 0; 958 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); 959 break; 960 } 961 case AS_HIDE_CURSOR: 962 { 963 STRACE(("ServerApp %s: Hide Cursor\n", Signature())); 964 fCursorHideLevel++; 965 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); 966 break; 967 } 968 case AS_OBSCURE_CURSOR: 969 { 970 STRACE(("ServerApp %s: Obscure Cursor\n", Signature())); 971 fDesktop->HWInterface()->ObscureCursor(); 972 break; 973 } 974 case AS_QUERY_CURSOR_HIDDEN: 975 { 976 STRACE(("ServerApp %s: Received IsCursorHidden request\n", 977 Signature())); 978 979 fLink.StartMessage(fCursorHideLevel > 0 ? B_OK : B_ERROR); 980 fLink.Flush(); 981 break; 982 } 983 case AS_SET_CURSOR: 984 { 985 STRACE(("ServerApp %s: SetCursor\n", Signature())); 986 987 // Attached data: 988 // 1) bool flag to send a reply 989 // 2) int32 token ID of the cursor to set 990 // 3) port_id port to receive a reply. Only exists if the sync flag 991 // is true. 992 bool sync; 993 int32 token; 994 995 link.Read<bool>(&sync); 996 if (link.Read<int32>(&token) != B_OK) 997 break; 998 999 if (!fDesktop->GetCursorManager().Lock()) 1000 break; 1001 1002 ServerCursor* oldCursor = fAppCursor; 1003 fAppCursor = fDesktop->GetCursorManager().FindCursor(token); 1004 if (fAppCursor != NULL) 1005 fAppCursor->AcquireReference(); 1006 1007 if (_HasWindowUnderMouse()) 1008 fDesktop->SetCursor(CurrentCursor()); 1009 1010 if (oldCursor != NULL) 1011 oldCursor->ReleaseReference(); 1012 1013 fDesktop->GetCursorManager().Unlock(); 1014 1015 if (sync) { 1016 // The application is expecting a reply 1017 fLink.StartMessage(B_OK); 1018 fLink.Flush(); 1019 } 1020 break; 1021 } 1022 case AS_SET_VIEW_CURSOR: 1023 { 1024 STRACE(("ServerApp %s: AS_SET_VIEW_CURSOR:\n", Signature())); 1025 1026 ViewSetViewCursorInfo info; 1027 if (link.Read<ViewSetViewCursorInfo>(&info) != B_OK) 1028 break; 1029 1030 if (fDesktop->GetCursorManager().Lock()) { 1031 ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor( 1032 info.cursorToken); 1033 // If we found a cursor, make sure it doesn't go away. If we 1034 // get a NULL cursor, it probably means we are supposed to use 1035 // the system default cursor. 1036 if (cursor != NULL) 1037 cursor->AcquireReference(); 1038 1039 fDesktop->GetCursorManager().Unlock(); 1040 1041 // We need to acquire the write lock here, since we cannot 1042 // afford that the window thread to which the view belongs 1043 // is running and messing with that same view. 1044 fDesktop->LockAllWindows(); 1045 1046 // Find the corresponding view by the given token. It's ok 1047 // if this view does not exist anymore, since it may have 1048 // already be deleted in the window thread before this 1049 // message got here. 1050 View* view; 1051 if (fViewTokens.GetToken(info.viewToken, B_HANDLER_TOKEN, 1052 (void**)&view) == B_OK) { 1053 // Set the cursor on the view. 1054 view->SetCursor(cursor); 1055 1056 // The cursor might need to be updated now. 1057 Window* window = view->Window(); 1058 if (window != NULL && window->IsFocus()) { 1059 if (fDesktop->ViewUnderMouse(window) == view->Token()) 1060 SetCurrentCursor(cursor); 1061 } 1062 } 1063 1064 fDesktop->UnlockAllWindows(); 1065 1066 // Release the temporary reference. 1067 if (cursor != NULL) 1068 cursor->ReleaseReference(); 1069 } 1070 1071 if (info.sync) { 1072 // sync the client (it can now delete the cursor) 1073 fLink.StartMessage(B_OK); 1074 fLink.Flush(); 1075 } 1076 break; 1077 } 1078 case AS_CREATE_CURSOR: 1079 { 1080 STRACE(("ServerApp %s: Create Cursor\n", Signature())); 1081 // Attached data: 1082 // 1) 68 bytes of fAppCursor data 1083 // 2) port_id reply port 1084 1085 status_t status = B_ERROR; 1086 uint8 cursorData[68]; 1087 ServerCursor* cursor = NULL; 1088 1089 // if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) { 1090 // cursor = new (nothrow) ServerCursor(cursorData); 1091 // if (cursor == NULL) 1092 // status = B_NO_MEMORY; 1093 // } 1094 // 1095 // if (cursor != NULL) { 1096 // cursor->SetOwningTeam(fClientTeam); 1097 // fDesktop->GetCursorManager().AddCursor(cursor); 1098 // 1099 // // Synchronous message - BApplication is waiting on the cursor's ID 1100 // fLink.StartMessage(B_OK); 1101 // fLink.Attach<int32>(cursor->Token()); 1102 // } else 1103 // fLink.StartMessage(status); 1104 1105 if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) { 1106 cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam, 1107 cursorData); 1108 if (cursor == NULL) 1109 status = B_NO_MEMORY; 1110 } 1111 1112 if (cursor != NULL) { 1113 // Synchronous message - BApplication is waiting on the 1114 // cursor's ID 1115 fLink.StartMessage(B_OK); 1116 fLink.Attach<int32>(cursor->Token()); 1117 } else 1118 fLink.StartMessage(status); 1119 1120 fLink.Flush(); 1121 break; 1122 } 1123 case AS_REFERENCE_CURSOR: 1124 { 1125 STRACE(("ServerApp %s: Reference BCursor\n", Signature())); 1126 // Attached data: 1127 // 1) int32 token ID of the cursor to reference 1128 int32 token; 1129 if (link.Read<int32>(&token) != B_OK) 1130 break; 1131 1132 if (!fDesktop->GetCursorManager().Lock()) 1133 break; 1134 1135 ServerCursor* cursor 1136 = fDesktop->GetCursorManager().FindCursor(token); 1137 if (cursor != NULL) 1138 cursor->AcquireReference(); 1139 1140 fDesktop->GetCursorManager().Unlock(); 1141 1142 break; 1143 } 1144 case AS_DELETE_CURSOR: 1145 { 1146 STRACE(("ServerApp %s: Delete BCursor\n", Signature())); 1147 // Attached data: 1148 // 1) int32 token ID of the cursor to delete 1149 int32 token; 1150 if (link.Read<int32>(&token) != B_OK) 1151 break; 1152 1153 if (!fDesktop->GetCursorManager().Lock()) 1154 break; 1155 1156 ServerCursor* cursor 1157 = fDesktop->GetCursorManager().FindCursor(token); 1158 if (cursor != NULL) 1159 cursor->ReleaseReference(); 1160 1161 fDesktop->GetCursorManager().Unlock(); 1162 1163 break; 1164 } 1165 1166 case AS_GET_SCROLLBAR_INFO: 1167 { 1168 STRACE(("ServerApp %s: Get ScrollBar info\n", Signature())); 1169 1170 if (fDesktop->LockSingleWindow()) { 1171 scroll_bar_info info; 1172 DesktopSettings settings(fDesktop); 1173 settings.GetScrollBarInfo(info); 1174 1175 fLink.StartMessage(B_OK); 1176 fLink.Attach<scroll_bar_info>(info); 1177 fDesktop->UnlockSingleWindow(); 1178 } else 1179 fLink.StartMessage(B_ERROR); 1180 1181 fLink.Flush(); 1182 break; 1183 } 1184 case AS_SET_SCROLLBAR_INFO: 1185 { 1186 STRACE(("ServerApp %s: Set ScrollBar info\n", Signature())); 1187 // Attached Data: 1188 // 1) scroll_bar_info scroll bar info structure 1189 scroll_bar_info info; 1190 if (link.Read<scroll_bar_info>(&info) == B_OK) { 1191 LockedDesktopSettings settings(fDesktop); 1192 settings.SetScrollBarInfo(info); 1193 } 1194 1195 fLink.StartMessage(B_OK); 1196 fLink.Flush(); 1197 break; 1198 } 1199 1200 case AS_GET_MENU_INFO: 1201 { 1202 STRACE(("ServerApp %s: Get menu info\n", Signature())); 1203 if (fDesktop->LockSingleWindow()) { 1204 menu_info info; 1205 DesktopSettings settings(fDesktop); 1206 settings.GetMenuInfo(info); 1207 1208 fLink.StartMessage(B_OK); 1209 fLink.Attach<menu_info>(info); 1210 1211 fDesktop->UnlockSingleWindow(); 1212 } else 1213 fLink.StartMessage(B_ERROR); 1214 1215 fLink.Flush(); 1216 break; 1217 } 1218 case AS_SET_MENU_INFO: 1219 { 1220 STRACE(("ServerApp %s: Set menu info\n", Signature())); 1221 menu_info info; 1222 if (link.Read<menu_info>(&info) == B_OK) { 1223 LockedDesktopSettings settings(fDesktop); 1224 settings.SetMenuInfo(info); 1225 // TODO: SetMenuInfo() should do some validity check, so 1226 // that the answer we're giving can actually be useful 1227 } 1228 1229 fLink.StartMessage(B_OK); 1230 fLink.Flush(); 1231 break; 1232 } 1233 1234 case AS_SET_MOUSE_MODE: 1235 { 1236 STRACE(("ServerApp %s: Set Mouse Focus mode\n", 1237 Signature())); 1238 // Attached Data: 1239 // 1) enum mode_mouse mouse focus mode 1240 mode_mouse mouseMode; 1241 if (link.Read<mode_mouse>(&mouseMode) == B_OK) { 1242 LockedDesktopSettings settings(fDesktop); 1243 settings.SetMouseMode(mouseMode); 1244 } 1245 break; 1246 } 1247 case AS_GET_MOUSE_MODE: 1248 { 1249 STRACE(("ServerApp %s: Get Mouse Focus mode\n", 1250 Signature())); 1251 1252 if (fDesktop->LockSingleWindow()) { 1253 DesktopSettings settings(fDesktop); 1254 1255 fLink.StartMessage(B_OK); 1256 fLink.Attach<mode_mouse>(settings.MouseMode()); 1257 1258 fDesktop->UnlockSingleWindow(); 1259 } else 1260 fLink.StartMessage(B_ERROR); 1261 1262 fLink.Flush(); 1263 break; 1264 } 1265 case AS_SET_FOCUS_FOLLOWS_MOUSE_MODE: 1266 { 1267 STRACE(("ServerApp %s: Set Focus Follows Mouse mode\n", Signature())); 1268 // Attached Data: 1269 // 1) enum mode_focus_follows_mouse FFM mouse mode 1270 mode_focus_follows_mouse focusFollowsMousMode; 1271 if (link.Read<mode_focus_follows_mouse>(&focusFollowsMousMode) == B_OK) { 1272 LockedDesktopSettings settings(fDesktop); 1273 settings.SetFocusFollowsMouseMode(focusFollowsMousMode); 1274 } 1275 break; 1276 } 1277 case AS_GET_FOCUS_FOLLOWS_MOUSE_MODE: 1278 { 1279 STRACE(("ServerApp %s: Get Focus Follows Mouse mode\n", Signature())); 1280 1281 if (fDesktop->LockSingleWindow()) { 1282 DesktopSettings settings(fDesktop); 1283 1284 fLink.StartMessage(B_OK); 1285 fLink.Attach<mode_focus_follows_mouse>( 1286 settings.FocusFollowsMouseMode()); 1287 1288 fDesktop->UnlockSingleWindow(); 1289 } else 1290 fLink.StartMessage(B_ERROR); 1291 1292 fLink.Flush(); 1293 break; 1294 } 1295 case AS_SET_ACCEPT_FIRST_CLICK: 1296 { 1297 STRACE(("ServerApp %s: Set Accept First Click\n", Signature())); 1298 // Attached Data: 1299 // 1) bool accept_first_click 1300 bool acceptFirstClick; 1301 if (link.Read<bool>(&acceptFirstClick) == B_OK) { 1302 LockedDesktopSettings settings(fDesktop); 1303 settings.SetAcceptFirstClick(acceptFirstClick); 1304 } 1305 break; 1306 } 1307 case AS_GET_ACCEPT_FIRST_CLICK: 1308 { 1309 STRACE(("ServerApp %s: Get Accept First Click\n", Signature())); 1310 1311 if (fDesktop->LockSingleWindow()) { 1312 DesktopSettings settings(fDesktop); 1313 1314 fLink.StartMessage(B_OK); 1315 fLink.Attach<bool>(settings.AcceptFirstClick()); 1316 1317 fDesktop->UnlockSingleWindow(); 1318 } else 1319 fLink.StartMessage(B_ERROR); 1320 1321 fLink.Flush(); 1322 break; 1323 } 1324 1325 case AS_GET_SHOW_ALL_DRAGGERS: 1326 { 1327 STRACE(("ServerApp %s: Get Show All Draggers\n", Signature())); 1328 1329 if (fDesktop->LockSingleWindow()) { 1330 DesktopSettings settings(fDesktop); 1331 1332 fLink.StartMessage(B_OK); 1333 fLink.Attach<bool>(settings.ShowAllDraggers()); 1334 1335 fDesktop->UnlockSingleWindow(); 1336 } else 1337 fLink.StartMessage(B_ERROR); 1338 1339 fLink.Flush(); 1340 break; 1341 } 1342 1343 case AS_SET_SHOW_ALL_DRAGGERS: 1344 { 1345 STRACE(("ServerApp %s: Set Show All Draggers\n", Signature())); 1346 1347 bool changed = false; 1348 bool show; 1349 if (link.Read<bool>(&show) == B_OK) { 1350 LockedDesktopSettings settings(fDesktop); 1351 if (show != settings.ShowAllDraggers()) { 1352 settings.SetShowAllDraggers(show); 1353 changed = true; 1354 } 1355 } 1356 1357 if (changed) 1358 fDesktop->BroadcastToAllApps(kMsgUpdateShowAllDraggers); 1359 break; 1360 } 1361 1362 case kMsgUpdateShowAllDraggers: 1363 { 1364 bool show = false; 1365 if (fDesktop->LockSingleWindow()) { 1366 DesktopSettings settings(fDesktop); 1367 show = settings.ShowAllDraggers(); 1368 fDesktop->UnlockSingleWindow(); 1369 } 1370 BMessage update(_SHOW_DRAG_HANDLES_); 1371 update.AddBool("show", show); 1372 1373 SendMessageToClient(&update); 1374 break; 1375 } 1376 1377 /* font messages */ 1378 1379 case AS_SET_SYSTEM_FONT: 1380 { 1381 FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature())); 1382 // gets: 1383 // 1) string - font type ("plain", ...) 1384 // 2) string - family 1385 // 3) string - style 1386 // 4) float - size 1387 1388 char type[B_OS_NAME_LENGTH]; 1389 font_family familyName; 1390 font_style styleName; 1391 float size; 1392 1393 if (link.ReadString(type, sizeof(type)) == B_OK 1394 && link.ReadString(familyName, sizeof(familyName)) == B_OK 1395 && link.ReadString(styleName, sizeof(styleName)) == B_OK 1396 && link.Read<float>(&size) == B_OK) { 1397 gFontManager->Lock(); 1398 1399 FontStyle* style 1400 = gFontManager->GetStyle(familyName, styleName); 1401 if (style != NULL) { 1402 ServerFont font(*style, size); 1403 gFontManager->Unlock(); 1404 // We must not have locked the font manager when 1405 // locking the desktop (through LockedDesktopSettings 1406 // below) 1407 1408 LockedDesktopSettings settings(fDesktop); 1409 1410 // TODO: Should we also update our internal copies now? 1411 if (!strcmp(type, "plain")) 1412 settings.SetDefaultPlainFont(font); 1413 else if (!strcmp(type, "bold")) 1414 settings.SetDefaultBoldFont(font); 1415 else if (!strcmp(type, "fixed")) 1416 settings.SetDefaultFixedFont(font); 1417 } else 1418 gFontManager->Unlock(); 1419 } 1420 break; 1421 } 1422 case AS_GET_SYSTEM_DEFAULT_FONT: 1423 { 1424 // input: 1425 // 1) string - font type ("plain", ...) 1426 1427 ServerFont font; 1428 1429 char type[B_OS_NAME_LENGTH]; 1430 status_t status = link.ReadString(type, sizeof(type)); 1431 if (status == B_OK) { 1432 if (!strcmp(type, "plain")) { 1433 font = *gFontManager->DefaultPlainFont(); 1434 } else if (!strcmp(type, "bold")) { 1435 font = *gFontManager->DefaultBoldFont(); 1436 } else if (!strcmp(type, "fixed")) { 1437 font = *gFontManager->DefaultFixedFont(); 1438 } else 1439 status = B_BAD_VALUE; 1440 } 1441 1442 if (status == B_OK) { 1443 // returns: 1444 // 1) string - family 1445 // 2) string - style 1446 // 3) float - size 1447 1448 fLink.StartMessage(B_OK); 1449 fLink.AttachString(font.Family()); 1450 fLink.AttachString(font.Style()); 1451 fLink.Attach<float>(font.Size()); 1452 } else 1453 fLink.StartMessage(status); 1454 1455 fLink.Flush(); 1456 break; 1457 } 1458 case AS_GET_SYSTEM_FONTS: 1459 { 1460 FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature())); 1461 // Returns: 1462 // 1) uint16 - family ID 1463 // 2) uint16 - style ID 1464 // 3) float - size in points 1465 // 4) uint16 - face flags 1466 // 5) uint32 - font flags 1467 1468 if (!fDesktop->LockSingleWindow()) { 1469 fLink.StartMessage(B_OK); 1470 fLink.Flush(); 1471 break; 1472 } 1473 1474 // The client is requesting the system fonts, this 1475 // could happend either at application start up, or 1476 // because the client is resyncing with the global 1477 // fonts. So we record the current system wide fonts 1478 // into our own copies at this point. 1479 DesktopSettings settings(fDesktop); 1480 1481 settings.GetDefaultPlainFont(fPlainFont); 1482 settings.GetDefaultBoldFont(fBoldFont); 1483 settings.GetDefaultFixedFont(fFixedFont); 1484 1485 fLink.StartMessage(B_OK); 1486 1487 for (int32 i = 0; i < 3; i++) { 1488 ServerFont* font = NULL; 1489 switch (i) { 1490 case 0: 1491 font = &fPlainFont; 1492 fLink.AttachString("plain"); 1493 break; 1494 case 1: 1495 font = &fBoldFont; 1496 fLink.AttachString("bold"); 1497 break; 1498 case 2: 1499 font = &fFixedFont; 1500 fLink.AttachString("fixed"); 1501 break; 1502 } 1503 1504 fLink.Attach<uint16>(font->FamilyID()); 1505 fLink.Attach<uint16>(font->StyleID()); 1506 fLink.Attach<float>(font->Size()); 1507 fLink.Attach<uint16>(font->Face()); 1508 fLink.Attach<uint32>(font->Flags()); 1509 } 1510 1511 fDesktop->UnlockSingleWindow(); 1512 fLink.Flush(); 1513 break; 1514 } 1515 case AS_GET_FONT_LIST_REVISION: 1516 { 1517 STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature())); 1518 1519 fLink.StartMessage(B_OK); 1520 fLink.Attach<int32>( 1521 gFontManager->CheckRevision(fDesktop->UserID())); 1522 fLink.Flush(); 1523 break; 1524 } 1525 case AS_GET_FAMILY_AND_STYLES: 1526 { 1527 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature())); 1528 // Attached Data: 1529 // 1) int32 the index of the font family to get 1530 1531 // Returns: 1532 // 1) string - name of family 1533 // 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT) 1534 // 3) count of styles in that family 1535 // For each style: 1536 // 1) string - name of style 1537 // 2) uint16 - face of style 1538 // 3) uint32 - flags of style 1539 1540 int32 index; 1541 link.Read<int32>(&index); 1542 1543 gFontManager->Lock(); 1544 1545 FontFamily* family = gFontManager->FamilyAt(index); 1546 if (family) { 1547 fLink.StartMessage(B_OK); 1548 fLink.AttachString(family->Name()); 1549 fLink.Attach<uint32>(family->Flags()); 1550 1551 int32 count = family->CountStyles(); 1552 fLink.Attach<int32>(count); 1553 1554 for (int32 i = 0; i < count; i++) { 1555 FontStyle* style = family->StyleAt(i); 1556 1557 fLink.AttachString(style->Name()); 1558 fLink.Attach<uint16>(style->Face()); 1559 fLink.Attach<uint32>(style->Flags()); 1560 } 1561 } else 1562 fLink.StartMessage(B_BAD_VALUE); 1563 1564 gFontManager->Unlock(); 1565 fLink.Flush(); 1566 break; 1567 } 1568 case AS_GET_FAMILY_AND_STYLE: 1569 { 1570 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE\n", Signature())); 1571 // Attached Data: 1572 // 1) uint16 - family ID 1573 // 2) uint16 - style ID 1574 1575 // Returns: 1576 // 1) font_family The name of the font family 1577 // 2) font_style - name of the style 1578 uint16 familyID, styleID; 1579 link.Read<uint16>(&familyID); 1580 link.Read<uint16>(&styleID); 1581 1582 gFontManager->Lock(); 1583 1584 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1585 if (fontStyle != NULL) { 1586 fLink.StartMessage(B_OK); 1587 fLink.AttachString(fontStyle->Family()->Name()); 1588 fLink.AttachString(fontStyle->Name()); 1589 } else 1590 fLink.StartMessage(B_BAD_VALUE); 1591 1592 fLink.Flush(); 1593 gFontManager->Unlock(); 1594 break; 1595 } 1596 case AS_GET_FAMILY_AND_STYLE_IDS: 1597 { 1598 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE_IDS\n", 1599 Signature())); 1600 1601 // Attached Data: 1602 // 1) font_family - name of font family to use 1603 // 2) font_style - name of style in family 1604 // 3) family ID - only used if 1) is empty 1605 // 4) style ID - only used if 2) is empty 1606 // 5) face - the font's current face 1607 1608 // Returns: 1609 // 1) uint16 - family ID 1610 // 2) uint16 - style ID 1611 // 3) uint16 - face 1612 1613 font_family family; 1614 font_style style; 1615 uint16 familyID, styleID; 1616 uint16 face; 1617 if (link.ReadString(family, sizeof(font_family)) == B_OK 1618 && link.ReadString(style, sizeof(font_style)) == B_OK 1619 && link.Read<uint16>(&familyID) == B_OK 1620 && link.Read<uint16>(&styleID) == B_OK 1621 && link.Read<uint16>(&face) == B_OK) { 1622 // get the font and return IDs and face 1623 gFontManager->Lock(); 1624 1625 FontStyle *fontStyle = gFontManager->GetStyle(family, style, 1626 familyID, styleID, face); 1627 1628 if (fontStyle != NULL) { 1629 fLink.StartMessage(B_OK); 1630 fLink.Attach<uint16>(fontStyle->Family()->ID()); 1631 fLink.Attach<uint16>(fontStyle->ID()); 1632 1633 // we try to keep the font face close to what we got 1634 face = fontStyle->PreservedFace(face); 1635 1636 fLink.Attach<uint16>(face); 1637 } else 1638 fLink.StartMessage(B_NAME_NOT_FOUND); 1639 1640 gFontManager->Unlock(); 1641 } else 1642 fLink.StartMessage(B_BAD_VALUE); 1643 1644 fLink.Flush(); 1645 break; 1646 } 1647 case AS_GET_FONT_FILE_FORMAT: 1648 { 1649 FTRACE(("ServerApp %s: AS_GET_FONT_FILE_FORMAT\n", Signature())); 1650 // Attached Data: 1651 // 1) uint16 - family ID 1652 // 2) uint16 - style ID 1653 1654 // Returns: 1655 // 1) uint16 font_file_format of font 1656 1657 int32 familyID, styleID; 1658 link.Read<int32>(&familyID); 1659 link.Read<int32>(&styleID); 1660 1661 gFontManager->Lock(); 1662 1663 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1664 if (fontStyle) { 1665 fLink.StartMessage(B_OK); 1666 fLink.Attach<uint16>((uint16)fontStyle->FileFormat()); 1667 } else 1668 fLink.StartMessage(B_BAD_VALUE); 1669 1670 gFontManager->Unlock(); 1671 fLink.Flush(); 1672 break; 1673 } 1674 case AS_GET_STRING_WIDTHS: 1675 { 1676 FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature())); 1677 // Attached Data: 1678 // 1) uint16 ID of family 1679 // 2) uint16 ID of style 1680 // 3) float point size of font 1681 // 4) uint8 spacing to use 1682 // 5) int32 numStrings 1683 // 6) int32 string length to measure (numStrings times) 1684 // 7) string String to measure (numStrings times) 1685 1686 // Returns: 1687 // 1) float - width of the string in pixels (numStrings times) 1688 1689 uint16 family, style; 1690 float size; 1691 uint8 spacing; 1692 1693 link.Read<uint16>(&family); 1694 link.Read<uint16>(&style); 1695 link.Read<float>(&size); 1696 link.Read<uint8>(&spacing); 1697 int32 numStrings; 1698 if (link.Read<int32>(&numStrings) != B_OK) { 1699 // this results in a B_BAD_VALUE return 1700 numStrings = 0; 1701 size = 0.0f; 1702 } 1703 1704 // TODO: don't use the stack for this - numStrings could be large 1705 float widthArray[numStrings]; 1706 int32 lengthArray[numStrings]; 1707 char *stringArray[numStrings]; 1708 for (int32 i = 0; i < numStrings; i++) { 1709 // This version of ReadString allocates the strings, we free 1710 // them below 1711 link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]); 1712 } 1713 1714 ServerFont font; 1715 1716 if (font.SetFamilyAndStyle(family, style) == B_OK && size > 0) { 1717 font.SetSize(size); 1718 font.SetSpacing(spacing); 1719 1720 for (int32 i = 0; i < numStrings; i++) { 1721 if (!stringArray[i] || lengthArray[i] <= 0) 1722 widthArray[i] = 0.0; 1723 else { 1724 widthArray[i] = font.StringWidth(stringArray[i], 1725 lengthArray[i]); 1726 } 1727 } 1728 1729 fLink.StartMessage(B_OK); 1730 fLink.Attach(widthArray, sizeof(widthArray)); 1731 } else 1732 fLink.StartMessage(B_BAD_VALUE); 1733 1734 fLink.Flush(); 1735 1736 for (int32 i = 0; i < numStrings; i++) { 1737 free(stringArray[i]); 1738 } 1739 break; 1740 } 1741 case AS_GET_FONT_BOUNDING_BOX: 1742 { 1743 FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX unimplemented\n", 1744 Signature())); 1745 // Attached Data: 1746 // 1) uint16 - family ID 1747 // 2) uint16 - style ID 1748 1749 // Returns: 1750 // 1) BRect - box holding entire font 1751 1752 // ToDo: implement me! 1753 fLink.StartMessage(B_ERROR); 1754 fLink.Flush(); 1755 break; 1756 } 1757 case AS_GET_TUNED_COUNT: 1758 { 1759 FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature())); 1760 // Attached Data: 1761 // 1) uint16 - family ID 1762 // 2) uint16 - style ID 1763 1764 // Returns: 1765 // 1) int32 - number of font strikes available 1766 uint16 familyID, styleID; 1767 link.Read<uint16>(&familyID); 1768 link.Read<uint16>(&styleID); 1769 1770 gFontManager->Lock(); 1771 1772 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1773 if (fontStyle != NULL) { 1774 fLink.StartMessage(B_OK); 1775 fLink.Attach<int32>(fontStyle->TunedCount()); 1776 } else 1777 fLink.StartMessage(B_BAD_VALUE); 1778 1779 gFontManager->Unlock(); 1780 fLink.Flush(); 1781 break; 1782 } 1783 case AS_GET_TUNED_INFO: 1784 { 1785 FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n", 1786 Signature())); 1787 // Attached Data: 1788 // 1) uint16 - family ID 1789 // 2) uint16 - style ID 1790 // 3) uint32 - index of the particular font strike 1791 1792 // Returns: 1793 // 1) tuned_font_info - info on the strike specified 1794 // ToDo: implement me! 1795 fLink.StartMessage(B_ERROR); 1796 fLink.Flush(); 1797 break; 1798 } 1799 case AS_GET_EXTRA_FONT_FLAGS: 1800 { 1801 FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n", 1802 Signature())); 1803 // Attached Data: 1804 // 1) uint16 - family ID 1805 // 2) uint16 - style ID 1806 1807 // Returns: 1808 // 1) uint32 - extra font flags 1809 uint16 familyID, styleID; 1810 link.Read<uint16>(&familyID); 1811 link.Read<uint16>(&styleID); 1812 1813 gFontManager->Lock(); 1814 1815 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1816 if (fontStyle != NULL) { 1817 fLink.StartMessage(B_OK); 1818 fLink.Attach<uint32>(fontStyle->Flags()); 1819 } else 1820 fLink.StartMessage(B_BAD_VALUE); 1821 1822 gFontManager->Unlock(); 1823 fLink.Flush(); 1824 break; 1825 } 1826 case AS_GET_FONT_HEIGHT: 1827 { 1828 FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature())); 1829 // Attached Data: 1830 // 1) uint16 family ID 1831 // 2) uint16 style ID 1832 // 3) float size 1833 uint16 familyID, styleID; 1834 float size; 1835 link.Read<uint16>(&familyID); 1836 link.Read<uint16>(&styleID); 1837 link.Read<float>(&size); 1838 1839 gFontManager->Lock(); 1840 1841 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1842 if (fontStyle != NULL) { 1843 font_height height; 1844 fontStyle->GetHeight(size, height); 1845 1846 fLink.StartMessage(B_OK); 1847 fLink.Attach<font_height>(height); 1848 } else 1849 fLink.StartMessage(B_BAD_VALUE); 1850 1851 gFontManager->Unlock(); 1852 fLink.Flush(); 1853 break; 1854 } 1855 case AS_GET_GLYPH_SHAPES: 1856 { 1857 FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature())); 1858 // Attached Data: 1859 // 1) uint16 - family ID 1860 // 2) uint16 - style ID 1861 // 3) float - point size 1862 // 4) float - shear 1863 // 5) float - rotation 1864 // 6) float - false bold width 1865 // 6) uint32 - flags 1866 // 7) int32 - numChars 1867 // 8) int32 - numBytes 1868 // 8) char - chars (bytesInBuffer times) 1869 1870 // Returns: 1871 // 1) BShape - glyph shape 1872 // numChars times 1873 1874 uint16 familyID, styleID; 1875 uint32 flags; 1876 float size, shear, rotation, falseBoldWidth; 1877 1878 link.Read<uint16>(&familyID); 1879 link.Read<uint16>(&styleID); 1880 link.Read<float>(&size); 1881 link.Read<float>(&shear); 1882 link.Read<float>(&rotation); 1883 link.Read<float>(&falseBoldWidth); 1884 link.Read<uint32>(&flags); 1885 1886 int32 numChars, numBytes; 1887 link.Read<int32>(&numChars); 1888 link.Read<int32>(&numBytes); 1889 1890 // TODO: proper error checking 1891 char* charArray = new (nothrow) char[numBytes]; 1892 link.Read(charArray, numBytes); 1893 1894 ServerFont font; 1895 status_t status = font.SetFamilyAndStyle(familyID, styleID); 1896 if (status == B_OK) { 1897 font.SetSize(size); 1898 font.SetShear(shear); 1899 font.SetRotation(rotation); 1900 font.SetFalseBoldWidth(falseBoldWidth); 1901 font.SetFlags(flags); 1902 1903 // TODO: proper error checking 1904 BShape** shapes = new (nothrow) BShape*[numChars]; 1905 status = font.GetGlyphShapes(charArray, numChars, shapes); 1906 if (status == B_OK) { 1907 fLink.StartMessage(B_OK); 1908 for (int32 i = 0; i < numChars; i++) { 1909 fLink.AttachShape(*shapes[i]); 1910 delete shapes[i]; 1911 } 1912 } else 1913 fLink.StartMessage(status); 1914 1915 delete[] shapes; 1916 } else 1917 fLink.StartMessage(status); 1918 1919 delete[] charArray; 1920 fLink.Flush(); 1921 break; 1922 } 1923 case AS_GET_HAS_GLYPHS: 1924 { 1925 FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature())); 1926 // Attached Data: 1927 // 1) uint16 - family ID 1928 // 2) uint16 - style ID 1929 // 3) int32 - numChars 1930 // 4) int32 - numBytes 1931 // 5) char - the char buffer with size numBytes 1932 1933 uint16 familyID, styleID; 1934 link.Read<uint16>(&familyID); 1935 link.Read<uint16>(&styleID); 1936 1937 int32 numChars, numBytes; 1938 link.Read<int32>(&numChars); 1939 link.Read<int32>(&numBytes); 1940 // TODO: proper error checking 1941 char* charArray = new (nothrow) char[numBytes]; 1942 link.Read(charArray, numBytes); 1943 1944 ServerFont font; 1945 status_t status = font.SetFamilyAndStyle(familyID, styleID); 1946 if (status == B_OK) { 1947 bool hasArray[numChars]; 1948 status = font.GetHasGlyphs(charArray, numBytes, hasArray); 1949 if (status == B_OK) { 1950 fLink.StartMessage(B_OK); 1951 fLink.Attach(hasArray, sizeof(hasArray)); 1952 } else 1953 fLink.StartMessage(status); 1954 } else 1955 fLink.StartMessage(status); 1956 1957 delete[] charArray; 1958 fLink.Flush(); 1959 break; 1960 } 1961 case AS_GET_EDGES: 1962 { 1963 FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature())); 1964 // Attached Data: 1965 // 1) uint16 - family ID 1966 // 2) uint16 - style ID 1967 // 3) int32 - numChars 1968 // 4) int32 - numBytes 1969 // 5) char - the char buffer with size numBytes 1970 1971 uint16 familyID, styleID; 1972 link.Read<uint16>(&familyID); 1973 link.Read<uint16>(&styleID); 1974 1975 int32 numChars; 1976 link.Read<int32>(&numChars); 1977 1978 uint32 numBytes; 1979 link.Read<uint32>(&numBytes); 1980 // TODO: proper error checking 1981 char* charArray = new (nothrow) char[numBytes]; 1982 link.Read(charArray, numBytes); 1983 1984 ServerFont font; 1985 status_t status = font.SetFamilyAndStyle(familyID, styleID); 1986 if (status == B_OK) { 1987 edge_info edgeArray[numChars]; 1988 status = font.GetEdges(charArray, numBytes, edgeArray); 1989 if (status == B_OK) { 1990 fLink.StartMessage(B_OK); 1991 fLink.Attach(edgeArray, sizeof(edgeArray)); 1992 } else 1993 fLink.StartMessage(status); 1994 } else 1995 fLink.StartMessage(status); 1996 1997 delete[] charArray; 1998 fLink.Flush(); 1999 break; 2000 } 2001 case AS_GET_ESCAPEMENTS: 2002 { 2003 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature())); 2004 // Attached Data: 2005 // 1) uint16 - family ID 2006 // 2) uint16 - style ID 2007 // 3) float - point size 2008 // 4) uint8 - spacing 2009 // 5) float - rotation 2010 // 6) uint32 - flags 2011 // 7) int32 - numChars 2012 // 8) char - char -\ both 2013 // 9) BPoint - offset -/ (numChars times) 2014 2015 // Returns: 2016 // 1) BPoint - escapement 2017 // numChars times 2018 2019 uint16 familyID, styleID; 2020 uint32 flags; 2021 float size, rotation; 2022 uint8 spacing; 2023 2024 link.Read<uint16>(&familyID); 2025 link.Read<uint16>(&styleID); 2026 link.Read<float>(&size); 2027 link.Read<uint8>(&spacing); 2028 link.Read<float>(&rotation); 2029 link.Read<uint32>(&flags); 2030 2031 escapement_delta delta; 2032 link.Read<float>(&delta.nonspace); 2033 link.Read<float>(&delta.space); 2034 2035 bool wantsOffsets; 2036 link.Read<bool>(&wantsOffsets); 2037 2038 int32 numChars; 2039 link.Read<int32>(&numChars); 2040 2041 uint32 numBytes; 2042 link.Read<uint32>(&numBytes); 2043 2044 char* charArray = new(std::nothrow) char[numBytes]; 2045 BPoint* escapements = new(std::nothrow) BPoint[numChars]; 2046 BPoint* offsets = NULL; 2047 if (wantsOffsets) 2048 offsets = new(std::nothrow) BPoint[numChars]; 2049 2050 if (charArray == NULL || escapements == NULL 2051 || (offsets == NULL && wantsOffsets)) { 2052 delete[] charArray; 2053 delete[] escapements; 2054 delete[] offsets; 2055 2056 fLink.StartMessage(B_NO_MEMORY); 2057 fLink.Flush(); 2058 break; 2059 } 2060 2061 link.Read(charArray, numBytes); 2062 2063 ServerFont font; 2064 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2065 if (status == B_OK) { 2066 font.SetSize(size); 2067 font.SetSpacing(spacing); 2068 font.SetRotation(rotation); 2069 font.SetFlags(flags); 2070 2071 status = font.GetEscapements(charArray, numBytes, numChars, 2072 delta, escapements, offsets); 2073 2074 if (status == B_OK) { 2075 fLink.StartMessage(B_OK); 2076 for (int32 i = 0; i < numChars; i++) 2077 fLink.Attach<BPoint>(escapements[i]); 2078 2079 if (offsets) { 2080 for (int32 i = 0; i < numChars; i++) 2081 fLink.Attach<BPoint>(offsets[i]); 2082 } 2083 } else 2084 fLink.StartMessage(status); 2085 2086 delete[] escapements; 2087 delete[] offsets; 2088 } else 2089 fLink.StartMessage(status); 2090 2091 delete[] charArray; 2092 fLink.Flush(); 2093 break; 2094 } 2095 case AS_GET_ESCAPEMENTS_AS_FLOATS: 2096 { 2097 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature())); 2098 // Attached Data: 2099 // 1) uint16 - family ID 2100 // 2) uint16 - style ID 2101 // 3) float - point size 2102 // 4) uint8 - spacing 2103 // 5) float - rotation 2104 // 6) uint32 - flags 2105 2106 // 7) float - additional "nonspace" delta 2107 // 8) float - additional "space" delta 2108 2109 // 9) int32 - numChars 2110 // 10) int32 - numBytes 2111 // 11) char - the char buffer with size numBytes 2112 2113 // Returns: 2114 // 1) float - escapement buffer with numChar entries 2115 2116 uint16 familyID, styleID; 2117 uint32 flags; 2118 float size, rotation; 2119 uint8 spacing; 2120 2121 link.Read<uint16>(&familyID); 2122 link.Read<uint16>(&styleID); 2123 link.Read<float>(&size); 2124 link.Read<uint8>(&spacing); 2125 link.Read<float>(&rotation); 2126 link.Read<uint32>(&flags); 2127 2128 escapement_delta delta; 2129 link.Read<float>(&delta.nonspace); 2130 link.Read<float>(&delta.space); 2131 2132 int32 numChars; 2133 link.Read<int32>(&numChars); 2134 2135 uint32 numBytes; 2136 link.Read<uint32>(&numBytes); 2137 2138 char* charArray = new (nothrow) char[numBytes]; 2139 float* escapements = new (nothrow) float[numChars]; 2140 if (charArray == NULL || escapements == NULL) { 2141 delete[] charArray; 2142 delete[] escapements; 2143 fLink.StartMessage(B_NO_MEMORY); 2144 fLink.Flush(); 2145 break; 2146 } 2147 2148 link.Read(charArray, numBytes); 2149 2150 // figure out escapements 2151 2152 ServerFont font; 2153 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2154 if (status == B_OK) { 2155 font.SetSize(size); 2156 font.SetSpacing(spacing); 2157 font.SetRotation(rotation); 2158 font.SetFlags(flags); 2159 2160 status = font.GetEscapements(charArray, numBytes, numChars, 2161 delta, escapements); 2162 2163 if (status == B_OK) { 2164 fLink.StartMessage(B_OK); 2165 fLink.Attach(escapements, numChars * sizeof(float)); 2166 } 2167 } 2168 2169 delete[] charArray; 2170 delete[] escapements; 2171 2172 if (status != B_OK) 2173 fLink.StartMessage(status); 2174 2175 fLink.Flush(); 2176 break; 2177 } 2178 case AS_GET_BOUNDINGBOXES_CHARS: 2179 case AS_GET_BOUNDINGBOXES_STRING: 2180 { 2181 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature())); 2182 // Attached Data: 2183 // 1) uint16 - family ID 2184 // 2) uint16 - style ID 2185 // 3) float - point size 2186 // 4) float - rotation 2187 // 5) float - shear 2188 // 6) float - false bold width 2189 // 7) uint8 - spacing 2190 // 8) uint32 - flags 2191 2192 // 9) font_metric_mode - mode 2193 // 10) bool - string escapement 2194 2195 // 11) escapement_delta - additional delta 2196 2197 // 12) int32 - numChars 2198 // 13) int32 - numBytes 2199 // 14) char - the char buffer with size numBytes 2200 2201 // Returns: 2202 // 1) BRect - rects with numChar entries 2203 2204 uint16 familyID, styleID; 2205 uint32 flags; 2206 float size, rotation, shear, falseBoldWidth; 2207 uint8 spacing; 2208 font_metric_mode mode; 2209 bool stringEscapement; 2210 2211 link.Read<uint16>(&familyID); 2212 link.Read<uint16>(&styleID); 2213 link.Read<float>(&size); 2214 link.Read<float>(&rotation); 2215 link.Read<float>(&shear); 2216 link.Read<float>(&falseBoldWidth); 2217 link.Read<uint8>(&spacing); 2218 link.Read<uint32>(&flags); 2219 link.Read<font_metric_mode>(&mode); 2220 link.Read<bool>(&stringEscapement); 2221 2222 escapement_delta delta; 2223 link.Read<escapement_delta>(&delta); 2224 2225 int32 numChars; 2226 link.Read<int32>(&numChars); 2227 2228 uint32 numBytes; 2229 link.Read<uint32>(&numBytes); 2230 2231 bool success = false; 2232 2233 char* charArray = new(std::nothrow) char[numBytes]; 2234 BRect* rectArray = new(std::nothrow) BRect[numChars]; 2235 if (charArray != NULL && rectArray != NULL) { 2236 link.Read(charArray, numBytes); 2237 2238 // figure out escapements 2239 2240 ServerFont font; 2241 if (font.SetFamilyAndStyle(familyID, styleID) == B_OK) { 2242 font.SetSize(size); 2243 font.SetRotation(rotation); 2244 font.SetShear(shear); 2245 font.SetFalseBoldWidth(falseBoldWidth); 2246 font.SetSpacing(spacing); 2247 font.SetFlags(flags); 2248 2249 // TODO: implement for real 2250 if (font.GetBoundingBoxes(charArray, numBytes, 2251 rectArray, stringEscapement, mode, delta, 2252 code == AS_GET_BOUNDINGBOXES_STRING) == B_OK) { 2253 fLink.StartMessage(B_OK); 2254 fLink.Attach(rectArray, sizeof(rectArray)); 2255 success = true; 2256 } 2257 } 2258 } 2259 2260 if (!success) 2261 fLink.StartMessage(B_ERROR); 2262 2263 fLink.Flush(); 2264 2265 delete[] charArray; 2266 delete[] rectArray; 2267 break; 2268 } 2269 case AS_GET_BOUNDINGBOXES_STRINGS: 2270 { 2271 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n", 2272 Signature())); 2273 2274 // Attached Data: 2275 // 1) uint16 - family ID 2276 // 2) uint16 - style ID 2277 // 3) float - point size 2278 // 4) float - rotation 2279 // 5) float - shear 2280 // 6) float - false bold width 2281 // 7) uint8 - spacing 2282 // 8) uint32 - flags 2283 2284 // 9) font_metric_mode - mode 2285 // 10) int32 numStrings 2286 2287 // 11) escapement_delta - additional delta (numStrings times) 2288 // 12) int32 string length to measure (numStrings times) 2289 // 13) string - string (numStrings times) 2290 2291 // Returns: 2292 // 1) BRect - rects with numStrings entries 2293 2294 uint16 familyID, styleID; 2295 uint32 flags; 2296 float ptsize, rotation, shear, falseBoldWidth; 2297 uint8 spacing; 2298 font_metric_mode mode; 2299 2300 link.Read<uint16>(&familyID); 2301 link.Read<uint16>(&styleID); 2302 link.Read<float>(&ptsize); 2303 link.Read<float>(&rotation); 2304 link.Read<float>(&shear); 2305 link.Read<float>(&falseBoldWidth); 2306 link.Read<uint8>(&spacing); 2307 link.Read<uint32>(&flags); 2308 link.Read<font_metric_mode>(&mode); 2309 2310 int32 numStrings; 2311 link.Read<int32>(&numStrings); 2312 2313 escapement_delta deltaArray[numStrings]; 2314 char* stringArray[numStrings]; 2315 int32 lengthArray[numStrings]; 2316 for(int32 i = 0; i < numStrings; i++) { 2317 // This version of ReadString allocates the strings, we free 2318 // them below 2319 // TODO: this does not work on 64-bit (size_t != int32) 2320 link.ReadString(&stringArray[i], (size_t*)&lengthArray[i]); 2321 link.Read<escapement_delta>(&deltaArray[i]); 2322 } 2323 2324 // TODO: don't do this on the heap! (at least check the size before) 2325 BRect rectArray[numStrings]; 2326 2327 ServerFont font; 2328 bool success = false; 2329 if (font.SetFamilyAndStyle(familyID, styleID) == B_OK) { 2330 font.SetSize(ptsize); 2331 font.SetRotation(rotation); 2332 font.SetShear(shear); 2333 font.SetFalseBoldWidth(falseBoldWidth); 2334 font.SetSpacing(spacing); 2335 font.SetFlags(flags); 2336 2337 if (font.GetBoundingBoxesForStrings(stringArray, lengthArray, 2338 numStrings, rectArray, mode, deltaArray) == B_OK) { 2339 fLink.StartMessage(B_OK); 2340 fLink.Attach(rectArray, sizeof(rectArray)); 2341 success = true; 2342 } 2343 } 2344 2345 for (int32 i = 0; i < numStrings; i++) 2346 free(stringArray[i]); 2347 2348 if (!success) 2349 fLink.StartMessage(B_ERROR); 2350 2351 fLink.Flush(); 2352 break; 2353 } 2354 2355 // Screen commands 2356 2357 case AS_VALID_SCREEN_ID: 2358 { 2359 // Attached data 2360 // 1) int32 screen 2361 int32 id; 2362 if (link.Read<int32>(&id) == B_OK 2363 && id == B_MAIN_SCREEN_ID.id) 2364 fLink.StartMessage(B_OK); 2365 else 2366 fLink.StartMessage(B_ERROR); 2367 2368 fLink.Flush(); 2369 break; 2370 } 2371 2372 case AS_GET_NEXT_SCREEN_ID: 2373 { 2374 // Attached data 2375 // 1) int32 screen 2376 int32 id; 2377 link.Read<int32>(&id); 2378 2379 // TODO: for now, just say we're the last one 2380 fLink.StartMessage(B_ENTRY_NOT_FOUND); 2381 fLink.Flush(); 2382 break; 2383 } 2384 2385 case AS_GET_SCREEN_ID_FROM_WINDOW: 2386 { 2387 status_t status = B_BAD_VALUE; 2388 2389 // Attached data 2390 // 1) int32 - window client token 2391 int32 clientToken; 2392 if (link.Read<int32>(&clientToken) != B_OK) 2393 status = B_BAD_DATA; 2394 else { 2395 BAutolock locker(fWindowListLock); 2396 2397 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 2398 ServerWindow* serverWindow = fWindowList.ItemAt(i); 2399 2400 if (serverWindow->ClientToken() == clientToken) { 2401 AutoReadLocker _(fDesktop->ScreenLocker()); 2402 2403 // found it! 2404 Window* window = serverWindow->Window(); 2405 const Screen* screen = NULL; 2406 if (window != NULL) 2407 screen = window->Screen(); 2408 2409 if (screen == NULL) { 2410 // The window hasn't been added to the desktop yet, 2411 // or it's an offscreen window 2412 break; 2413 } 2414 2415 fLink.StartMessage(B_OK); 2416 fLink.Attach<int32>(screen->ID()); 2417 status = B_OK; 2418 break; 2419 } 2420 } 2421 } 2422 2423 if (status != B_OK) 2424 fLink.StartMessage(status); 2425 fLink.Flush(); 2426 break; 2427 } 2428 2429 case AS_SCREEN_GET_MODE: 2430 { 2431 STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature())); 2432 // Attached data 2433 // 1) int32 screen 2434 // 2) uint32 workspace index 2435 2436 int32 id; 2437 link.Read<int32>(&id); 2438 uint32 workspace; 2439 link.Read<uint32>(&workspace); 2440 2441 display_mode mode; 2442 status_t status = fDesktop->GetScreenMode(workspace, id, mode); 2443 2444 fLink.StartMessage(status); 2445 if (status == B_OK) 2446 fLink.Attach<display_mode>(mode); 2447 fLink.Flush(); 2448 break; 2449 } 2450 case AS_SCREEN_SET_MODE: 2451 { 2452 STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature())); 2453 // Attached data 2454 // 1) int32 screen 2455 // 2) workspace index 2456 // 3) display_mode to set 2457 // 4) 'makeDefault' boolean 2458 2459 int32 id; 2460 link.Read<int32>(&id); 2461 uint32 workspace; 2462 link.Read<uint32>(&workspace); 2463 2464 display_mode mode; 2465 link.Read<display_mode>(&mode); 2466 2467 bool makeDefault = false; 2468 status_t status = link.Read<bool>(&makeDefault); 2469 2470 if (status == B_OK) { 2471 status = fDesktop->SetScreenMode(workspace, id, mode, 2472 makeDefault); 2473 } 2474 if (status == B_OK) { 2475 if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX 2476 && fDesktop->LockSingleWindow()) { 2477 workspace = fDesktop->CurrentWorkspace(); 2478 fDesktop->UnlockSingleWindow(); 2479 } 2480 2481 if (!makeDefault) { 2482 // Memorize the screen change, so that it can be reverted 2483 // later 2484 fTemporaryDisplayModeChange |= 1 << workspace; 2485 } else 2486 fTemporaryDisplayModeChange &= ~(1 << workspace); 2487 } 2488 2489 fLink.StartMessage(status); 2490 fLink.Flush(); 2491 break; 2492 } 2493 2494 case AS_PROPOSE_MODE: 2495 { 2496 STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature())); 2497 int32 id; 2498 link.Read<int32>(&id); 2499 2500 display_mode target, low, high; 2501 link.Read<display_mode>(&target); 2502 link.Read<display_mode>(&low); 2503 link.Read<display_mode>(&high); 2504 status_t status = fDesktop->HWInterface()->ProposeMode(&target, 2505 &low, &high); 2506 2507 // ProposeMode() returns B_BAD_VALUE to hint that the candidate is 2508 // not within the given limits (but is supported) 2509 if (status == B_OK || status == B_BAD_VALUE) { 2510 fLink.StartMessage(B_OK); 2511 fLink.Attach<display_mode>(target); 2512 fLink.Attach<bool>(status == B_OK); 2513 } else 2514 fLink.StartMessage(status); 2515 2516 fLink.Flush(); 2517 break; 2518 } 2519 2520 case AS_GET_MODE_LIST: 2521 { 2522 int32 id; 2523 link.Read<int32>(&id); 2524 // TODO: use this screen id 2525 2526 display_mode* modeList; 2527 uint32 count; 2528 status_t status = fDesktop->HWInterface()->GetModeList(&modeList, 2529 &count); 2530 if (status == B_OK) { 2531 fLink.StartMessage(B_OK); 2532 fLink.Attach<uint32>(count); 2533 fLink.Attach(modeList, sizeof(display_mode) * count); 2534 2535 delete[] modeList; 2536 } else 2537 fLink.StartMessage(status); 2538 2539 fLink.Flush(); 2540 break; 2541 } 2542 2543 case AS_GET_SCREEN_FRAME: 2544 { 2545 STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature())); 2546 // Attached data 2547 // 1) int32 screen 2548 // 2) uint32 workspace index 2549 2550 int32 id; 2551 link.Read<int32>(&id); 2552 uint32 workspace; 2553 link.Read<uint32>(&workspace); 2554 2555 BRect frame; 2556 status_t status = fDesktop->GetScreenFrame(workspace, id, frame); 2557 2558 fLink.StartMessage(status); 2559 if (status == B_OK) 2560 fLink.Attach<BRect>(frame); 2561 2562 fLink.Flush(); 2563 break; 2564 } 2565 2566 case AS_SCREEN_GET_COLORMAP: 2567 { 2568 STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature())); 2569 2570 int32 id; 2571 link.Read<int32>(&id); 2572 2573 const color_map* colorMap = SystemColorMap(); 2574 if (colorMap != NULL) { 2575 fLink.StartMessage(B_OK); 2576 fLink.Attach<color_map>(*colorMap); 2577 } else 2578 fLink.StartMessage(B_ERROR); 2579 2580 fLink.Flush(); 2581 break; 2582 } 2583 2584 case AS_GET_DESKTOP_COLOR: 2585 { 2586 STRACE(("ServerApp %s: get desktop color\n", Signature())); 2587 2588 uint32 index; 2589 link.Read<uint32>(&index); 2590 2591 fLink.StartMessage(B_OK); 2592 fDesktop->Lock(); 2593 2594 // we're nice to our children (and also take the default case 2595 // into account which asks for the current workspace) 2596 if (index >= (uint32)kMaxWorkspaces) 2597 index = fDesktop->CurrentWorkspace(); 2598 2599 Workspace workspace(*fDesktop, index); 2600 fLink.Attach<rgb_color>(workspace.Color()); 2601 2602 fDesktop->Unlock(); 2603 fLink.Flush(); 2604 break; 2605 } 2606 2607 case AS_SET_DESKTOP_COLOR: 2608 { 2609 STRACE(("ServerApp %s: set desktop color\n", Signature())); 2610 2611 rgb_color color; 2612 uint32 index; 2613 bool makeDefault; 2614 2615 link.Read<rgb_color>(&color); 2616 link.Read<uint32>(&index); 2617 if (link.Read<bool>(&makeDefault) != B_OK) 2618 break; 2619 2620 fDesktop->Lock(); 2621 2622 // we're nice to our children (and also take the default case 2623 // into account which asks for the current workspace) 2624 if (index >= (uint32)kMaxWorkspaces) 2625 index = fDesktop->CurrentWorkspace(); 2626 2627 Workspace workspace(*fDesktop, index); 2628 workspace.SetColor(color, makeDefault); 2629 2630 fDesktop->Unlock(); 2631 break; 2632 } 2633 2634 case AS_SET_UI_COLOR: 2635 { 2636 STRACE(("ServerApp %s: Set UI Color\n", Signature())); 2637 // Attached Data: 2638 // 1) color_which which 2639 // 2) rgb_color color 2640 color_which which; 2641 rgb_color color; 2642 2643 link.Read<color_which>(&which); 2644 if (link.Read<rgb_color>(&color) == B_OK) { 2645 LockedDesktopSettings settings(fDesktop); 2646 settings.SetUIColor(which, color); 2647 } 2648 break; 2649 } 2650 2651 case AS_GET_ACCELERANT_INFO: 2652 { 2653 STRACE(("ServerApp %s: get accelerant info\n", Signature())); 2654 2655 // We aren't using the screen_id for now... 2656 int32 id; 2657 link.Read<int32>(&id); 2658 2659 accelerant_device_info accelerantInfo; 2660 // TODO: I wonder if there should be a "desktop" lock... 2661 status_t status 2662 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo); 2663 if (status == B_OK) { 2664 fLink.StartMessage(B_OK); 2665 fLink.Attach<accelerant_device_info>(accelerantInfo); 2666 } else 2667 fLink.StartMessage(status); 2668 2669 fLink.Flush(); 2670 break; 2671 } 2672 2673 case AS_GET_MONITOR_INFO: 2674 { 2675 STRACE(("ServerApp %s: get monitor info\n", Signature())); 2676 2677 // We aren't using the screen_id for now... 2678 int32 id; 2679 link.Read<int32>(&id); 2680 2681 monitor_info info; 2682 // TODO: I wonder if there should be a "desktop" lock... 2683 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info); 2684 if (status == B_OK) { 2685 fLink.StartMessage(B_OK); 2686 fLink.Attach<monitor_info>(info); 2687 } else 2688 fLink.StartMessage(status); 2689 2690 fLink.Flush(); 2691 break; 2692 } 2693 2694 case AS_GET_FRAME_BUFFER_CONFIG: 2695 { 2696 STRACE(("ServerApp %s: get frame buffer config\n", Signature())); 2697 2698 // We aren't using the screen_id for now... 2699 int32 id; 2700 link.Read<int32>(&id); 2701 2702 frame_buffer_config config; 2703 // TODO: I wonder if there should be a "desktop" lock... 2704 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config); 2705 if (status == B_OK) { 2706 fLink.StartMessage(B_OK); 2707 fLink.Attach<frame_buffer_config>(config); 2708 } else 2709 fLink.StartMessage(status); 2710 2711 fLink.Flush(); 2712 break; 2713 } 2714 2715 case AS_GET_RETRACE_SEMAPHORE: 2716 { 2717 STRACE(("ServerApp %s: get retrace semaphore\n", Signature())); 2718 2719 // We aren't using the screen_id for now... 2720 int32 id; 2721 link.Read<int32>(&id); 2722 2723 fLink.StartMessage(B_OK); 2724 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore()); 2725 fLink.Flush(); 2726 break; 2727 } 2728 2729 case AS_GET_TIMING_CONSTRAINTS: 2730 { 2731 STRACE(("ServerApp %s: get timing constraints\n", Signature())); 2732 // We aren't using the screen_id for now... 2733 int32 id; 2734 link.Read<int32>(&id); 2735 2736 display_timing_constraints constraints; 2737 status_t status = fDesktop->HWInterface()->GetTimingConstraints( 2738 &constraints); 2739 if (status == B_OK) { 2740 fLink.StartMessage(B_OK); 2741 fLink.Attach<display_timing_constraints>(constraints); 2742 } else 2743 fLink.StartMessage(status); 2744 2745 fLink.Flush(); 2746 break; 2747 } 2748 2749 case AS_GET_PIXEL_CLOCK_LIMITS: 2750 { 2751 STRACE(("ServerApp %s: get pixel clock limits\n", Signature())); 2752 // We aren't using the screen_id for now... 2753 int32 id; 2754 link.Read<int32>(&id); 2755 display_mode mode; 2756 link.Read<display_mode>(&mode); 2757 2758 uint32 low, high; 2759 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode, 2760 &low, &high); 2761 if (status == B_OK) { 2762 fLink.StartMessage(B_OK); 2763 fLink.Attach<uint32>(low); 2764 fLink.Attach<uint32>(high); 2765 } else 2766 fLink.StartMessage(status); 2767 2768 fLink.Flush(); 2769 break; 2770 } 2771 2772 case AS_SET_DPMS: 2773 { 2774 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature())); 2775 int32 id; 2776 link.Read<int32>(&id); 2777 2778 uint32 mode; 2779 link.Read<uint32>(&mode); 2780 2781 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode); 2782 fLink.StartMessage(status); 2783 2784 fLink.Flush(); 2785 break; 2786 } 2787 2788 case AS_GET_DPMS_STATE: 2789 { 2790 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature())); 2791 2792 int32 id; 2793 link.Read<int32>(&id); 2794 2795 uint32 state = fDesktop->HWInterface()->DPMSMode(); 2796 fLink.StartMessage(B_OK); 2797 fLink.Attach<uint32>(state); 2798 fLink.Flush(); 2799 break; 2800 } 2801 2802 case AS_GET_DPMS_CAPABILITIES: 2803 { 2804 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature())); 2805 int32 id; 2806 link.Read<int32>(&id); 2807 2808 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities(); 2809 fLink.StartMessage(B_OK); 2810 fLink.Attach<uint32>(capabilities); 2811 fLink.Flush(); 2812 break; 2813 } 2814 2815 case AS_READ_BITMAP: 2816 { 2817 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature())); 2818 int32 token; 2819 link.Read<int32>(&token); 2820 2821 bool drawCursor = true; 2822 link.Read<bool>(&drawCursor); 2823 2824 BRect bounds; 2825 link.Read<BRect>(&bounds); 2826 2827 ServerBitmap* bitmap = GetBitmap(token); 2828 if (bitmap != NULL) { 2829 if (fDesktop->GetDrawingEngine()->ReadBitmap(bitmap, 2830 drawCursor, bounds) == B_OK) { 2831 fLink.StartMessage(B_OK); 2832 } else 2833 fLink.StartMessage(B_BAD_VALUE); 2834 2835 bitmap->ReleaseReference(); 2836 } else 2837 fLink.StartMessage(B_BAD_VALUE); 2838 2839 fLink.Flush(); 2840 break; 2841 } 2842 2843 case AS_GET_ACCELERANT_PATH: 2844 { 2845 int32 id; 2846 fLink.Read<int32>(&id); 2847 2848 BString path; 2849 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path); 2850 fLink.StartMessage(status); 2851 if (status == B_OK) 2852 fLink.AttachString(path.String()); 2853 2854 fLink.Flush(); 2855 break; 2856 } 2857 2858 case AS_GET_DRIVER_PATH: 2859 { 2860 int32 id; 2861 fLink.Read<int32>(&id); 2862 2863 BString path; 2864 status_t status = fDesktop->HWInterface()->GetDriverPath(path); 2865 fLink.StartMessage(status); 2866 if (status == B_OK) 2867 fLink.AttachString(path.String()); 2868 2869 fLink.Flush(); 2870 break; 2871 } 2872 2873 // BWindowScreen communication 2874 2875 case AS_DIRECT_SCREEN_LOCK: 2876 { 2877 bool lock; 2878 link.Read<bool>(&lock); 2879 2880 status_t status; 2881 if (lock) 2882 status = fDesktop->LockDirectScreen(ClientTeam()); 2883 else 2884 status = fDesktop->UnlockDirectScreen(ClientTeam()); 2885 2886 fLink.StartMessage(status); 2887 fLink.Flush(); 2888 break; 2889 } 2890 2891 // Hinting and aliasing 2892 2893 case AS_SET_SUBPIXEL_ANTIALIASING: 2894 { 2895 bool subpix; 2896 if (link.Read<bool>(&subpix) == B_OK) { 2897 LockedDesktopSettings settings(fDesktop); 2898 settings.SetSubpixelAntialiasing(subpix); 2899 } 2900 fDesktop->Redraw(); 2901 break; 2902 } 2903 2904 case AS_GET_SUBPIXEL_ANTIALIASING: 2905 { 2906 DesktopSettings settings(fDesktop); 2907 fLink.StartMessage(B_OK); 2908 fLink.Attach<bool>(settings.SubpixelAntialiasing()); 2909 fLink.Flush(); 2910 break; 2911 } 2912 2913 case AS_SET_HINTING: 2914 { 2915 uint8 hinting; 2916 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) { 2917 LockedDesktopSettings settings(fDesktop); 2918 if (hinting != settings.Hinting()) { 2919 settings.SetHinting(hinting); 2920 fDesktop->Redraw(); 2921 } 2922 } 2923 break; 2924 } 2925 2926 case AS_GET_HINTING: 2927 { 2928 DesktopSettings settings(fDesktop); 2929 fLink.StartMessage(B_OK); 2930 fLink.Attach<uint8>(settings.Hinting()); 2931 fLink.Flush(); 2932 break; 2933 } 2934 2935 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: 2936 { 2937 uint8 averageWeight; 2938 if (link.Read<uint8>(&averageWeight) == B_OK) { 2939 LockedDesktopSettings settings(fDesktop); 2940 settings.SetSubpixelAverageWeight(averageWeight); 2941 } 2942 fDesktop->Redraw(); 2943 break; 2944 } 2945 2946 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: 2947 { 2948 DesktopSettings settings(fDesktop); 2949 fLink.StartMessage(B_OK); 2950 fLink.Attach<uint8>(settings.SubpixelAverageWeight()); 2951 fLink.Flush(); 2952 break; 2953 } 2954 2955 case AS_SET_SUBPIXEL_ORDERING: 2956 { 2957 bool subpixelOrdering; 2958 if (link.Read<bool>(&subpixelOrdering) == B_OK) { 2959 LockedDesktopSettings settings(fDesktop); 2960 settings.SetSubpixelOrderingRegular(subpixelOrdering); 2961 } 2962 fDesktop->Redraw(); 2963 break; 2964 } 2965 2966 case AS_GET_SUBPIXEL_ORDERING: 2967 { 2968 DesktopSettings settings(fDesktop); 2969 fLink.StartMessage(B_OK); 2970 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular()); 2971 fLink.Flush(); 2972 break; 2973 } 2974 2975 default: 2976 printf("ServerApp %s received unhandled message code %ld\n", 2977 Signature(), code); 2978 2979 if (link.NeedsReply()) { 2980 // the client is now blocking and waiting for a reply! 2981 fLink.StartMessage(B_ERROR); 2982 fLink.Flush(); 2983 } else 2984 puts("message doesn't need a reply!"); 2985 break; 2986 } 2987 } 2988 2989 2990 /*! \brief The thread function ServerApps use to monitor messages 2991 */ 2992 void 2993 ServerApp::_MessageLooper() 2994 { 2995 // Message-dispatching loop for the ServerApp 2996 2997 // get our own team ID 2998 thread_info threadInfo; 2999 get_thread_info(fThread, &threadInfo); 3000 3001 // First let's tell the client how to talk with us. 3002 fLink.StartMessage(B_OK); 3003 fLink.Attach<port_id>(fMessagePort); 3004 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea()); 3005 fLink.Attach<team_id>(threadInfo.team); 3006 fLink.Flush(); 3007 3008 BPrivate::LinkReceiver &receiver = fLink.Receiver(); 3009 3010 int32 code; 3011 status_t err = B_OK; 3012 3013 while (!fQuitting) { 3014 STRACE(("info: ServerApp::_MessageLooper() listening on port %ld.\n", 3015 fMessagePort)); 3016 3017 err = receiver.GetNextMessage(code, B_INFINITE_TIMEOUT); 3018 if (err != B_OK || code == B_QUIT_REQUESTED) { 3019 STRACE(("ServerApp: application seems to be gone...\n")); 3020 3021 // Tell desktop to quit us 3022 BPrivate::LinkSender link(fDesktop->MessagePort()); 3023 link.StartMessage(AS_DELETE_APP); 3024 link.Attach<thread_id>(Thread()); 3025 link.Flush(); 3026 break; 3027 } 3028 3029 switch (code) { 3030 case kMsgAppQuit: 3031 // we receive this from our destructor on quit 3032 fQuitting = true; 3033 break; 3034 3035 case AS_QUIT_APP: 3036 { 3037 // This message is received only when the app_server is asked 3038 // to shut down in test/debug mode. Of course, if we are testing 3039 // while using AccelerantDriver, we do NOT want to shut down 3040 // client applications. The server can be quit in this fashion 3041 // through the driver's interface, such as closing the 3042 // ViewDriver's window. 3043 3044 STRACE(("ServerApp %s:Server shutdown notification received\n", 3045 Signature())); 3046 3047 // If we are using the real, accelerated version of the 3048 // DrawingEngine, we do NOT want the user to be able shut down 3049 // the server. The results would NOT be pretty 3050 #if TEST_MODE 3051 BMessage pleaseQuit(B_QUIT_REQUESTED); 3052 SendMessageToClient(&pleaseQuit); 3053 #endif 3054 break; 3055 } 3056 3057 default: 3058 STRACE(("ServerApp %s: Got a Message to dispatch\n", 3059 Signature())); 3060 _DispatchMessage(code, receiver); 3061 break; 3062 } 3063 } 3064 3065 // Quit() will send us a message; we're handling the exiting procedure 3066 thread_id sender; 3067 sem_id shutdownSemaphore; 3068 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id)); 3069 3070 delete this; 3071 3072 if (shutdownSemaphore >= B_OK) 3073 release_sem(shutdownSemaphore); 3074 } 3075 3076 3077 status_t 3078 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link, 3079 port_id& clientReplyPort) 3080 { 3081 // Attached data: 3082 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) 3083 // 2) BRect window frame 3084 // 3) uint32 window look 3085 // 4) uint32 window feel 3086 // 5) uint32 window flags 3087 // 6) uint32 workspace index 3088 // 7) int32 BHandler token of the window 3089 // 8) port_id window's reply port 3090 // 9) port_id window's looper port 3091 // 10) const char * title 3092 3093 BRect frame; 3094 int32 bitmapToken; 3095 uint32 look; 3096 uint32 feel; 3097 uint32 flags; 3098 uint32 workspaces; 3099 int32 token; 3100 port_id looperPort; 3101 char* title; 3102 3103 if (code == AS_CREATE_OFFSCREEN_WINDOW) 3104 link.Read<int32>(&bitmapToken); 3105 3106 link.Read<BRect>(&frame); 3107 link.Read<uint32>(&look); 3108 link.Read<uint32>(&feel); 3109 link.Read<uint32>(&flags); 3110 link.Read<uint32>(&workspaces); 3111 link.Read<int32>(&token); 3112 link.Read<port_id>(&clientReplyPort); 3113 link.Read<port_id>(&looperPort); 3114 if (link.ReadString(&title) != B_OK) 3115 return B_ERROR; 3116 3117 if (!frame.IsValid()) { 3118 // make sure we pass a valid rectangle to ServerWindow 3119 frame.right = frame.left + 1; 3120 frame.bottom = frame.top + 1; 3121 } 3122 3123 status_t status = B_NO_MEMORY; 3124 ServerWindow *window = NULL; 3125 3126 if (code == AS_CREATE_OFFSCREEN_WINDOW) { 3127 ServerBitmap* bitmap = GetBitmap(bitmapToken); 3128 3129 if (bitmap != NULL) { 3130 window = new (nothrow) OffscreenServerWindow(title, this, 3131 clientReplyPort, looperPort, token, bitmap); 3132 } else 3133 status = B_ERROR; 3134 } else { 3135 window = new (nothrow) ServerWindow(title, this, clientReplyPort, 3136 looperPort, token); 3137 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n", 3138 Signature(), title, frame.left, frame.top, 3139 frame.right, frame.bottom)); 3140 } 3141 3142 free(title); 3143 3144 // NOTE: the reply to the client is handled in ServerWindow::Run() 3145 if (window != NULL) { 3146 status = window->Init(frame, (window_look)look, (window_feel)feel, 3147 flags, workspaces); 3148 if (status == B_OK && !window->Run()) { 3149 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run the " 3150 "window thread\n"); 3151 status = B_ERROR; 3152 } 3153 3154 if (status != B_OK) 3155 delete window; 3156 } 3157 3158 return status; 3159 } 3160 3161 3162 bool 3163 ServerApp::_HasWindowUnderMouse() 3164 { 3165 BAutolock locker(fWindowListLock); 3166 3167 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 3168 ServerWindow* serverWindow = fWindowList.ItemAt(i); 3169 3170 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN) 3171 return true; 3172 } 3173 3174 return false; 3175 } 3176 3177 3178 bool 3179 ServerApp::_AddBitmap(ServerBitmap* bitmap) 3180 { 3181 BAutolock _(fMapLocker); 3182 3183 try { 3184 fBitmapMap.insert(std::make_pair(bitmap->Token(), bitmap)); 3185 } catch (std::bad_alloc& exception) { 3186 return false; 3187 } 3188 3189 bitmap->SetOwner(this); 3190 return true; 3191 } 3192 3193 3194 void 3195 ServerApp::_DeleteBitmap(ServerBitmap* bitmap) 3196 { 3197 ASSERT(fMapLocker.IsLocked()); 3198 3199 gBitmapManager->BitmapRemoved(bitmap); 3200 fBitmapMap.erase(bitmap->Token()); 3201 3202 bitmap->ReleaseReference(); 3203 } 3204 3205 3206 ServerBitmap* 3207 ServerApp::_FindBitmap(int32 token) const 3208 { 3209 ASSERT(fMapLocker.IsLocked()); 3210 3211 BitmapMap::const_iterator iterator = fBitmapMap.find(token); 3212 if (iterator == fBitmapMap.end()) 3213 return NULL; 3214 3215 return iterator->second; 3216 } 3217 3218 3219 ServerPicture* 3220 ServerApp::_FindPicture(int32 token) const 3221 { 3222 ASSERT(fMapLocker.IsLocked()); 3223 3224 PictureMap::const_iterator iterator = fPictureMap.find(token); 3225 if (iterator == fPictureMap.end()) 3226 return NULL; 3227 3228 return iterator->second; 3229 } 3230