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