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