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