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