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