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