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 for (int32 i = 0; i < numStrings; i++) { 1871 // This version of ReadString allocates the strings, we free 1872 // them below 1873 link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]); 1874 } 1875 1876 ServerFont font; 1877 1878 if (font.SetFamilyAndStyle(family, style) == B_OK && size > 0) { 1879 font.SetSize(size); 1880 font.SetSpacing(spacing); 1881 1882 for (int32 i = 0; i < numStrings; i++) { 1883 if (!stringArray[i] || lengthArray[i] <= 0) 1884 widthArray[i] = 0.0; 1885 else { 1886 widthArray[i] = font.StringWidth(stringArray[i], 1887 lengthArray[i]); 1888 } 1889 } 1890 1891 fLink.StartMessage(B_OK); 1892 fLink.Attach(widthArray, numStrings * sizeof(float)); 1893 } else 1894 fLink.StartMessage(B_BAD_VALUE); 1895 1896 fLink.Flush(); 1897 1898 for (int32 i = 0; i < numStrings; i++) 1899 free(stringArray[i]); 1900 break; 1901 } 1902 1903 case AS_GET_FONT_BOUNDING_BOX: 1904 { 1905 FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX unimplemented\n", 1906 Signature())); 1907 1908 // Attached Data: 1909 // 1) uint16 - family ID 1910 // 2) uint16 - style ID 1911 1912 // Returns: 1913 // 1) BRect - box holding entire font 1914 1915 // ToDo: implement me! 1916 fLink.StartMessage(B_ERROR); 1917 fLink.Flush(); 1918 break; 1919 } 1920 1921 case AS_GET_TUNED_COUNT: 1922 { 1923 FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature())); 1924 1925 // Attached Data: 1926 // 1) uint16 - family ID 1927 // 2) uint16 - style ID 1928 1929 // Returns: 1930 // 1) int32 - number of font strikes available 1931 1932 uint16 familyID, styleID; 1933 link.Read<uint16>(&familyID); 1934 link.Read<uint16>(&styleID); 1935 1936 gFontManager->Lock(); 1937 1938 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1939 if (fontStyle != NULL) { 1940 fLink.StartMessage(B_OK); 1941 fLink.Attach<int32>(fontStyle->TunedCount()); 1942 } else 1943 fLink.StartMessage(B_BAD_VALUE); 1944 1945 gFontManager->Unlock(); 1946 fLink.Flush(); 1947 break; 1948 } 1949 1950 case AS_GET_TUNED_INFO: 1951 { 1952 FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n", 1953 Signature())); 1954 1955 // Attached Data: 1956 // 1) uint16 - family ID 1957 // 2) uint16 - style ID 1958 // 3) uint32 - index of the particular font strike 1959 1960 // Returns: 1961 // 1) tuned_font_info - info on the strike specified 1962 // ToDo: implement me! 1963 1964 fLink.StartMessage(B_ERROR); 1965 fLink.Flush(); 1966 break; 1967 } 1968 1969 case AS_GET_EXTRA_FONT_FLAGS: 1970 { 1971 FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n", 1972 Signature())); 1973 1974 // Attached Data: 1975 // 1) uint16 - family ID 1976 // 2) uint16 - style ID 1977 1978 // Returns: 1979 // 1) uint32 - extra font flags 1980 1981 uint16 familyID, styleID; 1982 link.Read<uint16>(&familyID); 1983 link.Read<uint16>(&styleID); 1984 1985 gFontManager->Lock(); 1986 1987 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1988 if (fontStyle != NULL) { 1989 fLink.StartMessage(B_OK); 1990 fLink.Attach<uint32>(fontStyle->Flags()); 1991 } else 1992 fLink.StartMessage(B_BAD_VALUE); 1993 1994 gFontManager->Unlock(); 1995 fLink.Flush(); 1996 break; 1997 } 1998 1999 case AS_GET_FONT_HEIGHT: 2000 { 2001 FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature())); 2002 2003 // Attached Data: 2004 // 1) uint16 family ID 2005 // 2) uint16 style ID 2006 // 3) float size 2007 2008 uint16 familyID, styleID; 2009 float size; 2010 link.Read<uint16>(&familyID); 2011 link.Read<uint16>(&styleID); 2012 link.Read<float>(&size); 2013 2014 gFontManager->Lock(); 2015 2016 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2017 if (fontStyle != NULL) { 2018 font_height height; 2019 fontStyle->GetHeight(size, height); 2020 2021 fLink.StartMessage(B_OK); 2022 fLink.Attach<font_height>(height); 2023 } else 2024 fLink.StartMessage(B_BAD_VALUE); 2025 2026 gFontManager->Unlock(); 2027 fLink.Flush(); 2028 break; 2029 } 2030 2031 case AS_GET_GLYPH_SHAPES: 2032 { 2033 FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature())); 2034 2035 // Attached Data: 2036 // 1) uint16 - family ID 2037 // 2) uint16 - style ID 2038 // 3) float - point size 2039 // 4) float - shear 2040 // 5) float - rotation 2041 // 6) float - false bold width 2042 // 6) uint32 - flags 2043 // 7) int32 - numChars 2044 // 8) int32 - numBytes 2045 // 8) char - chars (bytesInBuffer times) 2046 2047 // Returns: 2048 // 1) BShape - glyph shape 2049 // numChars times 2050 2051 uint16 familyID, styleID; 2052 uint32 flags; 2053 float size, shear, rotation, falseBoldWidth; 2054 2055 link.Read<uint16>(&familyID); 2056 link.Read<uint16>(&styleID); 2057 link.Read<float>(&size); 2058 link.Read<float>(&shear); 2059 link.Read<float>(&rotation); 2060 link.Read<float>(&falseBoldWidth); 2061 link.Read<uint32>(&flags); 2062 2063 int32 numChars, numBytes; 2064 link.Read<int32>(&numChars); 2065 link.Read<int32>(&numBytes); 2066 2067 // TODO: proper error checking 2068 char* charArray = new (nothrow) char[numBytes]; 2069 link.Read(charArray, numBytes); 2070 2071 ServerFont font; 2072 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2073 if (status == B_OK) { 2074 font.SetSize(size); 2075 font.SetShear(shear); 2076 font.SetRotation(rotation); 2077 font.SetFalseBoldWidth(falseBoldWidth); 2078 font.SetFlags(flags); 2079 2080 // TODO: proper error checking 2081 BShape** shapes = new (nothrow) BShape*[numChars]; 2082 status = font.GetGlyphShapes(charArray, numChars, shapes); 2083 if (status == B_OK) { 2084 fLink.StartMessage(B_OK); 2085 for (int32 i = 0; i < numChars; i++) { 2086 fLink.AttachShape(*shapes[i]); 2087 delete shapes[i]; 2088 } 2089 } else 2090 fLink.StartMessage(status); 2091 2092 delete[] shapes; 2093 } else 2094 fLink.StartMessage(status); 2095 2096 delete[] charArray; 2097 fLink.Flush(); 2098 break; 2099 } 2100 2101 case AS_GET_HAS_GLYPHS: 2102 { 2103 FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature())); 2104 2105 // Attached Data: 2106 // 1) uint16 - family ID 2107 // 2) uint16 - style ID 2108 // 3) int32 - numChars 2109 // 4) int32 - numBytes 2110 // 5) char - the char buffer with size numBytes 2111 2112 uint16 familyID, styleID; 2113 link.Read<uint16>(&familyID); 2114 link.Read<uint16>(&styleID); 2115 2116 int32 numChars, numBytes; 2117 link.Read<int32>(&numChars); 2118 link.Read<int32>(&numBytes); 2119 // TODO: proper error checking 2120 char* charArray = new (nothrow) char[numBytes]; 2121 link.Read(charArray, numBytes); 2122 2123 ServerFont font; 2124 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2125 if (status == B_OK) { 2126 bool hasArray[numChars]; 2127 status = font.GetHasGlyphs(charArray, numBytes, hasArray); 2128 if (status == B_OK) { 2129 fLink.StartMessage(B_OK); 2130 fLink.Attach(hasArray, sizeof(hasArray)); 2131 } else 2132 fLink.StartMessage(status); 2133 } else 2134 fLink.StartMessage(status); 2135 2136 delete[] charArray; 2137 fLink.Flush(); 2138 break; 2139 } 2140 2141 case AS_GET_EDGES: 2142 { 2143 FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature())); 2144 2145 // Attached Data: 2146 // 1) uint16 - family ID 2147 // 2) uint16 - style ID 2148 // 3) int32 - numChars 2149 // 4) int32 - numBytes 2150 // 5) char - the char buffer with size numBytes 2151 2152 uint16 familyID, styleID; 2153 link.Read<uint16>(&familyID); 2154 link.Read<uint16>(&styleID); 2155 2156 int32 numChars; 2157 link.Read<int32>(&numChars); 2158 2159 uint32 numBytes; 2160 link.Read<uint32>(&numBytes); 2161 // TODO: proper error checking 2162 char* charArray = new (nothrow) char[numBytes]; 2163 link.Read(charArray, numBytes); 2164 2165 ServerFont font; 2166 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2167 if (status == B_OK) { 2168 edge_info edgeArray[numChars]; 2169 status = font.GetEdges(charArray, numBytes, edgeArray); 2170 if (status == B_OK) { 2171 fLink.StartMessage(B_OK); 2172 fLink.Attach(edgeArray, sizeof(edgeArray)); 2173 } else 2174 fLink.StartMessage(status); 2175 } else 2176 fLink.StartMessage(status); 2177 2178 delete[] charArray; 2179 fLink.Flush(); 2180 break; 2181 } 2182 2183 case AS_GET_ESCAPEMENTS: 2184 { 2185 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature())); 2186 2187 // Attached Data: 2188 // 1) uint16 - family ID 2189 // 2) uint16 - style ID 2190 // 3) float - point size 2191 // 4) uint8 - spacing 2192 // 5) float - rotation 2193 // 6) uint32 - flags 2194 // 7) int32 - numChars 2195 // 8) char - char -\ both 2196 // 9) BPoint - offset -/ (numChars times) 2197 2198 // Returns: 2199 // 1) BPoint - escapement 2200 // numChars times 2201 2202 uint16 familyID, styleID; 2203 uint32 flags; 2204 float size, rotation; 2205 uint8 spacing; 2206 2207 link.Read<uint16>(&familyID); 2208 link.Read<uint16>(&styleID); 2209 link.Read<float>(&size); 2210 link.Read<uint8>(&spacing); 2211 link.Read<float>(&rotation); 2212 link.Read<uint32>(&flags); 2213 2214 escapement_delta delta; 2215 link.Read<float>(&delta.nonspace); 2216 link.Read<float>(&delta.space); 2217 2218 bool wantsOffsets; 2219 link.Read<bool>(&wantsOffsets); 2220 2221 int32 numChars; 2222 link.Read<int32>(&numChars); 2223 2224 uint32 numBytes; 2225 link.Read<uint32>(&numBytes); 2226 2227 char* charArray = new(std::nothrow) char[numBytes]; 2228 BPoint* escapements = new(std::nothrow) BPoint[numChars]; 2229 BPoint* offsets = NULL; 2230 if (wantsOffsets) 2231 offsets = new(std::nothrow) BPoint[numChars]; 2232 2233 if (charArray == NULL || escapements == NULL 2234 || (offsets == NULL && wantsOffsets)) { 2235 delete[] charArray; 2236 delete[] escapements; 2237 delete[] offsets; 2238 2239 fLink.StartMessage(B_NO_MEMORY); 2240 fLink.Flush(); 2241 break; 2242 } 2243 2244 link.Read(charArray, numBytes); 2245 2246 ServerFont font; 2247 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2248 if (status == B_OK) { 2249 font.SetSize(size); 2250 font.SetSpacing(spacing); 2251 font.SetRotation(rotation); 2252 font.SetFlags(flags); 2253 2254 status = font.GetEscapements(charArray, numBytes, numChars, 2255 delta, escapements, offsets); 2256 2257 if (status == B_OK) { 2258 fLink.StartMessage(B_OK); 2259 for (int32 i = 0; i < numChars; i++) 2260 fLink.Attach<BPoint>(escapements[i]); 2261 2262 if (offsets) { 2263 for (int32 i = 0; i < numChars; i++) 2264 fLink.Attach<BPoint>(offsets[i]); 2265 } 2266 } else 2267 fLink.StartMessage(status); 2268 } else 2269 fLink.StartMessage(status); 2270 2271 delete[] charArray; 2272 delete[] escapements; 2273 delete[] offsets; 2274 fLink.Flush(); 2275 break; 2276 } 2277 2278 case AS_GET_ESCAPEMENTS_AS_FLOATS: 2279 { 2280 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature())); 2281 2282 // Attached Data: 2283 // 1) uint16 - family ID 2284 // 2) uint16 - style ID 2285 // 3) float - point size 2286 // 4) uint8 - spacing 2287 // 5) float - rotation 2288 // 6) uint32 - flags 2289 // 7) float - additional "nonspace" delta 2290 // 8) float - additional "space" delta 2291 // 9) int32 - numChars 2292 // 10) int32 - numBytes 2293 // 11) char - the char buffer with size numBytes 2294 2295 // Returns: 2296 // 1) float - escapement buffer with numChar entries 2297 2298 uint16 familyID, styleID; 2299 uint32 flags; 2300 float size, rotation; 2301 uint8 spacing; 2302 2303 link.Read<uint16>(&familyID); 2304 link.Read<uint16>(&styleID); 2305 link.Read<float>(&size); 2306 link.Read<uint8>(&spacing); 2307 link.Read<float>(&rotation); 2308 link.Read<uint32>(&flags); 2309 2310 escapement_delta delta; 2311 link.Read<float>(&delta.nonspace); 2312 link.Read<float>(&delta.space); 2313 2314 int32 numChars; 2315 link.Read<int32>(&numChars); 2316 2317 uint32 numBytes; 2318 link.Read<uint32>(&numBytes); 2319 2320 char* charArray = new (nothrow) char[numBytes]; 2321 float* escapements = new (nothrow) float[numChars]; 2322 if (charArray == NULL || escapements == NULL) { 2323 delete[] charArray; 2324 delete[] escapements; 2325 fLink.StartMessage(B_NO_MEMORY); 2326 fLink.Flush(); 2327 break; 2328 } 2329 2330 link.Read(charArray, numBytes); 2331 2332 // figure out escapements 2333 2334 ServerFont font; 2335 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2336 if (status == B_OK) { 2337 font.SetSize(size); 2338 font.SetSpacing(spacing); 2339 font.SetRotation(rotation); 2340 font.SetFlags(flags); 2341 2342 status = font.GetEscapements(charArray, numBytes, numChars, 2343 delta, escapements); 2344 2345 if (status == B_OK) { 2346 fLink.StartMessage(B_OK); 2347 fLink.Attach(escapements, numChars * sizeof(float)); 2348 } 2349 } 2350 2351 delete[] charArray; 2352 delete[] escapements; 2353 2354 if (status != B_OK) 2355 fLink.StartMessage(status); 2356 2357 fLink.Flush(); 2358 break; 2359 } 2360 2361 case AS_GET_BOUNDINGBOXES_CHARS: 2362 case AS_GET_BOUNDINGBOXES_STRING: 2363 { 2364 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature())); 2365 2366 // Attached Data: 2367 // 1) uint16 - family ID 2368 // 2) uint16 - style ID 2369 // 3) float - point size 2370 // 4) float - rotation 2371 // 5) float - shear 2372 // 6) float - false bold width 2373 // 7) uint8 - spacing 2374 // 8) uint32 - flags 2375 // 9) font_metric_mode - mode 2376 // 10) bool - string escapement 2377 // 11) escapement_delta - additional delta 2378 // 12) int32 - numChars 2379 // 13) int32 - numBytes 2380 // 14) char - the char buffer with size numBytes 2381 2382 // Returns: 2383 // 1) BRect - rects with numChar entries 2384 2385 uint16 familyID, styleID; 2386 uint32 flags; 2387 float size, rotation, shear, falseBoldWidth; 2388 uint8 spacing; 2389 font_metric_mode mode; 2390 bool stringEscapement; 2391 2392 link.Read<uint16>(&familyID); 2393 link.Read<uint16>(&styleID); 2394 link.Read<float>(&size); 2395 link.Read<float>(&rotation); 2396 link.Read<float>(&shear); 2397 link.Read<float>(&falseBoldWidth); 2398 link.Read<uint8>(&spacing); 2399 link.Read<uint32>(&flags); 2400 link.Read<font_metric_mode>(&mode); 2401 link.Read<bool>(&stringEscapement); 2402 2403 escapement_delta delta; 2404 link.Read<escapement_delta>(&delta); 2405 2406 int32 numChars; 2407 link.Read<int32>(&numChars); 2408 2409 uint32 numBytes; 2410 link.Read<uint32>(&numBytes); 2411 2412 bool success = false; 2413 2414 char* charArray = new(std::nothrow) char[numBytes]; 2415 BRect* rectArray = new(std::nothrow) BRect[numChars]; 2416 if (charArray != NULL && rectArray != NULL) { 2417 link.Read(charArray, numBytes); 2418 2419 // figure out escapements 2420 2421 ServerFont font; 2422 if (font.SetFamilyAndStyle(familyID, styleID) == B_OK) { 2423 font.SetSize(size); 2424 font.SetRotation(rotation); 2425 font.SetShear(shear); 2426 font.SetFalseBoldWidth(falseBoldWidth); 2427 font.SetSpacing(spacing); 2428 font.SetFlags(flags); 2429 2430 // TODO: implement for real 2431 if (font.GetBoundingBoxes(charArray, numBytes, 2432 rectArray, stringEscapement, mode, delta, 2433 code == AS_GET_BOUNDINGBOXES_STRING) == B_OK) { 2434 2435 fLink.StartMessage(B_OK); 2436 for (int32 i = 0; i < numChars; i++) 2437 fLink.Attach<BRect>(rectArray[i]); 2438 2439 success = true; 2440 } 2441 } 2442 } 2443 2444 if (!success) 2445 fLink.StartMessage(B_ERROR); 2446 2447 fLink.Flush(); 2448 2449 delete[] charArray; 2450 delete[] rectArray; 2451 break; 2452 } 2453 2454 case AS_GET_BOUNDINGBOXES_STRINGS: 2455 { 2456 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n", 2457 Signature())); 2458 2459 // Attached Data: 2460 // 1) uint16 - family ID 2461 // 2) uint16 - style ID 2462 // 3) float - point size 2463 // 4) float - rotation 2464 // 5) float - shear 2465 // 6) float - false bold width 2466 // 7) uint8 - spacing 2467 // 8) uint32 - flags 2468 // 9) font_metric_mode - mode 2469 // 10) int32 numStrings 2470 // 11) escapement_delta - additional delta (numStrings times) 2471 // 12) int32 string length to measure (numStrings times) 2472 // 13) string - string (numStrings times) 2473 2474 // Returns: 2475 // 1) BRect - rects with numStrings entries 2476 2477 uint16 familyID, styleID; 2478 uint32 flags; 2479 float ptsize, rotation, shear, falseBoldWidth; 2480 uint8 spacing; 2481 font_metric_mode mode; 2482 2483 link.Read<uint16>(&familyID); 2484 link.Read<uint16>(&styleID); 2485 link.Read<float>(&ptsize); 2486 link.Read<float>(&rotation); 2487 link.Read<float>(&shear); 2488 link.Read<float>(&falseBoldWidth); 2489 link.Read<uint8>(&spacing); 2490 link.Read<uint32>(&flags); 2491 link.Read<font_metric_mode>(&mode); 2492 2493 int32 numStrings; 2494 link.Read<int32>(&numStrings); 2495 2496 escapement_delta deltaArray[numStrings]; 2497 char* stringArray[numStrings]; 2498 int32 lengthArray[numStrings]; 2499 for(int32 i = 0; i < numStrings; i++) { 2500 // This version of ReadString allocates the strings, we free 2501 // them below 2502 // TODO: this does not work on 64-bit (size_t != int32) 2503 link.ReadString(&stringArray[i], (size_t*)&lengthArray[i]); 2504 link.Read<escapement_delta>(&deltaArray[i]); 2505 } 2506 2507 BStackOrHeapArray<BRect, 64> rectArray(numStrings); 2508 2509 ServerFont font; 2510 bool success = false; 2511 if (font.SetFamilyAndStyle(familyID, styleID) == B_OK) { 2512 font.SetSize(ptsize); 2513 font.SetRotation(rotation); 2514 font.SetShear(shear); 2515 font.SetFalseBoldWidth(falseBoldWidth); 2516 font.SetSpacing(spacing); 2517 font.SetFlags(flags); 2518 2519 if (font.GetBoundingBoxesForStrings(stringArray, lengthArray, 2520 numStrings, rectArray, mode, deltaArray) == B_OK) { 2521 fLink.StartMessage(B_OK); 2522 fLink.Attach(rectArray, numStrings * sizeof(BRect)); 2523 success = true; 2524 } 2525 } 2526 2527 for (int32 i = 0; i < numStrings; i++) 2528 free(stringArray[i]); 2529 2530 if (!success) 2531 fLink.StartMessage(B_ERROR); 2532 2533 fLink.Flush(); 2534 break; 2535 } 2536 2537 // Screen commands 2538 2539 case AS_VALID_SCREEN_ID: 2540 { 2541 // Attached data 2542 // 1) int32 screen 2543 2544 int32 id; 2545 if (link.Read<int32>(&id) == B_OK 2546 && id == B_MAIN_SCREEN_ID.id) 2547 fLink.StartMessage(B_OK); 2548 else 2549 fLink.StartMessage(B_ERROR); 2550 2551 fLink.Flush(); 2552 break; 2553 } 2554 2555 case AS_GET_NEXT_SCREEN_ID: 2556 { 2557 // Attached data 2558 // 1) int32 screen 2559 2560 int32 id; 2561 link.Read<int32>(&id); 2562 2563 // TODO: for now, just say we're the last one 2564 fLink.StartMessage(B_ENTRY_NOT_FOUND); 2565 fLink.Flush(); 2566 break; 2567 } 2568 2569 case AS_GET_SCREEN_ID_FROM_WINDOW: 2570 { 2571 status_t status = B_BAD_VALUE; 2572 2573 // Attached data 2574 // 1) int32 - window client token 2575 2576 int32 clientToken; 2577 if (link.Read<int32>(&clientToken) != B_OK) 2578 status = B_BAD_DATA; 2579 else { 2580 BAutolock locker(fWindowListLock); 2581 2582 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 2583 ServerWindow* serverWindow = fWindowList.ItemAt(i); 2584 2585 if (serverWindow->ClientToken() == clientToken) { 2586 AutoReadLocker _(fDesktop->ScreenLocker()); 2587 2588 // found it! 2589 Window* window = serverWindow->Window(); 2590 const Screen* screen = NULL; 2591 if (window != NULL) 2592 screen = window->Screen(); 2593 2594 if (screen == NULL) { 2595 // The window hasn't been added to the desktop yet, 2596 // or it's an offscreen window 2597 break; 2598 } 2599 2600 fLink.StartMessage(B_OK); 2601 fLink.Attach<int32>(screen->ID()); 2602 status = B_OK; 2603 break; 2604 } 2605 } 2606 } 2607 2608 if (status != B_OK) 2609 fLink.StartMessage(status); 2610 fLink.Flush(); 2611 break; 2612 } 2613 2614 case AS_SCREEN_GET_MODE: 2615 { 2616 STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature())); 2617 2618 // Attached data 2619 // 1) int32 screen 2620 // 2) uint32 workspace index 2621 2622 int32 id; 2623 link.Read<int32>(&id); 2624 uint32 workspace; 2625 link.Read<uint32>(&workspace); 2626 2627 display_mode mode; 2628 status_t status = fDesktop->GetScreenMode(workspace, id, mode); 2629 2630 fLink.StartMessage(status); 2631 if (status == B_OK) 2632 fLink.Attach<display_mode>(mode); 2633 fLink.Flush(); 2634 break; 2635 } 2636 2637 case AS_SCREEN_SET_MODE: 2638 { 2639 STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature())); 2640 2641 // Attached data 2642 // 1) int32 screen 2643 // 2) workspace index 2644 // 3) display_mode to set 2645 // 4) 'makeDefault' boolean 2646 2647 int32 id; 2648 link.Read<int32>(&id); 2649 uint32 workspace; 2650 link.Read<uint32>(&workspace); 2651 2652 display_mode mode; 2653 link.Read<display_mode>(&mode); 2654 2655 bool makeDefault = false; 2656 status_t status = link.Read<bool>(&makeDefault); 2657 2658 if (status == B_OK) { 2659 status = fDesktop->SetScreenMode(workspace, id, mode, 2660 makeDefault); 2661 } 2662 if (status == B_OK) { 2663 if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX 2664 && fDesktop->LockSingleWindow()) { 2665 workspace = fDesktop->CurrentWorkspace(); 2666 fDesktop->UnlockSingleWindow(); 2667 } 2668 2669 if (!makeDefault) { 2670 // Memorize the screen change, so that it can be reverted 2671 // later 2672 fTemporaryDisplayModeChange |= 1 << workspace; 2673 } else 2674 fTemporaryDisplayModeChange &= ~(1 << workspace); 2675 } 2676 2677 fLink.StartMessage(status); 2678 fLink.Flush(); 2679 break; 2680 } 2681 2682 case AS_PROPOSE_MODE: 2683 { 2684 STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature())); 2685 int32 id; 2686 link.Read<int32>(&id); 2687 2688 display_mode target, low, high; 2689 link.Read<display_mode>(&target); 2690 link.Read<display_mode>(&low); 2691 link.Read<display_mode>(&high); 2692 status_t status = fDesktop->HWInterface()->ProposeMode(&target, 2693 &low, &high); 2694 2695 // ProposeMode() returns B_BAD_VALUE to hint that the candidate is 2696 // not within the given limits (but is supported) 2697 if (status == B_OK || status == B_BAD_VALUE) { 2698 fLink.StartMessage(B_OK); 2699 fLink.Attach<display_mode>(target); 2700 fLink.Attach<bool>(status == B_OK); 2701 } else 2702 fLink.StartMessage(status); 2703 2704 fLink.Flush(); 2705 break; 2706 } 2707 2708 case AS_GET_MODE_LIST: 2709 { 2710 int32 id; 2711 link.Read<int32>(&id); 2712 // TODO: use this screen id 2713 2714 display_mode* modeList; 2715 uint32 count; 2716 status_t status = fDesktop->HWInterface()->GetModeList(&modeList, 2717 &count); 2718 if (status == B_OK) { 2719 fLink.StartMessage(B_OK); 2720 fLink.Attach<uint32>(count); 2721 fLink.Attach(modeList, sizeof(display_mode) * count); 2722 2723 delete[] modeList; 2724 } else 2725 fLink.StartMessage(status); 2726 2727 fLink.Flush(); 2728 break; 2729 } 2730 2731 case AS_GET_SCREEN_FRAME: 2732 { 2733 STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature())); 2734 2735 // Attached data 2736 // 1) int32 screen 2737 // 2) uint32 workspace index 2738 2739 int32 id; 2740 link.Read<int32>(&id); 2741 uint32 workspace; 2742 link.Read<uint32>(&workspace); 2743 2744 BRect frame; 2745 status_t status = fDesktop->GetScreenFrame(workspace, id, frame); 2746 2747 fLink.StartMessage(status); 2748 if (status == B_OK) 2749 fLink.Attach<BRect>(frame); 2750 2751 fLink.Flush(); 2752 break; 2753 } 2754 2755 case AS_SCREEN_GET_COLORMAP: 2756 { 2757 STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature())); 2758 2759 int32 id; 2760 link.Read<int32>(&id); 2761 2762 const color_map* colorMap = SystemColorMap(); 2763 if (colorMap != NULL) { 2764 fLink.StartMessage(B_OK); 2765 fLink.Attach<color_map>(*colorMap); 2766 } else 2767 fLink.StartMessage(B_ERROR); 2768 2769 fLink.Flush(); 2770 break; 2771 } 2772 2773 case AS_GET_DESKTOP_COLOR: 2774 { 2775 STRACE(("ServerApp %s: get desktop color\n", Signature())); 2776 2777 uint32 index; 2778 link.Read<uint32>(&index); 2779 2780 fLink.StartMessage(B_OK); 2781 fDesktop->LockSingleWindow(); 2782 2783 // we're nice to our children (and also take the default case 2784 // into account which asks for the current workspace) 2785 if (index >= (uint32)kMaxWorkspaces) 2786 index = fDesktop->CurrentWorkspace(); 2787 2788 Workspace workspace(*fDesktop, index, true); 2789 fLink.Attach<rgb_color>(workspace.Color()); 2790 2791 fDesktop->UnlockSingleWindow(); 2792 fLink.Flush(); 2793 break; 2794 } 2795 2796 case AS_SET_DESKTOP_COLOR: 2797 { 2798 STRACE(("ServerApp %s: set desktop color\n", Signature())); 2799 2800 rgb_color color; 2801 uint32 index; 2802 bool makeDefault; 2803 2804 link.Read<rgb_color>(&color); 2805 link.Read<uint32>(&index); 2806 if (link.Read<bool>(&makeDefault) != B_OK) 2807 break; 2808 2809 fDesktop->LockAllWindows(); 2810 2811 // we're nice to our children (and also take the default case 2812 // into account which asks for the current workspace) 2813 if (index >= (uint32)kMaxWorkspaces) 2814 index = fDesktop->CurrentWorkspace(); 2815 2816 Workspace workspace(*fDesktop, index); 2817 workspace.SetColor(color, makeDefault); 2818 2819 fDesktop->UnlockAllWindows(); 2820 break; 2821 } 2822 2823 case AS_GET_ACCELERANT_INFO: 2824 { 2825 STRACE(("ServerApp %s: get accelerant info\n", Signature())); 2826 2827 // We aren't using the screen_id for now... 2828 int32 id; 2829 link.Read<int32>(&id); 2830 2831 accelerant_device_info accelerantInfo; 2832 // TODO: I wonder if there should be a "desktop" lock... 2833 status_t status 2834 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo); 2835 if (status == B_OK) { 2836 fLink.StartMessage(B_OK); 2837 fLink.Attach<accelerant_device_info>(accelerantInfo); 2838 } else 2839 fLink.StartMessage(status); 2840 2841 fLink.Flush(); 2842 break; 2843 } 2844 2845 case AS_GET_MONITOR_INFO: 2846 { 2847 STRACE(("ServerApp %s: get monitor info\n", Signature())); 2848 2849 // We aren't using the screen_id for now... 2850 int32 id; 2851 link.Read<int32>(&id); 2852 2853 monitor_info info; 2854 // TODO: I wonder if there should be a "desktop" lock... 2855 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info); 2856 if (status == B_OK) { 2857 fLink.StartMessage(B_OK); 2858 fLink.Attach<monitor_info>(info); 2859 } else 2860 fLink.StartMessage(status); 2861 2862 fLink.Flush(); 2863 break; 2864 } 2865 2866 case AS_GET_FRAME_BUFFER_CONFIG: 2867 { 2868 STRACE(("ServerApp %s: get frame buffer config\n", Signature())); 2869 2870 // We aren't using the screen_id for now... 2871 int32 id; 2872 link.Read<int32>(&id); 2873 2874 frame_buffer_config config; 2875 // TODO: I wonder if there should be a "desktop" lock... 2876 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config); 2877 if (status == B_OK) { 2878 fLink.StartMessage(B_OK); 2879 fLink.Attach<frame_buffer_config>(config); 2880 } else 2881 fLink.StartMessage(status); 2882 2883 fLink.Flush(); 2884 break; 2885 } 2886 2887 case AS_GET_RETRACE_SEMAPHORE: 2888 { 2889 STRACE(("ServerApp %s: get retrace semaphore\n", Signature())); 2890 2891 // We aren't using the screen_id for now... 2892 int32 id; 2893 link.Read<int32>(&id); 2894 2895 fLink.StartMessage(B_OK); 2896 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore()); 2897 fLink.Flush(); 2898 break; 2899 } 2900 2901 case AS_GET_TIMING_CONSTRAINTS: 2902 { 2903 STRACE(("ServerApp %s: get timing constraints\n", Signature())); 2904 2905 // We aren't using the screen_id for now... 2906 int32 id; 2907 link.Read<int32>(&id); 2908 2909 display_timing_constraints constraints; 2910 status_t status = fDesktop->HWInterface()->GetTimingConstraints( 2911 &constraints); 2912 if (status == B_OK) { 2913 fLink.StartMessage(B_OK); 2914 fLink.Attach<display_timing_constraints>(constraints); 2915 } else 2916 fLink.StartMessage(status); 2917 2918 fLink.Flush(); 2919 break; 2920 } 2921 2922 case AS_GET_PIXEL_CLOCK_LIMITS: 2923 { 2924 STRACE(("ServerApp %s: get pixel clock limits\n", Signature())); 2925 // We aren't using the screen_id for now... 2926 int32 id; 2927 link.Read<int32>(&id); 2928 display_mode mode; 2929 link.Read<display_mode>(&mode); 2930 2931 uint32 low, high; 2932 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode, 2933 &low, &high); 2934 if (status == B_OK) { 2935 fLink.StartMessage(B_OK); 2936 fLink.Attach<uint32>(low); 2937 fLink.Attach<uint32>(high); 2938 } else 2939 fLink.StartMessage(status); 2940 2941 fLink.Flush(); 2942 break; 2943 } 2944 2945 case AS_SET_DPMS: 2946 { 2947 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature())); 2948 int32 id; 2949 link.Read<int32>(&id); 2950 2951 uint32 mode; 2952 link.Read<uint32>(&mode); 2953 2954 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode); 2955 fLink.StartMessage(status); 2956 2957 fLink.Flush(); 2958 break; 2959 } 2960 2961 case AS_GET_DPMS_STATE: 2962 { 2963 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature())); 2964 2965 int32 id; 2966 link.Read<int32>(&id); 2967 2968 uint32 state = fDesktop->HWInterface()->DPMSMode(); 2969 fLink.StartMessage(B_OK); 2970 fLink.Attach<uint32>(state); 2971 fLink.Flush(); 2972 break; 2973 } 2974 2975 case AS_GET_DPMS_CAPABILITIES: 2976 { 2977 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature())); 2978 int32 id; 2979 link.Read<int32>(&id); 2980 2981 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities(); 2982 fLink.StartMessage(B_OK); 2983 fLink.Attach<uint32>(capabilities); 2984 fLink.Flush(); 2985 break; 2986 } 2987 2988 case AS_READ_BITMAP: 2989 { 2990 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature())); 2991 int32 token; 2992 link.Read<int32>(&token); 2993 2994 bool drawCursor = true; 2995 link.Read<bool>(&drawCursor); 2996 2997 BRect bounds; 2998 link.Read<BRect>(&bounds); 2999 3000 bool success = false; 3001 3002 ServerBitmap* bitmap = GetBitmap(token); 3003 if (bitmap != NULL) { 3004 if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) { 3005 success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap, 3006 drawCursor, bounds) == B_OK; 3007 fDesktop->GetDrawingEngine()->UnlockExclusiveAccess(); 3008 } 3009 bitmap->ReleaseReference(); 3010 } 3011 3012 if (success) 3013 fLink.StartMessage(B_OK); 3014 else 3015 fLink.StartMessage(B_BAD_VALUE); 3016 3017 fLink.Flush(); 3018 break; 3019 } 3020 3021 case AS_GET_ACCELERANT_PATH: 3022 { 3023 int32 id; 3024 fLink.Read<int32>(&id); 3025 3026 BString path; 3027 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path); 3028 fLink.StartMessage(status); 3029 if (status == B_OK) 3030 fLink.AttachString(path.String()); 3031 3032 fLink.Flush(); 3033 break; 3034 } 3035 3036 case AS_GET_DRIVER_PATH: 3037 { 3038 int32 id; 3039 fLink.Read<int32>(&id); 3040 3041 BString path; 3042 status_t status = fDesktop->HWInterface()->GetDriverPath(path); 3043 fLink.StartMessage(status); 3044 if (status == B_OK) 3045 fLink.AttachString(path.String()); 3046 3047 fLink.Flush(); 3048 break; 3049 } 3050 3051 // BWindowScreen communication 3052 3053 case AS_DIRECT_SCREEN_LOCK: 3054 { 3055 bool lock; 3056 link.Read<bool>(&lock); 3057 3058 status_t status; 3059 if (lock) 3060 status = fDesktop->LockDirectScreen(ClientTeam()); 3061 else 3062 status = fDesktop->UnlockDirectScreen(ClientTeam()); 3063 3064 fLink.StartMessage(status); 3065 fLink.Flush(); 3066 break; 3067 } 3068 3069 // Hinting and aliasing 3070 3071 case AS_SET_SUBPIXEL_ANTIALIASING: 3072 { 3073 bool subpix; 3074 if (link.Read<bool>(&subpix) == B_OK) { 3075 LockedDesktopSettings settings(fDesktop); 3076 settings.SetSubpixelAntialiasing(subpix); 3077 } 3078 fDesktop->Redraw(); 3079 break; 3080 } 3081 3082 case AS_GET_SUBPIXEL_ANTIALIASING: 3083 { 3084 DesktopSettings settings(fDesktop); 3085 fLink.StartMessage(B_OK); 3086 fLink.Attach<bool>(settings.SubpixelAntialiasing()); 3087 fLink.Flush(); 3088 break; 3089 } 3090 3091 case AS_SET_HINTING: 3092 { 3093 uint8 hinting; 3094 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) { 3095 LockedDesktopSettings settings(fDesktop); 3096 if (hinting != settings.Hinting()) { 3097 settings.SetHinting(hinting); 3098 fDesktop->Redraw(); 3099 } 3100 } 3101 break; 3102 } 3103 3104 case AS_GET_HINTING: 3105 { 3106 DesktopSettings settings(fDesktop); 3107 fLink.StartMessage(B_OK); 3108 fLink.Attach<uint8>(settings.Hinting()); 3109 fLink.Flush(); 3110 break; 3111 } 3112 3113 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: 3114 { 3115 uint8 averageWeight; 3116 if (link.Read<uint8>(&averageWeight) == B_OK) { 3117 LockedDesktopSettings settings(fDesktop); 3118 settings.SetSubpixelAverageWeight(averageWeight); 3119 } 3120 fDesktop->Redraw(); 3121 break; 3122 } 3123 3124 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: 3125 { 3126 DesktopSettings settings(fDesktop); 3127 fLink.StartMessage(B_OK); 3128 fLink.Attach<uint8>(settings.SubpixelAverageWeight()); 3129 fLink.Flush(); 3130 break; 3131 } 3132 3133 case AS_SET_SUBPIXEL_ORDERING: 3134 { 3135 bool subpixelOrdering; 3136 if (link.Read<bool>(&subpixelOrdering) == B_OK) { 3137 LockedDesktopSettings settings(fDesktop); 3138 settings.SetSubpixelOrderingRegular(subpixelOrdering); 3139 } 3140 fDesktop->Redraw(); 3141 break; 3142 } 3143 3144 case AS_GET_SUBPIXEL_ORDERING: 3145 { 3146 DesktopSettings settings(fDesktop); 3147 fLink.StartMessage(B_OK); 3148 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular()); 3149 fLink.Flush(); 3150 break; 3151 } 3152 3153 default: 3154 printf("ServerApp %s received unhandled message code %" B_PRId32 3155 "\n", Signature(), code); 3156 3157 if (link.NeedsReply()) { 3158 // the client is now blocking and waiting for a reply! 3159 fLink.StartMessage(B_ERROR); 3160 fLink.Flush(); 3161 } else 3162 puts("message doesn't need a reply!"); 3163 break; 3164 } 3165 } 3166 3167 3168 /*! \brief The thread function ServerApps use to monitor messages 3169 */ 3170 void 3171 ServerApp::_MessageLooper() 3172 { 3173 // Message-dispatching loop for the ServerApp 3174 3175 // get our own team ID 3176 thread_info threadInfo; 3177 get_thread_info(fThread, &threadInfo); 3178 3179 // First let's tell the client how to talk with us. 3180 fLink.StartMessage(B_OK); 3181 fLink.Attach<port_id>(fMessagePort); 3182 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea()); 3183 fLink.Attach<team_id>(threadInfo.team); 3184 fLink.Flush(); 3185 3186 BPrivate::LinkReceiver &receiver = fLink.Receiver(); 3187 3188 int32 code; 3189 status_t err = B_OK; 3190 3191 while (!fQuitting) { 3192 STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32 3193 ".\n", fMessagePort)); 3194 3195 err = receiver.GetNextMessage(code); 3196 if (err != B_OK || code == B_QUIT_REQUESTED) { 3197 STRACE(("ServerApp: application seems to be gone...\n")); 3198 3199 // Tell desktop to quit us 3200 BPrivate::LinkSender link(fDesktop->MessagePort()); 3201 link.StartMessage(AS_DELETE_APP); 3202 link.Attach<thread_id>(Thread()); 3203 link.Flush(); 3204 break; 3205 } 3206 3207 switch (code) { 3208 case kMsgAppQuit: 3209 // we receive this from our destructor on quit 3210 fQuitting = true; 3211 break; 3212 3213 case AS_QUIT_APP: 3214 { 3215 // This message is received only when the app_server is asked 3216 // to shut down in test/debug mode. Of course, if we are testing 3217 // while using AccelerantDriver, we do NOT want to shut down 3218 // client applications. The server can be quit in this fashion 3219 // through the driver's interface, such as closing the 3220 // ViewDriver's window. 3221 3222 STRACE(("ServerApp %s:Server shutdown notification received\n", 3223 Signature())); 3224 3225 // If we are using the real, accelerated version of the 3226 // DrawingEngine, we do NOT want the user to be able shut down 3227 // the server. The results would NOT be pretty 3228 #if TEST_MODE 3229 BMessage pleaseQuit(B_QUIT_REQUESTED); 3230 SendMessageToClient(&pleaseQuit); 3231 #endif 3232 break; 3233 } 3234 3235 default: 3236 STRACE(("ServerApp %s: Got a Message to dispatch\n", 3237 Signature())); 3238 _DispatchMessage(code, receiver); 3239 break; 3240 } 3241 } 3242 3243 // Quit() will send us a message; we're handling the exiting procedure 3244 thread_id sender; 3245 sem_id shutdownSemaphore; 3246 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id)); 3247 3248 delete this; 3249 3250 if (shutdownSemaphore >= B_OK) 3251 release_sem(shutdownSemaphore); 3252 } 3253 3254 3255 status_t 3256 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link, 3257 port_id& clientReplyPort) 3258 { 3259 // Attached data: 3260 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) 3261 // 2) BRect window frame 3262 // 3) uint32 window look 3263 // 4) uint32 window feel 3264 // 5) uint32 window flags 3265 // 6) uint32 workspace index 3266 // 7) int32 BHandler token of the window 3267 // 8) port_id window's reply port 3268 // 9) port_id window's looper port 3269 // 10) const char * title 3270 3271 BRect frame; 3272 int32 bitmapToken; 3273 uint32 look; 3274 uint32 feel; 3275 uint32 flags; 3276 uint32 workspaces; 3277 int32 token; 3278 port_id looperPort; 3279 char* title; 3280 3281 if (code == AS_CREATE_OFFSCREEN_WINDOW) 3282 link.Read<int32>(&bitmapToken); 3283 3284 link.Read<BRect>(&frame); 3285 link.Read<uint32>(&look); 3286 link.Read<uint32>(&feel); 3287 link.Read<uint32>(&flags); 3288 link.Read<uint32>(&workspaces); 3289 link.Read<int32>(&token); 3290 link.Read<port_id>(&clientReplyPort); 3291 link.Read<port_id>(&looperPort); 3292 if (link.ReadString(&title) != B_OK) 3293 return B_ERROR; 3294 3295 if (!frame.IsValid()) { 3296 // make sure we pass a valid rectangle to ServerWindow 3297 frame.right = frame.left + 1; 3298 frame.bottom = frame.top + 1; 3299 } 3300 3301 status_t status = B_NO_MEMORY; 3302 ServerWindow *window = NULL; 3303 3304 if (code == AS_CREATE_OFFSCREEN_WINDOW) { 3305 ServerBitmap* bitmap = GetBitmap(bitmapToken); 3306 3307 if (bitmap != NULL) { 3308 window = new (nothrow) OffscreenServerWindow(title, this, 3309 clientReplyPort, looperPort, token, bitmap); 3310 } else 3311 status = B_ERROR; 3312 } else { 3313 window = new (nothrow) ServerWindow(title, this, clientReplyPort, 3314 looperPort, token); 3315 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n", 3316 Signature(), title, frame.left, frame.top, 3317 frame.right, frame.bottom)); 3318 } 3319 3320 free(title); 3321 3322 // NOTE: the reply to the client is handled in ServerWindow::Run() 3323 if (window != NULL) { 3324 status = window->Init(frame, (window_look)look, (window_feel)feel, 3325 flags, workspaces); 3326 if (status == B_OK) { 3327 status = window->Run(); 3328 if (status != B_OK) { 3329 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run " 3330 "the window thread\n"); 3331 } 3332 } 3333 3334 if (status != B_OK) 3335 delete window; 3336 } 3337 3338 return status; 3339 } 3340 3341 3342 bool 3343 ServerApp::_HasWindowUnderMouse() 3344 { 3345 BAutolock locker(fWindowListLock); 3346 3347 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 3348 ServerWindow* serverWindow = fWindowList.ItemAt(i); 3349 3350 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN) 3351 return true; 3352 } 3353 3354 return false; 3355 } 3356 3357 3358 bool 3359 ServerApp::_AddBitmap(ServerBitmap* bitmap) 3360 { 3361 BAutolock _(fMapLocker); 3362 3363 try { 3364 fBitmapMap.insert(std::make_pair(bitmap->Token(), bitmap)); 3365 } catch (std::bad_alloc& exception) { 3366 return false; 3367 } 3368 3369 bitmap->SetOwner(this); 3370 return true; 3371 } 3372 3373 3374 void 3375 ServerApp::_DeleteBitmap(ServerBitmap* bitmap) 3376 { 3377 ASSERT(fMapLocker.IsLocked()); 3378 3379 gBitmapManager->BitmapRemoved(bitmap); 3380 fBitmapMap.erase(bitmap->Token()); 3381 3382 bitmap->ReleaseReference(); 3383 } 3384 3385 3386 ServerBitmap* 3387 ServerApp::_FindBitmap(int32 token) const 3388 { 3389 ASSERT(fMapLocker.IsLocked()); 3390 3391 BitmapMap::const_iterator iterator = fBitmapMap.find(token); 3392 if (iterator == fBitmapMap.end()) 3393 return NULL; 3394 3395 return iterator->second; 3396 } 3397 3398 3399 ServerPicture* 3400 ServerApp::_FindPicture(int32 token) const 3401 { 3402 ASSERT(fMapLocker.IsLocked()); 3403 3404 PictureMap::const_iterator iterator = fPictureMap.find(token); 3405 if (iterator == fPictureMap.end()) 3406 return NULL; 3407 3408 return iterator->second; 3409 } 3410