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