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 2491 uint16 familyID, styleID; 2492 link.Read<uint16>(&familyID); 2493 link.Read<uint16>(&styleID); 2494 2495 int32 numChars, numBytes; 2496 link.Read<int32>(&numChars); 2497 link.Read<int32>(&numBytes); 2498 2499 BStackOrHeapArray<char, 256> charArray(numBytes); 2500 BStackOrHeapArray<bool, 256> hasArray(numChars); 2501 if (!charArray.IsValid() || !hasArray.IsValid()) { 2502 fLink.StartMessage(B_NO_MEMORY); 2503 fLink.Flush(); 2504 break; 2505 } 2506 2507 link.Read(charArray, numBytes); 2508 2509 ServerFont font; 2510 status_t status = font.SetFamilyAndStyle(familyID, styleID, 2511 fAppFontManager); 2512 2513 if (status == B_OK) { 2514 status = font.GetHasGlyphs(charArray, numBytes, numChars, 2515 hasArray); 2516 if (status == B_OK) { 2517 fLink.StartMessage(B_OK); 2518 fLink.Attach(hasArray, numChars * sizeof(bool)); 2519 } 2520 } 2521 2522 if (status != B_OK) 2523 fLink.StartMessage(status); 2524 2525 fLink.Flush(); 2526 break; 2527 } 2528 2529 case AS_GET_EDGES: 2530 { 2531 FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature())); 2532 2533 // Attached Data: 2534 // 1) uint16 - family ID 2535 // 2) uint16 - style ID 2536 // 3) int32 - numChars 2537 // 4) int32 - numBytes 2538 // 5) char - the char buffer with size numBytes 2539 2540 uint16 familyID, styleID; 2541 link.Read<uint16>(&familyID); 2542 link.Read<uint16>(&styleID); 2543 2544 int32 numChars; 2545 link.Read<int32>(&numChars); 2546 2547 uint32 numBytes; 2548 link.Read<uint32>(&numBytes); 2549 2550 BStackOrHeapArray<char, 256> charArray(numBytes); 2551 BStackOrHeapArray<edge_info, 64> edgeArray(numChars); 2552 if (!charArray.IsValid() || !edgeArray.IsValid()) { 2553 fLink.StartMessage(B_NO_MEMORY); 2554 fLink.Flush(); 2555 break; 2556 } 2557 2558 link.Read(charArray, numBytes); 2559 2560 ServerFont font; 2561 status_t status = font.SetFamilyAndStyle(familyID, styleID, 2562 fAppFontManager); 2563 2564 if (status == B_OK) { 2565 status = font.GetEdges(charArray, numBytes, numChars, 2566 edgeArray); 2567 if (status == B_OK) { 2568 fLink.StartMessage(B_OK); 2569 fLink.Attach(edgeArray, numChars * sizeof(edge_info)); 2570 } 2571 } 2572 2573 if (status != B_OK) 2574 fLink.StartMessage(status); 2575 2576 fLink.Flush(); 2577 break; 2578 } 2579 2580 case AS_GET_ESCAPEMENTS: 2581 { 2582 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature())); 2583 2584 // Attached Data: 2585 // 1) uint16 - family ID 2586 // 2) uint16 - style ID 2587 // 3) float - point size 2588 // 4) uint8 - spacing 2589 // 5) float - rotation 2590 // 6) uint32 - flags 2591 // 7) int32 - numChars 2592 // 8) char - char -\ both 2593 // 9) BPoint - offset -/ (numChars times) 2594 2595 // Returns: 2596 // 1) BPoint - escapement 2597 // numChars times 2598 2599 uint16 familyID, styleID; 2600 uint32 flags; 2601 float size, rotation; 2602 uint8 spacing; 2603 2604 link.Read<uint16>(&familyID); 2605 link.Read<uint16>(&styleID); 2606 link.Read<float>(&size); 2607 link.Read<uint8>(&spacing); 2608 link.Read<float>(&rotation); 2609 link.Read<uint32>(&flags); 2610 2611 escapement_delta delta; 2612 link.Read<float>(&delta.nonspace); 2613 link.Read<float>(&delta.space); 2614 2615 bool wantsOffsets; 2616 link.Read<bool>(&wantsOffsets); 2617 2618 int32 numChars; 2619 link.Read<int32>(&numChars); 2620 2621 uint32 numBytes; 2622 link.Read<uint32>(&numBytes); 2623 2624 BStackOrHeapArray<char, 256> charArray(numBytes); 2625 BStackOrHeapArray<BPoint, 64> escapements(numChars); 2626 BPoint* offsets = NULL; 2627 if (wantsOffsets) 2628 offsets = new(std::nothrow) BPoint[numChars]; 2629 2630 if (!charArray.IsValid() || !escapements.IsValid() 2631 || (offsets == NULL && wantsOffsets)) { 2632 delete[] offsets; 2633 fLink.StartMessage(B_NO_MEMORY); 2634 fLink.Flush(); 2635 break; 2636 } 2637 2638 link.Read(charArray, numBytes); 2639 2640 ServerFont font; 2641 status_t status = font.SetFamilyAndStyle(familyID, styleID, 2642 fAppFontManager); 2643 2644 if (status == B_OK) { 2645 font.SetSize(size); 2646 font.SetSpacing(spacing); 2647 font.SetRotation(rotation); 2648 font.SetFlags(flags); 2649 2650 status = font.GetEscapements(charArray, numBytes, numChars, 2651 delta, escapements, offsets); 2652 2653 if (status == B_OK) { 2654 fLink.StartMessage(B_OK); 2655 for (int32 i = 0; i < numChars; i++) 2656 fLink.Attach<BPoint>(escapements[i]); 2657 2658 if (wantsOffsets) { 2659 for (int32 i = 0; i < numChars; i++) 2660 fLink.Attach<BPoint>(offsets[i]); 2661 } 2662 } 2663 } 2664 2665 if (status != B_OK) 2666 fLink.StartMessage(status); 2667 2668 delete[] offsets; 2669 fLink.Flush(); 2670 break; 2671 } 2672 2673 case AS_GET_ESCAPEMENTS_AS_FLOATS: 2674 { 2675 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature())); 2676 2677 // Attached Data: 2678 // 1) uint16 - family ID 2679 // 2) uint16 - style ID 2680 // 3) float - point size 2681 // 4) uint8 - spacing 2682 // 5) float - rotation 2683 // 6) uint32 - flags 2684 // 7) float - additional "nonspace" delta 2685 // 8) float - additional "space" delta 2686 // 9) int32 - numChars 2687 // 10) int32 - numBytes 2688 // 11) char - the char buffer with size numBytes 2689 2690 // Returns: 2691 // 1) float - escapement buffer with numChar entries 2692 2693 uint16 familyID, styleID; 2694 uint32 flags; 2695 float size, rotation; 2696 uint8 spacing; 2697 2698 link.Read<uint16>(&familyID); 2699 link.Read<uint16>(&styleID); 2700 link.Read<float>(&size); 2701 link.Read<uint8>(&spacing); 2702 link.Read<float>(&rotation); 2703 link.Read<uint32>(&flags); 2704 2705 escapement_delta delta; 2706 link.Read<float>(&delta.nonspace); 2707 link.Read<float>(&delta.space); 2708 2709 int32 numChars; 2710 link.Read<int32>(&numChars); 2711 2712 uint32 numBytes; 2713 link.Read<uint32>(&numBytes); 2714 2715 BStackOrHeapArray<char, 256> charArray(numBytes); 2716 BStackOrHeapArray<float, 64> escapements(numChars); 2717 if (!charArray.IsValid() || !escapements.IsValid()) { 2718 fLink.StartMessage(B_NO_MEMORY); 2719 fLink.Flush(); 2720 break; 2721 } 2722 2723 link.Read(charArray, numBytes); 2724 2725 // figure out escapements 2726 2727 ServerFont font; 2728 status_t status = font.SetFamilyAndStyle(familyID, styleID, 2729 fAppFontManager); 2730 2731 if (status == B_OK) { 2732 font.SetSize(size); 2733 font.SetSpacing(spacing); 2734 font.SetRotation(rotation); 2735 font.SetFlags(flags); 2736 2737 status = font.GetEscapements(charArray, numBytes, numChars, 2738 delta, escapements); 2739 2740 if (status == B_OK) { 2741 fLink.StartMessage(B_OK); 2742 fLink.Attach(escapements, numChars * sizeof(float)); 2743 } 2744 } 2745 2746 if (status != B_OK) 2747 fLink.StartMessage(status); 2748 2749 fLink.Flush(); 2750 break; 2751 } 2752 2753 case AS_GET_BOUNDINGBOXES_CHARS: 2754 case AS_GET_BOUNDINGBOXES_STRING: 2755 { 2756 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature())); 2757 2758 // Attached Data: 2759 // 1) uint16 - family ID 2760 // 2) uint16 - style ID 2761 // 3) float - point size 2762 // 4) float - rotation 2763 // 5) float - shear 2764 // 6) float - false bold width 2765 // 7) uint8 - spacing 2766 // 8) uint32 - flags 2767 // 9) font_metric_mode - mode 2768 // 10) bool - string escapement 2769 // 11) escapement_delta - additional delta 2770 // 12) int32 - numChars 2771 // 13) int32 - numBytes 2772 // 14) char - the char buffer with size numBytes 2773 2774 // Returns: 2775 // 1) BRect - rects with numChar entries 2776 2777 uint16 familyID, styleID; 2778 uint32 flags; 2779 float size, rotation, shear, falseBoldWidth; 2780 uint8 spacing; 2781 font_metric_mode mode; 2782 bool stringEscapement; 2783 2784 link.Read<uint16>(&familyID); 2785 link.Read<uint16>(&styleID); 2786 link.Read<float>(&size); 2787 link.Read<float>(&rotation); 2788 link.Read<float>(&shear); 2789 link.Read<float>(&falseBoldWidth); 2790 link.Read<uint8>(&spacing); 2791 link.Read<uint32>(&flags); 2792 link.Read<font_metric_mode>(&mode); 2793 link.Read<bool>(&stringEscapement); 2794 2795 escapement_delta delta; 2796 link.Read<escapement_delta>(&delta); 2797 2798 int32 numChars; 2799 link.Read<int32>(&numChars); 2800 2801 uint32 numBytes; 2802 link.Read<uint32>(&numBytes); 2803 2804 BStackOrHeapArray<char, 256> charArray(numBytes); 2805 BStackOrHeapArray<BRect, 64> rectArray(numChars); 2806 if (!charArray.IsValid() || !rectArray.IsValid()) { 2807 fLink.StartMessage(B_NO_MEMORY); 2808 fLink.Flush(); 2809 break; 2810 } 2811 2812 link.Read(charArray, numBytes); 2813 2814 // figure out escapements 2815 2816 ServerFont font; 2817 status_t status = font.SetFamilyAndStyle(familyID, styleID, 2818 fAppFontManager); 2819 2820 if (status == B_OK) { 2821 font.SetSize(size); 2822 font.SetRotation(rotation); 2823 font.SetShear(shear); 2824 font.SetFalseBoldWidth(falseBoldWidth); 2825 font.SetSpacing(spacing); 2826 font.SetFlags(flags); 2827 2828 // TODO: implement for real 2829 status = font.GetBoundingBoxes(charArray, numBytes, 2830 numChars, rectArray, stringEscapement, mode, delta, 2831 code == AS_GET_BOUNDINGBOXES_STRING); 2832 if (status == B_OK) { 2833 fLink.StartMessage(B_OK); 2834 for (int32 i = 0; i < numChars; i++) 2835 fLink.Attach<BRect>(rectArray[i]); 2836 } 2837 } 2838 2839 if (status != B_OK) 2840 fLink.StartMessage(status); 2841 2842 fLink.Flush(); 2843 break; 2844 } 2845 2846 case AS_GET_BOUNDINGBOXES_STRINGS: 2847 { 2848 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n", 2849 Signature())); 2850 2851 // Attached Data: 2852 // 1) uint16 - family ID 2853 // 2) uint16 - style ID 2854 // 3) float - point size 2855 // 4) float - rotation 2856 // 5) float - shear 2857 // 6) float - false bold width 2858 // 7) uint8 - spacing 2859 // 8) uint32 - flags 2860 // 9) font_metric_mode - mode 2861 // 10) int32 numStrings 2862 // 11) escapement_delta - additional delta (numStrings times) 2863 // 12) int32 string length to measure (numStrings times) 2864 // 13) string - string (numStrings times) 2865 2866 // Returns: 2867 // 1) BRect - rects with numStrings entries 2868 2869 uint16 familyID, styleID; 2870 uint32 flags; 2871 float ptsize, rotation, shear, falseBoldWidth; 2872 uint8 spacing; 2873 font_metric_mode mode; 2874 2875 link.Read<uint16>(&familyID); 2876 link.Read<uint16>(&styleID); 2877 link.Read<float>(&ptsize); 2878 link.Read<float>(&rotation); 2879 link.Read<float>(&shear); 2880 link.Read<float>(&falseBoldWidth); 2881 link.Read<uint8>(&spacing); 2882 link.Read<uint32>(&flags); 2883 link.Read<font_metric_mode>(&mode); 2884 2885 int32 numStrings; 2886 link.Read<int32>(&numStrings); 2887 2888 BStackOrHeapArray<escapement_delta, 64> deltaArray(numStrings); 2889 BStackOrHeapArray<char*, 64> stringArray(numStrings); 2890 BStackOrHeapArray<size_t, 64> lengthArray(numStrings); 2891 BStackOrHeapArray<BRect, 64> rectArray(numStrings); 2892 if (!deltaArray.IsValid() || !stringArray.IsValid() 2893 || !lengthArray.IsValid() || !rectArray.IsValid()) { 2894 fLink.StartMessage(B_NO_MEMORY); 2895 fLink.Flush(); 2896 break; 2897 } 2898 2899 for (int32 i = 0; i < numStrings; i++) { 2900 // This version of ReadString allocates the strings, we free 2901 // them below 2902 link.ReadString(&stringArray[i], &lengthArray[i]); 2903 link.Read<escapement_delta>(&deltaArray[i]); 2904 } 2905 2906 ServerFont font; 2907 status_t status = font.SetFamilyAndStyle(familyID, styleID, 2908 fAppFontManager); 2909 2910 if (status == B_OK) { 2911 font.SetSize(ptsize); 2912 font.SetRotation(rotation); 2913 font.SetShear(shear); 2914 font.SetFalseBoldWidth(falseBoldWidth); 2915 font.SetSpacing(spacing); 2916 font.SetFlags(flags); 2917 2918 status = font.GetBoundingBoxesForStrings(stringArray, 2919 lengthArray, numStrings, rectArray, mode, deltaArray); 2920 if (status == B_OK) { 2921 fLink.StartMessage(B_OK); 2922 fLink.Attach(rectArray, numStrings * sizeof(BRect)); 2923 } 2924 } 2925 2926 for (int32 i = 0; i < numStrings; i++) 2927 free(stringArray[i]); 2928 2929 if (status != B_OK) 2930 fLink.StartMessage(status); 2931 2932 fLink.Flush(); 2933 break; 2934 } 2935 2936 // Screen commands 2937 2938 case AS_VALID_SCREEN_ID: 2939 { 2940 // Attached data 2941 // 1) int32 screen 2942 2943 int32 id; 2944 if (link.Read<int32>(&id) == B_OK 2945 && id == B_MAIN_SCREEN_ID.id) 2946 fLink.StartMessage(B_OK); 2947 else 2948 fLink.StartMessage(B_ERROR); 2949 2950 fLink.Flush(); 2951 break; 2952 } 2953 2954 case AS_GET_NEXT_SCREEN_ID: 2955 { 2956 // Attached data 2957 // 1) int32 screen 2958 2959 int32 id; 2960 link.Read<int32>(&id); 2961 2962 // TODO: for now, just say we're the last one 2963 fLink.StartMessage(B_ENTRY_NOT_FOUND); 2964 fLink.Flush(); 2965 break; 2966 } 2967 2968 case AS_GET_SCREEN_ID_FROM_WINDOW: 2969 { 2970 status_t status = B_BAD_VALUE; 2971 2972 // Attached data 2973 // 1) int32 - window client token 2974 2975 int32 clientToken; 2976 if (link.Read<int32>(&clientToken) != B_OK) 2977 status = B_BAD_DATA; 2978 else { 2979 BAutolock locker(fWindowListLock); 2980 2981 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 2982 ServerWindow* serverWindow = fWindowList.ItemAt(i); 2983 2984 if (serverWindow->ClientToken() == clientToken) { 2985 AutoReadLocker _(fDesktop->ScreenLocker()); 2986 2987 // found it! 2988 Window* window = serverWindow->Window(); 2989 const Screen* screen = NULL; 2990 if (window != NULL) 2991 screen = window->Screen(); 2992 2993 if (screen == NULL) { 2994 // The window hasn't been added to the desktop yet, 2995 // or it's an offscreen window 2996 break; 2997 } 2998 2999 fLink.StartMessage(B_OK); 3000 fLink.Attach<int32>(screen->ID()); 3001 status = B_OK; 3002 break; 3003 } 3004 } 3005 } 3006 3007 if (status != B_OK) 3008 fLink.StartMessage(status); 3009 fLink.Flush(); 3010 break; 3011 } 3012 3013 case AS_SCREEN_GET_MODE: 3014 { 3015 STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature())); 3016 3017 // Attached data 3018 // 1) int32 screen 3019 // 2) uint32 workspace index 3020 3021 int32 id; 3022 link.Read<int32>(&id); 3023 uint32 workspace; 3024 link.Read<uint32>(&workspace); 3025 3026 display_mode mode; 3027 status_t status = fDesktop->GetScreenMode(workspace, id, mode); 3028 3029 fLink.StartMessage(status); 3030 if (status == B_OK) 3031 fLink.Attach<display_mode>(mode); 3032 fLink.Flush(); 3033 break; 3034 } 3035 3036 case AS_SCREEN_SET_MODE: 3037 { 3038 STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature())); 3039 3040 // Attached data 3041 // 1) int32 screen 3042 // 2) workspace index 3043 // 3) display_mode to set 3044 // 4) 'makeDefault' boolean 3045 3046 int32 id; 3047 link.Read<int32>(&id); 3048 uint32 workspace; 3049 link.Read<uint32>(&workspace); 3050 3051 display_mode mode; 3052 link.Read<display_mode>(&mode); 3053 3054 bool makeDefault = false; 3055 status_t status = link.Read<bool>(&makeDefault); 3056 3057 if (status == B_OK) { 3058 status = fDesktop->SetScreenMode(workspace, id, mode, 3059 makeDefault); 3060 } 3061 if (status == B_OK) { 3062 if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX 3063 && fDesktop->LockSingleWindow()) { 3064 workspace = fDesktop->CurrentWorkspace(); 3065 fDesktop->UnlockSingleWindow(); 3066 } 3067 3068 if (!makeDefault) { 3069 // Memorize the screen change, so that it can be reverted 3070 // later 3071 fTemporaryDisplayModeChange |= 1 << workspace; 3072 } else 3073 fTemporaryDisplayModeChange &= ~(1 << workspace); 3074 } 3075 3076 fLink.StartMessage(status); 3077 fLink.Flush(); 3078 break; 3079 } 3080 3081 case AS_PROPOSE_MODE: 3082 { 3083 STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature())); 3084 int32 id; 3085 link.Read<int32>(&id); 3086 3087 display_mode target, low, high; 3088 link.Read<display_mode>(&target); 3089 link.Read<display_mode>(&low); 3090 link.Read<display_mode>(&high); 3091 status_t status = fDesktop->HWInterface()->ProposeMode(&target, 3092 &low, &high); 3093 3094 // ProposeMode() returns B_BAD_VALUE to hint that the candidate is 3095 // not within the given limits (but is supported) 3096 if (status == B_OK || status == B_BAD_VALUE) { 3097 fLink.StartMessage(B_OK); 3098 fLink.Attach<display_mode>(target); 3099 fLink.Attach<bool>(status == B_OK); 3100 } else 3101 fLink.StartMessage(status); 3102 3103 fLink.Flush(); 3104 break; 3105 } 3106 3107 case AS_GET_MODE_LIST: 3108 { 3109 int32 id; 3110 link.Read<int32>(&id); 3111 // TODO: use this screen id 3112 3113 display_mode* modeList; 3114 uint32 count; 3115 status_t status = fDesktop->HWInterface()->GetModeList(&modeList, 3116 &count); 3117 if (status == B_OK) { 3118 fLink.StartMessage(B_OK); 3119 fLink.Attach<uint32>(count); 3120 fLink.Attach(modeList, sizeof(display_mode) * count); 3121 3122 delete[] modeList; 3123 } else 3124 fLink.StartMessage(status); 3125 3126 fLink.Flush(); 3127 break; 3128 } 3129 3130 case AS_GET_SCREEN_FRAME: 3131 { 3132 STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature())); 3133 3134 // Attached data 3135 // 1) int32 screen 3136 // 2) uint32 workspace index 3137 3138 int32 id; 3139 link.Read<int32>(&id); 3140 uint32 workspace; 3141 link.Read<uint32>(&workspace); 3142 3143 BRect frame; 3144 status_t status = fDesktop->GetScreenFrame(workspace, id, frame); 3145 3146 fLink.StartMessage(status); 3147 if (status == B_OK) 3148 fLink.Attach<BRect>(frame); 3149 3150 fLink.Flush(); 3151 break; 3152 } 3153 3154 case AS_SCREEN_GET_COLORMAP: 3155 { 3156 STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature())); 3157 3158 int32 id; 3159 link.Read<int32>(&id); 3160 3161 const color_map* colorMap = SystemColorMap(); 3162 if (colorMap != NULL) { 3163 fLink.StartMessage(B_OK); 3164 fLink.Attach<color_map>(*colorMap); 3165 } else 3166 fLink.StartMessage(B_ERROR); 3167 3168 fLink.Flush(); 3169 break; 3170 } 3171 3172 case AS_GET_DESKTOP_COLOR: 3173 { 3174 STRACE(("ServerApp %s: get desktop color\n", Signature())); 3175 3176 uint32 index; 3177 link.Read<uint32>(&index); 3178 3179 fLink.StartMessage(B_OK); 3180 fDesktop->LockSingleWindow(); 3181 3182 // we're nice to our children (and also take the default case 3183 // into account which asks for the current workspace) 3184 if (index >= (uint32)kMaxWorkspaces) 3185 index = fDesktop->CurrentWorkspace(); 3186 3187 Workspace workspace(*fDesktop, index, true); 3188 fLink.Attach<rgb_color>(workspace.Color()); 3189 3190 fDesktop->UnlockSingleWindow(); 3191 fLink.Flush(); 3192 break; 3193 } 3194 3195 case AS_SET_DESKTOP_COLOR: 3196 { 3197 STRACE(("ServerApp %s: set desktop color\n", Signature())); 3198 3199 rgb_color color; 3200 uint32 index; 3201 bool makeDefault; 3202 3203 link.Read<rgb_color>(&color); 3204 link.Read<uint32>(&index); 3205 if (link.Read<bool>(&makeDefault) != B_OK) 3206 break; 3207 3208 fDesktop->LockAllWindows(); 3209 3210 // we're nice to our children (and also take the default case 3211 // into account which asks for the current workspace) 3212 if (index >= (uint32)kMaxWorkspaces) 3213 index = fDesktop->CurrentWorkspace(); 3214 3215 Workspace workspace(*fDesktop, index); 3216 workspace.SetColor(color, makeDefault); 3217 3218 fDesktop->UnlockAllWindows(); 3219 break; 3220 } 3221 3222 case AS_GET_ACCELERANT_INFO: 3223 { 3224 STRACE(("ServerApp %s: get accelerant info\n", Signature())); 3225 3226 // We aren't using the screen_id for now... 3227 int32 id; 3228 link.Read<int32>(&id); 3229 3230 accelerant_device_info accelerantInfo; 3231 // TODO: I wonder if there should be a "desktop" lock... 3232 status_t status 3233 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo); 3234 if (status == B_OK) { 3235 fLink.StartMessage(B_OK); 3236 fLink.Attach<accelerant_device_info>(accelerantInfo); 3237 } else 3238 fLink.StartMessage(status); 3239 3240 fLink.Flush(); 3241 break; 3242 } 3243 3244 case AS_GET_MONITOR_INFO: 3245 { 3246 STRACE(("ServerApp %s: get monitor info\n", Signature())); 3247 3248 // We aren't using the screen_id for now... 3249 int32 id; 3250 link.Read<int32>(&id); 3251 3252 monitor_info info; 3253 // TODO: I wonder if there should be a "desktop" lock... 3254 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info); 3255 if (status == B_OK) { 3256 fLink.StartMessage(B_OK); 3257 fLink.Attach<monitor_info>(info); 3258 } else 3259 fLink.StartMessage(status); 3260 3261 fLink.Flush(); 3262 break; 3263 } 3264 3265 case AS_GET_FRAME_BUFFER_CONFIG: 3266 { 3267 STRACE(("ServerApp %s: get frame buffer config\n", Signature())); 3268 3269 // We aren't using the screen_id for now... 3270 int32 id; 3271 link.Read<int32>(&id); 3272 3273 frame_buffer_config config; 3274 // TODO: I wonder if there should be a "desktop" lock... 3275 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config); 3276 if (status == B_OK) { 3277 fLink.StartMessage(B_OK); 3278 fLink.Attach<frame_buffer_config>(config); 3279 } else 3280 fLink.StartMessage(status); 3281 3282 fLink.Flush(); 3283 break; 3284 } 3285 3286 case AS_GET_RETRACE_SEMAPHORE: 3287 { 3288 STRACE(("ServerApp %s: get retrace semaphore\n", Signature())); 3289 3290 // We aren't using the screen_id for now... 3291 int32 id; 3292 link.Read<int32>(&id); 3293 3294 fLink.StartMessage(B_OK); 3295 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore()); 3296 fLink.Flush(); 3297 break; 3298 } 3299 3300 case AS_GET_TIMING_CONSTRAINTS: 3301 { 3302 STRACE(("ServerApp %s: get timing constraints\n", Signature())); 3303 3304 // We aren't using the screen_id for now... 3305 int32 id; 3306 link.Read<int32>(&id); 3307 3308 display_timing_constraints constraints; 3309 status_t status = fDesktop->HWInterface()->GetTimingConstraints( 3310 &constraints); 3311 if (status == B_OK) { 3312 fLink.StartMessage(B_OK); 3313 fLink.Attach<display_timing_constraints>(constraints); 3314 } else 3315 fLink.StartMessage(status); 3316 3317 fLink.Flush(); 3318 break; 3319 } 3320 3321 case AS_GET_PIXEL_CLOCK_LIMITS: 3322 { 3323 STRACE(("ServerApp %s: get pixel clock limits\n", Signature())); 3324 // We aren't using the screen_id for now... 3325 int32 id; 3326 link.Read<int32>(&id); 3327 display_mode mode; 3328 link.Read<display_mode>(&mode); 3329 3330 uint32 low, high; 3331 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode, 3332 &low, &high); 3333 if (status == B_OK) { 3334 fLink.StartMessage(B_OK); 3335 fLink.Attach<uint32>(low); 3336 fLink.Attach<uint32>(high); 3337 } else 3338 fLink.StartMessage(status); 3339 3340 fLink.Flush(); 3341 break; 3342 } 3343 3344 case AS_SET_DPMS: 3345 { 3346 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature())); 3347 int32 id; 3348 link.Read<int32>(&id); 3349 3350 uint32 mode; 3351 link.Read<uint32>(&mode); 3352 3353 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode); 3354 fLink.StartMessage(status); 3355 3356 fLink.Flush(); 3357 break; 3358 } 3359 3360 case AS_GET_DPMS_STATE: 3361 { 3362 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature())); 3363 3364 int32 id; 3365 link.Read<int32>(&id); 3366 3367 uint32 state = fDesktop->HWInterface()->DPMSMode(); 3368 fLink.StartMessage(B_OK); 3369 fLink.Attach<uint32>(state); 3370 fLink.Flush(); 3371 break; 3372 } 3373 3374 case AS_GET_DPMS_CAPABILITIES: 3375 { 3376 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature())); 3377 int32 id; 3378 link.Read<int32>(&id); 3379 3380 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities(); 3381 fLink.StartMessage(B_OK); 3382 fLink.Attach<uint32>(capabilities); 3383 fLink.Flush(); 3384 break; 3385 } 3386 3387 case AS_SCREEN_SET_BRIGHTNESS: 3388 { 3389 STRACE(("ServerApp %s: AS_SCREEN_SET_BRIGHTNESS\n", Signature())); 3390 int32 id; 3391 link.Read<int32>(&id); 3392 3393 float brightness; 3394 link.Read<float>(&brightness); 3395 3396 status_t status = fDesktop->SetBrightness(id, brightness); 3397 fLink.StartMessage(status); 3398 3399 fLink.Flush(); 3400 break; 3401 } 3402 3403 case AS_SCREEN_GET_BRIGHTNESS: 3404 { 3405 STRACE(("ServerApp %s: AS_SCREEN_GET_BRIGHTNESS\n", Signature())); 3406 int32 id; 3407 link.Read<int32>(&id); 3408 3409 float brightness; 3410 status_t result = fDesktop->HWInterface()->GetBrightness(&brightness); 3411 fLink.StartMessage(result); 3412 if (result == B_OK) 3413 fLink.Attach<float>(brightness); 3414 fLink.Flush(); 3415 break; 3416 } 3417 3418 case AS_READ_BITMAP: 3419 { 3420 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature())); 3421 int32 token; 3422 link.Read<int32>(&token); 3423 3424 bool drawCursor = true; 3425 link.Read<bool>(&drawCursor); 3426 3427 BRect bounds; 3428 link.Read<BRect>(&bounds); 3429 3430 bool success = false; 3431 3432 BReference<ServerBitmap> bitmap(GetBitmap(token), true); 3433 if (bitmap != NULL) { 3434 if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) { 3435 success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap, 3436 drawCursor, bounds) == B_OK; 3437 fDesktop->GetDrawingEngine()->UnlockExclusiveAccess(); 3438 } 3439 } 3440 3441 if (success) 3442 fLink.StartMessage(B_OK); 3443 else 3444 fLink.StartMessage(B_BAD_VALUE); 3445 3446 fLink.Flush(); 3447 break; 3448 } 3449 3450 case AS_GET_ACCELERANT_PATH: 3451 { 3452 int32 id; 3453 fLink.Read<int32>(&id); 3454 3455 BString path; 3456 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path); 3457 fLink.StartMessage(status); 3458 if (status == B_OK) 3459 fLink.AttachString(path.String()); 3460 3461 fLink.Flush(); 3462 break; 3463 } 3464 3465 case AS_GET_DRIVER_PATH: 3466 { 3467 int32 id; 3468 fLink.Read<int32>(&id); 3469 3470 BString path; 3471 status_t status = fDesktop->HWInterface()->GetDriverPath(path); 3472 fLink.StartMessage(status); 3473 if (status == B_OK) 3474 fLink.AttachString(path.String()); 3475 3476 fLink.Flush(); 3477 break; 3478 } 3479 3480 // BWindowScreen communication 3481 3482 case AS_DIRECT_SCREEN_LOCK: 3483 { 3484 bool lock; 3485 link.Read<bool>(&lock); 3486 3487 status_t status; 3488 if (lock) 3489 status = fDesktop->LockDirectScreen(ClientTeam()); 3490 else 3491 status = fDesktop->UnlockDirectScreen(ClientTeam()); 3492 3493 fLink.StartMessage(status); 3494 fLink.Flush(); 3495 break; 3496 } 3497 3498 // Hinting and aliasing 3499 3500 case AS_SET_SUBPIXEL_ANTIALIASING: 3501 { 3502 bool subpix; 3503 if (link.Read<bool>(&subpix) == B_OK) { 3504 LockedDesktopSettings settings(fDesktop); 3505 settings.SetSubpixelAntialiasing(subpix); 3506 } 3507 fDesktop->Redraw(); 3508 break; 3509 } 3510 3511 case AS_GET_SUBPIXEL_ANTIALIASING: 3512 { 3513 DesktopSettings settings(fDesktop); 3514 fLink.StartMessage(B_OK); 3515 fLink.Attach<bool>(settings.SubpixelAntialiasing()); 3516 fLink.Flush(); 3517 break; 3518 } 3519 3520 case AS_SET_HINTING: 3521 { 3522 uint8 hinting; 3523 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) { 3524 LockedDesktopSettings settings(fDesktop); 3525 if (hinting != settings.Hinting()) { 3526 settings.SetHinting(hinting); 3527 fDesktop->Redraw(); 3528 } 3529 } 3530 break; 3531 } 3532 3533 case AS_GET_HINTING: 3534 { 3535 DesktopSettings settings(fDesktop); 3536 fLink.StartMessage(B_OK); 3537 fLink.Attach<uint8>(settings.Hinting()); 3538 fLink.Flush(); 3539 break; 3540 } 3541 3542 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: 3543 { 3544 uint8 averageWeight; 3545 if (link.Read<uint8>(&averageWeight) == B_OK) { 3546 LockedDesktopSettings settings(fDesktop); 3547 settings.SetSubpixelAverageWeight(averageWeight); 3548 } 3549 fDesktop->Redraw(); 3550 break; 3551 } 3552 3553 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: 3554 { 3555 DesktopSettings settings(fDesktop); 3556 fLink.StartMessage(B_OK); 3557 fLink.Attach<uint8>(settings.SubpixelAverageWeight()); 3558 fLink.Flush(); 3559 break; 3560 } 3561 3562 case AS_SET_SUBPIXEL_ORDERING: 3563 { 3564 bool subpixelOrdering; 3565 if (link.Read<bool>(&subpixelOrdering) == B_OK) { 3566 LockedDesktopSettings settings(fDesktop); 3567 settings.SetSubpixelOrderingRegular(subpixelOrdering); 3568 } 3569 fDesktop->Redraw(); 3570 break; 3571 } 3572 3573 case AS_GET_SUBPIXEL_ORDERING: 3574 { 3575 DesktopSettings settings(fDesktop); 3576 fLink.StartMessage(B_OK); 3577 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular()); 3578 fLink.Flush(); 3579 break; 3580 } 3581 3582 default: 3583 printf("ServerApp %s received unhandled message code %" B_PRId32 3584 "\n", Signature(), code); 3585 3586 if (link.NeedsReply()) { 3587 // the client is now blocking and waiting for a reply! 3588 fLink.StartMessage(B_ERROR); 3589 fLink.Flush(); 3590 } else 3591 puts("message doesn't need a reply!"); 3592 break; 3593 } 3594 } 3595 3596 3597 /*! \brief The thread function ServerApps use to monitor messages 3598 */ 3599 void 3600 ServerApp::_MessageLooper() 3601 { 3602 // Message-dispatching loop for the ServerApp 3603 3604 // get our own team ID 3605 thread_info threadInfo; 3606 get_thread_info(fThread, &threadInfo); 3607 3608 // First let's tell the client how to talk with us. 3609 fLink.StartMessage(B_OK); 3610 fLink.Attach<port_id>(fMessagePort); 3611 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea()); 3612 fLink.Attach<team_id>(threadInfo.team); 3613 fLink.Flush(); 3614 3615 BPrivate::LinkReceiver &receiver = fLink.Receiver(); 3616 3617 int32 code; 3618 status_t err = B_OK; 3619 3620 while (!fQuitting) { 3621 STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32 3622 ".\n", fMessagePort)); 3623 3624 err = receiver.GetNextMessage(code); 3625 if (err != B_OK || code == B_QUIT_REQUESTED) { 3626 STRACE(("ServerApp: application seems to be gone...\n")); 3627 3628 // Tell desktop to quit us 3629 BPrivate::LinkSender link(fDesktop->MessagePort()); 3630 link.StartMessage(AS_DELETE_APP); 3631 link.Attach<thread_id>(Thread()); 3632 link.Flush(); 3633 break; 3634 } 3635 3636 switch (code) { 3637 case kMsgAppQuit: 3638 // we receive this from our destructor on quit 3639 fQuitting = true; 3640 break; 3641 3642 case AS_QUIT_APP: 3643 { 3644 // This message is received only when the app_server is asked 3645 // to shut down in test/debug mode. Of course, if we are testing 3646 // while using AccelerantDriver, we do NOT want to shut down 3647 // client applications. The server can be quit in this fashion 3648 // through the driver's interface, such as closing the 3649 // ViewDriver's window. 3650 3651 STRACE(("ServerApp %s:Server shutdown notification received\n", 3652 Signature())); 3653 3654 // If we are using the real, accelerated version of the 3655 // DrawingEngine, we do NOT want the user to be able shut down 3656 // the server. The results would NOT be pretty 3657 #if TEST_MODE 3658 BMessage pleaseQuit(B_QUIT_REQUESTED); 3659 SendMessageToClient(&pleaseQuit); 3660 #endif 3661 break; 3662 } 3663 3664 default: 3665 STRACE(("ServerApp %s: Got a Message to dispatch\n", 3666 Signature())); 3667 _DispatchMessage(code, receiver); 3668 break; 3669 } 3670 } 3671 3672 // Quit() will send us a message; we're handling the exiting procedure 3673 thread_id sender; 3674 sem_id shutdownSemaphore; 3675 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id)); 3676 3677 delete this; 3678 3679 if (shutdownSemaphore >= B_OK) 3680 release_sem(shutdownSemaphore); 3681 } 3682 3683 3684 status_t 3685 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link, 3686 port_id& clientReplyPort) 3687 { 3688 // Attached data: 3689 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW) 3690 // 2) BRect window frame 3691 // 3) uint32 window look 3692 // 4) uint32 window feel 3693 // 5) uint32 window flags 3694 // 6) uint32 workspace index 3695 // 7) int32 BHandler token of the window 3696 // 8) port_id window's reply port 3697 // 9) port_id window's looper port 3698 // 10) const char * title 3699 3700 BRect frame; 3701 int32 bitmapToken; 3702 uint32 look; 3703 uint32 feel; 3704 uint32 flags; 3705 uint32 workspaces; 3706 int32 token; 3707 port_id looperPort; 3708 char* title; 3709 3710 if (code == AS_CREATE_OFFSCREEN_WINDOW) 3711 link.Read<int32>(&bitmapToken); 3712 3713 link.Read<BRect>(&frame); 3714 link.Read<uint32>(&look); 3715 link.Read<uint32>(&feel); 3716 link.Read<uint32>(&flags); 3717 link.Read<uint32>(&workspaces); 3718 link.Read<int32>(&token); 3719 link.Read<port_id>(&clientReplyPort); 3720 link.Read<port_id>(&looperPort); 3721 if (link.ReadString(&title) != B_OK) 3722 return B_ERROR; 3723 3724 if (!frame.IsValid()) { 3725 // make sure we pass a valid rectangle to ServerWindow 3726 frame.right = frame.left + 1; 3727 frame.bottom = frame.top + 1; 3728 } 3729 3730 status_t status = B_NO_MEMORY; 3731 ServerWindow *window = NULL; 3732 3733 if (code == AS_CREATE_OFFSCREEN_WINDOW) { 3734 ServerBitmap* bitmap = GetBitmap(bitmapToken); 3735 3736 if (bitmap != NULL) { 3737 window = new (nothrow) OffscreenServerWindow(title, this, 3738 clientReplyPort, looperPort, token, bitmap); 3739 } else 3740 status = B_ERROR; 3741 } else { 3742 window = new (nothrow) ServerWindow(title, this, clientReplyPort, 3743 looperPort, token); 3744 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n", 3745 Signature(), title, frame.left, frame.top, 3746 frame.right, frame.bottom)); 3747 } 3748 3749 free(title); 3750 3751 // NOTE: the reply to the client is handled in ServerWindow::Run() 3752 if (window != NULL) { 3753 status = window->Init(frame, (window_look)look, (window_feel)feel, 3754 flags, workspaces); 3755 if (status == B_OK) { 3756 status = window->Run(); 3757 if (status != B_OK) { 3758 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run " 3759 "the window thread\n"); 3760 } 3761 } 3762 3763 if (status != B_OK) 3764 delete window; 3765 } 3766 3767 return status; 3768 } 3769 3770 3771 bool 3772 ServerApp::_HasWindowUnderMouse() 3773 { 3774 BAutolock locker(fWindowListLock); 3775 3776 for (int32 i = fWindowList.CountItems(); i-- > 0;) { 3777 ServerWindow* serverWindow = fWindowList.ItemAt(i); 3778 3779 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN) 3780 return true; 3781 } 3782 3783 return false; 3784 } 3785 3786 3787 bool 3788 ServerApp::_AddBitmap(ServerBitmap* bitmap) 3789 { 3790 BAutolock _(fMapLocker); 3791 3792 try { 3793 fBitmapMap.insert(std::make_pair(bitmap->Token(), BReference<ServerBitmap>(bitmap, false))); 3794 } catch (std::bad_alloc& exception) { 3795 return false; 3796 } 3797 3798 bitmap->SetOwner(this); 3799 return true; 3800 } 3801 3802 3803 void 3804 ServerApp::_DeleteBitmap(ServerBitmap* bitmap) 3805 { 3806 ASSERT(fMapLocker.IsLocked()); 3807 3808 gBitmapManager->BitmapRemoved(bitmap); 3809 fBitmapMap.erase(bitmap->Token()); 3810 } 3811 3812 3813 ServerBitmap* 3814 ServerApp::_FindBitmap(int32 token) const 3815 { 3816 ASSERT(fMapLocker.IsLocked()); 3817 3818 BitmapMap::const_iterator iterator = fBitmapMap.find(token); 3819 if (iterator == fBitmapMap.end()) 3820 return NULL; 3821 3822 return iterator->second; 3823 } 3824 3825 3826 ServerPicture* 3827 ServerApp::_FindPicture(int32 token) const 3828 { 3829 ASSERT(fMapLocker.IsLocked()); 3830 3831 PictureMap::const_iterator iterator = fPictureMap.find(token); 3832 if (iterator == fPictureMap.end()) 3833 return NULL; 3834 3835 return iterator->second; 3836 } 3837