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