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_CREATE_CURSOR_BITMAP: 1239 { 1240 STRACE(("ServerApp %s: Create Cursor bitmap\n", Signature())); 1241 1242 status_t status = B_ERROR; 1243 1244 int32 size = 0; 1245 BRect cursorRect; 1246 color_space colorspace = B_RGBA32; 1247 BPoint hotspot; 1248 ServerCursor* cursor = NULL; 1249 1250 if (link.Read<int32>(&size) == B_OK 1251 && link.Read<BRect>(&cursorRect) == B_OK 1252 && link.Read<color_space>(&colorspace) == B_OK 1253 && link.Read<BPoint>(&hotspot) == B_OK 1254 && size > 0) { 1255 1256 BStackOrHeapArray<uint8, 256> byteArray(size); 1257 if (!byteArray.IsValid()) { 1258 status = B_NO_MEMORY; 1259 } else if (link.Read(byteArray, size) == B_OK) { 1260 cursor = fDesktop->GetCursorManager().CreateCursor( 1261 fClientTeam, cursorRect, colorspace, 0, hotspot); 1262 if (cursor == NULL) 1263 status = B_NO_MEMORY; 1264 else 1265 memcpy(cursor->Bits(), byteArray, size); 1266 } 1267 } 1268 1269 if (cursor != NULL) { 1270 // Synchronous message - BApplication is waiting on the 1271 // cursor's ID 1272 fLink.StartMessage(B_OK); 1273 fLink.Attach<int32>(cursor->Token()); 1274 } else 1275 fLink.StartMessage(status); 1276 1277 fLink.Flush(); 1278 break; 1279 } 1280 1281 case AS_REFERENCE_CURSOR: 1282 { 1283 STRACE(("ServerApp %s: Reference BCursor\n", Signature())); 1284 1285 // Attached data: 1286 // 1) int32 token ID of the cursor to reference 1287 1288 int32 token; 1289 if (link.Read<int32>(&token) != B_OK) 1290 break; 1291 1292 if (!fDesktop->GetCursorManager().Lock()) 1293 break; 1294 1295 ServerCursor* cursor 1296 = fDesktop->GetCursorManager().FindCursor(token); 1297 if (cursor != NULL) 1298 cursor->AcquireReference(); 1299 1300 fDesktop->GetCursorManager().Unlock(); 1301 1302 break; 1303 } 1304 1305 case AS_DELETE_CURSOR: 1306 { 1307 STRACE(("ServerApp %s: Delete BCursor\n", Signature())); 1308 1309 // Attached data: 1310 // 1) int32 token ID of the cursor to delete 1311 1312 int32 token; 1313 if (link.Read<int32>(&token) != B_OK) 1314 break; 1315 1316 if (!fDesktop->GetCursorManager().Lock()) 1317 break; 1318 1319 ServerCursor* cursor 1320 = fDesktop->GetCursorManager().FindCursor(token); 1321 if (cursor != NULL) 1322 cursor->ReleaseReference(); 1323 1324 fDesktop->GetCursorManager().Unlock(); 1325 1326 break; 1327 } 1328 1329 case AS_GET_CURSOR_POSITION: 1330 { 1331 STRACE(("ServerApp %s: Get Cursor position\n", Signature())); 1332 1333 // Returns 1334 // 1) BPoint mouse location 1335 // 2) int32 button state 1336 1337 BPoint where; 1338 int32 buttons; 1339 fDesktop->GetLastMouseState(&where, &buttons); 1340 fLink.StartMessage(B_OK); 1341 fLink.Attach<BPoint>(where); 1342 fLink.Attach<int32>(buttons); 1343 fLink.Flush(); 1344 break; 1345 } 1346 1347 case AS_GET_CURSOR_BITMAP: 1348 { 1349 STRACE(("ServerApp %s: Get Cursor bitmap\n", Signature())); 1350 1351 // Returns 1352 // 1) uint32 number of data bytes of the bitmap 1353 // 2) uint32 cursor width in number of pixels 1354 // 3) uint32 cursor height in number of pixels 1355 // 4) BPoint cursor hot spot 1356 // 5) cursor bitmap data 1357 1358 ServerCursorReference cursorRef = fDesktop->Cursor(); 1359 ServerCursor* cursor = cursorRef.Get(); 1360 if (cursor != NULL) { 1361 uint32 size = cursor->BitsLength(); 1362 fLink.StartMessage(B_OK); 1363 fLink.Attach<uint32>(size); 1364 fLink.Attach<uint32>(cursor->Width()); 1365 fLink.Attach<uint32>(cursor->Height()); 1366 fLink.Attach<color_space>(cursor->ColorSpace()); 1367 fLink.Attach<BPoint>(cursor->GetHotSpot()); 1368 fLink.Attach(cursor->Bits(), size); 1369 } else 1370 fLink.StartMessage(B_ERROR); 1371 1372 fLink.Flush(); 1373 1374 break; 1375 } 1376 1377 case AS_GET_SCROLLBAR_INFO: 1378 { 1379 STRACE(("ServerApp %s: Get ScrollBar info\n", Signature())); 1380 1381 if (fDesktop->LockSingleWindow()) { 1382 scroll_bar_info info; 1383 DesktopSettings settings(fDesktop); 1384 settings.GetScrollBarInfo(info); 1385 1386 fLink.StartMessage(B_OK); 1387 fLink.Attach<scroll_bar_info>(info); 1388 fDesktop->UnlockSingleWindow(); 1389 } else 1390 fLink.StartMessage(B_ERROR); 1391 1392 fLink.Flush(); 1393 break; 1394 } 1395 1396 case AS_SET_SCROLLBAR_INFO: 1397 { 1398 STRACE(("ServerApp %s: Set ScrollBar info\n", Signature())); 1399 1400 // Attached Data: 1401 // 1) scroll_bar_info scroll bar info structure 1402 1403 scroll_bar_info info; 1404 if (link.Read<scroll_bar_info>(&info) == B_OK) { 1405 LockedDesktopSettings settings(fDesktop); 1406 settings.SetScrollBarInfo(info); 1407 } 1408 1409 fLink.StartMessage(B_OK); 1410 fLink.Flush(); 1411 break; 1412 } 1413 1414 case AS_GET_MENU_INFO: 1415 { 1416 STRACE(("ServerApp %s: Get menu info\n", Signature())); 1417 if (fDesktop->LockSingleWindow()) { 1418 menu_info info; 1419 DesktopSettings settings(fDesktop); 1420 settings.GetMenuInfo(info); 1421 1422 fLink.StartMessage(B_OK); 1423 fLink.Attach<menu_info>(info); 1424 1425 fDesktop->UnlockSingleWindow(); 1426 } else 1427 fLink.StartMessage(B_ERROR); 1428 1429 fLink.Flush(); 1430 break; 1431 } 1432 1433 case AS_SET_MENU_INFO: 1434 { 1435 STRACE(("ServerApp %s: Set menu info\n", Signature())); 1436 menu_info info; 1437 if (link.Read<menu_info>(&info) == B_OK) { 1438 LockedDesktopSettings settings(fDesktop); 1439 settings.SetMenuInfo(info); 1440 // TODO: SetMenuInfo() should do some validity check, so 1441 // that the answer we're giving can actually be useful 1442 } 1443 1444 fLink.StartMessage(B_OK); 1445 fLink.Flush(); 1446 break; 1447 } 1448 1449 case AS_SET_MOUSE_MODE: 1450 { 1451 STRACE(("ServerApp %s: Set Mouse Focus mode\n", 1452 Signature())); 1453 1454 // Attached Data: 1455 // 1) enum mode_mouse mouse focus mode 1456 1457 mode_mouse mouseMode; 1458 if (link.Read<mode_mouse>(&mouseMode) == B_OK) { 1459 LockedDesktopSettings settings(fDesktop); 1460 settings.SetMouseMode(mouseMode); 1461 } 1462 break; 1463 } 1464 1465 case AS_GET_MOUSE_MODE: 1466 { 1467 STRACE(("ServerApp %s: Get Mouse Focus mode\n", 1468 Signature())); 1469 1470 if (fDesktop->LockSingleWindow()) { 1471 DesktopSettings settings(fDesktop); 1472 1473 fLink.StartMessage(B_OK); 1474 fLink.Attach<mode_mouse>(settings.MouseMode()); 1475 1476 fDesktop->UnlockSingleWindow(); 1477 } else 1478 fLink.StartMessage(B_ERROR); 1479 1480 fLink.Flush(); 1481 break; 1482 } 1483 1484 case AS_SET_FOCUS_FOLLOWS_MOUSE_MODE: 1485 { 1486 STRACE(("ServerApp %s: Set Focus Follows Mouse mode\n", Signature())); 1487 1488 // Attached Data: 1489 // 1) enum mode_focus_follows_mouse FFM mouse mode 1490 1491 mode_focus_follows_mouse focusFollowsMousMode; 1492 if (link.Read<mode_focus_follows_mouse>(&focusFollowsMousMode) == B_OK) { 1493 LockedDesktopSettings settings(fDesktop); 1494 settings.SetFocusFollowsMouseMode(focusFollowsMousMode); 1495 } 1496 break; 1497 } 1498 1499 case AS_GET_FOCUS_FOLLOWS_MOUSE_MODE: 1500 { 1501 STRACE(("ServerApp %s: Get Focus Follows Mouse mode\n", Signature())); 1502 1503 if (fDesktop->LockSingleWindow()) { 1504 DesktopSettings settings(fDesktop); 1505 1506 fLink.StartMessage(B_OK); 1507 fLink.Attach<mode_focus_follows_mouse>( 1508 settings.FocusFollowsMouseMode()); 1509 1510 fDesktop->UnlockSingleWindow(); 1511 } else 1512 fLink.StartMessage(B_ERROR); 1513 1514 fLink.Flush(); 1515 break; 1516 } 1517 1518 case AS_SET_ACCEPT_FIRST_CLICK: 1519 { 1520 STRACE(("ServerApp %s: Set Accept First Click\n", Signature())); 1521 1522 // Attached Data: 1523 // 1) bool accept_first_click 1524 1525 bool acceptFirstClick; 1526 if (link.Read<bool>(&acceptFirstClick) == B_OK) { 1527 LockedDesktopSettings settings(fDesktop); 1528 settings.SetAcceptFirstClick(acceptFirstClick); 1529 } 1530 break; 1531 } 1532 1533 case AS_GET_ACCEPT_FIRST_CLICK: 1534 { 1535 STRACE(("ServerApp %s: Get Accept First Click\n", Signature())); 1536 1537 if (fDesktop->LockSingleWindow()) { 1538 DesktopSettings settings(fDesktop); 1539 1540 fLink.StartMessage(B_OK); 1541 fLink.Attach<bool>(settings.AcceptFirstClick()); 1542 1543 fDesktop->UnlockSingleWindow(); 1544 } else 1545 fLink.StartMessage(B_ERROR); 1546 1547 fLink.Flush(); 1548 break; 1549 } 1550 1551 case AS_GET_SHOW_ALL_DRAGGERS: 1552 { 1553 STRACE(("ServerApp %s: Get Show All Draggers\n", Signature())); 1554 1555 if (fDesktop->LockSingleWindow()) { 1556 DesktopSettings settings(fDesktop); 1557 1558 fLink.StartMessage(B_OK); 1559 fLink.Attach<bool>(settings.ShowAllDraggers()); 1560 1561 fDesktop->UnlockSingleWindow(); 1562 } else 1563 fLink.StartMessage(B_ERROR); 1564 1565 fLink.Flush(); 1566 break; 1567 } 1568 1569 case AS_SET_SHOW_ALL_DRAGGERS: 1570 { 1571 STRACE(("ServerApp %s: Set Show All Draggers\n", Signature())); 1572 1573 bool changed = false; 1574 bool show; 1575 if (link.Read<bool>(&show) == B_OK) { 1576 LockedDesktopSettings settings(fDesktop); 1577 if (show != settings.ShowAllDraggers()) { 1578 settings.SetShowAllDraggers(show); 1579 changed = true; 1580 } 1581 } 1582 1583 if (changed) 1584 fDesktop->BroadcastToAllApps(kMsgUpdateShowAllDraggers); 1585 break; 1586 } 1587 1588 case kMsgUpdateShowAllDraggers: 1589 { 1590 bool show = false; 1591 if (fDesktop->LockSingleWindow()) { 1592 DesktopSettings settings(fDesktop); 1593 show = settings.ShowAllDraggers(); 1594 fDesktop->UnlockSingleWindow(); 1595 } 1596 BMessage update(_SHOW_DRAG_HANDLES_); 1597 update.AddBool("show", show); 1598 1599 SendMessageToClient(&update); 1600 break; 1601 } 1602 1603 /* font messages */ 1604 1605 case AS_SET_SYSTEM_FONT: 1606 { 1607 FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature())); 1608 // gets: 1609 // 1) string - font type ("plain", ...) 1610 // 2) string - family 1611 // 3) string - style 1612 // 4) float - size 1613 1614 char type[B_OS_NAME_LENGTH]; 1615 font_family familyName; 1616 font_style styleName; 1617 float size; 1618 1619 if (link.ReadString(type, sizeof(type)) == B_OK 1620 && link.ReadString(familyName, sizeof(familyName)) == B_OK 1621 && link.ReadString(styleName, sizeof(styleName)) == B_OK 1622 && link.Read<float>(&size) == B_OK) { 1623 gFontManager->Lock(); 1624 1625 FontStyle* style 1626 = gFontManager->GetStyle(familyName, styleName); 1627 if (style != NULL) { 1628 ServerFont font(*style, size); 1629 gFontManager->Unlock(); 1630 // We must not have locked the font manager when 1631 // locking the desktop (through LockedDesktopSettings 1632 // below) 1633 1634 LockedDesktopSettings settings(fDesktop); 1635 1636 // TODO: Should we also update our internal copies now? 1637 if (strcmp(type, "plain") == 0) 1638 settings.SetDefaultPlainFont(font); 1639 else if (strcmp(type, "bold") == 0) 1640 settings.SetDefaultBoldFont(font); 1641 else if (strcmp(type, "fixed") == 0) 1642 settings.SetDefaultFixedFont(font); 1643 } else 1644 gFontManager->Unlock(); 1645 } 1646 break; 1647 } 1648 1649 case AS_GET_SYSTEM_DEFAULT_FONT: 1650 { 1651 // input: 1652 // 1) string - font type ("plain", ...) 1653 1654 ServerFont font; 1655 1656 char type[B_OS_NAME_LENGTH]; 1657 status_t status = link.ReadString(type, sizeof(type)); 1658 if (status == B_OK) { 1659 if (!strcmp(type, "plain")) { 1660 font = *gFontManager->DefaultPlainFont(); 1661 } else if (!strcmp(type, "bold")) { 1662 font = *gFontManager->DefaultBoldFont(); 1663 } else if (!strcmp(type, "fixed")) { 1664 font = *gFontManager->DefaultFixedFont(); 1665 } else 1666 status = B_BAD_VALUE; 1667 } 1668 1669 if (status == B_OK) { 1670 // returns: 1671 // 1) string - family 1672 // 2) string - style 1673 // 3) float - size 1674 1675 fLink.StartMessage(B_OK); 1676 fLink.AttachString(font.Family()); 1677 fLink.AttachString(font.Style()); 1678 fLink.Attach<float>(font.Size()); 1679 } else 1680 fLink.StartMessage(status); 1681 1682 fLink.Flush(); 1683 break; 1684 } 1685 1686 case AS_GET_SYSTEM_FONTS: 1687 { 1688 FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature())); 1689 // Returns: 1690 // 1) uint16 - family ID 1691 // 2) uint16 - style ID 1692 // 3) float - size in points 1693 // 4) uint16 - face flags 1694 // 5) uint32 - font flags 1695 1696 if (!fDesktop->LockSingleWindow()) { 1697 fLink.StartMessage(B_OK); 1698 fLink.Flush(); 1699 break; 1700 } 1701 1702 // The client is requesting the system fonts, this 1703 // could happend either at application start up, or 1704 // because the client is resyncing with the global 1705 // fonts. So we record the current system wide fonts 1706 // into our own copies at this point. 1707 DesktopSettings settings(fDesktop); 1708 1709 settings.GetDefaultPlainFont(fPlainFont); 1710 settings.GetDefaultBoldFont(fBoldFont); 1711 settings.GetDefaultFixedFont(fFixedFont); 1712 1713 fLink.StartMessage(B_OK); 1714 1715 for (int32 i = 0; i < 3; i++) { 1716 ServerFont* font = NULL; 1717 switch (i) { 1718 case 0: 1719 font = &fPlainFont; 1720 fLink.AttachString("plain"); 1721 break; 1722 1723 case 1: 1724 font = &fBoldFont; 1725 fLink.AttachString("bold"); 1726 break; 1727 1728 case 2: 1729 font = &fFixedFont; 1730 fLink.AttachString("fixed"); 1731 break; 1732 } 1733 1734 fLink.Attach<uint16>(font->FamilyID()); 1735 fLink.Attach<uint16>(font->StyleID()); 1736 fLink.Attach<float>(font->Size()); 1737 fLink.Attach<uint16>(font->Face()); 1738 fLink.Attach<uint32>(font->Flags()); 1739 } 1740 1741 fDesktop->UnlockSingleWindow(); 1742 fLink.Flush(); 1743 break; 1744 } 1745 1746 case AS_GET_FONT_LIST_REVISION: 1747 { 1748 STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature())); 1749 1750 fLink.StartMessage(B_OK); 1751 fLink.Attach<int32>( 1752 gFontManager->CheckRevision(fDesktop->UserID())); 1753 fLink.Flush(); 1754 break; 1755 } 1756 1757 case AS_GET_FAMILY_AND_STYLES: 1758 { 1759 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature())); 1760 1761 // Attached Data: 1762 // 1) int32 the index of the font family to get 1763 1764 // Returns: 1765 // 1) string - name of family 1766 // 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT) 1767 // 3) count of styles in that family 1768 // For each style: 1769 // 1) string - name of style 1770 // 2) uint16 - face of style 1771 // 3) uint32 - flags of style 1772 1773 int32 index; 1774 link.Read<int32>(&index); 1775 1776 gFontManager->Lock(); 1777 1778 FontFamily* family = gFontManager->FamilyAt(index); 1779 if (family) { 1780 fLink.StartMessage(B_OK); 1781 fLink.AttachString(family->Name()); 1782 fLink.Attach<uint32>(family->Flags()); 1783 1784 int32 count = family->CountStyles(); 1785 fLink.Attach<int32>(count); 1786 1787 for (int32 i = 0; i < count; i++) { 1788 FontStyle* style = family->StyleAt(i); 1789 1790 fLink.AttachString(style->Name()); 1791 fLink.Attach<uint16>(style->Face()); 1792 fLink.Attach<uint32>(style->Flags()); 1793 } 1794 } else 1795 fLink.StartMessage(B_BAD_VALUE); 1796 1797 gFontManager->Unlock(); 1798 fLink.Flush(); 1799 break; 1800 } 1801 1802 case AS_GET_FAMILY_AND_STYLE: 1803 { 1804 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE\n", Signature())); 1805 1806 // Attached Data: 1807 // 1) uint16 - family ID 1808 // 2) uint16 - style ID 1809 1810 // Returns: 1811 // 1) font_family The name of the font family 1812 // 2) font_style - name of the style 1813 1814 uint16 familyID, styleID; 1815 link.Read<uint16>(&familyID); 1816 link.Read<uint16>(&styleID); 1817 1818 gFontManager->Lock(); 1819 1820 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1821 if (fontStyle != NULL) { 1822 fLink.StartMessage(B_OK); 1823 fLink.AttachString(fontStyle->Family()->Name()); 1824 fLink.AttachString(fontStyle->Name()); 1825 } else 1826 fLink.StartMessage(B_BAD_VALUE); 1827 1828 fLink.Flush(); 1829 gFontManager->Unlock(); 1830 break; 1831 } 1832 1833 case AS_GET_FAMILY_AND_STYLE_IDS: 1834 { 1835 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE_IDS\n", 1836 Signature())); 1837 1838 // Attached Data: 1839 // 1) font_family - name of font family to use 1840 // 2) font_style - name of style in family 1841 // 3) family ID - only used if 1) is empty 1842 // 4) style ID - only used if 2) is empty 1843 // 5) face - the font's current face 1844 1845 // Returns: 1846 // 1) uint16 - family ID 1847 // 2) uint16 - style ID 1848 // 3) uint16 - face 1849 1850 font_family family; 1851 font_style style; 1852 uint16 familyID, styleID; 1853 uint16 face; 1854 if (link.ReadString(family, sizeof(font_family)) == B_OK 1855 && link.ReadString(style, sizeof(font_style)) == B_OK 1856 && link.Read<uint16>(&familyID) == B_OK 1857 && link.Read<uint16>(&styleID) == B_OK 1858 && link.Read<uint16>(&face) == B_OK) { 1859 // get the font and return IDs and face 1860 gFontManager->Lock(); 1861 1862 FontStyle *fontStyle = gFontManager->GetStyle(family, style, 1863 familyID, styleID, face); 1864 1865 if (fontStyle != NULL) { 1866 fLink.StartMessage(B_OK); 1867 fLink.Attach<uint16>(fontStyle->Family()->ID()); 1868 fLink.Attach<uint16>(fontStyle->ID()); 1869 1870 // we try to keep the font face close to what we got 1871 face = fontStyle->PreservedFace(face); 1872 1873 fLink.Attach<uint16>(face); 1874 } else 1875 fLink.StartMessage(B_NAME_NOT_FOUND); 1876 1877 gFontManager->Unlock(); 1878 } else 1879 fLink.StartMessage(B_BAD_VALUE); 1880 1881 fLink.Flush(); 1882 break; 1883 } 1884 1885 case AS_GET_FONT_FILE_FORMAT: 1886 { 1887 FTRACE(("ServerApp %s: AS_GET_FONT_FILE_FORMAT\n", Signature())); 1888 1889 // Attached Data: 1890 // 1) uint16 - family ID 1891 // 2) uint16 - style ID 1892 1893 // Returns: 1894 // 1) uint16 font_file_format of font 1895 1896 int32 familyID, styleID; 1897 link.Read<int32>(&familyID); 1898 link.Read<int32>(&styleID); 1899 1900 gFontManager->Lock(); 1901 1902 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1903 if (fontStyle) { 1904 fLink.StartMessage(B_OK); 1905 fLink.Attach<uint16>((uint16)fontStyle->FileFormat()); 1906 } else 1907 fLink.StartMessage(B_BAD_VALUE); 1908 1909 gFontManager->Unlock(); 1910 fLink.Flush(); 1911 break; 1912 } 1913 1914 case AS_GET_STRING_WIDTHS: 1915 { 1916 FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature())); 1917 1918 // Attached Data: 1919 // 1) uint16 ID of family 1920 // 2) uint16 ID of style 1921 // 3) float point size of font 1922 // 4) uint8 spacing to use 1923 // 5) int32 numStrings 1924 // 6) int32 string length to measure (numStrings times) 1925 // 7) string String to measure (numStrings times) 1926 1927 // Returns: 1928 // 1) float - width of the string in pixels (numStrings times) 1929 1930 uint16 family, style; 1931 float size; 1932 uint8 spacing; 1933 1934 link.Read<uint16>(&family); 1935 link.Read<uint16>(&style); 1936 link.Read<float>(&size); 1937 link.Read<uint8>(&spacing); 1938 int32 numStrings; 1939 if (link.Read<int32>(&numStrings) != B_OK) { 1940 // this results in a B_BAD_VALUE return 1941 numStrings = 0; 1942 size = 0.0f; 1943 } 1944 1945 BStackOrHeapArray<float, 64> widthArray(numStrings); 1946 BStackOrHeapArray<int32, 64> lengthArray(numStrings); 1947 BStackOrHeapArray<char*, 64> stringArray(numStrings); 1948 if (!widthArray.IsValid() || !lengthArray.IsValid() 1949 || !stringArray.IsValid()) { 1950 fLink.StartMessage(B_NO_MEMORY); 1951 fLink.Flush(); 1952 break; 1953 } 1954 1955 for (int32 i = 0; i < numStrings; i++) { 1956 // This version of ReadString allocates the strings, we free 1957 // them below 1958 link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]); 1959 } 1960 1961 ServerFont font; 1962 1963 if (font.SetFamilyAndStyle(family, style) == B_OK && size > 0) { 1964 font.SetSize(size); 1965 font.SetSpacing(spacing); 1966 1967 for (int32 i = 0; i < numStrings; i++) { 1968 if (!stringArray[i] || lengthArray[i] <= 0) 1969 widthArray[i] = 0.0; 1970 else { 1971 widthArray[i] = font.StringWidth(stringArray[i], 1972 lengthArray[i]); 1973 } 1974 } 1975 1976 fLink.StartMessage(B_OK); 1977 fLink.Attach(widthArray, numStrings * sizeof(float)); 1978 } else 1979 fLink.StartMessage(B_BAD_VALUE); 1980 1981 fLink.Flush(); 1982 1983 for (int32 i = 0; i < numStrings; i++) 1984 free(stringArray[i]); 1985 break; 1986 } 1987 1988 case AS_GET_FONT_BOUNDING_BOX: 1989 { 1990 FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX unimplemented\n", 1991 Signature())); 1992 1993 // Attached Data: 1994 // 1) uint16 - family ID 1995 // 2) uint16 - style ID 1996 1997 // Returns: 1998 // 1) BRect - box holding entire font 1999 2000 // ToDo: implement me! 2001 fLink.StartMessage(B_ERROR); 2002 fLink.Flush(); 2003 break; 2004 } 2005 2006 case AS_GET_TUNED_COUNT: 2007 { 2008 FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature())); 2009 2010 // Attached Data: 2011 // 1) uint16 - family ID 2012 // 2) uint16 - style ID 2013 2014 // Returns: 2015 // 1) int32 - number of font strikes available 2016 2017 uint16 familyID, styleID; 2018 link.Read<uint16>(&familyID); 2019 link.Read<uint16>(&styleID); 2020 2021 gFontManager->Lock(); 2022 2023 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2024 if (fontStyle != NULL) { 2025 fLink.StartMessage(B_OK); 2026 fLink.Attach<int32>(fontStyle->TunedCount()); 2027 } else 2028 fLink.StartMessage(B_BAD_VALUE); 2029 2030 gFontManager->Unlock(); 2031 fLink.Flush(); 2032 break; 2033 } 2034 2035 case AS_GET_TUNED_INFO: 2036 { 2037 FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n", 2038 Signature())); 2039 2040 // Attached Data: 2041 // 1) uint16 - family ID 2042 // 2) uint16 - style ID 2043 // 3) uint32 - index of the particular font strike 2044 2045 // Returns: 2046 // 1) tuned_font_info - info on the strike specified 2047 // ToDo: implement me! 2048 2049 fLink.StartMessage(B_ERROR); 2050 fLink.Flush(); 2051 break; 2052 } 2053 2054 case AS_GET_EXTRA_FONT_FLAGS: 2055 { 2056 FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n", 2057 Signature())); 2058 2059 // Attached Data: 2060 // 1) uint16 - family ID 2061 // 2) uint16 - style ID 2062 2063 // Returns: 2064 // 1) uint32 - extra font flags 2065 2066 uint16 familyID, styleID; 2067 link.Read<uint16>(&familyID); 2068 link.Read<uint16>(&styleID); 2069 2070 gFontManager->Lock(); 2071 2072 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2073 if (fontStyle != NULL) { 2074 fLink.StartMessage(B_OK); 2075 fLink.Attach<uint32>(fontStyle->Flags()); 2076 } else 2077 fLink.StartMessage(B_BAD_VALUE); 2078 2079 gFontManager->Unlock(); 2080 fLink.Flush(); 2081 break; 2082 } 2083 2084 case AS_GET_FONT_HEIGHT: 2085 { 2086 FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature())); 2087 2088 // Attached Data: 2089 // 1) uint16 family ID 2090 // 2) uint16 style ID 2091 // 3) float size 2092 2093 uint16 familyID, styleID; 2094 float size; 2095 link.Read<uint16>(&familyID); 2096 link.Read<uint16>(&styleID); 2097 link.Read<float>(&size); 2098 2099 gFontManager->Lock(); 2100 2101 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2102 if (fontStyle != NULL) { 2103 font_height height; 2104 fontStyle->GetHeight(size, height); 2105 2106 fLink.StartMessage(B_OK); 2107 fLink.Attach<font_height>(height); 2108 } else 2109 fLink.StartMessage(B_BAD_VALUE); 2110 2111 gFontManager->Unlock(); 2112 fLink.Flush(); 2113 break; 2114 } 2115 2116 case AS_GET_UNICODE_BLOCKS: 2117 { 2118 FTRACE(("ServerApp %s: AS_GET_UNICODE_BLOCKS\n", Signature())); 2119 2120 // Attached Data: 2121 // 1) uint16 family ID 2122 // 2) uint16 style ID 2123 2124 // Returns: 2125 // 1) unicode_block - bitfield of Unicode blocks in font 2126 2127 uint16 familyID, styleID; 2128 link.Read<uint16>(&familyID); 2129 link.Read<uint16>(&styleID); 2130 2131 ServerFont font; 2132 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2133 if (status == B_OK) { 2134 unicode_block blocksForFont; 2135 font.GetUnicodeBlocks(blocksForFont); 2136 2137 fLink.StartMessage(B_OK); 2138 fLink.Attach<unicode_block>(blocksForFont); 2139 } else 2140 fLink.StartMessage(status); 2141 2142 fLink.Flush(); 2143 break; 2144 } 2145 2146 case AS_GET_HAS_UNICODE_BLOCK: 2147 { 2148 FTRACE(("ServerApp %s: AS_INCLUDES_UNICODE_BLOCK\n", Signature())); 2149 2150 // Attached Data: 2151 // 1) uint16 family ID 2152 // 2) uint16 style ID 2153 // 3) uint32 start of unicode block 2154 // 4) uint32 end of unicode block 2155 2156 // Returns: 2157 // 1) bool - whether or not font includes specified block range 2158 2159 uint16 familyID, styleID; 2160 uint32 start, end; 2161 link.Read<uint16>(&familyID); 2162 link.Read<uint16>(&styleID); 2163 link.Read<uint32>(&start); 2164 link.Read<uint32>(&end); 2165 2166 ServerFont font; 2167 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2168 if (status == B_OK) { 2169 bool hasBlock; 2170 2171 status = font.IncludesUnicodeBlock(start, end, hasBlock); 2172 fLink.StartMessage(status); 2173 fLink.Attach<bool>(hasBlock); 2174 } else 2175 fLink.StartMessage(status); 2176 2177 fLink.Flush(); 2178 break; 2179 } 2180 2181 case AS_GET_GLYPH_SHAPES: 2182 { 2183 FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature())); 2184 2185 // Attached Data: 2186 // 1) uint16 - family ID 2187 // 2) uint16 - style ID 2188 // 3) float - point size 2189 // 4) float - shear 2190 // 5) float - rotation 2191 // 6) float - false bold width 2192 // 6) uint32 - flags 2193 // 7) int32 - numChars 2194 // 8) int32 - numBytes 2195 // 8) char - chars (numBytes times) 2196 2197 // Returns: 2198 // 1) BShape - glyph shape 2199 // numChars times 2200 2201 uint16 familyID, styleID; 2202 uint32 flags; 2203 float size, shear, rotation, falseBoldWidth; 2204 2205 link.Read<uint16>(&familyID); 2206 link.Read<uint16>(&styleID); 2207 link.Read<float>(&size); 2208 link.Read<float>(&shear); 2209 link.Read<float>(&rotation); 2210 link.Read<float>(&falseBoldWidth); 2211 link.Read<uint32>(&flags); 2212 2213 int32 numChars, numBytes; 2214 link.Read<int32>(&numChars); 2215 link.Read<int32>(&numBytes); 2216 2217 BStackOrHeapArray<char, 256> charArray(numBytes); 2218 BStackOrHeapArray<BShape*, 64> shapes(numChars); 2219 if (!charArray.IsValid() || !shapes.IsValid()) { 2220 fLink.StartMessage(B_NO_MEMORY); 2221 fLink.Flush(); 2222 break; 2223 } 2224 2225 link.Read(charArray, numBytes); 2226 2227 ServerFont font; 2228 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2229 if (status == B_OK) { 2230 font.SetSize(size); 2231 font.SetShear(shear); 2232 font.SetRotation(rotation); 2233 font.SetFalseBoldWidth(falseBoldWidth); 2234 font.SetFlags(flags); 2235 2236 status = font.GetGlyphShapes(charArray, numChars, shapes); 2237 if (status == B_OK) { 2238 fLink.StartMessage(B_OK); 2239 for (int32 i = 0; i < numChars; i++) { 2240 fLink.AttachShape(*shapes[i]); 2241 delete shapes[i]; 2242 } 2243 } 2244 } 2245 2246 if (status != B_OK) 2247 fLink.StartMessage(status); 2248 2249 fLink.Flush(); 2250 break; 2251 } 2252 2253 case AS_GET_HAS_GLYPHS: 2254 { 2255 FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature())); 2256 2257 // Attached Data: 2258 // 1) uint16 - family ID 2259 // 2) uint16 - style ID 2260 // 3) int32 - numChars 2261 // 4) int32 - numBytes 2262 // 5) char - the char buffer with size numBytes 2263 2264 uint16 familyID, styleID; 2265 link.Read<uint16>(&familyID); 2266 link.Read<uint16>(&styleID); 2267 2268 int32 numChars, numBytes; 2269 link.Read<int32>(&numChars); 2270 link.Read<int32>(&numBytes); 2271 2272 BStackOrHeapArray<char, 256> charArray(numBytes); 2273 BStackOrHeapArray<bool, 256> hasArray(numChars); 2274 if (!charArray.IsValid() || !hasArray.IsValid()) { 2275 fLink.StartMessage(B_NO_MEMORY); 2276 fLink.Flush(); 2277 break; 2278 } 2279 2280 link.Read(charArray, numBytes); 2281 2282 ServerFont font; 2283 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2284 if (status == B_OK) { 2285 status = font.GetHasGlyphs(charArray, numBytes, numChars, 2286 hasArray); 2287 if (status == B_OK) { 2288 fLink.StartMessage(B_OK); 2289 fLink.Attach(hasArray, numChars * sizeof(bool)); 2290 } 2291 } 2292 2293 if (status != B_OK) 2294 fLink.StartMessage(status); 2295 2296 fLink.Flush(); 2297 break; 2298 } 2299 2300 case AS_GET_EDGES: 2301 { 2302 FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature())); 2303 2304 // Attached Data: 2305 // 1) uint16 - family ID 2306 // 2) uint16 - style ID 2307 // 3) int32 - numChars 2308 // 4) int32 - numBytes 2309 // 5) char - the char buffer with size numBytes 2310 2311 uint16 familyID, styleID; 2312 link.Read<uint16>(&familyID); 2313 link.Read<uint16>(&styleID); 2314 2315 int32 numChars; 2316 link.Read<int32>(&numChars); 2317 2318 uint32 numBytes; 2319 link.Read<uint32>(&numBytes); 2320 2321 BStackOrHeapArray<char, 256> charArray(numBytes); 2322 BStackOrHeapArray<edge_info, 64> edgeArray(numChars); 2323 if (!charArray.IsValid() || !edgeArray.IsValid()) { 2324 fLink.StartMessage(B_NO_MEMORY); 2325 fLink.Flush(); 2326 break; 2327 } 2328 2329 link.Read(charArray, numBytes); 2330 2331 ServerFont font; 2332 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2333 if (status == B_OK) { 2334 status = font.GetEdges(charArray, numBytes, numChars, 2335 edgeArray); 2336 if (status == B_OK) { 2337 fLink.StartMessage(B_OK); 2338 fLink.Attach(edgeArray, numChars * sizeof(edge_info)); 2339 } 2340 } 2341 2342 if (status != B_OK) 2343 fLink.StartMessage(status); 2344 2345 fLink.Flush(); 2346 break; 2347 } 2348 2349 case AS_GET_ESCAPEMENTS: 2350 { 2351 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature())); 2352 2353 // Attached Data: 2354 // 1) uint16 - family ID 2355 // 2) uint16 - style ID 2356 // 3) float - point size 2357 // 4) uint8 - spacing 2358 // 5) float - rotation 2359 // 6) uint32 - flags 2360 // 7) int32 - numChars 2361 // 8) char - char -\ both 2362 // 9) BPoint - offset -/ (numChars times) 2363 2364 // Returns: 2365 // 1) BPoint - escapement 2366 // numChars times 2367 2368 uint16 familyID, styleID; 2369 uint32 flags; 2370 float size, rotation; 2371 uint8 spacing; 2372 2373 link.Read<uint16>(&familyID); 2374 link.Read<uint16>(&styleID); 2375 link.Read<float>(&size); 2376 link.Read<uint8>(&spacing); 2377 link.Read<float>(&rotation); 2378 link.Read<uint32>(&flags); 2379 2380 escapement_delta delta; 2381 link.Read<float>(&delta.nonspace); 2382 link.Read<float>(&delta.space); 2383 2384 bool wantsOffsets; 2385 link.Read<bool>(&wantsOffsets); 2386 2387 int32 numChars; 2388 link.Read<int32>(&numChars); 2389 2390 uint32 numBytes; 2391 link.Read<uint32>(&numBytes); 2392 2393 BStackOrHeapArray<char, 256> charArray(numBytes); 2394 BStackOrHeapArray<BPoint, 64> escapements(numChars); 2395 BPoint* offsets = NULL; 2396 if (wantsOffsets) 2397 offsets = new(std::nothrow) BPoint[numChars]; 2398 2399 if (!charArray.IsValid() || !escapements.IsValid() 2400 || (offsets == NULL && wantsOffsets)) { 2401 delete[] offsets; 2402 fLink.StartMessage(B_NO_MEMORY); 2403 fLink.Flush(); 2404 break; 2405 } 2406 2407 link.Read(charArray, numBytes); 2408 2409 ServerFont font; 2410 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2411 if (status == B_OK) { 2412 font.SetSize(size); 2413 font.SetSpacing(spacing); 2414 font.SetRotation(rotation); 2415 font.SetFlags(flags); 2416 2417 status = font.GetEscapements(charArray, numBytes, numChars, 2418 delta, escapements, offsets); 2419 2420 if (status == B_OK) { 2421 fLink.StartMessage(B_OK); 2422 for (int32 i = 0; i < numChars; i++) 2423 fLink.Attach<BPoint>(escapements[i]); 2424 2425 if (wantsOffsets) { 2426 for (int32 i = 0; i < numChars; i++) 2427 fLink.Attach<BPoint>(offsets[i]); 2428 } 2429 } 2430 } 2431 2432 if (status != B_OK) 2433 fLink.StartMessage(status); 2434 2435 delete[] offsets; 2436 fLink.Flush(); 2437 break; 2438 } 2439 2440 case AS_GET_ESCAPEMENTS_AS_FLOATS: 2441 { 2442 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature())); 2443 2444 // Attached Data: 2445 // 1) uint16 - family ID 2446 // 2) uint16 - style ID 2447 // 3) float - point size 2448 // 4) uint8 - spacing 2449 // 5) float - rotation 2450 // 6) uint32 - flags 2451 // 7) float - additional "nonspace" delta 2452 // 8) float - additional "space" delta 2453 // 9) int32 - numChars 2454 // 10) int32 - numBytes 2455 // 11) char - the char buffer with size numBytes 2456 2457 // Returns: 2458 // 1) float - escapement buffer with numChar entries 2459 2460 uint16 familyID, styleID; 2461 uint32 flags; 2462 float size, rotation; 2463 uint8 spacing; 2464 2465 link.Read<uint16>(&familyID); 2466 link.Read<uint16>(&styleID); 2467 link.Read<float>(&size); 2468 link.Read<uint8>(&spacing); 2469 link.Read<float>(&rotation); 2470 link.Read<uint32>(&flags); 2471 2472 escapement_delta delta; 2473 link.Read<float>(&delta.nonspace); 2474 link.Read<float>(&delta.space); 2475 2476 int32 numChars; 2477 link.Read<int32>(&numChars); 2478 2479 uint32 numBytes; 2480 link.Read<uint32>(&numBytes); 2481 2482 BStackOrHeapArray<char, 256> charArray(numBytes); 2483 BStackOrHeapArray<float, 64> escapements(numChars); 2484 if (!charArray.IsValid() || !escapements.IsValid()) { 2485 fLink.StartMessage(B_NO_MEMORY); 2486 fLink.Flush(); 2487 break; 2488 } 2489 2490 link.Read(charArray, numBytes); 2491 2492 // figure out escapements 2493 2494 ServerFont font; 2495 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2496 if (status == B_OK) { 2497 font.SetSize(size); 2498 font.SetSpacing(spacing); 2499 font.SetRotation(rotation); 2500 font.SetFlags(flags); 2501 2502 status = font.GetEscapements(charArray, numBytes, numChars, 2503 delta, escapements); 2504 2505 if (status == B_OK) { 2506 fLink.StartMessage(B_OK); 2507 fLink.Attach(escapements, numChars * sizeof(float)); 2508 } 2509 } 2510 2511 if (status != B_OK) 2512 fLink.StartMessage(status); 2513 2514 fLink.Flush(); 2515 break; 2516 } 2517 2518 case AS_GET_BOUNDINGBOXES_CHARS: 2519 case AS_GET_BOUNDINGBOXES_STRING: 2520 { 2521 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature())); 2522 2523 // Attached Data: 2524 // 1) uint16 - family ID 2525 // 2) uint16 - style ID 2526 // 3) float - point size 2527 // 4) float - rotation 2528 // 5) float - shear 2529 // 6) float - false bold width 2530 // 7) uint8 - spacing 2531 // 8) uint32 - flags 2532 // 9) font_metric_mode - mode 2533 // 10) bool - string escapement 2534 // 11) escapement_delta - additional delta 2535 // 12) int32 - numChars 2536 // 13) int32 - numBytes 2537 // 14) char - the char buffer with size numBytes 2538 2539 // Returns: 2540 // 1) BRect - rects with numChar entries 2541 2542 uint16 familyID, styleID; 2543 uint32 flags; 2544 float size, rotation, shear, falseBoldWidth; 2545 uint8 spacing; 2546 font_metric_mode mode; 2547 bool stringEscapement; 2548 2549 link.Read<uint16>(&familyID); 2550 link.Read<uint16>(&styleID); 2551 link.Read<float>(&size); 2552 link.Read<float>(&rotation); 2553 link.Read<float>(&shear); 2554 link.Read<float>(&falseBoldWidth); 2555 link.Read<uint8>(&spacing); 2556 link.Read<uint32>(&flags); 2557 link.Read<font_metric_mode>(&mode); 2558 link.Read<bool>(&stringEscapement); 2559 2560 escapement_delta delta; 2561 link.Read<escapement_delta>(&delta); 2562 2563 int32 numChars; 2564 link.Read<int32>(&numChars); 2565 2566 uint32 numBytes; 2567 link.Read<uint32>(&numBytes); 2568 2569 BStackOrHeapArray<char, 256> charArray(numBytes); 2570 BStackOrHeapArray<BRect, 64> rectArray(numChars); 2571 if (!charArray.IsValid() || !rectArray.IsValid()) { 2572 fLink.StartMessage(B_NO_MEMORY); 2573 fLink.Flush(); 2574 break; 2575 } 2576 2577 link.Read(charArray, numBytes); 2578 2579 // figure out escapements 2580 2581 ServerFont font; 2582 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2583 if (status == B_OK) { 2584 font.SetSize(size); 2585 font.SetRotation(rotation); 2586 font.SetShear(shear); 2587 font.SetFalseBoldWidth(falseBoldWidth); 2588 font.SetSpacing(spacing); 2589 font.SetFlags(flags); 2590 2591 // TODO: implement for real 2592 status = font.GetBoundingBoxes(charArray, numBytes, 2593 numChars, rectArray, stringEscapement, mode, delta, 2594 code == AS_GET_BOUNDINGBOXES_STRING); 2595 if (status == B_OK) { 2596 fLink.StartMessage(B_OK); 2597 for (int32 i = 0; i < numChars; i++) 2598 fLink.Attach<BRect>(rectArray[i]); 2599 } 2600 } 2601 2602 if (status != B_OK) 2603 fLink.StartMessage(status); 2604 2605 fLink.Flush(); 2606 break; 2607 } 2608 2609 case AS_GET_BOUNDINGBOXES_STRINGS: 2610 { 2611 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n", 2612 Signature())); 2613 2614 // Attached Data: 2615 // 1) uint16 - family ID 2616 // 2) uint16 - style ID 2617 // 3) float - point size 2618 // 4) float - rotation 2619 // 5) float - shear 2620 // 6) float - false bold width 2621 // 7) uint8 - spacing 2622 // 8) uint32 - flags 2623 // 9) font_metric_mode - mode 2624 // 10) int32 numStrings 2625 // 11) escapement_delta - additional delta (numStrings times) 2626 // 12) int32 string length to measure (numStrings times) 2627 // 13) string - string (numStrings times) 2628 2629 // Returns: 2630 // 1) BRect - rects with numStrings entries 2631 2632 uint16 familyID, styleID; 2633 uint32 flags; 2634 float ptsize, rotation, shear, falseBoldWidth; 2635 uint8 spacing; 2636 font_metric_mode mode; 2637 2638 link.Read<uint16>(&familyID); 2639 link.Read<uint16>(&styleID); 2640 link.Read<float>(&ptsize); 2641 link.Read<float>(&rotation); 2642 link.Read<float>(&shear); 2643 link.Read<float>(&falseBoldWidth); 2644 link.Read<uint8>(&spacing); 2645 link.Read<uint32>(&flags); 2646 link.Read<font_metric_mode>(&mode); 2647 2648 int32 numStrings; 2649 link.Read<int32>(&numStrings); 2650 2651 BStackOrHeapArray<escapement_delta, 64> deltaArray(numStrings); 2652 BStackOrHeapArray<char*, 64> stringArray(numStrings); 2653 BStackOrHeapArray<size_t, 64> lengthArray(numStrings); 2654 BStackOrHeapArray<BRect, 64> rectArray(numStrings); 2655 if (!deltaArray.IsValid() || !stringArray.IsValid() 2656 || !lengthArray.IsValid() || !rectArray.IsValid()) { 2657 fLink.StartMessage(B_NO_MEMORY); 2658 fLink.Flush(); 2659 break; 2660 } 2661 2662 for (int32 i = 0; i < numStrings; i++) { 2663 // This version of ReadString allocates the strings, we free 2664 // them below 2665 link.ReadString(&stringArray[i], &lengthArray[i]); 2666 link.Read<escapement_delta>(&deltaArray[i]); 2667 } 2668 2669 ServerFont font; 2670 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2671 if (status == B_OK) { 2672 font.SetSize(ptsize); 2673 font.SetRotation(rotation); 2674 font.SetShear(shear); 2675 font.SetFalseBoldWidth(falseBoldWidth); 2676 font.SetSpacing(spacing); 2677 font.SetFlags(flags); 2678 2679 status = font.GetBoundingBoxesForStrings(stringArray, 2680 lengthArray, numStrings, rectArray, mode, deltaArray); 2681 if (status == B_OK) { 2682 fLink.StartMessage(B_OK); 2683 fLink.Attach(rectArray, numStrings * sizeof(BRect)); 2684 } 2685 } 2686 2687 for (int32 i = 0; i < numStrings; i++) 2688 free(stringArray[i]); 2689 2690 if (status != B_OK) 2691 fLink.StartMessage(status); 2692 2693 fLink.Flush(); 2694 break; 2695 } 2696 2697 // Screen commands 2698 2699 case AS_VALID_SCREEN_ID: 2700 { 2701 // Attached data 2702 // 1) int32 screen 2703 2704 int32 id; 2705 if (link.Read<int32>(&id) == B_OK 2706 && id == B_MAIN_SCREEN_ID.id) 2707 fLink.StartMessage(B_OK); 2708 else 2709 fLink.StartMessage(B_ERROR); 2710 2711 fLink.Flush(); 2712 break; 2713 } 2714 2715 case AS_GET_NEXT_SCREEN_ID: 2716 { 2717 // Attached data 2718 // 1) int32 screen 2719 2720 int32 id; 2721 link.Read<int32>(&id); 2722 2723 // TODO: for now, just say we're the last one 2724 fLink.StartMessage(B_ENTRY_NOT_FOUND); 2725 fLink.Flush(); 2726 break; 2727 } 2728 2729 case AS_GET_SCREEN_ID_FROM_WINDOW: 2730 { 2731 status_t status = B_BAD_VALUE; 2732 2733 // Attached data 2734 // 1) int32 - window client token 2735 2736 int32 clientToken; 2737 if (link.Read<int32>(&clientToken) != B_OK) 2738 status = B_BAD_DATA; 2739 else { 2740 BAutolock locker(fWindowListLock); 2741 2742 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 2743 ServerWindow* serverWindow = fWindowList.ItemAt(i); 2744 2745 if (serverWindow->ClientToken() == clientToken) { 2746 AutoReadLocker _(fDesktop->ScreenLocker()); 2747 2748 // found it! 2749 Window* window = serverWindow->Window(); 2750 const Screen* screen = NULL; 2751 if (window != NULL) 2752 screen = window->Screen(); 2753 2754 if (screen == NULL) { 2755 // The window hasn't been added to the desktop yet, 2756 // or it's an offscreen window 2757 break; 2758 } 2759 2760 fLink.StartMessage(B_OK); 2761 fLink.Attach<int32>(screen->ID()); 2762 status = B_OK; 2763 break; 2764 } 2765 } 2766 } 2767 2768 if (status != B_OK) 2769 fLink.StartMessage(status); 2770 fLink.Flush(); 2771 break; 2772 } 2773 2774 case AS_SCREEN_GET_MODE: 2775 { 2776 STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature())); 2777 2778 // Attached data 2779 // 1) int32 screen 2780 // 2) uint32 workspace index 2781 2782 int32 id; 2783 link.Read<int32>(&id); 2784 uint32 workspace; 2785 link.Read<uint32>(&workspace); 2786 2787 display_mode mode; 2788 status_t status = fDesktop->GetScreenMode(workspace, id, mode); 2789 2790 fLink.StartMessage(status); 2791 if (status == B_OK) 2792 fLink.Attach<display_mode>(mode); 2793 fLink.Flush(); 2794 break; 2795 } 2796 2797 case AS_SCREEN_SET_MODE: 2798 { 2799 STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature())); 2800 2801 // Attached data 2802 // 1) int32 screen 2803 // 2) workspace index 2804 // 3) display_mode to set 2805 // 4) 'makeDefault' boolean 2806 2807 int32 id; 2808 link.Read<int32>(&id); 2809 uint32 workspace; 2810 link.Read<uint32>(&workspace); 2811 2812 display_mode mode; 2813 link.Read<display_mode>(&mode); 2814 2815 bool makeDefault = false; 2816 status_t status = link.Read<bool>(&makeDefault); 2817 2818 if (status == B_OK) { 2819 status = fDesktop->SetScreenMode(workspace, id, mode, 2820 makeDefault); 2821 } 2822 if (status == B_OK) { 2823 if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX 2824 && fDesktop->LockSingleWindow()) { 2825 workspace = fDesktop->CurrentWorkspace(); 2826 fDesktop->UnlockSingleWindow(); 2827 } 2828 2829 if (!makeDefault) { 2830 // Memorize the screen change, so that it can be reverted 2831 // later 2832 fTemporaryDisplayModeChange |= 1 << workspace; 2833 } else 2834 fTemporaryDisplayModeChange &= ~(1 << workspace); 2835 } 2836 2837 fLink.StartMessage(status); 2838 fLink.Flush(); 2839 break; 2840 } 2841 2842 case AS_PROPOSE_MODE: 2843 { 2844 STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature())); 2845 int32 id; 2846 link.Read<int32>(&id); 2847 2848 display_mode target, low, high; 2849 link.Read<display_mode>(&target); 2850 link.Read<display_mode>(&low); 2851 link.Read<display_mode>(&high); 2852 status_t status = fDesktop->HWInterface()->ProposeMode(&target, 2853 &low, &high); 2854 2855 // ProposeMode() returns B_BAD_VALUE to hint that the candidate is 2856 // not within the given limits (but is supported) 2857 if (status == B_OK || status == B_BAD_VALUE) { 2858 fLink.StartMessage(B_OK); 2859 fLink.Attach<display_mode>(target); 2860 fLink.Attach<bool>(status == B_OK); 2861 } else 2862 fLink.StartMessage(status); 2863 2864 fLink.Flush(); 2865 break; 2866 } 2867 2868 case AS_GET_MODE_LIST: 2869 { 2870 int32 id; 2871 link.Read<int32>(&id); 2872 // TODO: use this screen id 2873 2874 display_mode* modeList; 2875 uint32 count; 2876 status_t status = fDesktop->HWInterface()->GetModeList(&modeList, 2877 &count); 2878 if (status == B_OK) { 2879 fLink.StartMessage(B_OK); 2880 fLink.Attach<uint32>(count); 2881 fLink.Attach(modeList, sizeof(display_mode) * count); 2882 2883 delete[] modeList; 2884 } else 2885 fLink.StartMessage(status); 2886 2887 fLink.Flush(); 2888 break; 2889 } 2890 2891 case AS_GET_SCREEN_FRAME: 2892 { 2893 STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature())); 2894 2895 // Attached data 2896 // 1) int32 screen 2897 // 2) uint32 workspace index 2898 2899 int32 id; 2900 link.Read<int32>(&id); 2901 uint32 workspace; 2902 link.Read<uint32>(&workspace); 2903 2904 BRect frame; 2905 status_t status = fDesktop->GetScreenFrame(workspace, id, frame); 2906 2907 fLink.StartMessage(status); 2908 if (status == B_OK) 2909 fLink.Attach<BRect>(frame); 2910 2911 fLink.Flush(); 2912 break; 2913 } 2914 2915 case AS_SCREEN_GET_COLORMAP: 2916 { 2917 STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature())); 2918 2919 int32 id; 2920 link.Read<int32>(&id); 2921 2922 const color_map* colorMap = SystemColorMap(); 2923 if (colorMap != NULL) { 2924 fLink.StartMessage(B_OK); 2925 fLink.Attach<color_map>(*colorMap); 2926 } else 2927 fLink.StartMessage(B_ERROR); 2928 2929 fLink.Flush(); 2930 break; 2931 } 2932 2933 case AS_GET_DESKTOP_COLOR: 2934 { 2935 STRACE(("ServerApp %s: get desktop color\n", Signature())); 2936 2937 uint32 index; 2938 link.Read<uint32>(&index); 2939 2940 fLink.StartMessage(B_OK); 2941 fDesktop->LockSingleWindow(); 2942 2943 // we're nice to our children (and also take the default case 2944 // into account which asks for the current workspace) 2945 if (index >= (uint32)kMaxWorkspaces) 2946 index = fDesktop->CurrentWorkspace(); 2947 2948 Workspace workspace(*fDesktop, index, true); 2949 fLink.Attach<rgb_color>(workspace.Color()); 2950 2951 fDesktop->UnlockSingleWindow(); 2952 fLink.Flush(); 2953 break; 2954 } 2955 2956 case AS_SET_DESKTOP_COLOR: 2957 { 2958 STRACE(("ServerApp %s: set desktop color\n", Signature())); 2959 2960 rgb_color color; 2961 uint32 index; 2962 bool makeDefault; 2963 2964 link.Read<rgb_color>(&color); 2965 link.Read<uint32>(&index); 2966 if (link.Read<bool>(&makeDefault) != B_OK) 2967 break; 2968 2969 fDesktop->LockAllWindows(); 2970 2971 // we're nice to our children (and also take the default case 2972 // into account which asks for the current workspace) 2973 if (index >= (uint32)kMaxWorkspaces) 2974 index = fDesktop->CurrentWorkspace(); 2975 2976 Workspace workspace(*fDesktop, index); 2977 workspace.SetColor(color, makeDefault); 2978 2979 fDesktop->UnlockAllWindows(); 2980 break; 2981 } 2982 2983 case AS_GET_ACCELERANT_INFO: 2984 { 2985 STRACE(("ServerApp %s: get accelerant info\n", Signature())); 2986 2987 // We aren't using the screen_id for now... 2988 int32 id; 2989 link.Read<int32>(&id); 2990 2991 accelerant_device_info accelerantInfo; 2992 // TODO: I wonder if there should be a "desktop" lock... 2993 status_t status 2994 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo); 2995 if (status == B_OK) { 2996 fLink.StartMessage(B_OK); 2997 fLink.Attach<accelerant_device_info>(accelerantInfo); 2998 } else 2999 fLink.StartMessage(status); 3000 3001 fLink.Flush(); 3002 break; 3003 } 3004 3005 case AS_GET_MONITOR_INFO: 3006 { 3007 STRACE(("ServerApp %s: get monitor info\n", Signature())); 3008 3009 // We aren't using the screen_id for now... 3010 int32 id; 3011 link.Read<int32>(&id); 3012 3013 monitor_info info; 3014 // TODO: I wonder if there should be a "desktop" lock... 3015 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info); 3016 if (status == B_OK) { 3017 fLink.StartMessage(B_OK); 3018 fLink.Attach<monitor_info>(info); 3019 } else 3020 fLink.StartMessage(status); 3021 3022 fLink.Flush(); 3023 break; 3024 } 3025 3026 case AS_GET_FRAME_BUFFER_CONFIG: 3027 { 3028 STRACE(("ServerApp %s: get frame buffer config\n", Signature())); 3029 3030 // We aren't using the screen_id for now... 3031 int32 id; 3032 link.Read<int32>(&id); 3033 3034 frame_buffer_config config; 3035 // TODO: I wonder if there should be a "desktop" lock... 3036 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config); 3037 if (status == B_OK) { 3038 fLink.StartMessage(B_OK); 3039 fLink.Attach<frame_buffer_config>(config); 3040 } else 3041 fLink.StartMessage(status); 3042 3043 fLink.Flush(); 3044 break; 3045 } 3046 3047 case AS_GET_RETRACE_SEMAPHORE: 3048 { 3049 STRACE(("ServerApp %s: get retrace semaphore\n", Signature())); 3050 3051 // We aren't using the screen_id for now... 3052 int32 id; 3053 link.Read<int32>(&id); 3054 3055 fLink.StartMessage(B_OK); 3056 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore()); 3057 fLink.Flush(); 3058 break; 3059 } 3060 3061 case AS_GET_TIMING_CONSTRAINTS: 3062 { 3063 STRACE(("ServerApp %s: get timing constraints\n", Signature())); 3064 3065 // We aren't using the screen_id for now... 3066 int32 id; 3067 link.Read<int32>(&id); 3068 3069 display_timing_constraints constraints; 3070 status_t status = fDesktop->HWInterface()->GetTimingConstraints( 3071 &constraints); 3072 if (status == B_OK) { 3073 fLink.StartMessage(B_OK); 3074 fLink.Attach<display_timing_constraints>(constraints); 3075 } else 3076 fLink.StartMessage(status); 3077 3078 fLink.Flush(); 3079 break; 3080 } 3081 3082 case AS_GET_PIXEL_CLOCK_LIMITS: 3083 { 3084 STRACE(("ServerApp %s: get pixel clock limits\n", Signature())); 3085 // We aren't using the screen_id for now... 3086 int32 id; 3087 link.Read<int32>(&id); 3088 display_mode mode; 3089 link.Read<display_mode>(&mode); 3090 3091 uint32 low, high; 3092 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode, 3093 &low, &high); 3094 if (status == B_OK) { 3095 fLink.StartMessage(B_OK); 3096 fLink.Attach<uint32>(low); 3097 fLink.Attach<uint32>(high); 3098 } else 3099 fLink.StartMessage(status); 3100 3101 fLink.Flush(); 3102 break; 3103 } 3104 3105 case AS_SET_DPMS: 3106 { 3107 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature())); 3108 int32 id; 3109 link.Read<int32>(&id); 3110 3111 uint32 mode; 3112 link.Read<uint32>(&mode); 3113 3114 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode); 3115 fLink.StartMessage(status); 3116 3117 fLink.Flush(); 3118 break; 3119 } 3120 3121 case AS_GET_DPMS_STATE: 3122 { 3123 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature())); 3124 3125 int32 id; 3126 link.Read<int32>(&id); 3127 3128 uint32 state = fDesktop->HWInterface()->DPMSMode(); 3129 fLink.StartMessage(B_OK); 3130 fLink.Attach<uint32>(state); 3131 fLink.Flush(); 3132 break; 3133 } 3134 3135 case AS_GET_DPMS_CAPABILITIES: 3136 { 3137 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature())); 3138 int32 id; 3139 link.Read<int32>(&id); 3140 3141 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities(); 3142 fLink.StartMessage(B_OK); 3143 fLink.Attach<uint32>(capabilities); 3144 fLink.Flush(); 3145 break; 3146 } 3147 3148 case AS_SCREEN_SET_BRIGHTNESS: 3149 { 3150 STRACE(("ServerApp %s: AS_SCREEN_SET_BRIGHTNESS\n", Signature())); 3151 int32 id; 3152 link.Read<int32>(&id); 3153 3154 float brightness; 3155 link.Read<float>(&brightness); 3156 3157 status_t status = fDesktop->SetBrightness(id, brightness); 3158 fLink.StartMessage(status); 3159 3160 fLink.Flush(); 3161 break; 3162 } 3163 3164 case AS_SCREEN_GET_BRIGHTNESS: 3165 { 3166 STRACE(("ServerApp %s: AS_SCREEN_GET_BRIGHTNESS\n", Signature())); 3167 int32 id; 3168 link.Read<int32>(&id); 3169 3170 float brightness; 3171 status_t result = fDesktop->HWInterface()->GetBrightness(&brightness); 3172 fLink.StartMessage(result); 3173 if (result == B_OK) 3174 fLink.Attach<float>(brightness); 3175 fLink.Flush(); 3176 break; 3177 } 3178 3179 case AS_READ_BITMAP: 3180 { 3181 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature())); 3182 int32 token; 3183 link.Read<int32>(&token); 3184 3185 bool drawCursor = true; 3186 link.Read<bool>(&drawCursor); 3187 3188 BRect bounds; 3189 link.Read<BRect>(&bounds); 3190 3191 bool success = false; 3192 3193 ServerBitmap* bitmap = GetBitmap(token); 3194 if (bitmap != NULL) { 3195 if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) { 3196 success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap, 3197 drawCursor, bounds) == B_OK; 3198 fDesktop->GetDrawingEngine()->UnlockExclusiveAccess(); 3199 } 3200 bitmap->ReleaseReference(); 3201 } 3202 3203 if (success) 3204 fLink.StartMessage(B_OK); 3205 else 3206 fLink.StartMessage(B_BAD_VALUE); 3207 3208 fLink.Flush(); 3209 break; 3210 } 3211 3212 case AS_GET_ACCELERANT_PATH: 3213 { 3214 int32 id; 3215 fLink.Read<int32>(&id); 3216 3217 BString path; 3218 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path); 3219 fLink.StartMessage(status); 3220 if (status == B_OK) 3221 fLink.AttachString(path.String()); 3222 3223 fLink.Flush(); 3224 break; 3225 } 3226 3227 case AS_GET_DRIVER_PATH: 3228 { 3229 int32 id; 3230 fLink.Read<int32>(&id); 3231 3232 BString path; 3233 status_t status = fDesktop->HWInterface()->GetDriverPath(path); 3234 fLink.StartMessage(status); 3235 if (status == B_OK) 3236 fLink.AttachString(path.String()); 3237 3238 fLink.Flush(); 3239 break; 3240 } 3241 3242 // BWindowScreen communication 3243 3244 case AS_DIRECT_SCREEN_LOCK: 3245 { 3246 bool lock; 3247 link.Read<bool>(&lock); 3248 3249 status_t status; 3250 if (lock) 3251 status = fDesktop->LockDirectScreen(ClientTeam()); 3252 else 3253 status = fDesktop->UnlockDirectScreen(ClientTeam()); 3254 3255 fLink.StartMessage(status); 3256 fLink.Flush(); 3257 break; 3258 } 3259 3260 // Hinting and aliasing 3261 3262 case AS_SET_SUBPIXEL_ANTIALIASING: 3263 { 3264 bool subpix; 3265 if (link.Read<bool>(&subpix) == B_OK) { 3266 LockedDesktopSettings settings(fDesktop); 3267 settings.SetSubpixelAntialiasing(subpix); 3268 } 3269 fDesktop->Redraw(); 3270 break; 3271 } 3272 3273 case AS_GET_SUBPIXEL_ANTIALIASING: 3274 { 3275 DesktopSettings settings(fDesktop); 3276 fLink.StartMessage(B_OK); 3277 fLink.Attach<bool>(settings.SubpixelAntialiasing()); 3278 fLink.Flush(); 3279 break; 3280 } 3281 3282 case AS_SET_HINTING: 3283 { 3284 uint8 hinting; 3285 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) { 3286 LockedDesktopSettings settings(fDesktop); 3287 if (hinting != settings.Hinting()) { 3288 settings.SetHinting(hinting); 3289 fDesktop->Redraw(); 3290 } 3291 } 3292 break; 3293 } 3294 3295 case AS_GET_HINTING: 3296 { 3297 DesktopSettings settings(fDesktop); 3298 fLink.StartMessage(B_OK); 3299 fLink.Attach<uint8>(settings.Hinting()); 3300 fLink.Flush(); 3301 break; 3302 } 3303 3304 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: 3305 { 3306 uint8 averageWeight; 3307 if (link.Read<uint8>(&averageWeight) == B_OK) { 3308 LockedDesktopSettings settings(fDesktop); 3309 settings.SetSubpixelAverageWeight(averageWeight); 3310 } 3311 fDesktop->Redraw(); 3312 break; 3313 } 3314 3315 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: 3316 { 3317 DesktopSettings settings(fDesktop); 3318 fLink.StartMessage(B_OK); 3319 fLink.Attach<uint8>(settings.SubpixelAverageWeight()); 3320 fLink.Flush(); 3321 break; 3322 } 3323 3324 case AS_SET_SUBPIXEL_ORDERING: 3325 { 3326 bool subpixelOrdering; 3327 if (link.Read<bool>(&subpixelOrdering) == B_OK) { 3328 LockedDesktopSettings settings(fDesktop); 3329 settings.SetSubpixelOrderingRegular(subpixelOrdering); 3330 } 3331 fDesktop->Redraw(); 3332 break; 3333 } 3334 3335 case AS_GET_SUBPIXEL_ORDERING: 3336 { 3337 DesktopSettings settings(fDesktop); 3338 fLink.StartMessage(B_OK); 3339 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular()); 3340 fLink.Flush(); 3341 break; 3342 } 3343 3344 default: 3345 printf("ServerApp %s received unhandled message code %" B_PRId32 3346 "\n", Signature(), code); 3347 3348 if (link.NeedsReply()) { 3349 // the client is now blocking and waiting for a reply! 3350 fLink.StartMessage(B_ERROR); 3351 fLink.Flush(); 3352 } else 3353 puts("message doesn't need a reply!"); 3354 break; 3355 } 3356 } 3357 3358 3359 /*! \brief The thread function ServerApps use to monitor messages 3360 */ 3361 void 3362 ServerApp::_MessageLooper() 3363 { 3364 // Message-dispatching loop for the ServerApp 3365 3366 // get our own team ID 3367 thread_info threadInfo; 3368 get_thread_info(fThread, &threadInfo); 3369 3370 // First let's tell the client how to talk with us. 3371 fLink.StartMessage(B_OK); 3372 fLink.Attach<port_id>(fMessagePort); 3373 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea()); 3374 fLink.Attach<team_id>(threadInfo.team); 3375 fLink.Flush(); 3376 3377 BPrivate::LinkReceiver &receiver = fLink.Receiver(); 3378 3379 int32 code; 3380 status_t err = B_OK; 3381 3382 while (!fQuitting) { 3383 STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32 3384 ".\n", fMessagePort)); 3385 3386 err = receiver.GetNextMessage(code); 3387 if (err != B_OK || code == B_QUIT_REQUESTED) { 3388 STRACE(("ServerApp: application seems to be gone...\n")); 3389 3390 // Tell desktop to quit us 3391 BPrivate::LinkSender link(fDesktop->MessagePort()); 3392 link.StartMessage(AS_DELETE_APP); 3393 link.Attach<thread_id>(Thread()); 3394 link.Flush(); 3395 break; 3396 } 3397 3398 switch (code) { 3399 case kMsgAppQuit: 3400 // we receive this from our destructor on quit 3401 fQuitting = true; 3402 break; 3403 3404 case AS_QUIT_APP: 3405 { 3406 // This message is received only when the app_server is asked 3407 // to shut down in test/debug mode. Of course, if we are testing 3408 // while using AccelerantDriver, we do NOT want to shut down 3409 // client applications. The server can be quit in this fashion 3410 // through the driver's interface, such as closing the 3411 // ViewDriver's window. 3412 3413 STRACE(("ServerApp %s:Server shutdown notification received\n", 3414 Signature())); 3415 3416 // If we are using the real, accelerated version of the 3417 // DrawingEngine, we do NOT want the user to be able shut down 3418 // the server. The results would NOT be pretty 3419 #if TEST_MODE 3420 BMessage pleaseQuit(B_QUIT_REQUESTED); 3421 SendMessageToClient(&pleaseQuit); 3422 #endif 3423 break; 3424 } 3425 3426 default: 3427 STRACE(("ServerApp %s: Got a Message to dispatch\n", 3428 Signature())); 3429 _DispatchMessage(code, receiver); 3430 break; 3431 } 3432 } 3433 3434 // Quit() will send us a message; we're handling the exiting procedure 3435 thread_id sender; 3436 sem_id shutdownSemaphore; 3437 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id)); 3438 3439 delete this; 3440 3441 if (shutdownSemaphore >= B_OK) 3442 release_sem(shutdownSemaphore); 3443 } 3444 3445 3446 status_t 3447 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link, 3448 port_id& clientReplyPort) 3449 { 3450 // Attached data: 3451 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) 3452 // 2) BRect window frame 3453 // 3) uint32 window look 3454 // 4) uint32 window feel 3455 // 5) uint32 window flags 3456 // 6) uint32 workspace index 3457 // 7) int32 BHandler token of the window 3458 // 8) port_id window's reply port 3459 // 9) port_id window's looper port 3460 // 10) const char * title 3461 3462 BRect frame; 3463 int32 bitmapToken; 3464 uint32 look; 3465 uint32 feel; 3466 uint32 flags; 3467 uint32 workspaces; 3468 int32 token; 3469 port_id looperPort; 3470 char* title; 3471 3472 if (code == AS_CREATE_OFFSCREEN_WINDOW) 3473 link.Read<int32>(&bitmapToken); 3474 3475 link.Read<BRect>(&frame); 3476 link.Read<uint32>(&look); 3477 link.Read<uint32>(&feel); 3478 link.Read<uint32>(&flags); 3479 link.Read<uint32>(&workspaces); 3480 link.Read<int32>(&token); 3481 link.Read<port_id>(&clientReplyPort); 3482 link.Read<port_id>(&looperPort); 3483 if (link.ReadString(&title) != B_OK) 3484 return B_ERROR; 3485 3486 if (!frame.IsValid()) { 3487 // make sure we pass a valid rectangle to ServerWindow 3488 frame.right = frame.left + 1; 3489 frame.bottom = frame.top + 1; 3490 } 3491 3492 status_t status = B_NO_MEMORY; 3493 ServerWindow *window = NULL; 3494 3495 if (code == AS_CREATE_OFFSCREEN_WINDOW) { 3496 ServerBitmap* bitmap = GetBitmap(bitmapToken); 3497 3498 if (bitmap != NULL) { 3499 window = new (nothrow) OffscreenServerWindow(title, this, 3500 clientReplyPort, looperPort, token, bitmap); 3501 } else 3502 status = B_ERROR; 3503 } else { 3504 window = new (nothrow) ServerWindow(title, this, clientReplyPort, 3505 looperPort, token); 3506 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n", 3507 Signature(), title, frame.left, frame.top, 3508 frame.right, frame.bottom)); 3509 } 3510 3511 free(title); 3512 3513 // NOTE: the reply to the client is handled in ServerWindow::Run() 3514 if (window != NULL) { 3515 status = window->Init(frame, (window_look)look, (window_feel)feel, 3516 flags, workspaces); 3517 if (status == B_OK) { 3518 status = window->Run(); 3519 if (status != B_OK) { 3520 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run " 3521 "the window thread\n"); 3522 } 3523 } 3524 3525 if (status != B_OK) 3526 delete window; 3527 } 3528 3529 return status; 3530 } 3531 3532 3533 bool 3534 ServerApp::_HasWindowUnderMouse() 3535 { 3536 BAutolock locker(fWindowListLock); 3537 3538 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 3539 ServerWindow* serverWindow = fWindowList.ItemAt(i); 3540 3541 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN) 3542 return true; 3543 } 3544 3545 return false; 3546 } 3547 3548 3549 bool 3550 ServerApp::_AddBitmap(ServerBitmap* bitmap) 3551 { 3552 BAutolock _(fMapLocker); 3553 3554 try { 3555 fBitmapMap.insert(std::make_pair(bitmap->Token(), bitmap)); 3556 } catch (std::bad_alloc& exception) { 3557 return false; 3558 } 3559 3560 bitmap->SetOwner(this); 3561 return true; 3562 } 3563 3564 3565 void 3566 ServerApp::_DeleteBitmap(ServerBitmap* bitmap) 3567 { 3568 ASSERT(fMapLocker.IsLocked()); 3569 3570 gBitmapManager->BitmapRemoved(bitmap); 3571 fBitmapMap.erase(bitmap->Token()); 3572 3573 bitmap->ReleaseReference(); 3574 } 3575 3576 3577 ServerBitmap* 3578 ServerApp::_FindBitmap(int32 token) const 3579 { 3580 ASSERT(fMapLocker.IsLocked()); 3581 3582 BitmapMap::const_iterator iterator = fBitmapMap.find(token); 3583 if (iterator == fBitmapMap.end()) 3584 return NULL; 3585 3586 return iterator->second; 3587 } 3588 3589 3590 ServerPicture* 3591 ServerApp::_FindPicture(int32 token) const 3592 { 3593 ASSERT(fMapLocker.IsLocked()); 3594 3595 PictureMap::const_iterator iterator = fPictureMap.find(token); 3596 if (iterator == fPictureMap.end()) 3597 return NULL; 3598 3599 return iterator->second; 3600 } 3601