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