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