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