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