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