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