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