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