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