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