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