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 38 #include <FontPrivate.h> 39 #include <MessengerPrivate.h> 40 #include <PrivateScreen.h> 41 #include <RosterPrivate.h> 42 #include <ServerProtocol.h> 43 #include <WindowPrivate.h> 44 45 #include "AppServer.h" 46 #include "BitmapManager.h" 47 #include "CursorManager.h" 48 #include "CursorSet.h" 49 #include "Desktop.h" 50 #include "DecorManager.h" 51 #include "DrawingEngine.h" 52 #include "EventStream.h" 53 #include "FontManager.h" 54 #include "HWInterface.h" 55 #include "InputManager.h" 56 #include "OffscreenServerWindow.h" 57 #include "Screen.h" 58 #include "ServerBitmap.h" 59 #include "ServerConfig.h" 60 #include "ServerCursor.h" 61 #include "ServerPicture.h" 62 #include "ServerTokenSpace.h" 63 #include "ServerWindow.h" 64 #include "SystemPalette.h" 65 #include "Window.h" 66 67 68 //#define DEBUG_SERVERAPP 69 #ifdef DEBUG_SERVERAPP 70 # define STRACE(x) debug_printf x 71 #else 72 # define STRACE(x) ; 73 #endif 74 75 //#define DEBUG_SERVERAPP_FONT 76 #ifdef DEBUG_SERVERAPP_FONT 77 # define FTRACE(x) debug_printf x 78 #else 79 # define FTRACE(x) ; 80 #endif 81 82 using std::nothrow; 83 84 static const uint32 kMsgUpdateShowAllDraggers = '_adg'; 85 static const uint32 kMsgAppQuit = 'appQ'; 86 87 88 ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort, 89 port_id clientLooperPort, team_id clientTeam, 90 int32 clientToken, const char* signature) 91 : 92 MessageLooper("application"), 93 94 fMessagePort(-1), 95 fClientReplyPort(clientReplyPort), 96 fDesktop(desktop), 97 fSignature(signature), 98 fClientTeam(clientTeam), 99 fWindowListLock("window list"), 100 fTemporaryDisplayModeChange(0), 101 fMapLocker("server app maps"), 102 fAppCursor(NULL), 103 fViewCursor(NULL), 104 fCursorHideLevel(0), 105 fIsActive(false), 106 fMemoryAllocator(this) 107 { 108 if (fSignature == "") 109 fSignature = "application/no-signature"; 110 111 char name[B_OS_NAME_LENGTH]; 112 snprintf(name, sizeof(name), "a<%" B_PRId32 ":%s", clientTeam, 113 SignatureLeaf()); 114 115 fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name); 116 if (fMessagePort < B_OK) 117 return; 118 119 fLink.SetSenderPort(fClientReplyPort); 120 fLink.SetReceiverPort(fMessagePort); 121 fLink.SetTargetTeam(clientTeam); 122 123 // we let the application own the port, so that we get aware when it's gone 124 if (set_port_owner(fMessagePort, clientTeam) < B_OK) { 125 delete_port(fMessagePort); 126 fMessagePort = -1; 127 return; 128 } 129 130 BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam, 131 clientLooperPort, clientToken); 132 133 fInitialWorkspace = desktop->CurrentWorkspace(); 134 // TODO: this should probably be retrieved when the app is loaded! 135 136 // record the current system wide fonts.. 137 desktop->LockSingleWindow(); 138 DesktopSettings settings(desktop); 139 settings.GetDefaultPlainFont(fPlainFont); 140 settings.GetDefaultBoldFont(fBoldFont); 141 settings.GetDefaultFixedFont(fFixedFont); 142 desktop->UnlockSingleWindow(); 143 144 STRACE(("ServerApp %s:\n", Signature())); 145 STRACE(("\tBApp port: %" B_PRId32 "\n", fClientReplyPort)); 146 STRACE(("\tReceiver port: %" B_PRId32 "\n", fMessagePort)); 147 } 148 149 150 ServerApp::~ServerApp() 151 { 152 STRACE(("*ServerApp %s:~ServerApp()\n", Signature())); 153 ASSERT(fQuitting); 154 155 // quit all server windows 156 157 fWindowListLock.Lock(); 158 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 159 ServerWindow* window = fWindowList.ItemAt(i); 160 window->Quit(); 161 } 162 fWindowListLock.Unlock(); 163 164 // wait for the windows to quit 165 snooze(20000); 166 167 fDesktop->RevertScreenModes(fTemporaryDisplayModeChange); 168 169 fWindowListLock.Lock(); 170 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 171 ServerWindow* window = fWindowList.ItemAt(i); 172 173 // A window could have been removed in the mean time 174 // (if those 20 milli seconds from above weren't enough) 175 if (window == NULL) 176 continue; 177 178 sem_id deathSemaphore = window->DeathSemaphore(); 179 fWindowListLock.Unlock(); 180 181 // wait 3 seconds for our window to quit - that's quite a long 182 // time, but killing it might have desastrous effects 183 if (MessageLooper::WaitForQuit(deathSemaphore, 3000000) != B_OK) { 184 // This really shouldn't happen, as it shows we're buggy 185 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 186 syslog(LOG_ERR, "ServerApp %s: ServerWindow doesn't respond!\n", 187 Signature()); 188 #else 189 debugger("ServerWindow doesn't respond!\n"); 190 #endif 191 } 192 fWindowListLock.Lock(); 193 } 194 195 fMemoryAllocator.Detach(); 196 fMapLocker.Lock(); 197 198 while (!fBitmapMap.empty()) 199 _DeleteBitmap(fBitmapMap.begin()->second); 200 201 while (!fPictureMap.empty()) 202 fPictureMap.begin()->second->SetOwner(NULL); 203 204 fDesktop->GetCursorManager().DeleteCursors(fClientTeam); 205 206 STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature())); 207 } 208 209 210 /*! \brief Checks if the application was initialized correctly 211 */ 212 status_t 213 ServerApp::InitCheck() 214 { 215 if (fMessagePort < B_OK) 216 return fMessagePort; 217 218 if (fClientReplyPort < B_OK) 219 return fClientReplyPort; 220 221 if (fWindowListLock.Sem() < B_OK) 222 return fWindowListLock.Sem(); 223 224 return B_OK; 225 } 226 227 228 void 229 ServerApp::Quit() 230 { 231 Quit(-1); 232 } 233 234 235 /*! \brief This quits the application and deletes it. You're not supposed 236 to call its destructor directly. 237 238 At the point you're calling this method, the application should already 239 be removed from the application list. 240 */ 241 void 242 ServerApp::Quit(sem_id shutdownSemaphore) 243 { 244 if (fThread < B_OK) { 245 delete this; 246 return; 247 } 248 249 // execute application deletion in the message looper thread 250 251 fQuitting = true; 252 PostMessage(kMsgAppQuit); 253 254 send_data(fThread, 'QUIT', &shutdownSemaphore, sizeof(sem_id)); 255 } 256 257 258 /*! \brief Sets the ServerApp's active status 259 \param value The new status of the ServerApp. 260 261 This changes an internal flag and also sets the current cursor to the one 262 specified by the application 263 */ 264 void 265 ServerApp::Activate(bool value) 266 { 267 if (fIsActive == value) 268 return; 269 270 fIsActive = value; 271 272 if (fIsActive) { 273 // notify registrar about the active app 274 BRoster::Private roster; 275 roster.UpdateActiveApp(ClientTeam()); 276 277 if (_HasWindowUnderMouse()) { 278 // Set the cursor to the application cursor, if any 279 fDesktop->SetCursor(CurrentCursor()); 280 } 281 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); 282 } 283 } 284 285 286 /*! \brief Send a message to the ServerApp's BApplication 287 \param message The message to send 288 */ 289 void 290 ServerApp::SendMessageToClient(BMessage* message) const 291 { 292 status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL, 293 100000); 294 if (status != B_OK) { 295 syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(), 296 strerror(status)); 297 } 298 } 299 300 301 void 302 ServerApp::SetCurrentCursor(ServerCursor* cursor) 303 { 304 if (fViewCursor != cursor) { 305 if (fViewCursor) 306 fViewCursor->ReleaseReference(); 307 308 fViewCursor = cursor; 309 310 if (fViewCursor) 311 fViewCursor->AcquireReference(); 312 } 313 314 fDesktop->SetCursor(CurrentCursor()); 315 } 316 317 318 ServerCursor* 319 ServerApp::CurrentCursor() const 320 { 321 if (fViewCursor != NULL) 322 return fViewCursor; 323 324 return fAppCursor; 325 } 326 327 328 bool 329 ServerApp::AddWindow(ServerWindow* window) 330 { 331 BAutolock locker(fWindowListLock); 332 333 return fWindowList.AddItem(window); 334 } 335 336 337 void 338 ServerApp::RemoveWindow(ServerWindow* window) 339 { 340 BAutolock locker(fWindowListLock); 341 342 fWindowList.RemoveItem(window); 343 } 344 345 346 bool 347 ServerApp::InWorkspace(int32 index) const 348 { 349 BAutolock locker(fWindowListLock); 350 351 // we could cache this, but then we'd have to recompute the cached 352 // value everytime a window has closed or changed workspaces 353 354 // TODO: support initial application workspace! 355 356 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 357 ServerWindow* serverWindow = fWindowList.ItemAt(i); 358 359 const Window* window = serverWindow->Window(); 360 if (window == NULL || window->IsOffscreenWindow()) 361 continue; 362 363 // only normal and unhidden windows count 364 365 if (window->IsNormal() && !window->IsHidden() 366 && window->InWorkspace(index)) 367 return true; 368 } 369 370 return false; 371 } 372 373 374 uint32 375 ServerApp::Workspaces() const 376 { 377 uint32 workspaces = 0; 378 379 BAutolock locker(fWindowListLock); 380 381 // we could cache this, but then we'd have to recompute the cached 382 // value everytime a window has closed or changed workspaces 383 384 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 385 ServerWindow* serverWindow = fWindowList.ItemAt(i); 386 387 const Window* window = serverWindow->Window(); 388 if (window == NULL || window->IsOffscreenWindow()) 389 continue; 390 391 // only normal and unhidden windows count 392 393 if (window->IsNormal() && !window->IsHidden()) 394 workspaces |= window->Workspaces(); 395 } 396 397 // TODO: add initial application workspace! 398 return workspaces; 399 } 400 401 402 /*! \brief Acquires a reference of the desired bitmap, if available. 403 \param token ID token of the bitmap to find 404 \return The bitmap having that ID or NULL if not found 405 */ 406 ServerBitmap* 407 ServerApp::GetBitmap(int32 token) const 408 { 409 if (token < 1) 410 return NULL; 411 412 BAutolock _(fMapLocker); 413 414 ServerBitmap* bitmap = _FindBitmap(token); 415 if (bitmap == NULL) 416 return NULL; 417 418 bitmap->AcquireReference(); 419 420 return bitmap; 421 } 422 423 424 ServerPicture* 425 ServerApp::CreatePicture(const ServerPicture* original) 426 { 427 ServerPicture* picture; 428 if (original != NULL) 429 picture = new(std::nothrow) ServerPicture(*original); 430 else 431 picture = new(std::nothrow) ServerPicture(); 432 433 if (picture != NULL && !picture->SetOwner(this)) 434 picture->ReleaseReference(); 435 436 return picture; 437 } 438 439 440 ServerPicture* 441 ServerApp::GetPicture(int32 token) const 442 { 443 if (token < 1) 444 return NULL; 445 446 BAutolock _(fMapLocker); 447 448 ServerPicture* picture = _FindPicture(token); 449 if (picture == NULL) 450 return NULL; 451 452 picture->AcquireReference(); 453 454 return picture; 455 } 456 457 458 /*! To be called only by ServerPicture itself.*/ 459 bool 460 ServerApp::AddPicture(ServerPicture* picture) 461 { 462 BAutolock _(fMapLocker); 463 464 ASSERT(picture->Owner() == NULL); 465 466 try { 467 fPictureMap.insert(std::make_pair(picture->Token(), picture)); 468 } catch (std::bad_alloc& exception) { 469 return false; 470 } 471 472 return true; 473 } 474 475 476 /*! To be called only by ServerPicture itself.*/ 477 void 478 ServerApp::RemovePicture(ServerPicture* picture) 479 { 480 BAutolock _(fMapLocker); 481 482 ASSERT(picture->Owner() == this); 483 484 fPictureMap.erase(picture->Token()); 485 picture->ReleaseReference(); 486 } 487 488 489 /*! Called from the ClientMemoryAllocator whenever a server area could be 490 deleted. 491 A message is then sent to the client telling it that it can delete its 492 client area, too. 493 */ 494 void 495 ServerApp::NotifyDeleteClientArea(area_id serverArea) 496 { 497 BMessage notify(kMsgDeleteServerMemoryArea); 498 notify.AddInt32("server area", serverArea); 499 500 SendMessageToClient(¬ify); 501 } 502 503 504 // #pragma mark - private methods 505 506 507 void 508 ServerApp::_GetLooperName(char* name, size_t length) 509 { 510 snprintf(name, length, "a:%" B_PRId32 ":%s", ClientTeam(), SignatureLeaf()); 511 } 512 513 514 /*! \brief Handler function for BApplication API messages 515 \param code Identifier code for the message. Equivalent to BMessage::what 516 \param buffer Any attachments 517 518 Note that the buffer's exact format is determined by the particular message. 519 All attachments are placed in the buffer via a PortLink, so it will be a 520 matter of casting and incrementing an index variable to access them. 521 */ 522 void 523 ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) 524 { 525 switch (code) { 526 case AS_REGISTER_INPUT_SERVER: 527 { 528 EventStream* stream 529 = new(std::nothrow) InputServerStream(fHandlerMessenger); 530 if (stream != NULL 531 && (!stream->IsValid() || !gInputManager->AddStream(stream))) { 532 delete stream; 533 break; 534 } 535 536 // TODO: this should be done using notifications (so that an 537 // abandoned stream will get noticed directly) 538 if (fDesktop->EventDispatcher().InitCheck() != B_OK) 539 fDesktop->EventDispatcher().SetTo(gInputManager->GetStream()); 540 break; 541 } 542 543 case AS_APP_CRASHED: 544 // Allow the debugger to show its window: if needed, remove any 545 // kWindowScreenFeels from the windows of this application 546 if (fDesktop->LockAllWindows()) { 547 if (fWindowListLock.Lock()) { 548 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 549 ServerWindow* serverWindow = fWindowList.ItemAt(i); 550 551 Window* window = serverWindow->Window(); 552 if (window == NULL || window->IsOffscreenWindow()) 553 continue; 554 555 if (window->Feel() == kWindowScreenFeel) 556 fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL); 557 } 558 559 fWindowListLock.Unlock(); 560 } 561 fDesktop->UnlockAllWindows(); 562 } 563 break; 564 565 case AS_DUMP_ALLOCATOR: 566 fMemoryAllocator.Dump(); 567 break; 568 case AS_DUMP_BITMAPS: 569 { 570 fMapLocker.Lock(); 571 572 debug_printf("Application %" B_PRId32 ", %s: %d bitmaps:\n", 573 ClientTeam(), Signature(), (int)fBitmapMap.size()); 574 575 BitmapMap::const_iterator iterator = fBitmapMap.begin(); 576 for (; iterator != fBitmapMap.end(); iterator++) { 577 ServerBitmap* bitmap = iterator->second; 578 debug_printf(" [%" B_PRId32 "] %" B_PRId32 "x%" B_PRId32 ", " 579 "area %" B_PRId32 ", size %" B_PRId32 "\n", 580 bitmap->Token(), bitmap->Width(), bitmap->Height(), 581 bitmap->Area(), bitmap->BitsLength()); 582 } 583 fMapLocker.Unlock(); 584 break; 585 } 586 587 case AS_CREATE_WINDOW: 588 case AS_CREATE_OFFSCREEN_WINDOW: 589 { 590 port_id clientReplyPort = -1; 591 status_t status = _CreateWindow(code, link, clientReplyPort); 592 593 // if sucessful, ServerWindow::Run() will already have replied 594 if (status < B_OK) { 595 // window creation failed, we need to notify the client 596 BPrivate::LinkSender reply(clientReplyPort); 597 reply.StartMessage(status); 598 reply.Flush(); 599 } 600 break; 601 } 602 603 case AS_GET_WINDOW_LIST: 604 { 605 team_id team; 606 if (link.Read<team_id>(&team) == B_OK) 607 fDesktop->WriteWindowList(team, fLink.Sender()); 608 break; 609 } 610 611 case AS_GET_WINDOW_INFO: 612 { 613 int32 serverToken; 614 if (link.Read<int32>(&serverToken) == B_OK) 615 fDesktop->WriteWindowInfo(serverToken, fLink.Sender()); 616 break; 617 } 618 619 case AS_GET_WINDOW_ORDER: 620 { 621 int32 workspace; 622 if (link.Read<int32>(&workspace) == B_OK) 623 fDesktop->WriteWindowOrder(workspace, fLink.Sender()); 624 break; 625 } 626 627 case AS_GET_APPLICATION_ORDER: 628 { 629 int32 workspace; 630 if (link.Read<int32>(&workspace) == B_OK) 631 fDesktop->WriteApplicationOrder(workspace, fLink.Sender()); 632 break; 633 } 634 635 case AS_MINIMIZE_TEAM: 636 { 637 team_id team; 638 if (link.Read<team_id>(&team) == B_OK) 639 fDesktop->MinimizeApplication(team); 640 break; 641 } 642 643 case AS_BRING_TEAM_TO_FRONT: 644 { 645 team_id team; 646 if (link.Read<team_id>(&team) == B_OK) 647 fDesktop->BringApplicationToFront(team); 648 break; 649 } 650 651 case AS_WINDOW_ACTION: 652 { 653 int32 token; 654 int32 action; 655 656 link.Read<int32>(&token); 657 if (link.Read<int32>(&action) != B_OK) 658 break; 659 660 fDesktop->WindowAction(token, action); 661 break; 662 } 663 664 // Decorator commands 665 666 case AS_SET_DECORATOR: 667 { 668 // Attached Data: 669 // path to decorator add-on 670 671 BString path; 672 link.ReadString(path); 673 674 status_t error = gDecorManager.SetDecorator(path, fDesktop); 675 676 fLink.Attach<status_t>(error); 677 fLink.Flush(); 678 679 if (error == B_OK) 680 fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR); 681 break; 682 } 683 684 case AS_GET_DECORATOR: 685 { 686 fLink.StartMessage(B_OK); 687 fLink.AttachString(gDecorManager.GetCurrentDecorator().String()); 688 fLink.Flush(); 689 break; 690 } 691 692 case AS_CREATE_BITMAP: 693 { 694 STRACE(("ServerApp %s: Received BBitmap creation request\n", 695 Signature())); 696 697 // Allocate a bitmap for an application 698 699 // Attached Data: 700 // 1) BRect bounds 701 // 2) color_space space 702 // 3) int32 bitmap_flags 703 // 4) int32 bytes_per_row 704 // 5) int32 screen_id 705 706 // Reply Data: 707 // 1) int32 server token 708 // 2) area_id id of the area in which the bitmap data resides 709 // 3) int32 area pointer offset used to calculate fBasePtr 710 711 // First, let's attempt to allocate the bitmap 712 ServerBitmap* bitmap = NULL; 713 uint8 allocationFlags = kAllocator; 714 715 BRect frame; 716 color_space colorSpace; 717 uint32 flags; 718 int32 bytesPerRow; 719 int32 screenID; 720 721 link.Read<BRect>(&frame); 722 link.Read<color_space>(&colorSpace); 723 link.Read<uint32>(&flags); 724 link.Read<int32>(&bytesPerRow); 725 if (link.Read<int32>(&screenID) == B_OK) { 726 // TODO: choose the right HWInterface with regards to the 727 // screenID 728 bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator, 729 *fDesktop->HWInterface(), frame, colorSpace, flags, 730 bytesPerRow, screenID, &allocationFlags); 731 } 732 733 STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n", 734 Signature(), frame.Width() + 1, frame.Height() + 1)); 735 736 if (bitmap != NULL && _AddBitmap(bitmap)) { 737 fLink.StartMessage(B_OK); 738 fLink.Attach<int32>(bitmap->Token()); 739 fLink.Attach<uint8>(allocationFlags); 740 741 fLink.Attach<area_id>(bitmap->Area()); 742 fLink.Attach<int32>(bitmap->AreaOffset()); 743 744 if ((allocationFlags & kFramebuffer) != 0) 745 fLink.Attach<int32>(bitmap->BytesPerRow()); 746 } else { 747 if (bitmap != NULL) 748 bitmap->ReleaseReference(); 749 750 fLink.StartMessage(B_NO_MEMORY); 751 } 752 753 fLink.Flush(); 754 break; 755 } 756 757 case AS_DELETE_BITMAP: 758 { 759 STRACE(("ServerApp %s: received BBitmap delete request\n", 760 Signature())); 761 762 // Attached Data: 763 // 1) int32 token 764 int32 token; 765 link.Read<int32>(&token); 766 767 fMapLocker.Lock(); 768 769 ServerBitmap* bitmap = _FindBitmap(token); 770 if (bitmap != NULL) { 771 STRACE(("ServerApp %s: Deleting Bitmap %" B_PRId32 "\n", 772 Signature(), token)); 773 774 _DeleteBitmap(bitmap); 775 } 776 777 fMapLocker.Unlock(); 778 break; 779 } 780 781 case AS_GET_BITMAP_OVERLAY_RESTRICTIONS: 782 { 783 overlay_restrictions restrictions; 784 status_t status = B_ERROR; 785 786 int32 token; 787 if (link.Read<int32>(&token) != B_OK) 788 break; 789 790 ServerBitmap* bitmap = GetBitmap(token); 791 if (bitmap != NULL) { 792 STRACE(("ServerApp %s: Get overlay restrictions for bitmap " 793 "%" B_PRId32 "\n", Signature(), token)); 794 795 status = fDesktop->HWInterface()->GetOverlayRestrictions( 796 bitmap->Overlay(), &restrictions); 797 798 bitmap->ReleaseReference(); 799 } 800 801 fLink.StartMessage(status); 802 if (status == B_OK) 803 fLink.Attach(&restrictions, sizeof(overlay_restrictions)); 804 805 fLink.Flush(); 806 break; 807 } 808 809 case AS_GET_BITMAP_SUPPORT_FLAGS: 810 { 811 uint32 colorSpace; 812 if (link.Read<uint32>(&colorSpace) != B_OK) 813 break; 814 815 bool overlay = fDesktop->HWInterface()->CheckOverlayRestrictions( 816 64, 64, (color_space)colorSpace); 817 uint32 flags = overlay ? B_BITMAPS_SUPPORT_OVERLAY : 0; 818 819 fLink.StartMessage(B_OK); 820 fLink.Attach<int32>(flags); 821 fLink.Flush(); 822 break; 823 } 824 825 case AS_RECONNECT_BITMAP: 826 { 827 // First, let's attempt to allocate the bitmap 828 ServerBitmap* bitmap = NULL; 829 830 BRect frame; 831 color_space colorSpace; 832 uint32 flags; 833 int32 bytesPerRow; 834 int32 screenID; 835 area_id clientArea; 836 int32 areaOffset; 837 838 link.Read<BRect>(&frame); 839 link.Read<color_space>(&colorSpace); 840 link.Read<uint32>(&flags); 841 link.Read<int32>(&bytesPerRow); 842 link.Read<int32>(&screenID); 843 link.Read<int32>(&clientArea); 844 if (link.Read<int32>(&areaOffset) == B_OK) { 845 // TODO: choose the right HWInterface with regards to the 846 // screenID 847 bitmap = gBitmapManager->CloneFromClient(clientArea, areaOffset, 848 frame, colorSpace, flags, bytesPerRow); 849 } 850 851 if (bitmap != NULL && _AddBitmap(bitmap)) { 852 fLink.StartMessage(B_OK); 853 fLink.Attach<int32>(bitmap->Token()); 854 855 fLink.Attach<area_id>(bitmap->Area()); 856 857 } else { 858 if (bitmap != NULL) 859 bitmap->ReleaseReference(); 860 861 fLink.StartMessage(B_NO_MEMORY); 862 } 863 864 fLink.Flush(); 865 break; 866 } 867 868 // Picture ops 869 870 case AS_CREATE_PICTURE: 871 { 872 // TODO: Maybe rename this to AS_UPLOAD_PICTURE ? 873 STRACE(("ServerApp %s: Create Picture\n", Signature())); 874 status_t status = B_NO_MEMORY; 875 876 ServerPicture* picture = CreatePicture(); 877 if (picture != NULL) { 878 int32 subPicturesCount = 0; 879 link.Read<int32>(&subPicturesCount); 880 for (int32 i = 0; i < subPicturesCount; i++) { 881 int32 token = -1; 882 link.Read<int32>(&token); 883 884 if (ServerPicture* subPicture = _FindPicture(token)) 885 picture->NestPicture(subPicture); 886 } 887 status = picture->ImportData(link); 888 } 889 if (status == B_OK) { 890 fLink.StartMessage(B_OK); 891 fLink.Attach<int32>(picture->Token()); 892 } else 893 fLink.StartMessage(status); 894 895 fLink.Flush(); 896 break; 897 } 898 899 case AS_DELETE_PICTURE: 900 { 901 STRACE(("ServerApp %s: Delete Picture\n", Signature())); 902 int32 token; 903 if (link.Read<int32>(&token) == B_OK) { 904 BAutolock _(fMapLocker); 905 906 ServerPicture* picture = _FindPicture(token); 907 if (picture != NULL) 908 picture->SetOwner(NULL); 909 } 910 break; 911 } 912 913 case AS_CLONE_PICTURE: 914 { 915 STRACE(("ServerApp %s: Clone Picture\n", Signature())); 916 int32 token; 917 ServerPicture* original = NULL; 918 if (link.Read<int32>(&token) == B_OK) 919 original = GetPicture(token); 920 921 if (original != NULL) { 922 ServerPicture* cloned = CreatePicture(original); 923 if (cloned != NULL) { 924 fLink.StartMessage(B_OK); 925 fLink.Attach<int32>(cloned->Token()); 926 } else 927 fLink.StartMessage(B_NO_MEMORY); 928 929 original->ReleaseReference(); 930 } else 931 fLink.StartMessage(B_BAD_VALUE); 932 933 fLink.Flush(); 934 break; 935 } 936 937 case AS_DOWNLOAD_PICTURE: 938 { 939 STRACE(("ServerApp %s: Download Picture\n", Signature())); 940 int32 token; 941 link.Read<int32>(&token); 942 ServerPicture* picture = GetPicture(token); 943 if (picture != NULL) { 944 picture->ExportData(fLink); 945 // ExportData() calls StartMessage() already 946 picture->ReleaseReference(); 947 } else 948 fLink.StartMessage(B_ERROR); 949 950 fLink.Flush(); 951 break; 952 } 953 954 case AS_CURRENT_WORKSPACE: 955 STRACE(("ServerApp %s: get current workspace\n", Signature())); 956 957 if (fDesktop->LockSingleWindow()) { 958 fLink.StartMessage(B_OK); 959 fLink.Attach<int32>(fDesktop->CurrentWorkspace()); 960 fDesktop->UnlockSingleWindow(); 961 } else 962 fLink.StartMessage(B_ERROR); 963 964 fLink.Flush(); 965 break; 966 967 case AS_ACTIVATE_WORKSPACE: 968 { 969 STRACE(("ServerApp %s: activate workspace\n", Signature())); 970 971 // TODO: See above 972 int32 index; 973 link.Read<int32>(&index); 974 975 bool takeFocusWindowThere; 976 link.Read<bool>(&takeFocusWindowThere); 977 978 fDesktop->SetWorkspace(index, takeFocusWindowThere); 979 break; 980 } 981 982 case AS_SET_WORKSPACE_LAYOUT: 983 { 984 int32 newColumns; 985 int32 newRows; 986 if (link.Read<int32>(&newColumns) == B_OK 987 && link.Read<int32>(&newRows) == B_OK) 988 fDesktop->SetWorkspacesLayout(newColumns, newRows); 989 break; 990 } 991 992 case AS_GET_WORKSPACE_LAYOUT: 993 { 994 if (fDesktop->LockSingleWindow()) { 995 DesktopSettings settings(fDesktop); 996 997 fLink.StartMessage(B_OK); 998 fLink.Attach<int32>(settings.WorkspacesColumns()); 999 fLink.Attach<int32>(settings.WorkspacesRows()); 1000 1001 fDesktop->UnlockSingleWindow(); 1002 } else 1003 fLink.StartMessage(B_ERROR); 1004 1005 fLink.Flush(); 1006 break; 1007 } 1008 1009 case AS_IDLE_TIME: 1010 STRACE(("ServerApp %s: idle time\n", Signature())); 1011 1012 fLink.StartMessage(B_OK); 1013 fLink.Attach<bigtime_t>(fDesktop->EventDispatcher().IdleTime()); 1014 fLink.Flush(); 1015 break; 1016 1017 case AS_SHOW_CURSOR: 1018 { 1019 STRACE(("ServerApp %s: Show Cursor\n", Signature())); 1020 fCursorHideLevel--; 1021 if (fCursorHideLevel < 0) 1022 fCursorHideLevel = 0; 1023 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); 1024 break; 1025 } 1026 1027 case AS_HIDE_CURSOR: 1028 { 1029 STRACE(("ServerApp %s: Hide Cursor\n", Signature())); 1030 fCursorHideLevel++; 1031 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); 1032 break; 1033 } 1034 1035 case AS_OBSCURE_CURSOR: 1036 { 1037 STRACE(("ServerApp %s: Obscure Cursor\n", Signature())); 1038 fDesktop->HWInterface()->ObscureCursor(); 1039 break; 1040 } 1041 1042 case AS_QUERY_CURSOR_HIDDEN: 1043 { 1044 STRACE(("ServerApp %s: Received IsCursorHidden request\n", 1045 Signature())); 1046 1047 fLink.StartMessage(fCursorHideLevel > 0 ? B_OK : B_ERROR); 1048 fLink.Flush(); 1049 break; 1050 } 1051 1052 case AS_SET_CURSOR: 1053 { 1054 STRACE(("ServerApp %s: SetCursor\n", Signature())); 1055 1056 // Attached data: 1057 // 1) bool flag to send a reply 1058 // 2) int32 token ID of the cursor to set 1059 // 3) port_id port to receive a reply. Only exists if the sync flag 1060 // is true. 1061 bool sync; 1062 int32 token; 1063 1064 link.Read<bool>(&sync); 1065 if (link.Read<int32>(&token) != B_OK) 1066 break; 1067 1068 if (!fDesktop->GetCursorManager().Lock()) 1069 break; 1070 1071 ServerCursor* oldCursor = fAppCursor; 1072 fAppCursor = fDesktop->GetCursorManager().FindCursor(token); 1073 if (fAppCursor != NULL) 1074 fAppCursor->AcquireReference(); 1075 1076 if (_HasWindowUnderMouse()) 1077 fDesktop->SetCursor(CurrentCursor()); 1078 1079 if (oldCursor != NULL) 1080 oldCursor->ReleaseReference(); 1081 1082 fDesktop->GetCursorManager().Unlock(); 1083 1084 if (sync) { 1085 // The application is expecting a reply 1086 fLink.StartMessage(B_OK); 1087 fLink.Flush(); 1088 } 1089 break; 1090 } 1091 1092 case AS_SET_VIEW_CURSOR: 1093 { 1094 STRACE(("ServerApp %s: AS_SET_VIEW_CURSOR:\n", Signature())); 1095 1096 ViewSetViewCursorInfo info; 1097 if (link.Read<ViewSetViewCursorInfo>(&info) != B_OK) 1098 break; 1099 1100 if (fDesktop->GetCursorManager().Lock()) { 1101 ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor( 1102 info.cursorToken); 1103 // If we found a cursor, make sure it doesn't go away. If we 1104 // get a NULL cursor, it probably means we are supposed to use 1105 // the system default cursor. 1106 if (cursor != NULL) 1107 cursor->AcquireReference(); 1108 1109 fDesktop->GetCursorManager().Unlock(); 1110 1111 // We need to acquire the write lock here, since we cannot 1112 // afford that the window thread to which the view belongs 1113 // is running and messing with that same view. 1114 fDesktop->LockAllWindows(); 1115 1116 // Find the corresponding view by the given token. It's ok 1117 // if this view does not exist anymore, since it may have 1118 // already be deleted in the window thread before this 1119 // message got here. 1120 View* view; 1121 if (fViewTokens.GetToken(info.viewToken, B_HANDLER_TOKEN, 1122 (void**)&view) == B_OK) { 1123 // Set the cursor on the view. 1124 view->SetCursor(cursor); 1125 1126 // The cursor might need to be updated now. 1127 Window* window = view->Window(); 1128 if (window != NULL && window->IsFocus()) { 1129 if (fDesktop->ViewUnderMouse(window) == view->Token()) 1130 SetCurrentCursor(cursor); 1131 } 1132 } 1133 1134 fDesktop->UnlockAllWindows(); 1135 1136 // Release the temporary reference. 1137 if (cursor != NULL) 1138 cursor->ReleaseReference(); 1139 } 1140 1141 if (info.sync) { 1142 // sync the client (it can now delete the cursor) 1143 fLink.StartMessage(B_OK); 1144 fLink.Flush(); 1145 } 1146 break; 1147 } 1148 1149 case AS_CREATE_CURSOR: 1150 { 1151 STRACE(("ServerApp %s: Create Cursor\n", Signature())); 1152 1153 // Attached data: 1154 // 1) 68 bytes of fAppCursor data 1155 // 2) port_id reply port 1156 1157 status_t status = B_ERROR; 1158 uint8 cursorData[68]; 1159 ServerCursor* cursor = NULL; 1160 1161 // if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) { 1162 // cursor = new (nothrow) ServerCursor(cursorData); 1163 // if (cursor == NULL) 1164 // status = B_NO_MEMORY; 1165 // } 1166 // 1167 // if (cursor != NULL) { 1168 // cursor->SetOwningTeam(fClientTeam); 1169 // fDesktop->GetCursorManager().AddCursor(cursor); 1170 // 1171 // // Synchronous message - BApplication is waiting on the cursor's ID 1172 // fLink.StartMessage(B_OK); 1173 // fLink.Attach<int32>(cursor->Token()); 1174 // } else 1175 // fLink.StartMessage(status); 1176 1177 if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) { 1178 cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam, 1179 cursorData); 1180 if (cursor == NULL) 1181 status = B_NO_MEMORY; 1182 } 1183 1184 if (cursor != NULL) { 1185 // Synchronous message - BApplication is waiting on the 1186 // cursor's ID 1187 fLink.StartMessage(B_OK); 1188 fLink.Attach<int32>(cursor->Token()); 1189 } else 1190 fLink.StartMessage(status); 1191 1192 fLink.Flush(); 1193 break; 1194 } 1195 1196 case AS_REFERENCE_CURSOR: 1197 { 1198 STRACE(("ServerApp %s: Reference BCursor\n", Signature())); 1199 1200 // Attached data: 1201 // 1) int32 token ID of the cursor to reference 1202 1203 int32 token; 1204 if (link.Read<int32>(&token) != B_OK) 1205 break; 1206 1207 if (!fDesktop->GetCursorManager().Lock()) 1208 break; 1209 1210 ServerCursor* cursor 1211 = fDesktop->GetCursorManager().FindCursor(token); 1212 if (cursor != NULL) 1213 cursor->AcquireReference(); 1214 1215 fDesktop->GetCursorManager().Unlock(); 1216 1217 break; 1218 } 1219 1220 case AS_DELETE_CURSOR: 1221 { 1222 STRACE(("ServerApp %s: Delete BCursor\n", Signature())); 1223 1224 // Attached data: 1225 // 1) int32 token ID of the cursor to delete 1226 1227 int32 token; 1228 if (link.Read<int32>(&token) != B_OK) 1229 break; 1230 1231 if (!fDesktop->GetCursorManager().Lock()) 1232 break; 1233 1234 ServerCursor* cursor 1235 = fDesktop->GetCursorManager().FindCursor(token); 1236 if (cursor != NULL) 1237 cursor->ReleaseReference(); 1238 1239 fDesktop->GetCursorManager().Unlock(); 1240 1241 break; 1242 } 1243 1244 case AS_GET_CURSOR_POSITION: 1245 { 1246 STRACE(("ServerApp %s: Get Cursor position\n", Signature())); 1247 1248 // Returns 1249 // 1) BPoint mouse location 1250 // 2) int32 button state 1251 1252 BPoint where; 1253 int32 buttons; 1254 fDesktop->GetLastMouseState(&where, &buttons); 1255 fLink.StartMessage(B_OK); 1256 fLink.Attach<BPoint>(where); 1257 fLink.Attach<int32>(buttons); 1258 fLink.Flush(); 1259 break; 1260 } 1261 1262 case AS_GET_CURSOR_BITMAP: 1263 { 1264 STRACE(("ServerApp %s: Get Cursor bitmap\n", Signature())); 1265 1266 // Returns 1267 // 1) uint32 number of data bytes of the bitmap 1268 // 2) uint32 cursor width in number of pixels 1269 // 3) uint32 cursor height in number of pixels 1270 // 4) BPoint cursor hot spot 1271 // 5) cursor bitmap data 1272 1273 ServerCursorReference cursorRef = fDesktop->Cursor(); 1274 ServerCursor* cursor = cursorRef.Get(); 1275 if (cursor != NULL) { 1276 uint32 size = cursor->BitsLength(); 1277 fLink.StartMessage(B_OK); 1278 fLink.Attach<uint32>(size); 1279 fLink.Attach<uint32>(cursor->Width()); 1280 fLink.Attach<uint32>(cursor->Height()); 1281 fLink.Attach<BPoint>(cursor->GetHotSpot()); 1282 fLink.Attach(cursor->Bits(), size); 1283 } else 1284 fLink.StartMessage(B_ERROR); 1285 1286 fLink.Flush(); 1287 1288 break; 1289 } 1290 1291 case AS_GET_SCROLLBAR_INFO: 1292 { 1293 STRACE(("ServerApp %s: Get ScrollBar info\n", Signature())); 1294 1295 if (fDesktop->LockSingleWindow()) { 1296 scroll_bar_info info; 1297 DesktopSettings settings(fDesktop); 1298 settings.GetScrollBarInfo(info); 1299 1300 fLink.StartMessage(B_OK); 1301 fLink.Attach<scroll_bar_info>(info); 1302 fDesktop->UnlockSingleWindow(); 1303 } else 1304 fLink.StartMessage(B_ERROR); 1305 1306 fLink.Flush(); 1307 break; 1308 } 1309 1310 case AS_SET_SCROLLBAR_INFO: 1311 { 1312 STRACE(("ServerApp %s: Set ScrollBar info\n", Signature())); 1313 1314 // Attached Data: 1315 // 1) scroll_bar_info scroll bar info structure 1316 1317 scroll_bar_info info; 1318 if (link.Read<scroll_bar_info>(&info) == B_OK) { 1319 LockedDesktopSettings settings(fDesktop); 1320 settings.SetScrollBarInfo(info); 1321 } 1322 1323 fLink.StartMessage(B_OK); 1324 fLink.Flush(); 1325 break; 1326 } 1327 1328 case AS_GET_MENU_INFO: 1329 { 1330 STRACE(("ServerApp %s: Get menu info\n", Signature())); 1331 if (fDesktop->LockSingleWindow()) { 1332 menu_info info; 1333 DesktopSettings settings(fDesktop); 1334 settings.GetMenuInfo(info); 1335 1336 fLink.StartMessage(B_OK); 1337 fLink.Attach<menu_info>(info); 1338 1339 fDesktop->UnlockSingleWindow(); 1340 } else 1341 fLink.StartMessage(B_ERROR); 1342 1343 fLink.Flush(); 1344 break; 1345 } 1346 1347 case AS_SET_MENU_INFO: 1348 { 1349 STRACE(("ServerApp %s: Set menu info\n", Signature())); 1350 menu_info info; 1351 if (link.Read<menu_info>(&info) == B_OK) { 1352 LockedDesktopSettings settings(fDesktop); 1353 settings.SetMenuInfo(info); 1354 // TODO: SetMenuInfo() should do some validity check, so 1355 // that the answer we're giving can actually be useful 1356 } 1357 1358 fLink.StartMessage(B_OK); 1359 fLink.Flush(); 1360 break; 1361 } 1362 1363 case AS_SET_MOUSE_MODE: 1364 { 1365 STRACE(("ServerApp %s: Set Mouse Focus mode\n", 1366 Signature())); 1367 1368 // Attached Data: 1369 // 1) enum mode_mouse mouse focus mode 1370 1371 mode_mouse mouseMode; 1372 if (link.Read<mode_mouse>(&mouseMode) == B_OK) { 1373 LockedDesktopSettings settings(fDesktop); 1374 settings.SetMouseMode(mouseMode); 1375 } 1376 break; 1377 } 1378 1379 case AS_GET_MOUSE_MODE: 1380 { 1381 STRACE(("ServerApp %s: Get Mouse Focus mode\n", 1382 Signature())); 1383 1384 if (fDesktop->LockSingleWindow()) { 1385 DesktopSettings settings(fDesktop); 1386 1387 fLink.StartMessage(B_OK); 1388 fLink.Attach<mode_mouse>(settings.MouseMode()); 1389 1390 fDesktop->UnlockSingleWindow(); 1391 } else 1392 fLink.StartMessage(B_ERROR); 1393 1394 fLink.Flush(); 1395 break; 1396 } 1397 1398 case AS_SET_FOCUS_FOLLOWS_MOUSE_MODE: 1399 { 1400 STRACE(("ServerApp %s: Set Focus Follows Mouse mode\n", Signature())); 1401 1402 // Attached Data: 1403 // 1) enum mode_focus_follows_mouse FFM mouse mode 1404 1405 mode_focus_follows_mouse focusFollowsMousMode; 1406 if (link.Read<mode_focus_follows_mouse>(&focusFollowsMousMode) == B_OK) { 1407 LockedDesktopSettings settings(fDesktop); 1408 settings.SetFocusFollowsMouseMode(focusFollowsMousMode); 1409 } 1410 break; 1411 } 1412 1413 case AS_GET_FOCUS_FOLLOWS_MOUSE_MODE: 1414 { 1415 STRACE(("ServerApp %s: Get Focus Follows Mouse mode\n", Signature())); 1416 1417 if (fDesktop->LockSingleWindow()) { 1418 DesktopSettings settings(fDesktop); 1419 1420 fLink.StartMessage(B_OK); 1421 fLink.Attach<mode_focus_follows_mouse>( 1422 settings.FocusFollowsMouseMode()); 1423 1424 fDesktop->UnlockSingleWindow(); 1425 } else 1426 fLink.StartMessage(B_ERROR); 1427 1428 fLink.Flush(); 1429 break; 1430 } 1431 1432 case AS_SET_ACCEPT_FIRST_CLICK: 1433 { 1434 STRACE(("ServerApp %s: Set Accept First Click\n", Signature())); 1435 1436 // Attached Data: 1437 // 1) bool accept_first_click 1438 1439 bool acceptFirstClick; 1440 if (link.Read<bool>(&acceptFirstClick) == B_OK) { 1441 LockedDesktopSettings settings(fDesktop); 1442 settings.SetAcceptFirstClick(acceptFirstClick); 1443 } 1444 break; 1445 } 1446 1447 case AS_GET_ACCEPT_FIRST_CLICK: 1448 { 1449 STRACE(("ServerApp %s: Get Accept First Click\n", Signature())); 1450 1451 if (fDesktop->LockSingleWindow()) { 1452 DesktopSettings settings(fDesktop); 1453 1454 fLink.StartMessage(B_OK); 1455 fLink.Attach<bool>(settings.AcceptFirstClick()); 1456 1457 fDesktop->UnlockSingleWindow(); 1458 } else 1459 fLink.StartMessage(B_ERROR); 1460 1461 fLink.Flush(); 1462 break; 1463 } 1464 1465 case AS_GET_SHOW_ALL_DRAGGERS: 1466 { 1467 STRACE(("ServerApp %s: Get Show All Draggers\n", Signature())); 1468 1469 if (fDesktop->LockSingleWindow()) { 1470 DesktopSettings settings(fDesktop); 1471 1472 fLink.StartMessage(B_OK); 1473 fLink.Attach<bool>(settings.ShowAllDraggers()); 1474 1475 fDesktop->UnlockSingleWindow(); 1476 } else 1477 fLink.StartMessage(B_ERROR); 1478 1479 fLink.Flush(); 1480 break; 1481 } 1482 1483 case AS_SET_SHOW_ALL_DRAGGERS: 1484 { 1485 STRACE(("ServerApp %s: Set Show All Draggers\n", Signature())); 1486 1487 bool changed = false; 1488 bool show; 1489 if (link.Read<bool>(&show) == B_OK) { 1490 LockedDesktopSettings settings(fDesktop); 1491 if (show != settings.ShowAllDraggers()) { 1492 settings.SetShowAllDraggers(show); 1493 changed = true; 1494 } 1495 } 1496 1497 if (changed) 1498 fDesktop->BroadcastToAllApps(kMsgUpdateShowAllDraggers); 1499 break; 1500 } 1501 1502 case kMsgUpdateShowAllDraggers: 1503 { 1504 bool show = false; 1505 if (fDesktop->LockSingleWindow()) { 1506 DesktopSettings settings(fDesktop); 1507 show = settings.ShowAllDraggers(); 1508 fDesktop->UnlockSingleWindow(); 1509 } 1510 BMessage update(_SHOW_DRAG_HANDLES_); 1511 update.AddBool("show", show); 1512 1513 SendMessageToClient(&update); 1514 break; 1515 } 1516 1517 /* font messages */ 1518 1519 case AS_SET_SYSTEM_FONT: 1520 { 1521 FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature())); 1522 // gets: 1523 // 1) string - font type ("plain", ...) 1524 // 2) string - family 1525 // 3) string - style 1526 // 4) float - size 1527 1528 char type[B_OS_NAME_LENGTH]; 1529 font_family familyName; 1530 font_style styleName; 1531 float size; 1532 1533 if (link.ReadString(type, sizeof(type)) == B_OK 1534 && link.ReadString(familyName, sizeof(familyName)) == B_OK 1535 && link.ReadString(styleName, sizeof(styleName)) == B_OK 1536 && link.Read<float>(&size) == B_OK) { 1537 gFontManager->Lock(); 1538 1539 FontStyle* style 1540 = gFontManager->GetStyle(familyName, styleName); 1541 if (style != NULL) { 1542 ServerFont font(*style, size); 1543 gFontManager->Unlock(); 1544 // We must not have locked the font manager when 1545 // locking the desktop (through LockedDesktopSettings 1546 // below) 1547 1548 LockedDesktopSettings settings(fDesktop); 1549 1550 // TODO: Should we also update our internal copies now? 1551 if (!strcmp(type, "plain")) 1552 settings.SetDefaultPlainFont(font); 1553 else if (!strcmp(type, "bold")) 1554 settings.SetDefaultBoldFont(font); 1555 else if (!strcmp(type, "fixed")) 1556 settings.SetDefaultFixedFont(font); 1557 } else 1558 gFontManager->Unlock(); 1559 } 1560 break; 1561 } 1562 1563 case AS_GET_SYSTEM_DEFAULT_FONT: 1564 { 1565 // input: 1566 // 1) string - font type ("plain", ...) 1567 1568 ServerFont font; 1569 1570 char type[B_OS_NAME_LENGTH]; 1571 status_t status = link.ReadString(type, sizeof(type)); 1572 if (status == B_OK) { 1573 if (!strcmp(type, "plain")) { 1574 font = *gFontManager->DefaultPlainFont(); 1575 } else if (!strcmp(type, "bold")) { 1576 font = *gFontManager->DefaultBoldFont(); 1577 } else if (!strcmp(type, "fixed")) { 1578 font = *gFontManager->DefaultFixedFont(); 1579 } else 1580 status = B_BAD_VALUE; 1581 } 1582 1583 if (status == B_OK) { 1584 // returns: 1585 // 1) string - family 1586 // 2) string - style 1587 // 3) float - size 1588 1589 fLink.StartMessage(B_OK); 1590 fLink.AttachString(font.Family()); 1591 fLink.AttachString(font.Style()); 1592 fLink.Attach<float>(font.Size()); 1593 } else 1594 fLink.StartMessage(status); 1595 1596 fLink.Flush(); 1597 break; 1598 } 1599 1600 case AS_GET_SYSTEM_FONTS: 1601 { 1602 FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature())); 1603 // Returns: 1604 // 1) uint16 - family ID 1605 // 2) uint16 - style ID 1606 // 3) float - size in points 1607 // 4) uint16 - face flags 1608 // 5) uint32 - font flags 1609 1610 if (!fDesktop->LockSingleWindow()) { 1611 fLink.StartMessage(B_OK); 1612 fLink.Flush(); 1613 break; 1614 } 1615 1616 // The client is requesting the system fonts, this 1617 // could happend either at application start up, or 1618 // because the client is resyncing with the global 1619 // fonts. So we record the current system wide fonts 1620 // into our own copies at this point. 1621 DesktopSettings settings(fDesktop); 1622 1623 settings.GetDefaultPlainFont(fPlainFont); 1624 settings.GetDefaultBoldFont(fBoldFont); 1625 settings.GetDefaultFixedFont(fFixedFont); 1626 1627 fLink.StartMessage(B_OK); 1628 1629 for (int32 i = 0; i < 3; i++) { 1630 ServerFont* font = NULL; 1631 switch (i) { 1632 case 0: 1633 font = &fPlainFont; 1634 fLink.AttachString("plain"); 1635 break; 1636 1637 case 1: 1638 font = &fBoldFont; 1639 fLink.AttachString("bold"); 1640 break; 1641 1642 case 2: 1643 font = &fFixedFont; 1644 fLink.AttachString("fixed"); 1645 break; 1646 } 1647 1648 fLink.Attach<uint16>(font->FamilyID()); 1649 fLink.Attach<uint16>(font->StyleID()); 1650 fLink.Attach<float>(font->Size()); 1651 fLink.Attach<uint16>(font->Face()); 1652 fLink.Attach<uint32>(font->Flags()); 1653 } 1654 1655 fDesktop->UnlockSingleWindow(); 1656 fLink.Flush(); 1657 break; 1658 } 1659 1660 case AS_GET_FONT_LIST_REVISION: 1661 { 1662 STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature())); 1663 1664 fLink.StartMessage(B_OK); 1665 fLink.Attach<int32>( 1666 gFontManager->CheckRevision(fDesktop->UserID())); 1667 fLink.Flush(); 1668 break; 1669 } 1670 1671 case AS_GET_FAMILY_AND_STYLES: 1672 { 1673 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature())); 1674 1675 // Attached Data: 1676 // 1) int32 the index of the font family to get 1677 1678 // Returns: 1679 // 1) string - name of family 1680 // 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT) 1681 // 3) count of styles in that family 1682 // For each style: 1683 // 1) string - name of style 1684 // 2) uint16 - face of style 1685 // 3) uint32 - flags of style 1686 1687 int32 index; 1688 link.Read<int32>(&index); 1689 1690 gFontManager->Lock(); 1691 1692 FontFamily* family = gFontManager->FamilyAt(index); 1693 if (family) { 1694 fLink.StartMessage(B_OK); 1695 fLink.AttachString(family->Name()); 1696 fLink.Attach<uint32>(family->Flags()); 1697 1698 int32 count = family->CountStyles(); 1699 fLink.Attach<int32>(count); 1700 1701 for (int32 i = 0; i < count; i++) { 1702 FontStyle* style = family->StyleAt(i); 1703 1704 fLink.AttachString(style->Name()); 1705 fLink.Attach<uint16>(style->Face()); 1706 fLink.Attach<uint32>(style->Flags()); 1707 } 1708 } else 1709 fLink.StartMessage(B_BAD_VALUE); 1710 1711 gFontManager->Unlock(); 1712 fLink.Flush(); 1713 break; 1714 } 1715 1716 case AS_GET_FAMILY_AND_STYLE: 1717 { 1718 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE\n", Signature())); 1719 1720 // Attached Data: 1721 // 1) uint16 - family ID 1722 // 2) uint16 - style ID 1723 1724 // Returns: 1725 // 1) font_family The name of the font family 1726 // 2) font_style - name of the style 1727 1728 uint16 familyID, styleID; 1729 link.Read<uint16>(&familyID); 1730 link.Read<uint16>(&styleID); 1731 1732 gFontManager->Lock(); 1733 1734 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1735 if (fontStyle != NULL) { 1736 fLink.StartMessage(B_OK); 1737 fLink.AttachString(fontStyle->Family()->Name()); 1738 fLink.AttachString(fontStyle->Name()); 1739 } else 1740 fLink.StartMessage(B_BAD_VALUE); 1741 1742 fLink.Flush(); 1743 gFontManager->Unlock(); 1744 break; 1745 } 1746 1747 case AS_GET_FAMILY_AND_STYLE_IDS: 1748 { 1749 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE_IDS\n", 1750 Signature())); 1751 1752 // Attached Data: 1753 // 1) font_family - name of font family to use 1754 // 2) font_style - name of style in family 1755 // 3) family ID - only used if 1) is empty 1756 // 4) style ID - only used if 2) is empty 1757 // 5) face - the font's current face 1758 1759 // Returns: 1760 // 1) uint16 - family ID 1761 // 2) uint16 - style ID 1762 // 3) uint16 - face 1763 1764 font_family family; 1765 font_style style; 1766 uint16 familyID, styleID; 1767 uint16 face; 1768 if (link.ReadString(family, sizeof(font_family)) == B_OK 1769 && link.ReadString(style, sizeof(font_style)) == B_OK 1770 && link.Read<uint16>(&familyID) == B_OK 1771 && link.Read<uint16>(&styleID) == B_OK 1772 && link.Read<uint16>(&face) == B_OK) { 1773 // get the font and return IDs and face 1774 gFontManager->Lock(); 1775 1776 FontStyle *fontStyle = gFontManager->GetStyle(family, style, 1777 familyID, styleID, face); 1778 1779 if (fontStyle != NULL) { 1780 fLink.StartMessage(B_OK); 1781 fLink.Attach<uint16>(fontStyle->Family()->ID()); 1782 fLink.Attach<uint16>(fontStyle->ID()); 1783 1784 // we try to keep the font face close to what we got 1785 face = fontStyle->PreservedFace(face); 1786 1787 fLink.Attach<uint16>(face); 1788 } else 1789 fLink.StartMessage(B_NAME_NOT_FOUND); 1790 1791 gFontManager->Unlock(); 1792 } else 1793 fLink.StartMessage(B_BAD_VALUE); 1794 1795 fLink.Flush(); 1796 break; 1797 } 1798 1799 case AS_GET_FONT_FILE_FORMAT: 1800 { 1801 FTRACE(("ServerApp %s: AS_GET_FONT_FILE_FORMAT\n", Signature())); 1802 1803 // Attached Data: 1804 // 1) uint16 - family ID 1805 // 2) uint16 - style ID 1806 1807 // Returns: 1808 // 1) uint16 font_file_format of font 1809 1810 int32 familyID, styleID; 1811 link.Read<int32>(&familyID); 1812 link.Read<int32>(&styleID); 1813 1814 gFontManager->Lock(); 1815 1816 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1817 if (fontStyle) { 1818 fLink.StartMessage(B_OK); 1819 fLink.Attach<uint16>((uint16)fontStyle->FileFormat()); 1820 } else 1821 fLink.StartMessage(B_BAD_VALUE); 1822 1823 gFontManager->Unlock(); 1824 fLink.Flush(); 1825 break; 1826 } 1827 1828 case AS_GET_STRING_WIDTHS: 1829 { 1830 FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature())); 1831 1832 // Attached Data: 1833 // 1) uint16 ID of family 1834 // 2) uint16 ID of style 1835 // 3) float point size of font 1836 // 4) uint8 spacing to use 1837 // 5) int32 numStrings 1838 // 6) int32 string length to measure (numStrings times) 1839 // 7) string String to measure (numStrings times) 1840 1841 // Returns: 1842 // 1) float - width of the string in pixels (numStrings times) 1843 1844 uint16 family, style; 1845 float size; 1846 uint8 spacing; 1847 1848 link.Read<uint16>(&family); 1849 link.Read<uint16>(&style); 1850 link.Read<float>(&size); 1851 link.Read<uint8>(&spacing); 1852 int32 numStrings; 1853 if (link.Read<int32>(&numStrings) != B_OK) { 1854 // this results in a B_BAD_VALUE return 1855 numStrings = 0; 1856 size = 0.0f; 1857 } 1858 1859 // TODO: don't use the stack for this - numStrings could be large 1860 float widthArray[numStrings]; 1861 int32 lengthArray[numStrings]; 1862 char *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, sizeof(widthArray)); 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 // TODO: don't do this on the heap! (at least check the size before) 2501 BRect 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, sizeof(rectArray)); 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_SET_UI_COLOR: 2818 { 2819 STRACE(("ServerApp %s: Set UI Color\n", Signature())); 2820 2821 // Attached Data: 2822 // 1) color_which which 2823 // 2) rgb_color color 2824 2825 color_which which; 2826 rgb_color color; 2827 2828 link.Read<color_which>(&which); 2829 if (link.Read<rgb_color>(&color) == B_OK) { 2830 LockedDesktopSettings settings(fDesktop); 2831 settings.SetUIColor(which, color); 2832 } 2833 break; 2834 } 2835 2836 case AS_GET_ACCELERANT_INFO: 2837 { 2838 STRACE(("ServerApp %s: get accelerant info\n", Signature())); 2839 2840 // We aren't using the screen_id for now... 2841 int32 id; 2842 link.Read<int32>(&id); 2843 2844 accelerant_device_info accelerantInfo; 2845 // TODO: I wonder if there should be a "desktop" lock... 2846 status_t status 2847 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo); 2848 if (status == B_OK) { 2849 fLink.StartMessage(B_OK); 2850 fLink.Attach<accelerant_device_info>(accelerantInfo); 2851 } else 2852 fLink.StartMessage(status); 2853 2854 fLink.Flush(); 2855 break; 2856 } 2857 2858 case AS_GET_MONITOR_INFO: 2859 { 2860 STRACE(("ServerApp %s: get monitor info\n", Signature())); 2861 2862 // We aren't using the screen_id for now... 2863 int32 id; 2864 link.Read<int32>(&id); 2865 2866 monitor_info info; 2867 // TODO: I wonder if there should be a "desktop" lock... 2868 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info); 2869 if (status == B_OK) { 2870 fLink.StartMessage(B_OK); 2871 fLink.Attach<monitor_info>(info); 2872 } else 2873 fLink.StartMessage(status); 2874 2875 fLink.Flush(); 2876 break; 2877 } 2878 2879 case AS_GET_FRAME_BUFFER_CONFIG: 2880 { 2881 STRACE(("ServerApp %s: get frame buffer config\n", Signature())); 2882 2883 // We aren't using the screen_id for now... 2884 int32 id; 2885 link.Read<int32>(&id); 2886 2887 frame_buffer_config config; 2888 // TODO: I wonder if there should be a "desktop" lock... 2889 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config); 2890 if (status == B_OK) { 2891 fLink.StartMessage(B_OK); 2892 fLink.Attach<frame_buffer_config>(config); 2893 } else 2894 fLink.StartMessage(status); 2895 2896 fLink.Flush(); 2897 break; 2898 } 2899 2900 case AS_GET_RETRACE_SEMAPHORE: 2901 { 2902 STRACE(("ServerApp %s: get retrace semaphore\n", Signature())); 2903 2904 // We aren't using the screen_id for now... 2905 int32 id; 2906 link.Read<int32>(&id); 2907 2908 fLink.StartMessage(B_OK); 2909 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore()); 2910 fLink.Flush(); 2911 break; 2912 } 2913 2914 case AS_GET_TIMING_CONSTRAINTS: 2915 { 2916 STRACE(("ServerApp %s: get timing constraints\n", Signature())); 2917 2918 // We aren't using the screen_id for now... 2919 int32 id; 2920 link.Read<int32>(&id); 2921 2922 display_timing_constraints constraints; 2923 status_t status = fDesktop->HWInterface()->GetTimingConstraints( 2924 &constraints); 2925 if (status == B_OK) { 2926 fLink.StartMessage(B_OK); 2927 fLink.Attach<display_timing_constraints>(constraints); 2928 } else 2929 fLink.StartMessage(status); 2930 2931 fLink.Flush(); 2932 break; 2933 } 2934 2935 case AS_GET_PIXEL_CLOCK_LIMITS: 2936 { 2937 STRACE(("ServerApp %s: get pixel clock limits\n", Signature())); 2938 // We aren't using the screen_id for now... 2939 int32 id; 2940 link.Read<int32>(&id); 2941 display_mode mode; 2942 link.Read<display_mode>(&mode); 2943 2944 uint32 low, high; 2945 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode, 2946 &low, &high); 2947 if (status == B_OK) { 2948 fLink.StartMessage(B_OK); 2949 fLink.Attach<uint32>(low); 2950 fLink.Attach<uint32>(high); 2951 } else 2952 fLink.StartMessage(status); 2953 2954 fLink.Flush(); 2955 break; 2956 } 2957 2958 case AS_SET_DPMS: 2959 { 2960 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature())); 2961 int32 id; 2962 link.Read<int32>(&id); 2963 2964 uint32 mode; 2965 link.Read<uint32>(&mode); 2966 2967 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode); 2968 fLink.StartMessage(status); 2969 2970 fLink.Flush(); 2971 break; 2972 } 2973 2974 case AS_GET_DPMS_STATE: 2975 { 2976 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature())); 2977 2978 int32 id; 2979 link.Read<int32>(&id); 2980 2981 uint32 state = fDesktop->HWInterface()->DPMSMode(); 2982 fLink.StartMessage(B_OK); 2983 fLink.Attach<uint32>(state); 2984 fLink.Flush(); 2985 break; 2986 } 2987 2988 case AS_GET_DPMS_CAPABILITIES: 2989 { 2990 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature())); 2991 int32 id; 2992 link.Read<int32>(&id); 2993 2994 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities(); 2995 fLink.StartMessage(B_OK); 2996 fLink.Attach<uint32>(capabilities); 2997 fLink.Flush(); 2998 break; 2999 } 3000 3001 case AS_READ_BITMAP: 3002 { 3003 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature())); 3004 int32 token; 3005 link.Read<int32>(&token); 3006 3007 bool drawCursor = true; 3008 link.Read<bool>(&drawCursor); 3009 3010 BRect bounds; 3011 link.Read<BRect>(&bounds); 3012 3013 bool success = false; 3014 3015 ServerBitmap* bitmap = GetBitmap(token); 3016 if (bitmap != NULL) { 3017 if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) { 3018 success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap, 3019 drawCursor, bounds) == B_OK; 3020 fDesktop->GetDrawingEngine()->UnlockExclusiveAccess(); 3021 } 3022 bitmap->ReleaseReference(); 3023 } 3024 3025 if (success) 3026 fLink.StartMessage(B_OK); 3027 else 3028 fLink.StartMessage(B_BAD_VALUE); 3029 3030 fLink.Flush(); 3031 break; 3032 } 3033 3034 case AS_GET_ACCELERANT_PATH: 3035 { 3036 int32 id; 3037 fLink.Read<int32>(&id); 3038 3039 BString path; 3040 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path); 3041 fLink.StartMessage(status); 3042 if (status == B_OK) 3043 fLink.AttachString(path.String()); 3044 3045 fLink.Flush(); 3046 break; 3047 } 3048 3049 case AS_GET_DRIVER_PATH: 3050 { 3051 int32 id; 3052 fLink.Read<int32>(&id); 3053 3054 BString path; 3055 status_t status = fDesktop->HWInterface()->GetDriverPath(path); 3056 fLink.StartMessage(status); 3057 if (status == B_OK) 3058 fLink.AttachString(path.String()); 3059 3060 fLink.Flush(); 3061 break; 3062 } 3063 3064 // BWindowScreen communication 3065 3066 case AS_DIRECT_SCREEN_LOCK: 3067 { 3068 bool lock; 3069 link.Read<bool>(&lock); 3070 3071 status_t status; 3072 if (lock) 3073 status = fDesktop->LockDirectScreen(ClientTeam()); 3074 else 3075 status = fDesktop->UnlockDirectScreen(ClientTeam()); 3076 3077 fLink.StartMessage(status); 3078 fLink.Flush(); 3079 break; 3080 } 3081 3082 // Hinting and aliasing 3083 3084 case AS_SET_SUBPIXEL_ANTIALIASING: 3085 { 3086 bool subpix; 3087 if (link.Read<bool>(&subpix) == B_OK) { 3088 LockedDesktopSettings settings(fDesktop); 3089 settings.SetSubpixelAntialiasing(subpix); 3090 } 3091 fDesktop->Redraw(); 3092 break; 3093 } 3094 3095 case AS_GET_SUBPIXEL_ANTIALIASING: 3096 { 3097 DesktopSettings settings(fDesktop); 3098 fLink.StartMessage(B_OK); 3099 fLink.Attach<bool>(settings.SubpixelAntialiasing()); 3100 fLink.Flush(); 3101 break; 3102 } 3103 3104 case AS_SET_HINTING: 3105 { 3106 uint8 hinting; 3107 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) { 3108 LockedDesktopSettings settings(fDesktop); 3109 if (hinting != settings.Hinting()) { 3110 settings.SetHinting(hinting); 3111 fDesktop->Redraw(); 3112 } 3113 } 3114 break; 3115 } 3116 3117 case AS_GET_HINTING: 3118 { 3119 DesktopSettings settings(fDesktop); 3120 fLink.StartMessage(B_OK); 3121 fLink.Attach<uint8>(settings.Hinting()); 3122 fLink.Flush(); 3123 break; 3124 } 3125 3126 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: 3127 { 3128 uint8 averageWeight; 3129 if (link.Read<uint8>(&averageWeight) == B_OK) { 3130 LockedDesktopSettings settings(fDesktop); 3131 settings.SetSubpixelAverageWeight(averageWeight); 3132 } 3133 fDesktop->Redraw(); 3134 break; 3135 } 3136 3137 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: 3138 { 3139 DesktopSettings settings(fDesktop); 3140 fLink.StartMessage(B_OK); 3141 fLink.Attach<uint8>(settings.SubpixelAverageWeight()); 3142 fLink.Flush(); 3143 break; 3144 } 3145 3146 case AS_SET_SUBPIXEL_ORDERING: 3147 { 3148 bool subpixelOrdering; 3149 if (link.Read<bool>(&subpixelOrdering) == B_OK) { 3150 LockedDesktopSettings settings(fDesktop); 3151 settings.SetSubpixelOrderingRegular(subpixelOrdering); 3152 } 3153 fDesktop->Redraw(); 3154 break; 3155 } 3156 3157 case AS_GET_SUBPIXEL_ORDERING: 3158 { 3159 DesktopSettings settings(fDesktop); 3160 fLink.StartMessage(B_OK); 3161 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular()); 3162 fLink.Flush(); 3163 break; 3164 } 3165 3166 default: 3167 printf("ServerApp %s received unhandled message code %" B_PRId32 3168 "\n", Signature(), code); 3169 3170 if (link.NeedsReply()) { 3171 // the client is now blocking and waiting for a reply! 3172 fLink.StartMessage(B_ERROR); 3173 fLink.Flush(); 3174 } else 3175 puts("message doesn't need a reply!"); 3176 break; 3177 } 3178 } 3179 3180 3181 /*! \brief The thread function ServerApps use to monitor messages 3182 */ 3183 void 3184 ServerApp::_MessageLooper() 3185 { 3186 // Message-dispatching loop for the ServerApp 3187 3188 // get our own team ID 3189 thread_info threadInfo; 3190 get_thread_info(fThread, &threadInfo); 3191 3192 // First let's tell the client how to talk with us. 3193 fLink.StartMessage(B_OK); 3194 fLink.Attach<port_id>(fMessagePort); 3195 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea()); 3196 fLink.Attach<team_id>(threadInfo.team); 3197 fLink.Flush(); 3198 3199 BPrivate::LinkReceiver &receiver = fLink.Receiver(); 3200 3201 int32 code; 3202 status_t err = B_OK; 3203 3204 while (!fQuitting) { 3205 STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32 3206 ".\n", fMessagePort)); 3207 3208 err = receiver.GetNextMessage(code, B_INFINITE_TIMEOUT); 3209 if (err != B_OK || code == B_QUIT_REQUESTED) { 3210 STRACE(("ServerApp: application seems to be gone...\n")); 3211 3212 // Tell desktop to quit us 3213 BPrivate::LinkSender link(fDesktop->MessagePort()); 3214 link.StartMessage(AS_DELETE_APP); 3215 link.Attach<thread_id>(Thread()); 3216 link.Flush(); 3217 break; 3218 } 3219 3220 switch (code) { 3221 case kMsgAppQuit: 3222 // we receive this from our destructor on quit 3223 fQuitting = true; 3224 break; 3225 3226 case AS_QUIT_APP: 3227 { 3228 // This message is received only when the app_server is asked 3229 // to shut down in test/debug mode. Of course, if we are testing 3230 // while using AccelerantDriver, we do NOT want to shut down 3231 // client applications. The server can be quit in this fashion 3232 // through the driver's interface, such as closing the 3233 // ViewDriver's window. 3234 3235 STRACE(("ServerApp %s:Server shutdown notification received\n", 3236 Signature())); 3237 3238 // If we are using the real, accelerated version of the 3239 // DrawingEngine, we do NOT want the user to be able shut down 3240 // the server. The results would NOT be pretty 3241 #if TEST_MODE 3242 BMessage pleaseQuit(B_QUIT_REQUESTED); 3243 SendMessageToClient(&pleaseQuit); 3244 #endif 3245 break; 3246 } 3247 3248 default: 3249 STRACE(("ServerApp %s: Got a Message to dispatch\n", 3250 Signature())); 3251 _DispatchMessage(code, receiver); 3252 break; 3253 } 3254 } 3255 3256 // Quit() will send us a message; we're handling the exiting procedure 3257 thread_id sender; 3258 sem_id shutdownSemaphore; 3259 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id)); 3260 3261 delete this; 3262 3263 if (shutdownSemaphore >= B_OK) 3264 release_sem(shutdownSemaphore); 3265 } 3266 3267 3268 status_t 3269 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link, 3270 port_id& clientReplyPort) 3271 { 3272 // Attached data: 3273 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) 3274 // 2) BRect window frame 3275 // 3) uint32 window look 3276 // 4) uint32 window feel 3277 // 5) uint32 window flags 3278 // 6) uint32 workspace index 3279 // 7) int32 BHandler token of the window 3280 // 8) port_id window's reply port 3281 // 9) port_id window's looper port 3282 // 10) const char * title 3283 3284 BRect frame; 3285 int32 bitmapToken; 3286 uint32 look; 3287 uint32 feel; 3288 uint32 flags; 3289 uint32 workspaces; 3290 int32 token; 3291 port_id looperPort; 3292 char* title; 3293 3294 if (code == AS_CREATE_OFFSCREEN_WINDOW) 3295 link.Read<int32>(&bitmapToken); 3296 3297 link.Read<BRect>(&frame); 3298 link.Read<uint32>(&look); 3299 link.Read<uint32>(&feel); 3300 link.Read<uint32>(&flags); 3301 link.Read<uint32>(&workspaces); 3302 link.Read<int32>(&token); 3303 link.Read<port_id>(&clientReplyPort); 3304 link.Read<port_id>(&looperPort); 3305 if (link.ReadString(&title) != B_OK) 3306 return B_ERROR; 3307 3308 if (!frame.IsValid()) { 3309 // make sure we pass a valid rectangle to ServerWindow 3310 frame.right = frame.left + 1; 3311 frame.bottom = frame.top + 1; 3312 } 3313 3314 status_t status = B_NO_MEMORY; 3315 ServerWindow *window = NULL; 3316 3317 if (code == AS_CREATE_OFFSCREEN_WINDOW) { 3318 ServerBitmap* bitmap = GetBitmap(bitmapToken); 3319 3320 if (bitmap != NULL) { 3321 window = new (nothrow) OffscreenServerWindow(title, this, 3322 clientReplyPort, looperPort, token, bitmap); 3323 } else 3324 status = B_ERROR; 3325 } else { 3326 window = new (nothrow) ServerWindow(title, this, clientReplyPort, 3327 looperPort, token); 3328 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n", 3329 Signature(), title, frame.left, frame.top, 3330 frame.right, frame.bottom)); 3331 } 3332 3333 free(title); 3334 3335 // NOTE: the reply to the client is handled in ServerWindow::Run() 3336 if (window != NULL) { 3337 status = window->Init(frame, (window_look)look, (window_feel)feel, 3338 flags, workspaces); 3339 if (status == B_OK && !window->Run()) { 3340 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run the " 3341 "window thread\n"); 3342 status = B_ERROR; 3343 } 3344 3345 if (status != B_OK) 3346 delete window; 3347 } 3348 3349 return status; 3350 } 3351 3352 3353 bool 3354 ServerApp::_HasWindowUnderMouse() 3355 { 3356 BAutolock locker(fWindowListLock); 3357 3358 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 3359 ServerWindow* serverWindow = fWindowList.ItemAt(i); 3360 3361 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN) 3362 return true; 3363 } 3364 3365 return false; 3366 } 3367 3368 3369 bool 3370 ServerApp::_AddBitmap(ServerBitmap* bitmap) 3371 { 3372 BAutolock _(fMapLocker); 3373 3374 try { 3375 fBitmapMap.insert(std::make_pair(bitmap->Token(), bitmap)); 3376 } catch (std::bad_alloc& exception) { 3377 return false; 3378 } 3379 3380 bitmap->SetOwner(this); 3381 return true; 3382 } 3383 3384 3385 void 3386 ServerApp::_DeleteBitmap(ServerBitmap* bitmap) 3387 { 3388 ASSERT(fMapLocker.IsLocked()); 3389 3390 gBitmapManager->BitmapRemoved(bitmap); 3391 fBitmapMap.erase(bitmap->Token()); 3392 3393 bitmap->ReleaseReference(); 3394 } 3395 3396 3397 ServerBitmap* 3398 ServerApp::_FindBitmap(int32 token) const 3399 { 3400 ASSERT(fMapLocker.IsLocked()); 3401 3402 BitmapMap::const_iterator iterator = fBitmapMap.find(token); 3403 if (iterator == fBitmapMap.end()) 3404 return NULL; 3405 3406 return iterator->second; 3407 } 3408 3409 3410 ServerPicture* 3411 ServerApp::_FindPicture(int32 token) const 3412 { 3413 ASSERT(fMapLocker.IsLocked()); 3414 3415 PictureMap::const_iterator iterator = fPictureMap.find(token); 3416 if (iterator == fPictureMap.end()) 3417 return NULL; 3418 3419 return iterator->second; 3420 } 3421