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