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; 1208 BRect cursorRect; 1209 color_space colorspace = B_RGBA32; 1210 BPoint hotspot; 1211 ServerCursor* cursor = NULL; 1212 1213 if (link.Read<int32>(&size) == B_OK 1214 && link.Read<BRect>(&cursorRect) == B_OK 1215 && link.Read<color_space>(&colorspace) == B_OK 1216 && link.Read<BPoint>(&hotspot) == B_OK 1217 && size > 0) { 1218 1219 BStackOrHeapArray<uint8, 256> byteArray(size); 1220 if (!byteArray.IsValid()) { 1221 status = B_NO_MEMORY; 1222 } else if (link.Read(byteArray, size) == B_OK) { 1223 cursor = fDesktop->GetCursorManager().CreateCursor( 1224 fClientTeam, cursorRect, colorspace, 0, hotspot); 1225 if (cursor == NULL) 1226 status = B_NO_MEMORY; 1227 else 1228 memcpy(cursor->Bits(), byteArray, size); 1229 } 1230 } 1231 1232 if (cursor != NULL) { 1233 // Synchronous message - BApplication is waiting on the 1234 // cursor's ID 1235 fLink.StartMessage(B_OK); 1236 fLink.Attach<int32>(cursor->Token()); 1237 } else 1238 fLink.StartMessage(status); 1239 1240 fLink.Flush(); 1241 break; 1242 } 1243 1244 case AS_REFERENCE_CURSOR: 1245 { 1246 STRACE(("ServerApp %s: Reference BCursor\n", Signature())); 1247 1248 // Attached data: 1249 // 1) int32 token ID of the cursor to reference 1250 1251 int32 token; 1252 if (link.Read<int32>(&token) != B_OK) 1253 break; 1254 1255 if (!fDesktop->GetCursorManager().Lock()) 1256 break; 1257 1258 ServerCursor* cursor 1259 = fDesktop->GetCursorManager().FindCursor(token); 1260 if (cursor != NULL) 1261 cursor->AcquireReference(); 1262 1263 fDesktop->GetCursorManager().Unlock(); 1264 1265 break; 1266 } 1267 1268 case AS_DELETE_CURSOR: 1269 { 1270 STRACE(("ServerApp %s: Delete BCursor\n", Signature())); 1271 1272 // Attached data: 1273 // 1) int32 token ID of the cursor to delete 1274 1275 int32 token; 1276 if (link.Read<int32>(&token) != B_OK) 1277 break; 1278 1279 if (!fDesktop->GetCursorManager().Lock()) 1280 break; 1281 1282 ServerCursor* cursor 1283 = fDesktop->GetCursorManager().FindCursor(token); 1284 if (cursor != NULL) 1285 cursor->ReleaseReference(); 1286 1287 fDesktop->GetCursorManager().Unlock(); 1288 1289 break; 1290 } 1291 1292 case AS_GET_CURSOR_POSITION: 1293 { 1294 STRACE(("ServerApp %s: Get Cursor position\n", Signature())); 1295 1296 // Returns 1297 // 1) BPoint mouse location 1298 // 2) int32 button state 1299 1300 BPoint where; 1301 int32 buttons; 1302 fDesktop->GetLastMouseState(&where, &buttons); 1303 fLink.StartMessage(B_OK); 1304 fLink.Attach<BPoint>(where); 1305 fLink.Attach<int32>(buttons); 1306 fLink.Flush(); 1307 break; 1308 } 1309 1310 case AS_GET_CURSOR_BITMAP: 1311 { 1312 STRACE(("ServerApp %s: Get Cursor bitmap\n", Signature())); 1313 1314 // Returns 1315 // 1) uint32 number of data bytes of the bitmap 1316 // 2) uint32 cursor width in number of pixels 1317 // 3) uint32 cursor height in number of pixels 1318 // 4) BPoint cursor hot spot 1319 // 5) cursor bitmap data 1320 1321 ServerCursorReference cursorRef = fDesktop->Cursor(); 1322 ServerCursor* cursor = cursorRef.Get(); 1323 if (cursor != NULL) { 1324 uint32 size = cursor->BitsLength(); 1325 fLink.StartMessage(B_OK); 1326 fLink.Attach<uint32>(size); 1327 fLink.Attach<uint32>(cursor->Width()); 1328 fLink.Attach<uint32>(cursor->Height()); 1329 fLink.Attach<color_space>(cursor->ColorSpace()); 1330 fLink.Attach<BPoint>(cursor->GetHotSpot()); 1331 fLink.Attach(cursor->Bits(), size); 1332 } else 1333 fLink.StartMessage(B_ERROR); 1334 1335 fLink.Flush(); 1336 1337 break; 1338 } 1339 1340 case AS_GET_SCROLLBAR_INFO: 1341 { 1342 STRACE(("ServerApp %s: Get ScrollBar info\n", Signature())); 1343 1344 if (fDesktop->LockSingleWindow()) { 1345 scroll_bar_info info; 1346 DesktopSettings settings(fDesktop); 1347 settings.GetScrollBarInfo(info); 1348 1349 fLink.StartMessage(B_OK); 1350 fLink.Attach<scroll_bar_info>(info); 1351 fDesktop->UnlockSingleWindow(); 1352 } else 1353 fLink.StartMessage(B_ERROR); 1354 1355 fLink.Flush(); 1356 break; 1357 } 1358 1359 case AS_SET_SCROLLBAR_INFO: 1360 { 1361 STRACE(("ServerApp %s: Set ScrollBar info\n", Signature())); 1362 1363 // Attached Data: 1364 // 1) scroll_bar_info scroll bar info structure 1365 1366 scroll_bar_info info; 1367 if (link.Read<scroll_bar_info>(&info) == B_OK) { 1368 LockedDesktopSettings settings(fDesktop); 1369 settings.SetScrollBarInfo(info); 1370 } 1371 1372 fLink.StartMessage(B_OK); 1373 fLink.Flush(); 1374 break; 1375 } 1376 1377 case AS_GET_MENU_INFO: 1378 { 1379 STRACE(("ServerApp %s: Get menu info\n", Signature())); 1380 if (fDesktop->LockSingleWindow()) { 1381 menu_info info; 1382 DesktopSettings settings(fDesktop); 1383 settings.GetMenuInfo(info); 1384 1385 fLink.StartMessage(B_OK); 1386 fLink.Attach<menu_info>(info); 1387 1388 fDesktop->UnlockSingleWindow(); 1389 } else 1390 fLink.StartMessage(B_ERROR); 1391 1392 fLink.Flush(); 1393 break; 1394 } 1395 1396 case AS_SET_MENU_INFO: 1397 { 1398 STRACE(("ServerApp %s: Set menu info\n", Signature())); 1399 menu_info info; 1400 if (link.Read<menu_info>(&info) == B_OK) { 1401 LockedDesktopSettings settings(fDesktop); 1402 settings.SetMenuInfo(info); 1403 // TODO: SetMenuInfo() should do some validity check, so 1404 // that the answer we're giving can actually be useful 1405 } 1406 1407 fLink.StartMessage(B_OK); 1408 fLink.Flush(); 1409 break; 1410 } 1411 1412 case AS_SET_MOUSE_MODE: 1413 { 1414 STRACE(("ServerApp %s: Set Mouse Focus mode\n", 1415 Signature())); 1416 1417 // Attached Data: 1418 // 1) enum mode_mouse mouse focus mode 1419 1420 mode_mouse mouseMode; 1421 if (link.Read<mode_mouse>(&mouseMode) == B_OK) { 1422 LockedDesktopSettings settings(fDesktop); 1423 settings.SetMouseMode(mouseMode); 1424 } 1425 break; 1426 } 1427 1428 case AS_GET_MOUSE_MODE: 1429 { 1430 STRACE(("ServerApp %s: Get Mouse Focus mode\n", 1431 Signature())); 1432 1433 if (fDesktop->LockSingleWindow()) { 1434 DesktopSettings settings(fDesktop); 1435 1436 fLink.StartMessage(B_OK); 1437 fLink.Attach<mode_mouse>(settings.MouseMode()); 1438 1439 fDesktop->UnlockSingleWindow(); 1440 } else 1441 fLink.StartMessage(B_ERROR); 1442 1443 fLink.Flush(); 1444 break; 1445 } 1446 1447 case AS_SET_FOCUS_FOLLOWS_MOUSE_MODE: 1448 { 1449 STRACE(("ServerApp %s: Set Focus Follows Mouse mode\n", Signature())); 1450 1451 // Attached Data: 1452 // 1) enum mode_focus_follows_mouse FFM mouse mode 1453 1454 mode_focus_follows_mouse focusFollowsMousMode; 1455 if (link.Read<mode_focus_follows_mouse>(&focusFollowsMousMode) == B_OK) { 1456 LockedDesktopSettings settings(fDesktop); 1457 settings.SetFocusFollowsMouseMode(focusFollowsMousMode); 1458 } 1459 break; 1460 } 1461 1462 case AS_GET_FOCUS_FOLLOWS_MOUSE_MODE: 1463 { 1464 STRACE(("ServerApp %s: Get Focus Follows Mouse mode\n", Signature())); 1465 1466 if (fDesktop->LockSingleWindow()) { 1467 DesktopSettings settings(fDesktop); 1468 1469 fLink.StartMessage(B_OK); 1470 fLink.Attach<mode_focus_follows_mouse>( 1471 settings.FocusFollowsMouseMode()); 1472 1473 fDesktop->UnlockSingleWindow(); 1474 } else 1475 fLink.StartMessage(B_ERROR); 1476 1477 fLink.Flush(); 1478 break; 1479 } 1480 1481 case AS_SET_ACCEPT_FIRST_CLICK: 1482 { 1483 STRACE(("ServerApp %s: Set Accept First Click\n", Signature())); 1484 1485 // Attached Data: 1486 // 1) bool accept_first_click 1487 1488 bool acceptFirstClick; 1489 if (link.Read<bool>(&acceptFirstClick) == B_OK) { 1490 LockedDesktopSettings settings(fDesktop); 1491 settings.SetAcceptFirstClick(acceptFirstClick); 1492 } 1493 break; 1494 } 1495 1496 case AS_GET_ACCEPT_FIRST_CLICK: 1497 { 1498 STRACE(("ServerApp %s: Get Accept First Click\n", Signature())); 1499 1500 if (fDesktop->LockSingleWindow()) { 1501 DesktopSettings settings(fDesktop); 1502 1503 fLink.StartMessage(B_OK); 1504 fLink.Attach<bool>(settings.AcceptFirstClick()); 1505 1506 fDesktop->UnlockSingleWindow(); 1507 } else 1508 fLink.StartMessage(B_ERROR); 1509 1510 fLink.Flush(); 1511 break; 1512 } 1513 1514 case AS_GET_SHOW_ALL_DRAGGERS: 1515 { 1516 STRACE(("ServerApp %s: Get Show All Draggers\n", Signature())); 1517 1518 if (fDesktop->LockSingleWindow()) { 1519 DesktopSettings settings(fDesktop); 1520 1521 fLink.StartMessage(B_OK); 1522 fLink.Attach<bool>(settings.ShowAllDraggers()); 1523 1524 fDesktop->UnlockSingleWindow(); 1525 } else 1526 fLink.StartMessage(B_ERROR); 1527 1528 fLink.Flush(); 1529 break; 1530 } 1531 1532 case AS_SET_SHOW_ALL_DRAGGERS: 1533 { 1534 STRACE(("ServerApp %s: Set Show All Draggers\n", Signature())); 1535 1536 bool changed = false; 1537 bool show; 1538 if (link.Read<bool>(&show) == B_OK) { 1539 LockedDesktopSettings settings(fDesktop); 1540 if (show != settings.ShowAllDraggers()) { 1541 settings.SetShowAllDraggers(show); 1542 changed = true; 1543 } 1544 } 1545 1546 if (changed) 1547 fDesktop->BroadcastToAllApps(kMsgUpdateShowAllDraggers); 1548 break; 1549 } 1550 1551 case kMsgUpdateShowAllDraggers: 1552 { 1553 bool show = false; 1554 if (fDesktop->LockSingleWindow()) { 1555 DesktopSettings settings(fDesktop); 1556 show = settings.ShowAllDraggers(); 1557 fDesktop->UnlockSingleWindow(); 1558 } 1559 BMessage update(_SHOW_DRAG_HANDLES_); 1560 update.AddBool("show", show); 1561 1562 SendMessageToClient(&update); 1563 break; 1564 } 1565 1566 /* font messages */ 1567 1568 case AS_SET_SYSTEM_FONT: 1569 { 1570 FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature())); 1571 // gets: 1572 // 1) string - font type ("plain", ...) 1573 // 2) string - family 1574 // 3) string - style 1575 // 4) float - size 1576 1577 char type[B_OS_NAME_LENGTH]; 1578 font_family familyName; 1579 font_style styleName; 1580 float size; 1581 1582 if (link.ReadString(type, sizeof(type)) == B_OK 1583 && link.ReadString(familyName, sizeof(familyName)) == B_OK 1584 && link.ReadString(styleName, sizeof(styleName)) == B_OK 1585 && link.Read<float>(&size) == B_OK) { 1586 gFontManager->Lock(); 1587 1588 FontStyle* style 1589 = gFontManager->GetStyle(familyName, styleName); 1590 if (style != NULL) { 1591 ServerFont font(*style, size); 1592 gFontManager->Unlock(); 1593 // We must not have locked the font manager when 1594 // locking the desktop (through LockedDesktopSettings 1595 // below) 1596 1597 LockedDesktopSettings settings(fDesktop); 1598 1599 // TODO: Should we also update our internal copies now? 1600 if (strcmp(type, "plain") == 0) 1601 settings.SetDefaultPlainFont(font); 1602 else if (strcmp(type, "bold") == 0) 1603 settings.SetDefaultBoldFont(font); 1604 else if (strcmp(type, "fixed") == 0) 1605 settings.SetDefaultFixedFont(font); 1606 } else 1607 gFontManager->Unlock(); 1608 } 1609 break; 1610 } 1611 1612 case AS_GET_SYSTEM_DEFAULT_FONT: 1613 { 1614 // input: 1615 // 1) string - font type ("plain", ...) 1616 1617 ServerFont font; 1618 1619 char type[B_OS_NAME_LENGTH]; 1620 status_t status = link.ReadString(type, sizeof(type)); 1621 if (status == B_OK) { 1622 if (!strcmp(type, "plain")) { 1623 font = *gFontManager->DefaultPlainFont(); 1624 } else if (!strcmp(type, "bold")) { 1625 font = *gFontManager->DefaultBoldFont(); 1626 } else if (!strcmp(type, "fixed")) { 1627 font = *gFontManager->DefaultFixedFont(); 1628 } else 1629 status = B_BAD_VALUE; 1630 } 1631 1632 if (status == B_OK) { 1633 // returns: 1634 // 1) string - family 1635 // 2) string - style 1636 // 3) float - size 1637 1638 fLink.StartMessage(B_OK); 1639 fLink.AttachString(font.Family()); 1640 fLink.AttachString(font.Style()); 1641 fLink.Attach<float>(font.Size()); 1642 } else 1643 fLink.StartMessage(status); 1644 1645 fLink.Flush(); 1646 break; 1647 } 1648 1649 case AS_GET_SYSTEM_FONTS: 1650 { 1651 FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature())); 1652 // Returns: 1653 // 1) uint16 - family ID 1654 // 2) uint16 - style ID 1655 // 3) float - size in points 1656 // 4) uint16 - face flags 1657 // 5) uint32 - font flags 1658 1659 if (!fDesktop->LockSingleWindow()) { 1660 fLink.StartMessage(B_OK); 1661 fLink.Flush(); 1662 break; 1663 } 1664 1665 // The client is requesting the system fonts, this 1666 // could happend either at application start up, or 1667 // because the client is resyncing with the global 1668 // fonts. So we record the current system wide fonts 1669 // into our own copies at this point. 1670 DesktopSettings settings(fDesktop); 1671 1672 settings.GetDefaultPlainFont(fPlainFont); 1673 settings.GetDefaultBoldFont(fBoldFont); 1674 settings.GetDefaultFixedFont(fFixedFont); 1675 1676 fLink.StartMessage(B_OK); 1677 1678 for (int32 i = 0; i < 3; i++) { 1679 ServerFont* font = NULL; 1680 switch (i) { 1681 case 0: 1682 font = &fPlainFont; 1683 fLink.AttachString("plain"); 1684 break; 1685 1686 case 1: 1687 font = &fBoldFont; 1688 fLink.AttachString("bold"); 1689 break; 1690 1691 case 2: 1692 font = &fFixedFont; 1693 fLink.AttachString("fixed"); 1694 break; 1695 } 1696 1697 fLink.Attach<uint16>(font->FamilyID()); 1698 fLink.Attach<uint16>(font->StyleID()); 1699 fLink.Attach<float>(font->Size()); 1700 fLink.Attach<uint16>(font->Face()); 1701 fLink.Attach<uint32>(font->Flags()); 1702 } 1703 1704 fDesktop->UnlockSingleWindow(); 1705 fLink.Flush(); 1706 break; 1707 } 1708 1709 case AS_GET_FONT_LIST_REVISION: 1710 { 1711 STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature())); 1712 1713 fLink.StartMessage(B_OK); 1714 fLink.Attach<int32>( 1715 gFontManager->CheckRevision(fDesktop->UserID())); 1716 fLink.Flush(); 1717 break; 1718 } 1719 1720 case AS_GET_FAMILY_AND_STYLES: 1721 { 1722 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature())); 1723 1724 // Attached Data: 1725 // 1) int32 the index of the font family to get 1726 1727 // Returns: 1728 // 1) string - name of family 1729 // 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT) 1730 // 3) count of styles in that family 1731 // For each style: 1732 // 1) string - name of style 1733 // 2) uint16 - face of style 1734 // 3) uint32 - flags of style 1735 1736 int32 index; 1737 link.Read<int32>(&index); 1738 1739 gFontManager->Lock(); 1740 1741 FontFamily* family = gFontManager->FamilyAt(index); 1742 if (family) { 1743 fLink.StartMessage(B_OK); 1744 fLink.AttachString(family->Name()); 1745 fLink.Attach<uint32>(family->Flags()); 1746 1747 int32 count = family->CountStyles(); 1748 fLink.Attach<int32>(count); 1749 1750 for (int32 i = 0; i < count; i++) { 1751 FontStyle* style = family->StyleAt(i); 1752 1753 fLink.AttachString(style->Name()); 1754 fLink.Attach<uint16>(style->Face()); 1755 fLink.Attach<uint32>(style->Flags()); 1756 } 1757 } else 1758 fLink.StartMessage(B_BAD_VALUE); 1759 1760 gFontManager->Unlock(); 1761 fLink.Flush(); 1762 break; 1763 } 1764 1765 case AS_GET_FAMILY_AND_STYLE: 1766 { 1767 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE\n", Signature())); 1768 1769 // Attached Data: 1770 // 1) uint16 - family ID 1771 // 2) uint16 - style ID 1772 1773 // Returns: 1774 // 1) font_family The name of the font family 1775 // 2) font_style - name of the style 1776 1777 uint16 familyID, styleID; 1778 link.Read<uint16>(&familyID); 1779 link.Read<uint16>(&styleID); 1780 1781 gFontManager->Lock(); 1782 1783 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1784 if (fontStyle != NULL) { 1785 fLink.StartMessage(B_OK); 1786 fLink.AttachString(fontStyle->Family()->Name()); 1787 fLink.AttachString(fontStyle->Name()); 1788 } else 1789 fLink.StartMessage(B_BAD_VALUE); 1790 1791 fLink.Flush(); 1792 gFontManager->Unlock(); 1793 break; 1794 } 1795 1796 case AS_GET_FAMILY_AND_STYLE_IDS: 1797 { 1798 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE_IDS\n", 1799 Signature())); 1800 1801 // Attached Data: 1802 // 1) font_family - name of font family to use 1803 // 2) font_style - name of style in family 1804 // 3) family ID - only used if 1) is empty 1805 // 4) style ID - only used if 2) is empty 1806 // 5) face - the font's current face 1807 1808 // Returns: 1809 // 1) uint16 - family ID 1810 // 2) uint16 - style ID 1811 // 3) uint16 - face 1812 1813 font_family family; 1814 font_style style; 1815 uint16 familyID, styleID; 1816 uint16 face; 1817 if (link.ReadString(family, sizeof(font_family)) == B_OK 1818 && link.ReadString(style, sizeof(font_style)) == B_OK 1819 && link.Read<uint16>(&familyID) == B_OK 1820 && link.Read<uint16>(&styleID) == B_OK 1821 && link.Read<uint16>(&face) == B_OK) { 1822 // get the font and return IDs and face 1823 gFontManager->Lock(); 1824 1825 FontStyle *fontStyle = gFontManager->GetStyle(family, style, 1826 familyID, styleID, face); 1827 1828 if (fontStyle != NULL) { 1829 fLink.StartMessage(B_OK); 1830 fLink.Attach<uint16>(fontStyle->Family()->ID()); 1831 fLink.Attach<uint16>(fontStyle->ID()); 1832 1833 // we try to keep the font face close to what we got 1834 face = fontStyle->PreservedFace(face); 1835 1836 fLink.Attach<uint16>(face); 1837 } else 1838 fLink.StartMessage(B_NAME_NOT_FOUND); 1839 1840 gFontManager->Unlock(); 1841 } else 1842 fLink.StartMessage(B_BAD_VALUE); 1843 1844 fLink.Flush(); 1845 break; 1846 } 1847 1848 case AS_GET_FONT_FILE_FORMAT: 1849 { 1850 FTRACE(("ServerApp %s: AS_GET_FONT_FILE_FORMAT\n", Signature())); 1851 1852 // Attached Data: 1853 // 1) uint16 - family ID 1854 // 2) uint16 - style ID 1855 1856 // Returns: 1857 // 1) uint16 font_file_format of font 1858 1859 int32 familyID, styleID; 1860 link.Read<int32>(&familyID); 1861 link.Read<int32>(&styleID); 1862 1863 gFontManager->Lock(); 1864 1865 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1866 if (fontStyle) { 1867 fLink.StartMessage(B_OK); 1868 fLink.Attach<uint16>((uint16)fontStyle->FileFormat()); 1869 } else 1870 fLink.StartMessage(B_BAD_VALUE); 1871 1872 gFontManager->Unlock(); 1873 fLink.Flush(); 1874 break; 1875 } 1876 1877 case AS_GET_STRING_WIDTHS: 1878 { 1879 FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature())); 1880 1881 // Attached Data: 1882 // 1) uint16 ID of family 1883 // 2) uint16 ID of style 1884 // 3) float point size of font 1885 // 4) uint8 spacing to use 1886 // 5) int32 numStrings 1887 // 6) int32 string length to measure (numStrings times) 1888 // 7) string String to measure (numStrings times) 1889 1890 // Returns: 1891 // 1) float - width of the string in pixels (numStrings times) 1892 1893 uint16 family, style; 1894 float size; 1895 uint8 spacing; 1896 1897 link.Read<uint16>(&family); 1898 link.Read<uint16>(&style); 1899 link.Read<float>(&size); 1900 link.Read<uint8>(&spacing); 1901 int32 numStrings; 1902 if (link.Read<int32>(&numStrings) != B_OK) { 1903 // this results in a B_BAD_VALUE return 1904 numStrings = 0; 1905 size = 0.0f; 1906 } 1907 1908 BStackOrHeapArray<float, 64> widthArray(numStrings); 1909 BStackOrHeapArray<int32, 64> lengthArray(numStrings); 1910 BStackOrHeapArray<char*, 64> stringArray(numStrings); 1911 if (!widthArray.IsValid() || !lengthArray.IsValid() 1912 || !stringArray.IsValid()) { 1913 fLink.StartMessage(B_NO_MEMORY); 1914 fLink.Flush(); 1915 break; 1916 } 1917 1918 for (int32 i = 0; i < numStrings; i++) { 1919 // This version of ReadString allocates the strings, we free 1920 // them below 1921 link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]); 1922 } 1923 1924 ServerFont font; 1925 1926 if (font.SetFamilyAndStyle(family, style) == B_OK && size > 0) { 1927 font.SetSize(size); 1928 font.SetSpacing(spacing); 1929 1930 for (int32 i = 0; i < numStrings; i++) { 1931 if (!stringArray[i] || lengthArray[i] <= 0) 1932 widthArray[i] = 0.0; 1933 else { 1934 widthArray[i] = font.StringWidth(stringArray[i], 1935 lengthArray[i]); 1936 } 1937 } 1938 1939 fLink.StartMessage(B_OK); 1940 fLink.Attach(widthArray, numStrings * sizeof(float)); 1941 } else 1942 fLink.StartMessage(B_BAD_VALUE); 1943 1944 fLink.Flush(); 1945 1946 for (int32 i = 0; i < numStrings; i++) 1947 free(stringArray[i]); 1948 break; 1949 } 1950 1951 case AS_GET_FONT_BOUNDING_BOX: 1952 { 1953 FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX unimplemented\n", 1954 Signature())); 1955 1956 // Attached Data: 1957 // 1) uint16 - family ID 1958 // 2) uint16 - style ID 1959 1960 // Returns: 1961 // 1) BRect - box holding entire font 1962 1963 // ToDo: implement me! 1964 fLink.StartMessage(B_ERROR); 1965 fLink.Flush(); 1966 break; 1967 } 1968 1969 case AS_GET_TUNED_COUNT: 1970 { 1971 FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature())); 1972 1973 // Attached Data: 1974 // 1) uint16 - family ID 1975 // 2) uint16 - style ID 1976 1977 // Returns: 1978 // 1) int32 - number of font strikes available 1979 1980 uint16 familyID, styleID; 1981 link.Read<uint16>(&familyID); 1982 link.Read<uint16>(&styleID); 1983 1984 gFontManager->Lock(); 1985 1986 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1987 if (fontStyle != NULL) { 1988 fLink.StartMessage(B_OK); 1989 fLink.Attach<int32>(fontStyle->TunedCount()); 1990 } else 1991 fLink.StartMessage(B_BAD_VALUE); 1992 1993 gFontManager->Unlock(); 1994 fLink.Flush(); 1995 break; 1996 } 1997 1998 case AS_GET_TUNED_INFO: 1999 { 2000 FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n", 2001 Signature())); 2002 2003 // Attached Data: 2004 // 1) uint16 - family ID 2005 // 2) uint16 - style ID 2006 // 3) uint32 - index of the particular font strike 2007 2008 // Returns: 2009 // 1) tuned_font_info - info on the strike specified 2010 // ToDo: implement me! 2011 2012 fLink.StartMessage(B_ERROR); 2013 fLink.Flush(); 2014 break; 2015 } 2016 2017 case AS_GET_EXTRA_FONT_FLAGS: 2018 { 2019 FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n", 2020 Signature())); 2021 2022 // Attached Data: 2023 // 1) uint16 - family ID 2024 // 2) uint16 - style ID 2025 2026 // Returns: 2027 // 1) uint32 - extra font flags 2028 2029 uint16 familyID, styleID; 2030 link.Read<uint16>(&familyID); 2031 link.Read<uint16>(&styleID); 2032 2033 gFontManager->Lock(); 2034 2035 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2036 if (fontStyle != NULL) { 2037 fLink.StartMessage(B_OK); 2038 fLink.Attach<uint32>(fontStyle->Flags()); 2039 } else 2040 fLink.StartMessage(B_BAD_VALUE); 2041 2042 gFontManager->Unlock(); 2043 fLink.Flush(); 2044 break; 2045 } 2046 2047 case AS_GET_FONT_HEIGHT: 2048 { 2049 FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature())); 2050 2051 // Attached Data: 2052 // 1) uint16 family ID 2053 // 2) uint16 style ID 2054 // 3) float size 2055 2056 uint16 familyID, styleID; 2057 float size; 2058 link.Read<uint16>(&familyID); 2059 link.Read<uint16>(&styleID); 2060 link.Read<float>(&size); 2061 2062 gFontManager->Lock(); 2063 2064 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2065 if (fontStyle != NULL) { 2066 font_height height; 2067 fontStyle->GetHeight(size, height); 2068 2069 fLink.StartMessage(B_OK); 2070 fLink.Attach<font_height>(height); 2071 } else 2072 fLink.StartMessage(B_BAD_VALUE); 2073 2074 gFontManager->Unlock(); 2075 fLink.Flush(); 2076 break; 2077 } 2078 2079 case AS_GET_UNICODE_BLOCKS: 2080 { 2081 FTRACE(("ServerApp %s: AS_GET_UNICODE_BLOCKS\n", Signature())); 2082 2083 // Attached Data: 2084 // 1) uint16 family ID 2085 // 2) uint16 style ID 2086 2087 // Returns: 2088 // 1) unicode_block - bitfield of Unicode blocks in font 2089 2090 uint16 familyID, styleID; 2091 link.Read<uint16>(&familyID); 2092 link.Read<uint16>(&styleID); 2093 2094 ServerFont font; 2095 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2096 if (status == B_OK) { 2097 unicode_block blocksForFont; 2098 font.GetUnicodeBlocks(blocksForFont); 2099 2100 fLink.StartMessage(B_OK); 2101 fLink.Attach<unicode_block>(blocksForFont); 2102 } else 2103 fLink.StartMessage(status); 2104 2105 fLink.Flush(); 2106 break; 2107 } 2108 2109 case AS_GET_HAS_UNICODE_BLOCK: 2110 { 2111 FTRACE(("ServerApp %s: AS_INCLUDES_UNICODE_BLOCK\n", Signature())); 2112 2113 // Attached Data: 2114 // 1) uint16 family ID 2115 // 2) uint16 style ID 2116 // 3) uint32 start of unicode block 2117 // 4) uint32 end of unicode block 2118 2119 // Returns: 2120 // 1) bool - whether or not font includes specified block range 2121 2122 uint16 familyID, styleID; 2123 uint32 start, end; 2124 link.Read<uint16>(&familyID); 2125 link.Read<uint16>(&styleID); 2126 link.Read<uint32>(&start); 2127 link.Read<uint32>(&end); 2128 2129 ServerFont font; 2130 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2131 if (status == B_OK) { 2132 bool hasBlock; 2133 2134 status = font.IncludesUnicodeBlock(start, end, hasBlock); 2135 fLink.StartMessage(status); 2136 fLink.Attach<bool>(hasBlock); 2137 } else 2138 fLink.StartMessage(status); 2139 2140 fLink.Flush(); 2141 break; 2142 } 2143 2144 case AS_GET_GLYPH_SHAPES: 2145 { 2146 FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature())); 2147 2148 // Attached Data: 2149 // 1) uint16 - family ID 2150 // 2) uint16 - style ID 2151 // 3) float - point size 2152 // 4) float - shear 2153 // 5) float - rotation 2154 // 6) float - false bold width 2155 // 6) uint32 - flags 2156 // 7) int32 - numChars 2157 // 8) int32 - numBytes 2158 // 8) char - chars (numBytes times) 2159 2160 // Returns: 2161 // 1) BShape - glyph shape 2162 // numChars times 2163 2164 uint16 familyID, styleID; 2165 uint32 flags; 2166 float size, shear, rotation, falseBoldWidth; 2167 2168 link.Read<uint16>(&familyID); 2169 link.Read<uint16>(&styleID); 2170 link.Read<float>(&size); 2171 link.Read<float>(&shear); 2172 link.Read<float>(&rotation); 2173 link.Read<float>(&falseBoldWidth); 2174 link.Read<uint32>(&flags); 2175 2176 int32 numChars, numBytes; 2177 link.Read<int32>(&numChars); 2178 link.Read<int32>(&numBytes); 2179 2180 BStackOrHeapArray<char, 256> charArray(numBytes); 2181 BStackOrHeapArray<BShape*, 64> shapes(numChars); 2182 if (!charArray.IsValid() || !shapes.IsValid()) { 2183 fLink.StartMessage(B_NO_MEMORY); 2184 fLink.Flush(); 2185 break; 2186 } 2187 2188 link.Read(charArray, numBytes); 2189 2190 ServerFont font; 2191 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2192 if (status == B_OK) { 2193 font.SetSize(size); 2194 font.SetShear(shear); 2195 font.SetRotation(rotation); 2196 font.SetFalseBoldWidth(falseBoldWidth); 2197 font.SetFlags(flags); 2198 2199 status = font.GetGlyphShapes(charArray, numChars, shapes); 2200 if (status == B_OK) { 2201 fLink.StartMessage(B_OK); 2202 for (int32 i = 0; i < numChars; i++) { 2203 fLink.AttachShape(*shapes[i]); 2204 delete shapes[i]; 2205 } 2206 } 2207 } 2208 2209 if (status != B_OK) 2210 fLink.StartMessage(status); 2211 2212 fLink.Flush(); 2213 break; 2214 } 2215 2216 case AS_GET_HAS_GLYPHS: 2217 { 2218 FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature())); 2219 2220 // Attached Data: 2221 // 1) uint16 - family ID 2222 // 2) uint16 - style ID 2223 // 3) int32 - numChars 2224 // 4) int32 - numBytes 2225 // 5) char - the char buffer with size numBytes 2226 2227 uint16 familyID, styleID; 2228 link.Read<uint16>(&familyID); 2229 link.Read<uint16>(&styleID); 2230 2231 int32 numChars, numBytes; 2232 link.Read<int32>(&numChars); 2233 link.Read<int32>(&numBytes); 2234 2235 BStackOrHeapArray<char, 256> charArray(numBytes); 2236 BStackOrHeapArray<bool, 256> hasArray(numChars); 2237 if (!charArray.IsValid() || !hasArray.IsValid()) { 2238 fLink.StartMessage(B_NO_MEMORY); 2239 fLink.Flush(); 2240 break; 2241 } 2242 2243 link.Read(charArray, numBytes); 2244 2245 ServerFont font; 2246 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2247 if (status == B_OK) { 2248 status = font.GetHasGlyphs(charArray, numBytes, numChars, 2249 hasArray); 2250 if (status == B_OK) { 2251 fLink.StartMessage(B_OK); 2252 fLink.Attach(hasArray, numChars * sizeof(bool)); 2253 } 2254 } 2255 2256 if (status != B_OK) 2257 fLink.StartMessage(status); 2258 2259 fLink.Flush(); 2260 break; 2261 } 2262 2263 case AS_GET_EDGES: 2264 { 2265 FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature())); 2266 2267 // Attached Data: 2268 // 1) uint16 - family ID 2269 // 2) uint16 - style ID 2270 // 3) int32 - numChars 2271 // 4) int32 - numBytes 2272 // 5) char - the char buffer with size numBytes 2273 2274 uint16 familyID, styleID; 2275 link.Read<uint16>(&familyID); 2276 link.Read<uint16>(&styleID); 2277 2278 int32 numChars; 2279 link.Read<int32>(&numChars); 2280 2281 uint32 numBytes; 2282 link.Read<uint32>(&numBytes); 2283 2284 BStackOrHeapArray<char, 256> charArray(numBytes); 2285 BStackOrHeapArray<edge_info, 64> edgeArray(numChars); 2286 if (!charArray.IsValid() || !edgeArray.IsValid()) { 2287 fLink.StartMessage(B_NO_MEMORY); 2288 fLink.Flush(); 2289 break; 2290 } 2291 2292 link.Read(charArray, numBytes); 2293 2294 ServerFont font; 2295 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2296 if (status == B_OK) { 2297 status = font.GetEdges(charArray, numBytes, numChars, 2298 edgeArray); 2299 if (status == B_OK) { 2300 fLink.StartMessage(B_OK); 2301 fLink.Attach(edgeArray, numChars * sizeof(edge_info)); 2302 } 2303 } 2304 2305 if (status != B_OK) 2306 fLink.StartMessage(status); 2307 2308 fLink.Flush(); 2309 break; 2310 } 2311 2312 case AS_GET_ESCAPEMENTS: 2313 { 2314 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature())); 2315 2316 // Attached Data: 2317 // 1) uint16 - family ID 2318 // 2) uint16 - style ID 2319 // 3) float - point size 2320 // 4) uint8 - spacing 2321 // 5) float - rotation 2322 // 6) uint32 - flags 2323 // 7) int32 - numChars 2324 // 8) char - char -\ both 2325 // 9) BPoint - offset -/ (numChars times) 2326 2327 // Returns: 2328 // 1) BPoint - escapement 2329 // numChars times 2330 2331 uint16 familyID, styleID; 2332 uint32 flags; 2333 float size, rotation; 2334 uint8 spacing; 2335 2336 link.Read<uint16>(&familyID); 2337 link.Read<uint16>(&styleID); 2338 link.Read<float>(&size); 2339 link.Read<uint8>(&spacing); 2340 link.Read<float>(&rotation); 2341 link.Read<uint32>(&flags); 2342 2343 escapement_delta delta; 2344 link.Read<float>(&delta.nonspace); 2345 link.Read<float>(&delta.space); 2346 2347 bool wantsOffsets; 2348 link.Read<bool>(&wantsOffsets); 2349 2350 int32 numChars; 2351 link.Read<int32>(&numChars); 2352 2353 uint32 numBytes; 2354 link.Read<uint32>(&numBytes); 2355 2356 BStackOrHeapArray<char, 256> charArray(numBytes); 2357 BStackOrHeapArray<BPoint, 64> escapements(numChars); 2358 BPoint* offsets = NULL; 2359 if (wantsOffsets) 2360 offsets = new(std::nothrow) BPoint[numChars]; 2361 2362 if (!charArray.IsValid() || !escapements.IsValid() 2363 || (offsets == NULL && wantsOffsets)) { 2364 delete[] offsets; 2365 fLink.StartMessage(B_NO_MEMORY); 2366 fLink.Flush(); 2367 break; 2368 } 2369 2370 link.Read(charArray, numBytes); 2371 2372 ServerFont font; 2373 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2374 if (status == B_OK) { 2375 font.SetSize(size); 2376 font.SetSpacing(spacing); 2377 font.SetRotation(rotation); 2378 font.SetFlags(flags); 2379 2380 status = font.GetEscapements(charArray, numBytes, numChars, 2381 delta, escapements, offsets); 2382 2383 if (status == B_OK) { 2384 fLink.StartMessage(B_OK); 2385 for (int32 i = 0; i < numChars; i++) 2386 fLink.Attach<BPoint>(escapements[i]); 2387 2388 if (wantsOffsets) { 2389 for (int32 i = 0; i < numChars; i++) 2390 fLink.Attach<BPoint>(offsets[i]); 2391 } 2392 } 2393 } 2394 2395 if (status != B_OK) 2396 fLink.StartMessage(status); 2397 2398 delete[] offsets; 2399 fLink.Flush(); 2400 break; 2401 } 2402 2403 case AS_GET_ESCAPEMENTS_AS_FLOATS: 2404 { 2405 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature())); 2406 2407 // Attached Data: 2408 // 1) uint16 - family ID 2409 // 2) uint16 - style ID 2410 // 3) float - point size 2411 // 4) uint8 - spacing 2412 // 5) float - rotation 2413 // 6) uint32 - flags 2414 // 7) float - additional "nonspace" delta 2415 // 8) float - additional "space" delta 2416 // 9) int32 - numChars 2417 // 10) int32 - numBytes 2418 // 11) char - the char buffer with size numBytes 2419 2420 // Returns: 2421 // 1) float - escapement buffer with numChar entries 2422 2423 uint16 familyID, styleID; 2424 uint32 flags; 2425 float size, rotation; 2426 uint8 spacing; 2427 2428 link.Read<uint16>(&familyID); 2429 link.Read<uint16>(&styleID); 2430 link.Read<float>(&size); 2431 link.Read<uint8>(&spacing); 2432 link.Read<float>(&rotation); 2433 link.Read<uint32>(&flags); 2434 2435 escapement_delta delta; 2436 link.Read<float>(&delta.nonspace); 2437 link.Read<float>(&delta.space); 2438 2439 int32 numChars; 2440 link.Read<int32>(&numChars); 2441 2442 uint32 numBytes; 2443 link.Read<uint32>(&numBytes); 2444 2445 BStackOrHeapArray<char, 256> charArray(numBytes); 2446 BStackOrHeapArray<float, 64> escapements(numChars); 2447 if (!charArray.IsValid() || !escapements.IsValid()) { 2448 fLink.StartMessage(B_NO_MEMORY); 2449 fLink.Flush(); 2450 break; 2451 } 2452 2453 link.Read(charArray, numBytes); 2454 2455 // figure out escapements 2456 2457 ServerFont font; 2458 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2459 if (status == B_OK) { 2460 font.SetSize(size); 2461 font.SetSpacing(spacing); 2462 font.SetRotation(rotation); 2463 font.SetFlags(flags); 2464 2465 status = font.GetEscapements(charArray, numBytes, numChars, 2466 delta, escapements); 2467 2468 if (status == B_OK) { 2469 fLink.StartMessage(B_OK); 2470 fLink.Attach(escapements, numChars * sizeof(float)); 2471 } 2472 } 2473 2474 if (status != B_OK) 2475 fLink.StartMessage(status); 2476 2477 fLink.Flush(); 2478 break; 2479 } 2480 2481 case AS_GET_BOUNDINGBOXES_CHARS: 2482 case AS_GET_BOUNDINGBOXES_STRING: 2483 { 2484 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature())); 2485 2486 // Attached Data: 2487 // 1) uint16 - family ID 2488 // 2) uint16 - style ID 2489 // 3) float - point size 2490 // 4) float - rotation 2491 // 5) float - shear 2492 // 6) float - false bold width 2493 // 7) uint8 - spacing 2494 // 8) uint32 - flags 2495 // 9) font_metric_mode - mode 2496 // 10) bool - string escapement 2497 // 11) escapement_delta - additional delta 2498 // 12) int32 - numChars 2499 // 13) int32 - numBytes 2500 // 14) char - the char buffer with size numBytes 2501 2502 // Returns: 2503 // 1) BRect - rects with numChar entries 2504 2505 uint16 familyID, styleID; 2506 uint32 flags; 2507 float size, rotation, shear, falseBoldWidth; 2508 uint8 spacing; 2509 font_metric_mode mode; 2510 bool stringEscapement; 2511 2512 link.Read<uint16>(&familyID); 2513 link.Read<uint16>(&styleID); 2514 link.Read<float>(&size); 2515 link.Read<float>(&rotation); 2516 link.Read<float>(&shear); 2517 link.Read<float>(&falseBoldWidth); 2518 link.Read<uint8>(&spacing); 2519 link.Read<uint32>(&flags); 2520 link.Read<font_metric_mode>(&mode); 2521 link.Read<bool>(&stringEscapement); 2522 2523 escapement_delta delta; 2524 link.Read<escapement_delta>(&delta); 2525 2526 int32 numChars; 2527 link.Read<int32>(&numChars); 2528 2529 uint32 numBytes; 2530 link.Read<uint32>(&numBytes); 2531 2532 BStackOrHeapArray<char, 256> charArray(numBytes); 2533 BStackOrHeapArray<BRect, 64> rectArray(numChars); 2534 if (!charArray.IsValid() || !rectArray.IsValid()) { 2535 fLink.StartMessage(B_NO_MEMORY); 2536 fLink.Flush(); 2537 break; 2538 } 2539 2540 link.Read(charArray, numBytes); 2541 2542 // figure out escapements 2543 2544 ServerFont font; 2545 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2546 if (status == B_OK) { 2547 font.SetSize(size); 2548 font.SetRotation(rotation); 2549 font.SetShear(shear); 2550 font.SetFalseBoldWidth(falseBoldWidth); 2551 font.SetSpacing(spacing); 2552 font.SetFlags(flags); 2553 2554 // TODO: implement for real 2555 status = font.GetBoundingBoxes(charArray, numBytes, 2556 numChars, rectArray, stringEscapement, mode, delta, 2557 code == AS_GET_BOUNDINGBOXES_STRING); 2558 if (status == B_OK) { 2559 fLink.StartMessage(B_OK); 2560 for (int32 i = 0; i < numChars; i++) 2561 fLink.Attach<BRect>(rectArray[i]); 2562 } 2563 } 2564 2565 if (status != B_OK) 2566 fLink.StartMessage(status); 2567 2568 fLink.Flush(); 2569 break; 2570 } 2571 2572 case AS_GET_BOUNDINGBOXES_STRINGS: 2573 { 2574 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n", 2575 Signature())); 2576 2577 // Attached Data: 2578 // 1) uint16 - family ID 2579 // 2) uint16 - style ID 2580 // 3) float - point size 2581 // 4) float - rotation 2582 // 5) float - shear 2583 // 6) float - false bold width 2584 // 7) uint8 - spacing 2585 // 8) uint32 - flags 2586 // 9) font_metric_mode - mode 2587 // 10) int32 numStrings 2588 // 11) escapement_delta - additional delta (numStrings times) 2589 // 12) int32 string length to measure (numStrings times) 2590 // 13) string - string (numStrings times) 2591 2592 // Returns: 2593 // 1) BRect - rects with numStrings entries 2594 2595 uint16 familyID, styleID; 2596 uint32 flags; 2597 float ptsize, rotation, shear, falseBoldWidth; 2598 uint8 spacing; 2599 font_metric_mode mode; 2600 2601 link.Read<uint16>(&familyID); 2602 link.Read<uint16>(&styleID); 2603 link.Read<float>(&ptsize); 2604 link.Read<float>(&rotation); 2605 link.Read<float>(&shear); 2606 link.Read<float>(&falseBoldWidth); 2607 link.Read<uint8>(&spacing); 2608 link.Read<uint32>(&flags); 2609 link.Read<font_metric_mode>(&mode); 2610 2611 int32 numStrings; 2612 link.Read<int32>(&numStrings); 2613 2614 BStackOrHeapArray<escapement_delta, 64> deltaArray(numStrings); 2615 BStackOrHeapArray<char*, 64> stringArray(numStrings); 2616 BStackOrHeapArray<size_t, 64> lengthArray(numStrings); 2617 BStackOrHeapArray<BRect, 64> rectArray(numStrings); 2618 if (!deltaArray.IsValid() || !stringArray.IsValid() 2619 || !lengthArray.IsValid() || !rectArray.IsValid()) { 2620 fLink.StartMessage(B_NO_MEMORY); 2621 fLink.Flush(); 2622 break; 2623 } 2624 2625 for (int32 i = 0; i < numStrings; i++) { 2626 // This version of ReadString allocates the strings, we free 2627 // them below 2628 link.ReadString(&stringArray[i], &lengthArray[i]); 2629 link.Read<escapement_delta>(&deltaArray[i]); 2630 } 2631 2632 ServerFont font; 2633 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2634 if (status == B_OK) { 2635 font.SetSize(ptsize); 2636 font.SetRotation(rotation); 2637 font.SetShear(shear); 2638 font.SetFalseBoldWidth(falseBoldWidth); 2639 font.SetSpacing(spacing); 2640 font.SetFlags(flags); 2641 2642 status = font.GetBoundingBoxesForStrings(stringArray, 2643 lengthArray, numStrings, rectArray, mode, deltaArray); 2644 if (status == B_OK) { 2645 fLink.StartMessage(B_OK); 2646 fLink.Attach(rectArray, numStrings * sizeof(BRect)); 2647 } 2648 } 2649 2650 for (int32 i = 0; i < numStrings; i++) 2651 free(stringArray[i]); 2652 2653 if (status != B_OK) 2654 fLink.StartMessage(status); 2655 2656 fLink.Flush(); 2657 break; 2658 } 2659 2660 // Screen commands 2661 2662 case AS_VALID_SCREEN_ID: 2663 { 2664 // Attached data 2665 // 1) int32 screen 2666 2667 int32 id; 2668 if (link.Read<int32>(&id) == B_OK 2669 && id == B_MAIN_SCREEN_ID.id) 2670 fLink.StartMessage(B_OK); 2671 else 2672 fLink.StartMessage(B_ERROR); 2673 2674 fLink.Flush(); 2675 break; 2676 } 2677 2678 case AS_GET_NEXT_SCREEN_ID: 2679 { 2680 // Attached data 2681 // 1) int32 screen 2682 2683 int32 id; 2684 link.Read<int32>(&id); 2685 2686 // TODO: for now, just say we're the last one 2687 fLink.StartMessage(B_ENTRY_NOT_FOUND); 2688 fLink.Flush(); 2689 break; 2690 } 2691 2692 case AS_GET_SCREEN_ID_FROM_WINDOW: 2693 { 2694 status_t status = B_BAD_VALUE; 2695 2696 // Attached data 2697 // 1) int32 - window client token 2698 2699 int32 clientToken; 2700 if (link.Read<int32>(&clientToken) != B_OK) 2701 status = B_BAD_DATA; 2702 else { 2703 BAutolock locker(fWindowListLock); 2704 2705 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 2706 ServerWindow* serverWindow = fWindowList.ItemAt(i); 2707 2708 if (serverWindow->ClientToken() == clientToken) { 2709 AutoReadLocker _(fDesktop->ScreenLocker()); 2710 2711 // found it! 2712 Window* window = serverWindow->Window(); 2713 const Screen* screen = NULL; 2714 if (window != NULL) 2715 screen = window->Screen(); 2716 2717 if (screen == NULL) { 2718 // The window hasn't been added to the desktop yet, 2719 // or it's an offscreen window 2720 break; 2721 } 2722 2723 fLink.StartMessage(B_OK); 2724 fLink.Attach<int32>(screen->ID()); 2725 status = B_OK; 2726 break; 2727 } 2728 } 2729 } 2730 2731 if (status != B_OK) 2732 fLink.StartMessage(status); 2733 fLink.Flush(); 2734 break; 2735 } 2736 2737 case AS_SCREEN_GET_MODE: 2738 { 2739 STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature())); 2740 2741 // Attached data 2742 // 1) int32 screen 2743 // 2) uint32 workspace index 2744 2745 int32 id; 2746 link.Read<int32>(&id); 2747 uint32 workspace; 2748 link.Read<uint32>(&workspace); 2749 2750 display_mode mode; 2751 status_t status = fDesktop->GetScreenMode(workspace, id, mode); 2752 2753 fLink.StartMessage(status); 2754 if (status == B_OK) 2755 fLink.Attach<display_mode>(mode); 2756 fLink.Flush(); 2757 break; 2758 } 2759 2760 case AS_SCREEN_SET_MODE: 2761 { 2762 STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature())); 2763 2764 // Attached data 2765 // 1) int32 screen 2766 // 2) workspace index 2767 // 3) display_mode to set 2768 // 4) 'makeDefault' boolean 2769 2770 int32 id; 2771 link.Read<int32>(&id); 2772 uint32 workspace; 2773 link.Read<uint32>(&workspace); 2774 2775 display_mode mode; 2776 link.Read<display_mode>(&mode); 2777 2778 bool makeDefault = false; 2779 status_t status = link.Read<bool>(&makeDefault); 2780 2781 if (status == B_OK) { 2782 status = fDesktop->SetScreenMode(workspace, id, mode, 2783 makeDefault); 2784 } 2785 if (status == B_OK) { 2786 if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX 2787 && fDesktop->LockSingleWindow()) { 2788 workspace = fDesktop->CurrentWorkspace(); 2789 fDesktop->UnlockSingleWindow(); 2790 } 2791 2792 if (!makeDefault) { 2793 // Memorize the screen change, so that it can be reverted 2794 // later 2795 fTemporaryDisplayModeChange |= 1 << workspace; 2796 } else 2797 fTemporaryDisplayModeChange &= ~(1 << workspace); 2798 } 2799 2800 fLink.StartMessage(status); 2801 fLink.Flush(); 2802 break; 2803 } 2804 2805 case AS_PROPOSE_MODE: 2806 { 2807 STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature())); 2808 int32 id; 2809 link.Read<int32>(&id); 2810 2811 display_mode target, low, high; 2812 link.Read<display_mode>(&target); 2813 link.Read<display_mode>(&low); 2814 link.Read<display_mode>(&high); 2815 status_t status = fDesktop->HWInterface()->ProposeMode(&target, 2816 &low, &high); 2817 2818 // ProposeMode() returns B_BAD_VALUE to hint that the candidate is 2819 // not within the given limits (but is supported) 2820 if (status == B_OK || status == B_BAD_VALUE) { 2821 fLink.StartMessage(B_OK); 2822 fLink.Attach<display_mode>(target); 2823 fLink.Attach<bool>(status == B_OK); 2824 } else 2825 fLink.StartMessage(status); 2826 2827 fLink.Flush(); 2828 break; 2829 } 2830 2831 case AS_GET_MODE_LIST: 2832 { 2833 int32 id; 2834 link.Read<int32>(&id); 2835 // TODO: use this screen id 2836 2837 display_mode* modeList; 2838 uint32 count; 2839 status_t status = fDesktop->HWInterface()->GetModeList(&modeList, 2840 &count); 2841 if (status == B_OK) { 2842 fLink.StartMessage(B_OK); 2843 fLink.Attach<uint32>(count); 2844 fLink.Attach(modeList, sizeof(display_mode) * count); 2845 2846 delete[] modeList; 2847 } else 2848 fLink.StartMessage(status); 2849 2850 fLink.Flush(); 2851 break; 2852 } 2853 2854 case AS_GET_SCREEN_FRAME: 2855 { 2856 STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature())); 2857 2858 // Attached data 2859 // 1) int32 screen 2860 // 2) uint32 workspace index 2861 2862 int32 id; 2863 link.Read<int32>(&id); 2864 uint32 workspace; 2865 link.Read<uint32>(&workspace); 2866 2867 BRect frame; 2868 status_t status = fDesktop->GetScreenFrame(workspace, id, frame); 2869 2870 fLink.StartMessage(status); 2871 if (status == B_OK) 2872 fLink.Attach<BRect>(frame); 2873 2874 fLink.Flush(); 2875 break; 2876 } 2877 2878 case AS_SCREEN_GET_COLORMAP: 2879 { 2880 STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature())); 2881 2882 int32 id; 2883 link.Read<int32>(&id); 2884 2885 const color_map* colorMap = SystemColorMap(); 2886 if (colorMap != NULL) { 2887 fLink.StartMessage(B_OK); 2888 fLink.Attach<color_map>(*colorMap); 2889 } else 2890 fLink.StartMessage(B_ERROR); 2891 2892 fLink.Flush(); 2893 break; 2894 } 2895 2896 case AS_GET_DESKTOP_COLOR: 2897 { 2898 STRACE(("ServerApp %s: get desktop color\n", Signature())); 2899 2900 uint32 index; 2901 link.Read<uint32>(&index); 2902 2903 fLink.StartMessage(B_OK); 2904 fDesktop->LockSingleWindow(); 2905 2906 // we're nice to our children (and also take the default case 2907 // into account which asks for the current workspace) 2908 if (index >= (uint32)kMaxWorkspaces) 2909 index = fDesktop->CurrentWorkspace(); 2910 2911 Workspace workspace(*fDesktop, index, true); 2912 fLink.Attach<rgb_color>(workspace.Color()); 2913 2914 fDesktop->UnlockSingleWindow(); 2915 fLink.Flush(); 2916 break; 2917 } 2918 2919 case AS_SET_DESKTOP_COLOR: 2920 { 2921 STRACE(("ServerApp %s: set desktop color\n", Signature())); 2922 2923 rgb_color color; 2924 uint32 index; 2925 bool makeDefault; 2926 2927 link.Read<rgb_color>(&color); 2928 link.Read<uint32>(&index); 2929 if (link.Read<bool>(&makeDefault) != B_OK) 2930 break; 2931 2932 fDesktop->LockAllWindows(); 2933 2934 // we're nice to our children (and also take the default case 2935 // into account which asks for the current workspace) 2936 if (index >= (uint32)kMaxWorkspaces) 2937 index = fDesktop->CurrentWorkspace(); 2938 2939 Workspace workspace(*fDesktop, index); 2940 workspace.SetColor(color, makeDefault); 2941 2942 fDesktop->UnlockAllWindows(); 2943 break; 2944 } 2945 2946 case AS_GET_ACCELERANT_INFO: 2947 { 2948 STRACE(("ServerApp %s: get accelerant info\n", Signature())); 2949 2950 // We aren't using the screen_id for now... 2951 int32 id; 2952 link.Read<int32>(&id); 2953 2954 accelerant_device_info accelerantInfo; 2955 // TODO: I wonder if there should be a "desktop" lock... 2956 status_t status 2957 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo); 2958 if (status == B_OK) { 2959 fLink.StartMessage(B_OK); 2960 fLink.Attach<accelerant_device_info>(accelerantInfo); 2961 } else 2962 fLink.StartMessage(status); 2963 2964 fLink.Flush(); 2965 break; 2966 } 2967 2968 case AS_GET_MONITOR_INFO: 2969 { 2970 STRACE(("ServerApp %s: get monitor info\n", Signature())); 2971 2972 // We aren't using the screen_id for now... 2973 int32 id; 2974 link.Read<int32>(&id); 2975 2976 monitor_info info; 2977 // TODO: I wonder if there should be a "desktop" lock... 2978 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info); 2979 if (status == B_OK) { 2980 fLink.StartMessage(B_OK); 2981 fLink.Attach<monitor_info>(info); 2982 } else 2983 fLink.StartMessage(status); 2984 2985 fLink.Flush(); 2986 break; 2987 } 2988 2989 case AS_GET_FRAME_BUFFER_CONFIG: 2990 { 2991 STRACE(("ServerApp %s: get frame buffer config\n", Signature())); 2992 2993 // We aren't using the screen_id for now... 2994 int32 id; 2995 link.Read<int32>(&id); 2996 2997 frame_buffer_config config; 2998 // TODO: I wonder if there should be a "desktop" lock... 2999 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config); 3000 if (status == B_OK) { 3001 fLink.StartMessage(B_OK); 3002 fLink.Attach<frame_buffer_config>(config); 3003 } else 3004 fLink.StartMessage(status); 3005 3006 fLink.Flush(); 3007 break; 3008 } 3009 3010 case AS_GET_RETRACE_SEMAPHORE: 3011 { 3012 STRACE(("ServerApp %s: get retrace semaphore\n", Signature())); 3013 3014 // We aren't using the screen_id for now... 3015 int32 id; 3016 link.Read<int32>(&id); 3017 3018 fLink.StartMessage(B_OK); 3019 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore()); 3020 fLink.Flush(); 3021 break; 3022 } 3023 3024 case AS_GET_TIMING_CONSTRAINTS: 3025 { 3026 STRACE(("ServerApp %s: get timing constraints\n", Signature())); 3027 3028 // We aren't using the screen_id for now... 3029 int32 id; 3030 link.Read<int32>(&id); 3031 3032 display_timing_constraints constraints; 3033 status_t status = fDesktop->HWInterface()->GetTimingConstraints( 3034 &constraints); 3035 if (status == B_OK) { 3036 fLink.StartMessage(B_OK); 3037 fLink.Attach<display_timing_constraints>(constraints); 3038 } else 3039 fLink.StartMessage(status); 3040 3041 fLink.Flush(); 3042 break; 3043 } 3044 3045 case AS_GET_PIXEL_CLOCK_LIMITS: 3046 { 3047 STRACE(("ServerApp %s: get pixel clock limits\n", Signature())); 3048 // We aren't using the screen_id for now... 3049 int32 id; 3050 link.Read<int32>(&id); 3051 display_mode mode; 3052 link.Read<display_mode>(&mode); 3053 3054 uint32 low, high; 3055 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode, 3056 &low, &high); 3057 if (status == B_OK) { 3058 fLink.StartMessage(B_OK); 3059 fLink.Attach<uint32>(low); 3060 fLink.Attach<uint32>(high); 3061 } else 3062 fLink.StartMessage(status); 3063 3064 fLink.Flush(); 3065 break; 3066 } 3067 3068 case AS_SET_DPMS: 3069 { 3070 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature())); 3071 int32 id; 3072 link.Read<int32>(&id); 3073 3074 uint32 mode; 3075 link.Read<uint32>(&mode); 3076 3077 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode); 3078 fLink.StartMessage(status); 3079 3080 fLink.Flush(); 3081 break; 3082 } 3083 3084 case AS_GET_DPMS_STATE: 3085 { 3086 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature())); 3087 3088 int32 id; 3089 link.Read<int32>(&id); 3090 3091 uint32 state = fDesktop->HWInterface()->DPMSMode(); 3092 fLink.StartMessage(B_OK); 3093 fLink.Attach<uint32>(state); 3094 fLink.Flush(); 3095 break; 3096 } 3097 3098 case AS_GET_DPMS_CAPABILITIES: 3099 { 3100 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature())); 3101 int32 id; 3102 link.Read<int32>(&id); 3103 3104 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities(); 3105 fLink.StartMessage(B_OK); 3106 fLink.Attach<uint32>(capabilities); 3107 fLink.Flush(); 3108 break; 3109 } 3110 3111 case AS_SCREEN_SET_BRIGHTNESS: 3112 { 3113 STRACE(("ServerApp %s: AS_SCREEN_SET_BRIGHTNESS\n", Signature())); 3114 int32 id; 3115 link.Read<int32>(&id); 3116 3117 float brightness; 3118 link.Read<float>(&brightness); 3119 3120 status_t status = fDesktop->SetBrightness(id, brightness); 3121 fLink.StartMessage(status); 3122 3123 fLink.Flush(); 3124 break; 3125 } 3126 3127 case AS_SCREEN_GET_BRIGHTNESS: 3128 { 3129 STRACE(("ServerApp %s: AS_SCREEN_GET_BRIGHTNESS\n", Signature())); 3130 int32 id; 3131 link.Read<int32>(&id); 3132 3133 float brightness; 3134 status_t result = fDesktop->HWInterface()->GetBrightness(&brightness); 3135 fLink.StartMessage(result); 3136 if (result == B_OK) 3137 fLink.Attach<float>(brightness); 3138 fLink.Flush(); 3139 break; 3140 } 3141 3142 case AS_READ_BITMAP: 3143 { 3144 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature())); 3145 int32 token; 3146 link.Read<int32>(&token); 3147 3148 bool drawCursor = true; 3149 link.Read<bool>(&drawCursor); 3150 3151 BRect bounds; 3152 link.Read<BRect>(&bounds); 3153 3154 bool success = false; 3155 3156 BReference<ServerBitmap> bitmap(GetBitmap(token), true); 3157 if (bitmap != NULL) { 3158 if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) { 3159 success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap, 3160 drawCursor, bounds) == B_OK; 3161 fDesktop->GetDrawingEngine()->UnlockExclusiveAccess(); 3162 } 3163 } 3164 3165 if (success) 3166 fLink.StartMessage(B_OK); 3167 else 3168 fLink.StartMessage(B_BAD_VALUE); 3169 3170 fLink.Flush(); 3171 break; 3172 } 3173 3174 case AS_GET_ACCELERANT_PATH: 3175 { 3176 int32 id; 3177 fLink.Read<int32>(&id); 3178 3179 BString path; 3180 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path); 3181 fLink.StartMessage(status); 3182 if (status == B_OK) 3183 fLink.AttachString(path.String()); 3184 3185 fLink.Flush(); 3186 break; 3187 } 3188 3189 case AS_GET_DRIVER_PATH: 3190 { 3191 int32 id; 3192 fLink.Read<int32>(&id); 3193 3194 BString path; 3195 status_t status = fDesktop->HWInterface()->GetDriverPath(path); 3196 fLink.StartMessage(status); 3197 if (status == B_OK) 3198 fLink.AttachString(path.String()); 3199 3200 fLink.Flush(); 3201 break; 3202 } 3203 3204 // BWindowScreen communication 3205 3206 case AS_DIRECT_SCREEN_LOCK: 3207 { 3208 bool lock; 3209 link.Read<bool>(&lock); 3210 3211 status_t status; 3212 if (lock) 3213 status = fDesktop->LockDirectScreen(ClientTeam()); 3214 else 3215 status = fDesktop->UnlockDirectScreen(ClientTeam()); 3216 3217 fLink.StartMessage(status); 3218 fLink.Flush(); 3219 break; 3220 } 3221 3222 // Hinting and aliasing 3223 3224 case AS_SET_SUBPIXEL_ANTIALIASING: 3225 { 3226 bool subpix; 3227 if (link.Read<bool>(&subpix) == B_OK) { 3228 LockedDesktopSettings settings(fDesktop); 3229 settings.SetSubpixelAntialiasing(subpix); 3230 } 3231 fDesktop->Redraw(); 3232 break; 3233 } 3234 3235 case AS_GET_SUBPIXEL_ANTIALIASING: 3236 { 3237 DesktopSettings settings(fDesktop); 3238 fLink.StartMessage(B_OK); 3239 fLink.Attach<bool>(settings.SubpixelAntialiasing()); 3240 fLink.Flush(); 3241 break; 3242 } 3243 3244 case AS_SET_HINTING: 3245 { 3246 uint8 hinting; 3247 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) { 3248 LockedDesktopSettings settings(fDesktop); 3249 if (hinting != settings.Hinting()) { 3250 settings.SetHinting(hinting); 3251 fDesktop->Redraw(); 3252 } 3253 } 3254 break; 3255 } 3256 3257 case AS_GET_HINTING: 3258 { 3259 DesktopSettings settings(fDesktop); 3260 fLink.StartMessage(B_OK); 3261 fLink.Attach<uint8>(settings.Hinting()); 3262 fLink.Flush(); 3263 break; 3264 } 3265 3266 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: 3267 { 3268 uint8 averageWeight; 3269 if (link.Read<uint8>(&averageWeight) == B_OK) { 3270 LockedDesktopSettings settings(fDesktop); 3271 settings.SetSubpixelAverageWeight(averageWeight); 3272 } 3273 fDesktop->Redraw(); 3274 break; 3275 } 3276 3277 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: 3278 { 3279 DesktopSettings settings(fDesktop); 3280 fLink.StartMessage(B_OK); 3281 fLink.Attach<uint8>(settings.SubpixelAverageWeight()); 3282 fLink.Flush(); 3283 break; 3284 } 3285 3286 case AS_SET_SUBPIXEL_ORDERING: 3287 { 3288 bool subpixelOrdering; 3289 if (link.Read<bool>(&subpixelOrdering) == B_OK) { 3290 LockedDesktopSettings settings(fDesktop); 3291 settings.SetSubpixelOrderingRegular(subpixelOrdering); 3292 } 3293 fDesktop->Redraw(); 3294 break; 3295 } 3296 3297 case AS_GET_SUBPIXEL_ORDERING: 3298 { 3299 DesktopSettings settings(fDesktop); 3300 fLink.StartMessage(B_OK); 3301 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular()); 3302 fLink.Flush(); 3303 break; 3304 } 3305 3306 default: 3307 printf("ServerApp %s received unhandled message code %" B_PRId32 3308 "\n", Signature(), code); 3309 3310 if (link.NeedsReply()) { 3311 // the client is now blocking and waiting for a reply! 3312 fLink.StartMessage(B_ERROR); 3313 fLink.Flush(); 3314 } else 3315 puts("message doesn't need a reply!"); 3316 break; 3317 } 3318 } 3319 3320 3321 /*! \brief The thread function ServerApps use to monitor messages 3322 */ 3323 void 3324 ServerApp::_MessageLooper() 3325 { 3326 // Message-dispatching loop for the ServerApp 3327 3328 // get our own team ID 3329 thread_info threadInfo; 3330 get_thread_info(fThread, &threadInfo); 3331 3332 // First let's tell the client how to talk with us. 3333 fLink.StartMessage(B_OK); 3334 fLink.Attach<port_id>(fMessagePort); 3335 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea()); 3336 fLink.Attach<team_id>(threadInfo.team); 3337 fLink.Flush(); 3338 3339 BPrivate::LinkReceiver &receiver = fLink.Receiver(); 3340 3341 int32 code; 3342 status_t err = B_OK; 3343 3344 while (!fQuitting) { 3345 STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32 3346 ".\n", fMessagePort)); 3347 3348 err = receiver.GetNextMessage(code); 3349 if (err != B_OK || code == B_QUIT_REQUESTED) { 3350 STRACE(("ServerApp: application seems to be gone...\n")); 3351 3352 // Tell desktop to quit us 3353 BPrivate::LinkSender link(fDesktop->MessagePort()); 3354 link.StartMessage(AS_DELETE_APP); 3355 link.Attach<thread_id>(Thread()); 3356 link.Flush(); 3357 break; 3358 } 3359 3360 switch (code) { 3361 case kMsgAppQuit: 3362 // we receive this from our destructor on quit 3363 fQuitting = true; 3364 break; 3365 3366 case AS_QUIT_APP: 3367 { 3368 // This message is received only when the app_server is asked 3369 // to shut down in test/debug mode. Of course, if we are testing 3370 // while using AccelerantDriver, we do NOT want to shut down 3371 // client applications. The server can be quit in this fashion 3372 // through the driver's interface, such as closing the 3373 // ViewDriver's window. 3374 3375 STRACE(("ServerApp %s:Server shutdown notification received\n", 3376 Signature())); 3377 3378 // If we are using the real, accelerated version of the 3379 // DrawingEngine, we do NOT want the user to be able shut down 3380 // the server. The results would NOT be pretty 3381 #if TEST_MODE 3382 BMessage pleaseQuit(B_QUIT_REQUESTED); 3383 SendMessageToClient(&pleaseQuit); 3384 #endif 3385 break; 3386 } 3387 3388 default: 3389 STRACE(("ServerApp %s: Got a Message to dispatch\n", 3390 Signature())); 3391 _DispatchMessage(code, receiver); 3392 break; 3393 } 3394 } 3395 3396 // Quit() will send us a message; we're handling the exiting procedure 3397 thread_id sender; 3398 sem_id shutdownSemaphore; 3399 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id)); 3400 3401 delete this; 3402 3403 if (shutdownSemaphore >= B_OK) 3404 release_sem(shutdownSemaphore); 3405 } 3406 3407 3408 status_t 3409 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link, 3410 port_id& clientReplyPort) 3411 { 3412 // Attached data: 3413 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) 3414 // 2) BRect window frame 3415 // 3) uint32 window look 3416 // 4) uint32 window feel 3417 // 5) uint32 window flags 3418 // 6) uint32 workspace index 3419 // 7) int32 BHandler token of the window 3420 // 8) port_id window's reply port 3421 // 9) port_id window's looper port 3422 // 10) const char * title 3423 3424 BRect frame; 3425 int32 bitmapToken; 3426 uint32 look; 3427 uint32 feel; 3428 uint32 flags; 3429 uint32 workspaces; 3430 int32 token; 3431 port_id looperPort; 3432 char* title; 3433 3434 if (code == AS_CREATE_OFFSCREEN_WINDOW) 3435 link.Read<int32>(&bitmapToken); 3436 3437 link.Read<BRect>(&frame); 3438 link.Read<uint32>(&look); 3439 link.Read<uint32>(&feel); 3440 link.Read<uint32>(&flags); 3441 link.Read<uint32>(&workspaces); 3442 link.Read<int32>(&token); 3443 link.Read<port_id>(&clientReplyPort); 3444 link.Read<port_id>(&looperPort); 3445 if (link.ReadString(&title) != B_OK) 3446 return B_ERROR; 3447 3448 if (!frame.IsValid()) { 3449 // make sure we pass a valid rectangle to ServerWindow 3450 frame.right = frame.left + 1; 3451 frame.bottom = frame.top + 1; 3452 } 3453 3454 status_t status = B_NO_MEMORY; 3455 ServerWindow *window = NULL; 3456 3457 if (code == AS_CREATE_OFFSCREEN_WINDOW) { 3458 ServerBitmap* bitmap = GetBitmap(bitmapToken); 3459 3460 if (bitmap != NULL) { 3461 window = new (nothrow) OffscreenServerWindow(title, this, 3462 clientReplyPort, looperPort, token, bitmap); 3463 } else 3464 status = B_ERROR; 3465 } else { 3466 window = new (nothrow) ServerWindow(title, this, clientReplyPort, 3467 looperPort, token); 3468 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n", 3469 Signature(), title, frame.left, frame.top, 3470 frame.right, frame.bottom)); 3471 } 3472 3473 free(title); 3474 3475 // NOTE: the reply to the client is handled in ServerWindow::Run() 3476 if (window != NULL) { 3477 status = window->Init(frame, (window_look)look, (window_feel)feel, 3478 flags, workspaces); 3479 if (status == B_OK) { 3480 status = window->Run(); 3481 if (status != B_OK) { 3482 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run " 3483 "the window thread\n"); 3484 } 3485 } 3486 3487 if (status != B_OK) 3488 delete window; 3489 } 3490 3491 return status; 3492 } 3493 3494 3495 bool 3496 ServerApp::_HasWindowUnderMouse() 3497 { 3498 BAutolock locker(fWindowListLock); 3499 3500 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 3501 ServerWindow* serverWindow = fWindowList.ItemAt(i); 3502 3503 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN) 3504 return true; 3505 } 3506 3507 return false; 3508 } 3509 3510 3511 bool 3512 ServerApp::_AddBitmap(ServerBitmap* bitmap) 3513 { 3514 BAutolock _(fMapLocker); 3515 3516 try { 3517 fBitmapMap.insert(std::make_pair(bitmap->Token(), BReference<ServerBitmap>(bitmap, false))); 3518 } catch (std::bad_alloc& exception) { 3519 return false; 3520 } 3521 3522 bitmap->SetOwner(this); 3523 return true; 3524 } 3525 3526 3527 void 3528 ServerApp::_DeleteBitmap(ServerBitmap* bitmap) 3529 { 3530 ASSERT(fMapLocker.IsLocked()); 3531 3532 gBitmapManager->BitmapRemoved(bitmap); 3533 fBitmapMap.erase(bitmap->Token()); 3534 } 3535 3536 3537 ServerBitmap* 3538 ServerApp::_FindBitmap(int32 token) const 3539 { 3540 ASSERT(fMapLocker.IsLocked()); 3541 3542 BitmapMap::const_iterator iterator = fBitmapMap.find(token); 3543 if (iterator == fBitmapMap.end()) 3544 return NULL; 3545 3546 return iterator->second; 3547 } 3548 3549 3550 ServerPicture* 3551 ServerApp::_FindPicture(int32 token) const 3552 { 3553 ASSERT(fMapLocker.IsLocked()); 3554 3555 PictureMap::const_iterator iterator = fPictureMap.find(token); 3556 if (iterator == fPictureMap.end()) 3557 return NULL; 3558 3559 return iterator->second; 3560 } 3561