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