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