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