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