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