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