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 unimplemented\n", 1955 Signature())); 1956 1957 // Attached Data: 1958 // 1) uint16 - family ID 1959 // 2) uint16 - style ID 1960 1961 // Returns: 1962 // 1) BRect - box holding entire font 1963 1964 // ToDo: implement me! 1965 fLink.StartMessage(B_ERROR); 1966 fLink.Flush(); 1967 break; 1968 } 1969 1970 case AS_GET_TUNED_COUNT: 1971 { 1972 FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature())); 1973 1974 // Attached Data: 1975 // 1) uint16 - family ID 1976 // 2) uint16 - style ID 1977 1978 // Returns: 1979 // 1) int32 - number of font strikes available 1980 1981 uint16 familyID, styleID; 1982 link.Read<uint16>(&familyID); 1983 link.Read<uint16>(&styleID); 1984 1985 gFontManager->Lock(); 1986 1987 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 1988 if (fontStyle != NULL) { 1989 fLink.StartMessage(B_OK); 1990 fLink.Attach<int32>(fontStyle->TunedCount()); 1991 } else 1992 fLink.StartMessage(B_BAD_VALUE); 1993 1994 gFontManager->Unlock(); 1995 fLink.Flush(); 1996 break; 1997 } 1998 1999 case AS_GET_TUNED_INFO: 2000 { 2001 FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n", 2002 Signature())); 2003 2004 // Attached Data: 2005 // 1) uint16 - family ID 2006 // 2) uint16 - style ID 2007 // 3) uint32 - index of the particular font strike 2008 2009 // Returns: 2010 // 1) tuned_font_info - info on the strike specified 2011 // ToDo: implement me! 2012 2013 fLink.StartMessage(B_ERROR); 2014 fLink.Flush(); 2015 break; 2016 } 2017 2018 case AS_GET_EXTRA_FONT_FLAGS: 2019 { 2020 FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n", 2021 Signature())); 2022 2023 // Attached Data: 2024 // 1) uint16 - family ID 2025 // 2) uint16 - style ID 2026 2027 // Returns: 2028 // 1) uint32 - extra font flags 2029 2030 uint16 familyID, styleID; 2031 link.Read<uint16>(&familyID); 2032 link.Read<uint16>(&styleID); 2033 2034 gFontManager->Lock(); 2035 2036 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2037 if (fontStyle != NULL) { 2038 fLink.StartMessage(B_OK); 2039 fLink.Attach<uint32>(fontStyle->Flags()); 2040 } else 2041 fLink.StartMessage(B_BAD_VALUE); 2042 2043 gFontManager->Unlock(); 2044 fLink.Flush(); 2045 break; 2046 } 2047 2048 case AS_GET_FONT_HEIGHT: 2049 { 2050 FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature())); 2051 2052 // Attached Data: 2053 // 1) uint16 family ID 2054 // 2) uint16 style ID 2055 // 3) float size 2056 2057 uint16 familyID, styleID; 2058 float size; 2059 link.Read<uint16>(&familyID); 2060 link.Read<uint16>(&styleID); 2061 link.Read<float>(&size); 2062 2063 gFontManager->Lock(); 2064 2065 FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); 2066 if (fontStyle != NULL) { 2067 font_height height; 2068 fontStyle->GetHeight(size, height); 2069 2070 fLink.StartMessage(B_OK); 2071 fLink.Attach<font_height>(height); 2072 } else 2073 fLink.StartMessage(B_BAD_VALUE); 2074 2075 gFontManager->Unlock(); 2076 fLink.Flush(); 2077 break; 2078 } 2079 2080 case AS_GET_UNICODE_BLOCKS: 2081 { 2082 FTRACE(("ServerApp %s: AS_GET_UNICODE_BLOCKS\n", Signature())); 2083 2084 // Attached Data: 2085 // 1) uint16 family ID 2086 // 2) uint16 style ID 2087 2088 // Returns: 2089 // 1) unicode_block - bitfield of Unicode blocks in font 2090 2091 uint16 familyID, styleID; 2092 link.Read<uint16>(&familyID); 2093 link.Read<uint16>(&styleID); 2094 2095 ServerFont font; 2096 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2097 if (status == B_OK) { 2098 unicode_block blocksForFont; 2099 font.GetUnicodeBlocks(blocksForFont); 2100 2101 fLink.StartMessage(B_OK); 2102 fLink.Attach<unicode_block>(blocksForFont); 2103 } else 2104 fLink.StartMessage(status); 2105 2106 fLink.Flush(); 2107 break; 2108 } 2109 2110 case AS_GET_HAS_UNICODE_BLOCK: 2111 { 2112 FTRACE(("ServerApp %s: AS_INCLUDES_UNICODE_BLOCK\n", Signature())); 2113 2114 // Attached Data: 2115 // 1) uint16 family ID 2116 // 2) uint16 style ID 2117 // 3) uint32 start of unicode block 2118 // 4) uint32 end of unicode block 2119 2120 // Returns: 2121 // 1) bool - whether or not font includes specified block range 2122 2123 uint16 familyID, styleID; 2124 uint32 start, end; 2125 link.Read<uint16>(&familyID); 2126 link.Read<uint16>(&styleID); 2127 link.Read<uint32>(&start); 2128 link.Read<uint32>(&end); 2129 2130 ServerFont font; 2131 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2132 if (status == B_OK) { 2133 bool hasBlock; 2134 2135 status = font.IncludesUnicodeBlock(start, end, hasBlock); 2136 fLink.StartMessage(status); 2137 fLink.Attach<bool>(hasBlock); 2138 } else 2139 fLink.StartMessage(status); 2140 2141 fLink.Flush(); 2142 break; 2143 } 2144 2145 case AS_GET_GLYPH_SHAPES: 2146 { 2147 FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature())); 2148 2149 // Attached Data: 2150 // 1) uint16 - family ID 2151 // 2) uint16 - style ID 2152 // 3) float - point size 2153 // 4) float - shear 2154 // 5) float - rotation 2155 // 6) float - false bold width 2156 // 6) uint32 - flags 2157 // 7) int32 - numChars 2158 // 8) int32 - numBytes 2159 // 8) char - chars (numBytes times) 2160 2161 // Returns: 2162 // 1) BShape - glyph shape 2163 // numChars times 2164 2165 uint16 familyID, styleID; 2166 uint32 flags; 2167 float size, shear, rotation, falseBoldWidth; 2168 2169 link.Read<uint16>(&familyID); 2170 link.Read<uint16>(&styleID); 2171 link.Read<float>(&size); 2172 link.Read<float>(&shear); 2173 link.Read<float>(&rotation); 2174 link.Read<float>(&falseBoldWidth); 2175 link.Read<uint32>(&flags); 2176 2177 int32 numChars, numBytes; 2178 link.Read<int32>(&numChars); 2179 link.Read<int32>(&numBytes); 2180 2181 BStackOrHeapArray<char, 256> charArray(numBytes); 2182 BStackOrHeapArray<BShape*, 64> shapes(numChars); 2183 if (!charArray.IsValid() || !shapes.IsValid()) { 2184 fLink.StartMessage(B_NO_MEMORY); 2185 fLink.Flush(); 2186 break; 2187 } 2188 2189 link.Read(charArray, numBytes); 2190 2191 ServerFont font; 2192 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2193 if (status == B_OK) { 2194 font.SetSize(size); 2195 font.SetShear(shear); 2196 font.SetRotation(rotation); 2197 font.SetFalseBoldWidth(falseBoldWidth); 2198 font.SetFlags(flags); 2199 2200 status = font.GetGlyphShapes(charArray, numChars, shapes); 2201 if (status == B_OK) { 2202 fLink.StartMessage(B_OK); 2203 for (int32 i = 0; i < numChars; i++) { 2204 fLink.AttachShape(*shapes[i]); 2205 delete shapes[i]; 2206 } 2207 } 2208 } 2209 2210 if (status != B_OK) 2211 fLink.StartMessage(status); 2212 2213 fLink.Flush(); 2214 break; 2215 } 2216 2217 case AS_GET_HAS_GLYPHS: 2218 { 2219 FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature())); 2220 2221 // Attached Data: 2222 // 1) uint16 - family ID 2223 // 2) uint16 - style ID 2224 // 3) int32 - numChars 2225 // 4) int32 - numBytes 2226 // 5) char - the char buffer with size numBytes 2227 2228 uint16 familyID, styleID; 2229 link.Read<uint16>(&familyID); 2230 link.Read<uint16>(&styleID); 2231 2232 int32 numChars, numBytes; 2233 link.Read<int32>(&numChars); 2234 link.Read<int32>(&numBytes); 2235 2236 BStackOrHeapArray<char, 256> charArray(numBytes); 2237 BStackOrHeapArray<bool, 256> hasArray(numChars); 2238 if (!charArray.IsValid() || !hasArray.IsValid()) { 2239 fLink.StartMessage(B_NO_MEMORY); 2240 fLink.Flush(); 2241 break; 2242 } 2243 2244 link.Read(charArray, numBytes); 2245 2246 ServerFont font; 2247 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2248 if (status == B_OK) { 2249 status = font.GetHasGlyphs(charArray, numBytes, numChars, 2250 hasArray); 2251 if (status == B_OK) { 2252 fLink.StartMessage(B_OK); 2253 fLink.Attach(hasArray, numChars * sizeof(bool)); 2254 } 2255 } 2256 2257 if (status != B_OK) 2258 fLink.StartMessage(status); 2259 2260 fLink.Flush(); 2261 break; 2262 } 2263 2264 case AS_GET_EDGES: 2265 { 2266 FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature())); 2267 2268 // Attached Data: 2269 // 1) uint16 - family ID 2270 // 2) uint16 - style ID 2271 // 3) int32 - numChars 2272 // 4) int32 - numBytes 2273 // 5) char - the char buffer with size numBytes 2274 2275 uint16 familyID, styleID; 2276 link.Read<uint16>(&familyID); 2277 link.Read<uint16>(&styleID); 2278 2279 int32 numChars; 2280 link.Read<int32>(&numChars); 2281 2282 uint32 numBytes; 2283 link.Read<uint32>(&numBytes); 2284 2285 BStackOrHeapArray<char, 256> charArray(numBytes); 2286 BStackOrHeapArray<edge_info, 64> edgeArray(numChars); 2287 if (!charArray.IsValid() || !edgeArray.IsValid()) { 2288 fLink.StartMessage(B_NO_MEMORY); 2289 fLink.Flush(); 2290 break; 2291 } 2292 2293 link.Read(charArray, numBytes); 2294 2295 ServerFont font; 2296 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2297 if (status == B_OK) { 2298 status = font.GetEdges(charArray, numBytes, numChars, 2299 edgeArray); 2300 if (status == B_OK) { 2301 fLink.StartMessage(B_OK); 2302 fLink.Attach(edgeArray, numChars * sizeof(edge_info)); 2303 } 2304 } 2305 2306 if (status != B_OK) 2307 fLink.StartMessage(status); 2308 2309 fLink.Flush(); 2310 break; 2311 } 2312 2313 case AS_GET_ESCAPEMENTS: 2314 { 2315 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature())); 2316 2317 // Attached Data: 2318 // 1) uint16 - family ID 2319 // 2) uint16 - style ID 2320 // 3) float - point size 2321 // 4) uint8 - spacing 2322 // 5) float - rotation 2323 // 6) uint32 - flags 2324 // 7) int32 - numChars 2325 // 8) char - char -\ both 2326 // 9) BPoint - offset -/ (numChars times) 2327 2328 // Returns: 2329 // 1) BPoint - escapement 2330 // numChars times 2331 2332 uint16 familyID, styleID; 2333 uint32 flags; 2334 float size, rotation; 2335 uint8 spacing; 2336 2337 link.Read<uint16>(&familyID); 2338 link.Read<uint16>(&styleID); 2339 link.Read<float>(&size); 2340 link.Read<uint8>(&spacing); 2341 link.Read<float>(&rotation); 2342 link.Read<uint32>(&flags); 2343 2344 escapement_delta delta; 2345 link.Read<float>(&delta.nonspace); 2346 link.Read<float>(&delta.space); 2347 2348 bool wantsOffsets; 2349 link.Read<bool>(&wantsOffsets); 2350 2351 int32 numChars; 2352 link.Read<int32>(&numChars); 2353 2354 uint32 numBytes; 2355 link.Read<uint32>(&numBytes); 2356 2357 BStackOrHeapArray<char, 256> charArray(numBytes); 2358 BStackOrHeapArray<BPoint, 64> escapements(numChars); 2359 BPoint* offsets = NULL; 2360 if (wantsOffsets) 2361 offsets = new(std::nothrow) BPoint[numChars]; 2362 2363 if (!charArray.IsValid() || !escapements.IsValid() 2364 || (offsets == NULL && wantsOffsets)) { 2365 delete[] offsets; 2366 fLink.StartMessage(B_NO_MEMORY); 2367 fLink.Flush(); 2368 break; 2369 } 2370 2371 link.Read(charArray, numBytes); 2372 2373 ServerFont font; 2374 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2375 if (status == B_OK) { 2376 font.SetSize(size); 2377 font.SetSpacing(spacing); 2378 font.SetRotation(rotation); 2379 font.SetFlags(flags); 2380 2381 status = font.GetEscapements(charArray, numBytes, numChars, 2382 delta, escapements, offsets); 2383 2384 if (status == B_OK) { 2385 fLink.StartMessage(B_OK); 2386 for (int32 i = 0; i < numChars; i++) 2387 fLink.Attach<BPoint>(escapements[i]); 2388 2389 if (wantsOffsets) { 2390 for (int32 i = 0; i < numChars; i++) 2391 fLink.Attach<BPoint>(offsets[i]); 2392 } 2393 } 2394 } 2395 2396 if (status != B_OK) 2397 fLink.StartMessage(status); 2398 2399 delete[] offsets; 2400 fLink.Flush(); 2401 break; 2402 } 2403 2404 case AS_GET_ESCAPEMENTS_AS_FLOATS: 2405 { 2406 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature())); 2407 2408 // Attached Data: 2409 // 1) uint16 - family ID 2410 // 2) uint16 - style ID 2411 // 3) float - point size 2412 // 4) uint8 - spacing 2413 // 5) float - rotation 2414 // 6) uint32 - flags 2415 // 7) float - additional "nonspace" delta 2416 // 8) float - additional "space" delta 2417 // 9) int32 - numChars 2418 // 10) int32 - numBytes 2419 // 11) char - the char buffer with size numBytes 2420 2421 // Returns: 2422 // 1) float - escapement buffer with numChar entries 2423 2424 uint16 familyID, styleID; 2425 uint32 flags; 2426 float size, rotation; 2427 uint8 spacing; 2428 2429 link.Read<uint16>(&familyID); 2430 link.Read<uint16>(&styleID); 2431 link.Read<float>(&size); 2432 link.Read<uint8>(&spacing); 2433 link.Read<float>(&rotation); 2434 link.Read<uint32>(&flags); 2435 2436 escapement_delta delta; 2437 link.Read<float>(&delta.nonspace); 2438 link.Read<float>(&delta.space); 2439 2440 int32 numChars; 2441 link.Read<int32>(&numChars); 2442 2443 uint32 numBytes; 2444 link.Read<uint32>(&numBytes); 2445 2446 BStackOrHeapArray<char, 256> charArray(numBytes); 2447 BStackOrHeapArray<float, 64> escapements(numChars); 2448 if (!charArray.IsValid() || !escapements.IsValid()) { 2449 fLink.StartMessage(B_NO_MEMORY); 2450 fLink.Flush(); 2451 break; 2452 } 2453 2454 link.Read(charArray, numBytes); 2455 2456 // figure out escapements 2457 2458 ServerFont font; 2459 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2460 if (status == B_OK) { 2461 font.SetSize(size); 2462 font.SetSpacing(spacing); 2463 font.SetRotation(rotation); 2464 font.SetFlags(flags); 2465 2466 status = font.GetEscapements(charArray, numBytes, numChars, 2467 delta, escapements); 2468 2469 if (status == B_OK) { 2470 fLink.StartMessage(B_OK); 2471 fLink.Attach(escapements, numChars * sizeof(float)); 2472 } 2473 } 2474 2475 if (status != B_OK) 2476 fLink.StartMessage(status); 2477 2478 fLink.Flush(); 2479 break; 2480 } 2481 2482 case AS_GET_BOUNDINGBOXES_CHARS: 2483 case AS_GET_BOUNDINGBOXES_STRING: 2484 { 2485 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature())); 2486 2487 // Attached Data: 2488 // 1) uint16 - family ID 2489 // 2) uint16 - style ID 2490 // 3) float - point size 2491 // 4) float - rotation 2492 // 5) float - shear 2493 // 6) float - false bold width 2494 // 7) uint8 - spacing 2495 // 8) uint32 - flags 2496 // 9) font_metric_mode - mode 2497 // 10) bool - string escapement 2498 // 11) escapement_delta - additional delta 2499 // 12) int32 - numChars 2500 // 13) int32 - numBytes 2501 // 14) char - the char buffer with size numBytes 2502 2503 // Returns: 2504 // 1) BRect - rects with numChar entries 2505 2506 uint16 familyID, styleID; 2507 uint32 flags; 2508 float size, rotation, shear, falseBoldWidth; 2509 uint8 spacing; 2510 font_metric_mode mode; 2511 bool stringEscapement; 2512 2513 link.Read<uint16>(&familyID); 2514 link.Read<uint16>(&styleID); 2515 link.Read<float>(&size); 2516 link.Read<float>(&rotation); 2517 link.Read<float>(&shear); 2518 link.Read<float>(&falseBoldWidth); 2519 link.Read<uint8>(&spacing); 2520 link.Read<uint32>(&flags); 2521 link.Read<font_metric_mode>(&mode); 2522 link.Read<bool>(&stringEscapement); 2523 2524 escapement_delta delta; 2525 link.Read<escapement_delta>(&delta); 2526 2527 int32 numChars; 2528 link.Read<int32>(&numChars); 2529 2530 uint32 numBytes; 2531 link.Read<uint32>(&numBytes); 2532 2533 BStackOrHeapArray<char, 256> charArray(numBytes); 2534 BStackOrHeapArray<BRect, 64> rectArray(numChars); 2535 if (!charArray.IsValid() || !rectArray.IsValid()) { 2536 fLink.StartMessage(B_NO_MEMORY); 2537 fLink.Flush(); 2538 break; 2539 } 2540 2541 link.Read(charArray, numBytes); 2542 2543 // figure out escapements 2544 2545 ServerFont font; 2546 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2547 if (status == B_OK) { 2548 font.SetSize(size); 2549 font.SetRotation(rotation); 2550 font.SetShear(shear); 2551 font.SetFalseBoldWidth(falseBoldWidth); 2552 font.SetSpacing(spacing); 2553 font.SetFlags(flags); 2554 2555 // TODO: implement for real 2556 status = font.GetBoundingBoxes(charArray, numBytes, 2557 numChars, rectArray, stringEscapement, mode, delta, 2558 code == AS_GET_BOUNDINGBOXES_STRING); 2559 if (status == B_OK) { 2560 fLink.StartMessage(B_OK); 2561 for (int32 i = 0; i < numChars; i++) 2562 fLink.Attach<BRect>(rectArray[i]); 2563 } 2564 } 2565 2566 if (status != B_OK) 2567 fLink.StartMessage(status); 2568 2569 fLink.Flush(); 2570 break; 2571 } 2572 2573 case AS_GET_BOUNDINGBOXES_STRINGS: 2574 { 2575 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n", 2576 Signature())); 2577 2578 // Attached Data: 2579 // 1) uint16 - family ID 2580 // 2) uint16 - style ID 2581 // 3) float - point size 2582 // 4) float - rotation 2583 // 5) float - shear 2584 // 6) float - false bold width 2585 // 7) uint8 - spacing 2586 // 8) uint32 - flags 2587 // 9) font_metric_mode - mode 2588 // 10) int32 numStrings 2589 // 11) escapement_delta - additional delta (numStrings times) 2590 // 12) int32 string length to measure (numStrings times) 2591 // 13) string - string (numStrings times) 2592 2593 // Returns: 2594 // 1) BRect - rects with numStrings entries 2595 2596 uint16 familyID, styleID; 2597 uint32 flags; 2598 float ptsize, rotation, shear, falseBoldWidth; 2599 uint8 spacing; 2600 font_metric_mode mode; 2601 2602 link.Read<uint16>(&familyID); 2603 link.Read<uint16>(&styleID); 2604 link.Read<float>(&ptsize); 2605 link.Read<float>(&rotation); 2606 link.Read<float>(&shear); 2607 link.Read<float>(&falseBoldWidth); 2608 link.Read<uint8>(&spacing); 2609 link.Read<uint32>(&flags); 2610 link.Read<font_metric_mode>(&mode); 2611 2612 int32 numStrings; 2613 link.Read<int32>(&numStrings); 2614 2615 BStackOrHeapArray<escapement_delta, 64> deltaArray(numStrings); 2616 BStackOrHeapArray<char*, 64> stringArray(numStrings); 2617 BStackOrHeapArray<size_t, 64> lengthArray(numStrings); 2618 BStackOrHeapArray<BRect, 64> rectArray(numStrings); 2619 if (!deltaArray.IsValid() || !stringArray.IsValid() 2620 || !lengthArray.IsValid() || !rectArray.IsValid()) { 2621 fLink.StartMessage(B_NO_MEMORY); 2622 fLink.Flush(); 2623 break; 2624 } 2625 2626 for (int32 i = 0; i < numStrings; i++) { 2627 // This version of ReadString allocates the strings, we free 2628 // them below 2629 link.ReadString(&stringArray[i], &lengthArray[i]); 2630 link.Read<escapement_delta>(&deltaArray[i]); 2631 } 2632 2633 ServerFont font; 2634 status_t status = font.SetFamilyAndStyle(familyID, styleID); 2635 if (status == B_OK) { 2636 font.SetSize(ptsize); 2637 font.SetRotation(rotation); 2638 font.SetShear(shear); 2639 font.SetFalseBoldWidth(falseBoldWidth); 2640 font.SetSpacing(spacing); 2641 font.SetFlags(flags); 2642 2643 status = font.GetBoundingBoxesForStrings(stringArray, 2644 lengthArray, numStrings, rectArray, mode, deltaArray); 2645 if (status == B_OK) { 2646 fLink.StartMessage(B_OK); 2647 fLink.Attach(rectArray, numStrings * sizeof(BRect)); 2648 } 2649 } 2650 2651 for (int32 i = 0; i < numStrings; i++) 2652 free(stringArray[i]); 2653 2654 if (status != B_OK) 2655 fLink.StartMessage(status); 2656 2657 fLink.Flush(); 2658 break; 2659 } 2660 2661 // Screen commands 2662 2663 case AS_VALID_SCREEN_ID: 2664 { 2665 // Attached data 2666 // 1) int32 screen 2667 2668 int32 id; 2669 if (link.Read<int32>(&id) == B_OK 2670 && id == B_MAIN_SCREEN_ID.id) 2671 fLink.StartMessage(B_OK); 2672 else 2673 fLink.StartMessage(B_ERROR); 2674 2675 fLink.Flush(); 2676 break; 2677 } 2678 2679 case AS_GET_NEXT_SCREEN_ID: 2680 { 2681 // Attached data 2682 // 1) int32 screen 2683 2684 int32 id; 2685 link.Read<int32>(&id); 2686 2687 // TODO: for now, just say we're the last one 2688 fLink.StartMessage(B_ENTRY_NOT_FOUND); 2689 fLink.Flush(); 2690 break; 2691 } 2692 2693 case AS_GET_SCREEN_ID_FROM_WINDOW: 2694 { 2695 status_t status = B_BAD_VALUE; 2696 2697 // Attached data 2698 // 1) int32 - window client token 2699 2700 int32 clientToken; 2701 if (link.Read<int32>(&clientToken) != B_OK) 2702 status = B_BAD_DATA; 2703 else { 2704 BAutolock locker(fWindowListLock); 2705 2706 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 2707 ServerWindow* serverWindow = fWindowList.ItemAt(i); 2708 2709 if (serverWindow->ClientToken() == clientToken) { 2710 AutoReadLocker _(fDesktop->ScreenLocker()); 2711 2712 // found it! 2713 Window* window = serverWindow->Window(); 2714 const Screen* screen = NULL; 2715 if (window != NULL) 2716 screen = window->Screen(); 2717 2718 if (screen == NULL) { 2719 // The window hasn't been added to the desktop yet, 2720 // or it's an offscreen window 2721 break; 2722 } 2723 2724 fLink.StartMessage(B_OK); 2725 fLink.Attach<int32>(screen->ID()); 2726 status = B_OK; 2727 break; 2728 } 2729 } 2730 } 2731 2732 if (status != B_OK) 2733 fLink.StartMessage(status); 2734 fLink.Flush(); 2735 break; 2736 } 2737 2738 case AS_SCREEN_GET_MODE: 2739 { 2740 STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature())); 2741 2742 // Attached data 2743 // 1) int32 screen 2744 // 2) uint32 workspace index 2745 2746 int32 id; 2747 link.Read<int32>(&id); 2748 uint32 workspace; 2749 link.Read<uint32>(&workspace); 2750 2751 display_mode mode; 2752 status_t status = fDesktop->GetScreenMode(workspace, id, mode); 2753 2754 fLink.StartMessage(status); 2755 if (status == B_OK) 2756 fLink.Attach<display_mode>(mode); 2757 fLink.Flush(); 2758 break; 2759 } 2760 2761 case AS_SCREEN_SET_MODE: 2762 { 2763 STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature())); 2764 2765 // Attached data 2766 // 1) int32 screen 2767 // 2) workspace index 2768 // 3) display_mode to set 2769 // 4) 'makeDefault' boolean 2770 2771 int32 id; 2772 link.Read<int32>(&id); 2773 uint32 workspace; 2774 link.Read<uint32>(&workspace); 2775 2776 display_mode mode; 2777 link.Read<display_mode>(&mode); 2778 2779 bool makeDefault = false; 2780 status_t status = link.Read<bool>(&makeDefault); 2781 2782 if (status == B_OK) { 2783 status = fDesktop->SetScreenMode(workspace, id, mode, 2784 makeDefault); 2785 } 2786 if (status == B_OK) { 2787 if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX 2788 && fDesktop->LockSingleWindow()) { 2789 workspace = fDesktop->CurrentWorkspace(); 2790 fDesktop->UnlockSingleWindow(); 2791 } 2792 2793 if (!makeDefault) { 2794 // Memorize the screen change, so that it can be reverted 2795 // later 2796 fTemporaryDisplayModeChange |= 1 << workspace; 2797 } else 2798 fTemporaryDisplayModeChange &= ~(1 << workspace); 2799 } 2800 2801 fLink.StartMessage(status); 2802 fLink.Flush(); 2803 break; 2804 } 2805 2806 case AS_PROPOSE_MODE: 2807 { 2808 STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature())); 2809 int32 id; 2810 link.Read<int32>(&id); 2811 2812 display_mode target, low, high; 2813 link.Read<display_mode>(&target); 2814 link.Read<display_mode>(&low); 2815 link.Read<display_mode>(&high); 2816 status_t status = fDesktop->HWInterface()->ProposeMode(&target, 2817 &low, &high); 2818 2819 // ProposeMode() returns B_BAD_VALUE to hint that the candidate is 2820 // not within the given limits (but is supported) 2821 if (status == B_OK || status == B_BAD_VALUE) { 2822 fLink.StartMessage(B_OK); 2823 fLink.Attach<display_mode>(target); 2824 fLink.Attach<bool>(status == B_OK); 2825 } else 2826 fLink.StartMessage(status); 2827 2828 fLink.Flush(); 2829 break; 2830 } 2831 2832 case AS_GET_MODE_LIST: 2833 { 2834 int32 id; 2835 link.Read<int32>(&id); 2836 // TODO: use this screen id 2837 2838 display_mode* modeList; 2839 uint32 count; 2840 status_t status = fDesktop->HWInterface()->GetModeList(&modeList, 2841 &count); 2842 if (status == B_OK) { 2843 fLink.StartMessage(B_OK); 2844 fLink.Attach<uint32>(count); 2845 fLink.Attach(modeList, sizeof(display_mode) * count); 2846 2847 delete[] modeList; 2848 } else 2849 fLink.StartMessage(status); 2850 2851 fLink.Flush(); 2852 break; 2853 } 2854 2855 case AS_GET_SCREEN_FRAME: 2856 { 2857 STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature())); 2858 2859 // Attached data 2860 // 1) int32 screen 2861 // 2) uint32 workspace index 2862 2863 int32 id; 2864 link.Read<int32>(&id); 2865 uint32 workspace; 2866 link.Read<uint32>(&workspace); 2867 2868 BRect frame; 2869 status_t status = fDesktop->GetScreenFrame(workspace, id, frame); 2870 2871 fLink.StartMessage(status); 2872 if (status == B_OK) 2873 fLink.Attach<BRect>(frame); 2874 2875 fLink.Flush(); 2876 break; 2877 } 2878 2879 case AS_SCREEN_GET_COLORMAP: 2880 { 2881 STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature())); 2882 2883 int32 id; 2884 link.Read<int32>(&id); 2885 2886 const color_map* colorMap = SystemColorMap(); 2887 if (colorMap != NULL) { 2888 fLink.StartMessage(B_OK); 2889 fLink.Attach<color_map>(*colorMap); 2890 } else 2891 fLink.StartMessage(B_ERROR); 2892 2893 fLink.Flush(); 2894 break; 2895 } 2896 2897 case AS_GET_DESKTOP_COLOR: 2898 { 2899 STRACE(("ServerApp %s: get desktop color\n", Signature())); 2900 2901 uint32 index; 2902 link.Read<uint32>(&index); 2903 2904 fLink.StartMessage(B_OK); 2905 fDesktop->LockSingleWindow(); 2906 2907 // we're nice to our children (and also take the default case 2908 // into account which asks for the current workspace) 2909 if (index >= (uint32)kMaxWorkspaces) 2910 index = fDesktop->CurrentWorkspace(); 2911 2912 Workspace workspace(*fDesktop, index, true); 2913 fLink.Attach<rgb_color>(workspace.Color()); 2914 2915 fDesktop->UnlockSingleWindow(); 2916 fLink.Flush(); 2917 break; 2918 } 2919 2920 case AS_SET_DESKTOP_COLOR: 2921 { 2922 STRACE(("ServerApp %s: set desktop color\n", Signature())); 2923 2924 rgb_color color; 2925 uint32 index; 2926 bool makeDefault; 2927 2928 link.Read<rgb_color>(&color); 2929 link.Read<uint32>(&index); 2930 if (link.Read<bool>(&makeDefault) != B_OK) 2931 break; 2932 2933 fDesktop->LockAllWindows(); 2934 2935 // we're nice to our children (and also take the default case 2936 // into account which asks for the current workspace) 2937 if (index >= (uint32)kMaxWorkspaces) 2938 index = fDesktop->CurrentWorkspace(); 2939 2940 Workspace workspace(*fDesktop, index); 2941 workspace.SetColor(color, makeDefault); 2942 2943 fDesktop->UnlockAllWindows(); 2944 break; 2945 } 2946 2947 case AS_GET_ACCELERANT_INFO: 2948 { 2949 STRACE(("ServerApp %s: get accelerant info\n", Signature())); 2950 2951 // We aren't using the screen_id for now... 2952 int32 id; 2953 link.Read<int32>(&id); 2954 2955 accelerant_device_info accelerantInfo; 2956 // TODO: I wonder if there should be a "desktop" lock... 2957 status_t status 2958 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo); 2959 if (status == B_OK) { 2960 fLink.StartMessage(B_OK); 2961 fLink.Attach<accelerant_device_info>(accelerantInfo); 2962 } else 2963 fLink.StartMessage(status); 2964 2965 fLink.Flush(); 2966 break; 2967 } 2968 2969 case AS_GET_MONITOR_INFO: 2970 { 2971 STRACE(("ServerApp %s: get monitor info\n", Signature())); 2972 2973 // We aren't using the screen_id for now... 2974 int32 id; 2975 link.Read<int32>(&id); 2976 2977 monitor_info info; 2978 // TODO: I wonder if there should be a "desktop" lock... 2979 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info); 2980 if (status == B_OK) { 2981 fLink.StartMessage(B_OK); 2982 fLink.Attach<monitor_info>(info); 2983 } else 2984 fLink.StartMessage(status); 2985 2986 fLink.Flush(); 2987 break; 2988 } 2989 2990 case AS_GET_FRAME_BUFFER_CONFIG: 2991 { 2992 STRACE(("ServerApp %s: get frame buffer config\n", Signature())); 2993 2994 // We aren't using the screen_id for now... 2995 int32 id; 2996 link.Read<int32>(&id); 2997 2998 frame_buffer_config config; 2999 // TODO: I wonder if there should be a "desktop" lock... 3000 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config); 3001 if (status == B_OK) { 3002 fLink.StartMessage(B_OK); 3003 fLink.Attach<frame_buffer_config>(config); 3004 } else 3005 fLink.StartMessage(status); 3006 3007 fLink.Flush(); 3008 break; 3009 } 3010 3011 case AS_GET_RETRACE_SEMAPHORE: 3012 { 3013 STRACE(("ServerApp %s: get retrace semaphore\n", Signature())); 3014 3015 // We aren't using the screen_id for now... 3016 int32 id; 3017 link.Read<int32>(&id); 3018 3019 fLink.StartMessage(B_OK); 3020 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore()); 3021 fLink.Flush(); 3022 break; 3023 } 3024 3025 case AS_GET_TIMING_CONSTRAINTS: 3026 { 3027 STRACE(("ServerApp %s: get timing constraints\n", Signature())); 3028 3029 // We aren't using the screen_id for now... 3030 int32 id; 3031 link.Read<int32>(&id); 3032 3033 display_timing_constraints constraints; 3034 status_t status = fDesktop->HWInterface()->GetTimingConstraints( 3035 &constraints); 3036 if (status == B_OK) { 3037 fLink.StartMessage(B_OK); 3038 fLink.Attach<display_timing_constraints>(constraints); 3039 } else 3040 fLink.StartMessage(status); 3041 3042 fLink.Flush(); 3043 break; 3044 } 3045 3046 case AS_GET_PIXEL_CLOCK_LIMITS: 3047 { 3048 STRACE(("ServerApp %s: get pixel clock limits\n", Signature())); 3049 // We aren't using the screen_id for now... 3050 int32 id; 3051 link.Read<int32>(&id); 3052 display_mode mode; 3053 link.Read<display_mode>(&mode); 3054 3055 uint32 low, high; 3056 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode, 3057 &low, &high); 3058 if (status == B_OK) { 3059 fLink.StartMessage(B_OK); 3060 fLink.Attach<uint32>(low); 3061 fLink.Attach<uint32>(high); 3062 } else 3063 fLink.StartMessage(status); 3064 3065 fLink.Flush(); 3066 break; 3067 } 3068 3069 case AS_SET_DPMS: 3070 { 3071 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature())); 3072 int32 id; 3073 link.Read<int32>(&id); 3074 3075 uint32 mode; 3076 link.Read<uint32>(&mode); 3077 3078 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode); 3079 fLink.StartMessage(status); 3080 3081 fLink.Flush(); 3082 break; 3083 } 3084 3085 case AS_GET_DPMS_STATE: 3086 { 3087 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature())); 3088 3089 int32 id; 3090 link.Read<int32>(&id); 3091 3092 uint32 state = fDesktop->HWInterface()->DPMSMode(); 3093 fLink.StartMessage(B_OK); 3094 fLink.Attach<uint32>(state); 3095 fLink.Flush(); 3096 break; 3097 } 3098 3099 case AS_GET_DPMS_CAPABILITIES: 3100 { 3101 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature())); 3102 int32 id; 3103 link.Read<int32>(&id); 3104 3105 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities(); 3106 fLink.StartMessage(B_OK); 3107 fLink.Attach<uint32>(capabilities); 3108 fLink.Flush(); 3109 break; 3110 } 3111 3112 case AS_SCREEN_SET_BRIGHTNESS: 3113 { 3114 STRACE(("ServerApp %s: AS_SCREEN_SET_BRIGHTNESS\n", Signature())); 3115 int32 id; 3116 link.Read<int32>(&id); 3117 3118 float brightness; 3119 link.Read<float>(&brightness); 3120 3121 status_t status = fDesktop->SetBrightness(id, brightness); 3122 fLink.StartMessage(status); 3123 3124 fLink.Flush(); 3125 break; 3126 } 3127 3128 case AS_SCREEN_GET_BRIGHTNESS: 3129 { 3130 STRACE(("ServerApp %s: AS_SCREEN_GET_BRIGHTNESS\n", Signature())); 3131 int32 id; 3132 link.Read<int32>(&id); 3133 3134 float brightness; 3135 status_t result = fDesktop->HWInterface()->GetBrightness(&brightness); 3136 fLink.StartMessage(result); 3137 if (result == B_OK) 3138 fLink.Attach<float>(brightness); 3139 fLink.Flush(); 3140 break; 3141 } 3142 3143 case AS_READ_BITMAP: 3144 { 3145 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature())); 3146 int32 token; 3147 link.Read<int32>(&token); 3148 3149 bool drawCursor = true; 3150 link.Read<bool>(&drawCursor); 3151 3152 BRect bounds; 3153 link.Read<BRect>(&bounds); 3154 3155 bool success = false; 3156 3157 BReference<ServerBitmap> bitmap(GetBitmap(token), true); 3158 if (bitmap != NULL) { 3159 if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) { 3160 success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap, 3161 drawCursor, bounds) == B_OK; 3162 fDesktop->GetDrawingEngine()->UnlockExclusiveAccess(); 3163 } 3164 } 3165 3166 if (success) 3167 fLink.StartMessage(B_OK); 3168 else 3169 fLink.StartMessage(B_BAD_VALUE); 3170 3171 fLink.Flush(); 3172 break; 3173 } 3174 3175 case AS_GET_ACCELERANT_PATH: 3176 { 3177 int32 id; 3178 fLink.Read<int32>(&id); 3179 3180 BString path; 3181 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path); 3182 fLink.StartMessage(status); 3183 if (status == B_OK) 3184 fLink.AttachString(path.String()); 3185 3186 fLink.Flush(); 3187 break; 3188 } 3189 3190 case AS_GET_DRIVER_PATH: 3191 { 3192 int32 id; 3193 fLink.Read<int32>(&id); 3194 3195 BString path; 3196 status_t status = fDesktop->HWInterface()->GetDriverPath(path); 3197 fLink.StartMessage(status); 3198 if (status == B_OK) 3199 fLink.AttachString(path.String()); 3200 3201 fLink.Flush(); 3202 break; 3203 } 3204 3205 // BWindowScreen communication 3206 3207 case AS_DIRECT_SCREEN_LOCK: 3208 { 3209 bool lock; 3210 link.Read<bool>(&lock); 3211 3212 status_t status; 3213 if (lock) 3214 status = fDesktop->LockDirectScreen(ClientTeam()); 3215 else 3216 status = fDesktop->UnlockDirectScreen(ClientTeam()); 3217 3218 fLink.StartMessage(status); 3219 fLink.Flush(); 3220 break; 3221 } 3222 3223 // Hinting and aliasing 3224 3225 case AS_SET_SUBPIXEL_ANTIALIASING: 3226 { 3227 bool subpix; 3228 if (link.Read<bool>(&subpix) == B_OK) { 3229 LockedDesktopSettings settings(fDesktop); 3230 settings.SetSubpixelAntialiasing(subpix); 3231 } 3232 fDesktop->Redraw(); 3233 break; 3234 } 3235 3236 case AS_GET_SUBPIXEL_ANTIALIASING: 3237 { 3238 DesktopSettings settings(fDesktop); 3239 fLink.StartMessage(B_OK); 3240 fLink.Attach<bool>(settings.SubpixelAntialiasing()); 3241 fLink.Flush(); 3242 break; 3243 } 3244 3245 case AS_SET_HINTING: 3246 { 3247 uint8 hinting; 3248 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) { 3249 LockedDesktopSettings settings(fDesktop); 3250 if (hinting != settings.Hinting()) { 3251 settings.SetHinting(hinting); 3252 fDesktop->Redraw(); 3253 } 3254 } 3255 break; 3256 } 3257 3258 case AS_GET_HINTING: 3259 { 3260 DesktopSettings settings(fDesktop); 3261 fLink.StartMessage(B_OK); 3262 fLink.Attach<uint8>(settings.Hinting()); 3263 fLink.Flush(); 3264 break; 3265 } 3266 3267 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: 3268 { 3269 uint8 averageWeight; 3270 if (link.Read<uint8>(&averageWeight) == B_OK) { 3271 LockedDesktopSettings settings(fDesktop); 3272 settings.SetSubpixelAverageWeight(averageWeight); 3273 } 3274 fDesktop->Redraw(); 3275 break; 3276 } 3277 3278 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: 3279 { 3280 DesktopSettings settings(fDesktop); 3281 fLink.StartMessage(B_OK); 3282 fLink.Attach<uint8>(settings.SubpixelAverageWeight()); 3283 fLink.Flush(); 3284 break; 3285 } 3286 3287 case AS_SET_SUBPIXEL_ORDERING: 3288 { 3289 bool subpixelOrdering; 3290 if (link.Read<bool>(&subpixelOrdering) == B_OK) { 3291 LockedDesktopSettings settings(fDesktop); 3292 settings.SetSubpixelOrderingRegular(subpixelOrdering); 3293 } 3294 fDesktop->Redraw(); 3295 break; 3296 } 3297 3298 case AS_GET_SUBPIXEL_ORDERING: 3299 { 3300 DesktopSettings settings(fDesktop); 3301 fLink.StartMessage(B_OK); 3302 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular()); 3303 fLink.Flush(); 3304 break; 3305 } 3306 3307 default: 3308 printf("ServerApp %s received unhandled message code %" B_PRId32 3309 "\n", Signature(), code); 3310 3311 if (link.NeedsReply()) { 3312 // the client is now blocking and waiting for a reply! 3313 fLink.StartMessage(B_ERROR); 3314 fLink.Flush(); 3315 } else 3316 puts("message doesn't need a reply!"); 3317 break; 3318 } 3319 } 3320 3321 3322 /*! \brief The thread function ServerApps use to monitor messages 3323 */ 3324 void 3325 ServerApp::_MessageLooper() 3326 { 3327 // Message-dispatching loop for the ServerApp 3328 3329 // get our own team ID 3330 thread_info threadInfo; 3331 get_thread_info(fThread, &threadInfo); 3332 3333 // First let's tell the client how to talk with us. 3334 fLink.StartMessage(B_OK); 3335 fLink.Attach<port_id>(fMessagePort); 3336 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea()); 3337 fLink.Attach<team_id>(threadInfo.team); 3338 fLink.Flush(); 3339 3340 BPrivate::LinkReceiver &receiver = fLink.Receiver(); 3341 3342 int32 code; 3343 status_t err = B_OK; 3344 3345 while (!fQuitting) { 3346 STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32 3347 ".\n", fMessagePort)); 3348 3349 err = receiver.GetNextMessage(code); 3350 if (err != B_OK || code == B_QUIT_REQUESTED) { 3351 STRACE(("ServerApp: application seems to be gone...\n")); 3352 3353 // Tell desktop to quit us 3354 BPrivate::LinkSender link(fDesktop->MessagePort()); 3355 link.StartMessage(AS_DELETE_APP); 3356 link.Attach<thread_id>(Thread()); 3357 link.Flush(); 3358 break; 3359 } 3360 3361 switch (code) { 3362 case kMsgAppQuit: 3363 // we receive this from our destructor on quit 3364 fQuitting = true; 3365 break; 3366 3367 case AS_QUIT_APP: 3368 { 3369 // This message is received only when the app_server is asked 3370 // to shut down in test/debug mode. Of course, if we are testing 3371 // while using AccelerantDriver, we do NOT want to shut down 3372 // client applications. The server can be quit in this fashion 3373 // through the driver's interface, such as closing the 3374 // ViewDriver's window. 3375 3376 STRACE(("ServerApp %s:Server shutdown notification received\n", 3377 Signature())); 3378 3379 // If we are using the real, accelerated version of the 3380 // DrawingEngine, we do NOT want the user to be able shut down 3381 // the server. The results would NOT be pretty 3382 #if TEST_MODE 3383 BMessage pleaseQuit(B_QUIT_REQUESTED); 3384 SendMessageToClient(&pleaseQuit); 3385 #endif 3386 break; 3387 } 3388 3389 default: 3390 STRACE(("ServerApp %s: Got a Message to dispatch\n", 3391 Signature())); 3392 _DispatchMessage(code, receiver); 3393 break; 3394 } 3395 } 3396 3397 // Quit() will send us a message; we're handling the exiting procedure 3398 thread_id sender; 3399 sem_id shutdownSemaphore; 3400 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id)); 3401 3402 delete this; 3403 3404 if (shutdownSemaphore >= B_OK) 3405 release_sem(shutdownSemaphore); 3406 } 3407 3408 3409 status_t 3410 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link, 3411 port_id& clientReplyPort) 3412 { 3413 // Attached data: 3414 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) 3415 // 2) BRect window frame 3416 // 3) uint32 window look 3417 // 4) uint32 window feel 3418 // 5) uint32 window flags 3419 // 6) uint32 workspace index 3420 // 7) int32 BHandler token of the window 3421 // 8) port_id window's reply port 3422 // 9) port_id window's looper port 3423 // 10) const char * title 3424 3425 BRect frame; 3426 int32 bitmapToken; 3427 uint32 look; 3428 uint32 feel; 3429 uint32 flags; 3430 uint32 workspaces; 3431 int32 token; 3432 port_id looperPort; 3433 char* title; 3434 3435 if (code == AS_CREATE_OFFSCREEN_WINDOW) 3436 link.Read<int32>(&bitmapToken); 3437 3438 link.Read<BRect>(&frame); 3439 link.Read<uint32>(&look); 3440 link.Read<uint32>(&feel); 3441 link.Read<uint32>(&flags); 3442 link.Read<uint32>(&workspaces); 3443 link.Read<int32>(&token); 3444 link.Read<port_id>(&clientReplyPort); 3445 link.Read<port_id>(&looperPort); 3446 if (link.ReadString(&title) != B_OK) 3447 return B_ERROR; 3448 3449 if (!frame.IsValid()) { 3450 // make sure we pass a valid rectangle to ServerWindow 3451 frame.right = frame.left + 1; 3452 frame.bottom = frame.top + 1; 3453 } 3454 3455 status_t status = B_NO_MEMORY; 3456 ServerWindow *window = NULL; 3457 3458 if (code == AS_CREATE_OFFSCREEN_WINDOW) { 3459 ServerBitmap* bitmap = GetBitmap(bitmapToken); 3460 3461 if (bitmap != NULL) { 3462 window = new (nothrow) OffscreenServerWindow(title, this, 3463 clientReplyPort, looperPort, token, bitmap); 3464 } else 3465 status = B_ERROR; 3466 } else { 3467 window = new (nothrow) ServerWindow(title, this, clientReplyPort, 3468 looperPort, token); 3469 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n", 3470 Signature(), title, frame.left, frame.top, 3471 frame.right, frame.bottom)); 3472 } 3473 3474 free(title); 3475 3476 // NOTE: the reply to the client is handled in ServerWindow::Run() 3477 if (window != NULL) { 3478 status = window->Init(frame, (window_look)look, (window_feel)feel, 3479 flags, workspaces); 3480 if (status == B_OK) { 3481 status = window->Run(); 3482 if (status != B_OK) { 3483 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run " 3484 "the window thread\n"); 3485 } 3486 } 3487 3488 if (status != B_OK) 3489 delete window; 3490 } 3491 3492 return status; 3493 } 3494 3495 3496 bool 3497 ServerApp::_HasWindowUnderMouse() 3498 { 3499 BAutolock locker(fWindowListLock); 3500 3501 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 3502 ServerWindow* serverWindow = fWindowList.ItemAt(i); 3503 3504 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN) 3505 return true; 3506 } 3507 3508 return false; 3509 } 3510 3511 3512 bool 3513 ServerApp::_AddBitmap(ServerBitmap* bitmap) 3514 { 3515 BAutolock _(fMapLocker); 3516 3517 try { 3518 fBitmapMap.insert(std::make_pair(bitmap->Token(), BReference<ServerBitmap>(bitmap, false))); 3519 } catch (std::bad_alloc& exception) { 3520 return false; 3521 } 3522 3523 bitmap->SetOwner(this); 3524 return true; 3525 } 3526 3527 3528 void 3529 ServerApp::_DeleteBitmap(ServerBitmap* bitmap) 3530 { 3531 ASSERT(fMapLocker.IsLocked()); 3532 3533 gBitmapManager->BitmapRemoved(bitmap); 3534 fBitmapMap.erase(bitmap->Token()); 3535 } 3536 3537 3538 ServerBitmap* 3539 ServerApp::_FindBitmap(int32 token) const 3540 { 3541 ASSERT(fMapLocker.IsLocked()); 3542 3543 BitmapMap::const_iterator iterator = fBitmapMap.find(token); 3544 if (iterator == fBitmapMap.end()) 3545 return NULL; 3546 3547 return iterator->second; 3548 } 3549 3550 3551 ServerPicture* 3552 ServerApp::_FindPicture(int32 token) const 3553 { 3554 ASSERT(fMapLocker.IsLocked()); 3555 3556 PictureMap::const_iterator iterator = fPictureMap.find(token); 3557 if (iterator == fPictureMap.end()) 3558 return NULL; 3559 3560 return iterator->second; 3561 } 3562