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