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