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