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