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