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