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