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