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