1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * Adrian Oanca <adioanca@gmail.com> 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 \class ServerWindow 15 \brief Shadow BWindow class 16 17 A ServerWindow handles all the intraserver tasks required of it by its BWindow. There are 18 too many tasks to list as being done by them, but they include handling View transactions, 19 coordinating and linking a window's WindowLayer half with its messaging half, dispatching 20 mouse and key events from the server to its window, and other such things. 21 */ 22 23 24 #include "ServerWindow.h" 25 26 #include "AppServer.h" 27 #include "DebugInfoManager.h" 28 #include "Desktop.h" 29 #include "DrawingEngine.h" 30 #include "HWInterface.h" 31 #include "Overlay.h" 32 #include "RAMLinkMsgReader.h" 33 #include "RenderingBuffer.h" 34 #include "ServerApp.h" 35 #include "ServerBitmap.h" 36 #include "ServerPicture.h" 37 #include "ServerProtocol.h" 38 #include "WindowLayer.h" 39 #include "WorkspacesLayer.h" 40 41 #include "clipping.h" 42 43 #include <DirectWindowPrivate.h> 44 #include <MessagePrivate.h> 45 #include <PictureProtocol.h> 46 #include <PortLink.h> 47 #include <WindowInfo.h> 48 #include <WindowPrivate.h> 49 50 #include <AppDefs.h> 51 #include <Autolock.h> 52 #include <DirectWindow.h> 53 #include <TokenSpace.h> 54 #include <View.h> 55 56 #include <new> 57 58 using std::nothrow; 59 60 //#define TRACE_SERVER_WINDOW 61 //#define TRACE_SERVER_WINDOW_MESSAGES 62 //#define PROFILE_MESSAGE_LOOP 63 64 65 #ifdef TRACE_SERVER_WINDOW 66 # include <stdio.h> 67 # define STRACE(x) printf x 68 #else 69 # define STRACE(x) ; 70 #endif 71 72 #ifdef TRACE_SERVER_WINDOW_MESSAGES 73 # include <stdio.h> 74 # define DTRACE(x) printf x 75 #else 76 # define DTRACE(x) ; 77 #endif 78 79 #ifdef PROFILE_MESSAGE_LOOP 80 static struct profile { int32 count; bigtime_t time; } sMessageProfile[AS_LAST_CODE]; 81 #endif 82 83 84 struct direct_window_data { 85 direct_window_data(); 86 ~direct_window_data(); 87 88 status_t InitCheck() const; 89 90 sem_id sem; 91 sem_id sem_ack; 92 area_id area; 93 bool started; 94 direct_buffer_info *buffer_info; 95 }; 96 97 98 direct_window_data::direct_window_data() 99 : 100 sem(-1), 101 sem_ack(-1), 102 area(-1), 103 started(false), 104 buffer_info(NULL) 105 { 106 area = create_area("direct area", (void **)&buffer_info, 107 B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_WRITE); 108 109 sem = create_sem(0, "direct sem"); 110 sem_ack = create_sem(0, "direct sem ack"); 111 } 112 113 114 direct_window_data::~direct_window_data() 115 { 116 // this should make the client die in case it's still running 117 buffer_info->bits = NULL; 118 buffer_info->bytes_per_row = 0; 119 120 delete_area(area); 121 delete_sem(sem); 122 delete_sem(sem_ack); 123 } 124 125 126 status_t 127 direct_window_data::InitCheck() const 128 { 129 if (area < B_OK) 130 return area; 131 if (sem < B_OK) 132 return sem; 133 if (sem_ack < B_OK) 134 return sem_ack; 135 136 return B_OK; 137 } 138 139 140 // #pragma mark - 141 142 143 /*! 144 Sets up the basic BWindow counterpart - you have to call Init() before 145 you can actually use it, though. 146 */ 147 ServerWindow::ServerWindow(const char *title, ServerApp *app, 148 port_id clientPort, port_id looperPort, int32 clientToken) 149 : MessageLooper(title && *title ? title : "Unnamed Window"), 150 fTitle(NULL), 151 fDesktop(app->GetDesktop()), 152 fServerApp(app), 153 fWindowLayer(NULL), 154 fWindowAddedToDesktop(false), 155 156 fClientTeam(app->ClientTeam()), 157 158 fMessagePort(-1), 159 fClientReplyPort(clientPort), 160 fClientLooperPort(looperPort), 161 162 fClientToken(clientToken), 163 164 fCurrentLayer(NULL), 165 fCurrentDrawingRegion(), 166 fCurrentDrawingRegionValid(false), 167 168 fDirectWindowData(NULL) 169 { 170 STRACE(("ServerWindow(%s)::ServerWindow()\n", title)); 171 172 SetTitle(title); 173 fServerToken = BPrivate::gDefaultTokens.NewToken(B_SERVER_TOKEN, this); 174 175 BMessenger::Private(fFocusMessenger).SetTo(fClientTeam, 176 looperPort, B_PREFERRED_TOKEN); 177 BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam, 178 looperPort, clientToken); 179 180 fEventTarget.SetTo(fFocusMessenger); 181 182 fDeathSemaphore = create_sem(0, "window death"); 183 } 184 185 186 //! Tears down all connections the main app_server objects, and deletes some internals. 187 ServerWindow::~ServerWindow() 188 { 189 STRACE(("ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this)); 190 191 if (!fWindowLayer->IsOffscreenWindow()) { 192 fWindowAddedToDesktop = false; 193 fDesktop->RemoveWindow(fWindowLayer); 194 } 195 196 if (App() != NULL) 197 App()->RemoveWindow(this); 198 199 delete fWindowLayer; 200 201 free(fTitle); 202 delete_port(fMessagePort); 203 204 BPrivate::gDefaultTokens.RemoveToken(fServerToken); 205 206 delete fDirectWindowData; 207 STRACE(("ServerWindow(%p) will exit NOW\n", this)); 208 209 delete_sem(fDeathSemaphore); 210 211 #ifdef PROFILE_MESSAGE_LOOP 212 for (int32 i = 0; i < AS_LAST_CODE; i++) { 213 if (sMessageProfile[i].count == 0) 214 continue; 215 printf("[%ld] called %ld times, %g secs (%Ld usecs per call)\n", 216 i, sMessageProfile[i].count, sMessageProfile[i].time / 1000000.0, 217 sMessageProfile[i].time / sMessageProfile[i].count); 218 } 219 #endif 220 } 221 222 223 status_t 224 ServerWindow::Init(BRect frame, window_look look, window_feel feel, 225 uint32 flags, uint32 workspace) 226 { 227 if (!App()->AddWindow(this)) { 228 fServerApp = NULL; 229 return B_NO_MEMORY; 230 } 231 232 if (fTitle == NULL) 233 return B_NO_MEMORY; 234 235 // fMessagePort is the port to which the app sends messages for the server 236 fMessagePort = create_port(100, fTitle); 237 if (fMessagePort < B_OK) 238 return fMessagePort; 239 240 fLink.SetSenderPort(fClientReplyPort); 241 fLink.SetReceiverPort(fMessagePort); 242 243 // We cannot call MakeWindowLayer in the constructor, since it 244 // is a virtual function! 245 fWindowLayer = MakeWindowLayer(frame, fTitle, look, feel, flags, workspace); 246 if (!fWindowLayer) 247 return B_NO_MEMORY; 248 249 if (!fWindowLayer->IsOffscreenWindow()) { 250 fDesktop->AddWindow(fWindowLayer); 251 fWindowAddedToDesktop = true; 252 } 253 254 return B_OK; 255 } 256 257 258 bool 259 ServerWindow::Run() 260 { 261 if (!MessageLooper::Run()) 262 return false; 263 264 // Send a reply to our window - it is expecting fMessagePort 265 // port and some other info 266 267 fLink.StartMessage(B_OK); 268 fLink.Attach<port_id>(fMessagePort); 269 270 int32 minWidth, maxWidth, minHeight, maxHeight; 271 fWindowLayer->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); 272 273 fLink.Attach<BRect>(fWindowLayer->Frame()); 274 fLink.Attach<float>((float)minWidth); 275 fLink.Attach<float>((float)maxWidth); 276 fLink.Attach<float>((float)minHeight); 277 fLink.Attach<float>((float)maxHeight); 278 fLink.Flush(); 279 280 return true; 281 } 282 283 284 void 285 ServerWindow::_PrepareQuit() 286 { 287 if (fThread == find_thread(NULL)) { 288 // make sure we're hidden 289 fDesktop->LockSingleWindow(); 290 _Hide(); 291 fDesktop->UnlockSingleWindow(); 292 } else if (fThread >= B_OK) 293 PostMessage(AS_HIDE_WINDOW); 294 } 295 296 297 void 298 ServerWindow::_GetLooperName(char* name, size_t length) 299 { 300 const char *title = Title(); 301 if (title == NULL || !title[0]) 302 title = "Unnamed Window"; 303 304 snprintf(name, length, "w:%ld:%s", ClientTeam(), title); 305 } 306 307 308 //! Forces the window layer to update its decorator 309 void 310 ServerWindow::ReplaceDecorator() 311 { 312 if (!IsLocked()) 313 debugger("you must lock a ServerWindow object before calling ::ReplaceDecorator()\n"); 314 315 STRACE(("ServerWindow %s: Replace Decorator\n", fTitle)); 316 //fWindowLayer->UpdateDecorator(); 317 } 318 319 320 //! Shows the window's WindowLayer 321 void 322 ServerWindow::_Show() 323 { 324 // NOTE: if you do something else, other than sending a port message, PLEASE lock 325 STRACE(("ServerWindow %s: _Show\n", Title())); 326 327 if (fQuitting || !fWindowLayer->IsHidden() || fWindowLayer->IsOffscreenWindow()) 328 return; 329 330 // TODO: race condition? maybe we need to dispatch a message to the desktop to show/hide us 331 // instead of doing it from this thread. 332 fDesktop->UnlockSingleWindow(); 333 fDesktop->ShowWindow(fWindowLayer); 334 fDesktop->LockSingleWindow(); 335 336 if (fDirectWindowData != NULL) 337 HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESET); 338 } 339 340 341 //! Hides the window's WindowLayer 342 void 343 ServerWindow::_Hide() 344 { 345 // NOTE: if you do something else, other than sending a port message, PLEASE lock 346 STRACE(("ServerWindow %s: _Hide\n", Title())); 347 348 if (fWindowLayer->IsHidden() || fWindowLayer->IsOffscreenWindow()) 349 return; 350 351 if (fDirectWindowData != NULL) 352 HandleDirectConnection(B_DIRECT_STOP); 353 354 // TODO: race condition? maybe we need to dispatch a message to the desktop to show/hide us 355 // instead of doing it from this thread. 356 fDesktop->UnlockSingleWindow(); 357 fDesktop->HideWindow(fWindowLayer); 358 fDesktop->LockSingleWindow(); 359 } 360 361 362 void 363 ServerWindow::RequestRedraw() 364 { 365 PostMessage(AS_REDRAW, 0); 366 // we don't care if this fails - it's only a notification, and if 367 // it fails, there are obviously enough messages in the queue 368 // already 369 370 atomic_add(&fRedrawRequested, 1); 371 } 372 373 374 void 375 ServerWindow::SetTitle(const char* newTitle) 376 { 377 char* oldTitle = fTitle; 378 379 if (newTitle == NULL) 380 newTitle = ""; 381 382 fTitle = strdup(newTitle); 383 if (fTitle == NULL) { 384 // out of memory condition 385 fTitle = oldTitle; 386 return; 387 } 388 389 free(oldTitle); 390 391 if (Thread() >= B_OK) { 392 char name[B_OS_NAME_LENGTH]; 393 _GetLooperName(name, sizeof(name)); 394 rename_thread(Thread(), name); 395 } 396 397 if (fWindowLayer != NULL) { 398 fDesktop->UnlockSingleWindow(); 399 fDesktop->SetWindowTitle(fWindowLayer, newTitle); 400 fDesktop->LockSingleWindow(); 401 } 402 } 403 404 405 //! Requests that the ServerWindow's BWindow quit 406 void 407 ServerWindow::NotifyQuitRequested() 408 { 409 // NOTE: if you do something else, other than sending a port message, PLEASE lock 410 STRACE(("ServerWindow %s: Quit\n", fTitle)); 411 412 BMessage msg(B_QUIT_REQUESTED); 413 SendMessageToClient(&msg); 414 } 415 416 417 void 418 ServerWindow::NotifyMinimize(bool minimize) 419 { 420 if (fWindowLayer->Feel() != B_NORMAL_WINDOW_FEEL) 421 return; 422 423 // The client is responsible for the actual minimization 424 425 BMessage msg(B_MINIMIZE); 426 msg.AddInt64("when", real_time_clock_usecs()); 427 msg.AddBool("minimize", minimize); 428 429 SendMessageToClient(&msg); 430 } 431 432 433 //! Sends a message to the client to perform a Zoom 434 void 435 ServerWindow::NotifyZoom() 436 { 437 // NOTE: if you do something else, other than sending a port message, PLEASE lock 438 BMessage msg(B_ZOOM); 439 SendMessageToClient(&msg); 440 } 441 442 443 void 444 ServerWindow::GetInfo(window_info& info) 445 { 446 info.team = ClientTeam(); 447 info.server_token = ServerToken(); 448 449 info.thread = Thread(); 450 info.client_token = ClientToken(); 451 info.client_port = fClientLooperPort; 452 info.workspaces = fWindowLayer->Workspaces(); 453 454 info.layer = 0; // ToDo: what is this??? 455 info.feel = fWindowLayer->Feel(); 456 info.flags = fWindowLayer->Flags(); 457 info.window_left = (int)floor(fWindowLayer->Frame().left); 458 info.window_top = (int)floor(fWindowLayer->Frame().top); 459 info.window_right = (int)floor(fWindowLayer->Frame().right); 460 info.window_bottom = (int)floor(fWindowLayer->Frame().bottom); 461 462 info.show_hide_level = fWindowLayer->IsHidden() ? 1 : 0; // ??? 463 info.is_mini = fWindowLayer->IsMinimized(); 464 } 465 466 467 /*! 468 Returns the ServerWindow's WindowLayer, if it exists and has been 469 added to the Desktop already. 470 In other words, you cannot assume this method will always give you 471 a valid pointer. 472 */ 473 WindowLayer* 474 ServerWindow::Window() const 475 { 476 // TODO: ensure desktop is locked! 477 if (!fWindowAddedToDesktop) 478 return NULL; 479 480 return fWindowLayer; 481 } 482 483 484 ViewLayer* 485 ServerWindow::_CreateLayerTree(BPrivate::LinkReceiver &link, ViewLayer **_parent) 486 { 487 // NOTE: no need to check for a lock. This is a private method. 488 489 int32 token; 490 BRect frame; 491 uint32 resizeMask; 492 uint32 eventMask; 493 uint32 eventOptions; 494 uint32 flags; 495 bool hidden; 496 int32 parentToken; 497 char* name = NULL; 498 rgb_color viewColor; 499 BPoint scrollingOffset; 500 501 link.Read<int32>(&token); 502 link.ReadString(&name); 503 link.Read<BRect>(&frame); 504 link.Read<BPoint>(&scrollingOffset); 505 link.Read<uint32>(&resizeMask); 506 link.Read<uint32>(&eventMask); 507 link.Read<uint32>(&eventOptions); 508 link.Read<uint32>(&flags); 509 link.Read<bool>(&hidden); 510 link.Read<rgb_color>(&viewColor); 511 link.Read<int32>(&parentToken); 512 513 STRACE(("ServerWindow(%s)::_CreateLayerTree()-> layer %s, token %ld\n", 514 fTitle, name, token)); 515 516 ViewLayer* newLayer; 517 518 if (link.Code() == AS_LAYER_CREATE_ROOT 519 && (fWindowLayer->Flags() & kWorkspacesWindowFlag) != 0) { 520 // this is a workspaces window! 521 newLayer = new (nothrow) WorkspacesLayer(frame, scrollingOffset, name, 522 token, resizeMask, flags); 523 } else { 524 newLayer = new (nothrow) ViewLayer(frame, scrollingOffset, name, token, 525 resizeMask, flags); 526 } 527 528 free(name); 529 530 if (newLayer == NULL) 531 return NULL; 532 533 // there is no way of setting this, other than manually :-) 534 newLayer->SetViewColor(viewColor); 535 newLayer->SetHidden(hidden); 536 newLayer->SetEventMask(eventMask, eventOptions); 537 538 if (eventMask != 0 || eventOptions != 0) { 539 fDesktop->UnlockSingleWindow(); 540 fDesktop->EventDispatcher().AddListener(EventTarget(), 541 newLayer->Token(), eventMask, eventOptions); 542 fDesktop->LockSingleWindow(); 543 } 544 545 DesktopSettings settings(fDesktop); 546 ServerFont font; 547 settings.GetDefaultPlainFont(font); 548 newLayer->CurrentState()->SetFont(font); 549 550 if (_parent) { 551 ViewLayer *parent; 552 if (App()->ViewTokens().GetToken(parentToken, B_HANDLER_TOKEN, 553 (void**)&parent) != B_OK 554 || parent->Window()->ServerWindow() != this) { 555 CRITICAL("View token not found!\n"); 556 parent = NULL; 557 } 558 559 *_parent = parent; 560 } 561 562 return newLayer; 563 } 564 565 566 /*! 567 Dispatches all window messages, and those view messages that 568 don't need a valid fCurrentLayer (ie. layer creation). 569 */ 570 void 571 ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) 572 { 573 switch (code) { 574 case AS_SHOW_WINDOW: 575 STRACE(("ServerWindow %s: Message AS_SHOW_WINDOW\n", Title())); 576 _Show(); 577 break; 578 579 case AS_HIDE_WINDOW: 580 STRACE(("ServerWindow %s: Message AS_HIDE_WINDOW\n", Title())); 581 _Hide(); 582 break; 583 584 case AS_MINIMIZE_WINDOW: 585 { 586 DTRACE(("ServerWindow %s: Message AS_MINIMIZE_WINDOW\n", Title())); 587 int32 showLevel; 588 bool minimize; 589 590 link.Read<bool>(&minimize); 591 if (link.Read<int32>(&showLevel) == B_OK) { 592 if (showLevel <= 0) { 593 // window is currently hidden - ignore the minimize request 594 break; 595 } 596 597 if (minimize && !fWindowLayer->IsHidden()) 598 _Hide(); 599 else if (!minimize && fWindowLayer->IsHidden()) 600 _Show(); 601 602 fWindowLayer->SetMinimized(minimize); 603 } 604 break; 605 } 606 607 case AS_ACTIVATE_WINDOW: 608 { 609 DTRACE(("ServerWindow %s: Message AS_ACTIVATE_WINDOW: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 610 bool activate = true; 611 612 link.Read<bool>(&activate); 613 614 fDesktop->UnlockSingleWindow(); 615 if (activate) 616 fDesktop->ActivateWindow(fWindowLayer); 617 else 618 fDesktop->SendWindowBehind(fWindowLayer, NULL); 619 fDesktop->LockSingleWindow(); 620 break; 621 } 622 case AS_SEND_BEHIND: 623 { 624 STRACE(("ServerWindow %s: Message AS_SEND_BEHIND\n", Title())); 625 int32 token; 626 team_id teamID; 627 status_t status; 628 629 link.Read<int32>(&token); 630 link.Read<team_id>(&teamID); 631 632 WindowLayer *behindOf; 633 if ((behindOf = fDesktop->FindWindowLayerByClientToken(token, teamID)) != NULL) { 634 fDesktop->UnlockSingleWindow(); 635 // TODO: there is a big race condition when we unlock here (window could be gone by now)! 636 fDesktop->SendWindowBehind(fWindowLayer, behindOf); 637 fDesktop->LockSingleWindow(); 638 status = B_OK; 639 } else 640 status = B_NAME_NOT_FOUND; 641 642 fLink.StartMessage(status); 643 fLink.Flush(); 644 break; 645 } 646 647 case B_QUIT_REQUESTED: 648 STRACE(("ServerWindow %s received quit request\n", Title())); 649 NotifyQuitRequested(); 650 break; 651 652 case AS_ENABLE_UPDATES: 653 { 654 STRACE(("ServerWindow %s: Message AS_ENABLE_UPDATES unimplemented\n", 655 Title())); 656 // TODO: AS_ENABLE_UPDATES 657 //fWindowLayer->EnableUpdateRequests(); 658 break; 659 } 660 case AS_DISABLE_UPDATES: 661 { 662 STRACE(("ServerWindow %s: Message AS_DISABLE_UPDATES unimplemented\n", 663 Title())); 664 // TODO: AS_DISABLE_UPDATES 665 //fWindowLayer->DisableUpdateRequests(); 666 break; 667 } 668 case AS_NEEDS_UPDATE: 669 { 670 STRACE(("ServerWindow %s: Message AS_NEEDS_UPDATE\n", Title())); 671 if (fWindowLayer->NeedsUpdate()) 672 fLink.StartMessage(B_OK); 673 else 674 fLink.StartMessage(B_ERROR); 675 fLink.Flush(); 676 break; 677 } 678 case AS_SET_WINDOW_TITLE: 679 { 680 char* newTitle; 681 if (link.ReadString(&newTitle) == B_OK) { 682 SetTitle(newTitle); 683 free(newTitle); 684 } 685 break; 686 } 687 688 case AS_ADD_TO_SUBSET: 689 { 690 STRACE(("ServerWindow %s: Message AS_ADD_TO_SUBSET\n", Title())); 691 status_t status = B_ERROR; 692 693 int32 token; 694 if (link.Read<int32>(&token) == B_OK) { 695 WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken( 696 token, App()->ClientTeam()); 697 if (windowLayer == NULL 698 || windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) { 699 status = B_BAD_VALUE; 700 } else { 701 fDesktop->UnlockSingleWindow(); 702 // TODO: there is a big race condition when we unlock here (window could be gone by now)! 703 status = fDesktop->AddWindowToSubset(fWindowLayer, windowLayer) 704 ? B_OK : B_NO_MEMORY; 705 fDesktop->LockSingleWindow(); 706 } 707 } 708 709 fLink.StartMessage(status); 710 fLink.Flush(); 711 break; 712 } 713 case AS_REMOVE_FROM_SUBSET: 714 { 715 STRACE(("ServerWindow %s: Message AS_REM_FROM_SUBSET\n", Title())); 716 status_t status = B_ERROR; 717 718 int32 token; 719 if (link.Read<int32>(&token) == B_OK) { 720 WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken( 721 token, App()->ClientTeam()); 722 if (windowLayer != NULL) { 723 fDesktop->UnlockSingleWindow(); 724 // TODO: there is a big race condition when we unlock here (window could be gone by now)! 725 fDesktop->RemoveWindowFromSubset(fWindowLayer, windowLayer); 726 fDesktop->LockSingleWindow(); 727 status = B_OK; 728 } else 729 status = B_BAD_VALUE; 730 } 731 732 fLink.StartMessage(status); 733 fLink.Flush(); 734 break; 735 } 736 737 case AS_SET_LOOK: 738 { 739 STRACE(("ServerWindow %s: Message AS_SET_LOOK\n", Title())); 740 741 status_t status = B_ERROR; 742 int32 look; 743 if (link.Read<int32>(&look) == B_OK) { 744 // test if look is valid 745 status = WindowLayer::IsValidLook((window_look)look) 746 ? B_OK : B_BAD_VALUE; 747 } 748 749 if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) { 750 fDesktop->UnlockSingleWindow(); 751 fDesktop->SetWindowLook(fWindowLayer, (window_look)look); 752 fDesktop->LockSingleWindow(); 753 } 754 755 fLink.StartMessage(status); 756 fLink.Flush(); 757 break; 758 } 759 case AS_SET_FEEL: 760 { 761 STRACE(("ServerWindow %s: Message AS_SET_FEEL\n", Title())); 762 763 status_t status = B_ERROR; 764 int32 feel; 765 if (link.Read<int32>(&feel) == B_OK) { 766 // test if feel is valid 767 status = WindowLayer::IsValidFeel((window_feel)feel) 768 ? B_OK : B_BAD_VALUE; 769 } 770 771 if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) { 772 fDesktop->UnlockSingleWindow(); 773 fDesktop->SetWindowFeel(fWindowLayer, (window_feel)feel); 774 fDesktop->LockSingleWindow(); 775 } 776 777 fLink.StartMessage(status); 778 fLink.Flush(); 779 break; 780 } 781 case AS_SET_FLAGS: 782 { 783 STRACE(("ServerWindow %s: Message AS_SET_FLAGS\n", Title())); 784 785 status_t status = B_ERROR; 786 uint32 flags; 787 if (link.Read<uint32>(&flags) == B_OK) { 788 // test if flags are valid 789 status = (flags & ~WindowLayer::ValidWindowFlags()) == 0 790 ? B_OK : B_BAD_VALUE; 791 } 792 793 if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) { 794 fDesktop->UnlockSingleWindow(); 795 fDesktop->SetWindowFlags(fWindowLayer, flags); 796 fDesktop->LockSingleWindow(); 797 } 798 799 fLink.StartMessage(status); 800 fLink.Flush(); 801 break; 802 } 803 #if 0 804 case AS_SET_ALIGNMENT: 805 { 806 // TODO: Implement AS_SET_ALIGNMENT 807 STRACE(("ServerWindow %s: Message Set_Alignment unimplemented\n", Title())); 808 break; 809 } 810 case AS_GET_ALIGNMENT: 811 { 812 // TODO: Implement AS_GET_ALIGNMENT 813 STRACE(("ServerWindow %s: Message Get_Alignment unimplemented\n", Title())); 814 break; 815 } 816 #endif 817 case AS_GET_WORKSPACES: 818 { 819 STRACE(("ServerWindow %s: Message AS_GET_WORKSPACES\n", Title())); 820 fLink.StartMessage(B_OK); 821 fLink.Attach<uint32>(fWindowLayer->Workspaces()); 822 fLink.Flush(); 823 break; 824 } 825 case AS_SET_WORKSPACES: 826 { 827 uint32 newWorkspaces; 828 if (link.Read<uint32>(&newWorkspaces) != B_OK) 829 break; 830 831 STRACE(("ServerWindow %s: Message AS_SET_WORKSPACES %lx\n", 832 Title(), newWorkspaces)); 833 834 fDesktop->UnlockSingleWindow(); 835 fDesktop->SetWindowWorkspaces(fWindowLayer, newWorkspaces); 836 fDesktop->LockSingleWindow(); 837 break; 838 } 839 case AS_WINDOW_RESIZE: 840 { 841 float xResizeBy; 842 float yResizeBy; 843 link.Read<float>(&xResizeBy); 844 if (link.Read<float>(&yResizeBy) != B_OK) 845 break; 846 847 STRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n", 848 Title(), xResizeBy, yResizeBy)); 849 850 if (fWindowLayer->IsResizing()) { 851 // While the user resizes the window, we ignore 852 // pragmatically set window bounds 853 fLink.StartMessage(B_BUSY); 854 } else { 855 fDesktop->UnlockSingleWindow(); 856 fDesktop->ResizeWindowBy(fWindowLayer, xResizeBy, yResizeBy); 857 fDesktop->LockSingleWindow(); 858 fLink.StartMessage(B_OK); 859 } 860 fLink.Flush(); 861 break; 862 } 863 case AS_WINDOW_MOVE: 864 { 865 float xMoveBy; 866 float yMoveBy; 867 link.Read<float>(&xMoveBy); 868 if (link.Read<float>(&yMoveBy) != B_OK) 869 break; 870 871 STRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n", 872 Title(), xMoveBy, yMoveBy)); 873 874 if (fWindowLayer->IsDragging()) { 875 // While the user moves the window, we ignore 876 // pragmatically set window positions 877 fLink.StartMessage(B_BUSY); 878 } else { 879 fDesktop->UnlockSingleWindow(); 880 fDesktop->MoveWindowBy(fWindowLayer, xMoveBy, yMoveBy); 881 fDesktop->LockSingleWindow(); 882 fLink.StartMessage(B_OK); 883 } 884 fLink.Flush(); 885 break; 886 } 887 case AS_SET_SIZE_LIMITS: 888 { 889 // Attached Data: 890 // 1) float minimum width 891 // 2) float maximum width 892 // 3) float minimum height 893 // 4) float maximum height 894 895 // TODO: for now, move the client to int32 as well! 896 int32 minWidth, maxWidth, minHeight, maxHeight; 897 float value; 898 link.Read<float>(&value); minWidth = (int32)value; 899 link.Read<float>(&value); maxWidth = (int32)value; 900 link.Read<float>(&value); minHeight = (int32)value; 901 link.Read<float>(&value); maxHeight = (int32)value; 902 /* 903 link.Read<int32>(&minWidth); 904 link.Read<int32>(&maxWidth); 905 link.Read<int32>(&minHeight); 906 link.Read<int32>(&maxHeight); 907 */ 908 fDesktop->UnlockSingleWindow(); 909 910 if (fDesktop->LockAllWindows()) { 911 fWindowLayer->SetSizeLimits(minWidth, maxWidth, 912 minHeight, maxHeight); 913 fDesktop->UnlockAllWindows(); 914 } 915 916 fDesktop->LockSingleWindow(); 917 918 // and now, sync the client to the limits that we were able to enforce 919 fWindowLayer->GetSizeLimits(&minWidth, &maxWidth, 920 &minHeight, &maxHeight); 921 922 fLink.StartMessage(B_OK); 923 fLink.Attach<BRect>(fWindowLayer->Frame()); 924 fLink.Attach<float>((float)minWidth); 925 fLink.Attach<float>((float)maxWidth); 926 fLink.Attach<float>((float)minHeight); 927 fLink.Attach<float>((float)maxHeight); 928 929 fLink.Flush(); 930 break; 931 } 932 933 case AS_SET_DECORATOR_SETTINGS: 934 { 935 STRACE(("ServerWindow %s: Message AS_SET_DECORATOR_SETTINGS\n")); 936 937 int32 size; 938 if (fWindowLayer && link.Read<int32>(&size) == B_OK) { 939 char buffer[size]; 940 if (link.Read(buffer, size) == B_OK) { 941 BMessage settings; 942 if (settings.Unflatten(buffer) == B_OK) { 943 fDesktop->UnlockSingleWindow(); 944 fDesktop->SetWindowDecoratorSettings(fWindowLayer, settings); 945 fDesktop->LockSingleWindow(); 946 } 947 } 948 } 949 break; 950 } 951 952 case AS_GET_DECORATOR_SETTINGS: 953 { 954 STRACE(("ServerWindow %s: Message AS_GET_DECORATOR_SETTINGS\n")); 955 956 bool success = false; 957 958 BMessage settings; 959 if (fWindowLayer->GetDecoratorSettings(&settings)) { 960 int32 size = settings.FlattenedSize(); 961 char buffer[size]; 962 if (settings.Flatten(buffer, size) == B_OK) { 963 success = true; 964 fLink.StartMessage(B_OK); 965 fLink.Attach<int32>(size); 966 fLink.Attach(buffer, size); 967 } 968 } 969 970 if (!success) 971 fLink.StartMessage(B_ERROR); 972 973 fLink.Flush(); 974 break; 975 } 976 977 case AS_REDRAW: 978 // Nothing to do here - the redraws are actually handled by looking 979 // at the fRedrawRequested member variable in _MessageLooper(). 980 break; 981 982 case AS_BEGIN_UPDATE: 983 DTRACE(("ServerWindowo %s: AS_BEGIN_UPDATE\n", Title())); 984 fWindowLayer->BeginUpdate(fLink); 985 break; 986 987 case AS_END_UPDATE: 988 DTRACE(("ServerWindowo %s: AS_END_UPDATE\n", Title())); 989 fWindowLayer->EndUpdate(); 990 break; 991 992 case AS_GET_MOUSE: 993 { 994 DTRACE(("ServerWindow %s: Message AS_GET_MOUSE\n", fTitle)); 995 996 fDesktop->UnlockSingleWindow(); 997 // Returns 998 // 1) BPoint mouse location 999 // 2) int32 button state 1000 1001 BPoint where; 1002 int32 buttons; 1003 fDesktop->EventDispatcher().GetMouse(where, buttons); 1004 fDesktop->LockSingleWindow(); 1005 1006 fLink.StartMessage(B_OK); 1007 fLink.Attach<BPoint>(where); 1008 fLink.Attach<int32>(buttons); 1009 fLink.Flush(); 1010 break; 1011 } 1012 1013 // BDirectWindow communication 1014 1015 case AS_DIRECT_WINDOW_GET_SYNC_DATA: 1016 { 1017 status_t status = _EnableDirectWindowMode(); 1018 1019 fLink.StartMessage(status); 1020 if (status == B_OK) { 1021 struct direct_window_sync_data syncData = { 1022 fDirectWindowData->area, 1023 fDirectWindowData->sem, 1024 fDirectWindowData->sem_ack 1025 }; 1026 1027 fLink.Attach(&syncData, sizeof(syncData)); 1028 } 1029 1030 fLink.Flush(); 1031 break; 1032 } 1033 case AS_DIRECT_WINDOW_SET_FULLSCREEN: 1034 { 1035 // TODO: maybe there is more to do than this? 1036 bool enable; 1037 link.Read<bool>(&enable); 1038 1039 status_t status = B_OK; 1040 if (!fWindowLayer->IsOffscreenWindow()) { 1041 fDesktop->UnlockSingleWindow(); 1042 fDesktop->SetWindowFeel(fWindowLayer, 1043 enable ? kWindowScreenFeel : B_NORMAL_WINDOW_FEEL); 1044 fDesktop->LockSingleWindow(); 1045 } else 1046 status = B_BAD_TYPE; 1047 1048 fLink.StartMessage(status); 1049 fLink.Flush(); 1050 break; 1051 } 1052 1053 // View creation and destruction (don't need a valid fCurrentLayer) 1054 1055 case AS_SET_CURRENT_LAYER: 1056 { 1057 int32 token; 1058 if (link.Read<int32>(&token) != B_OK) 1059 break; 1060 1061 ViewLayer *current; 1062 if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN, 1063 (void**)¤t) != B_OK 1064 || current->Window()->ServerWindow() != this) { 1065 // ToDo: if this happens, we probably want to kill the app and clean up 1066 fprintf(stderr, "ServerWindow %s: Message AS_SET_CURRENT_LAYER: layer not found, token %ld\n", fTitle, token); 1067 current = NULL; 1068 } else { 1069 DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token)); 1070 _SetCurrentLayer(current); 1071 } 1072 break; 1073 } 1074 1075 case AS_LAYER_CREATE_ROOT: 1076 { 1077 STRACE(("ServerWindow %s: Message AS_LAYER_CREATE_ROOT\n", fTitle)); 1078 1079 // Start receiving top_view data -- pass NULL as the parent view. 1080 // This should be the *only* place where this happens. 1081 if (fCurrentLayer != NULL) { 1082 fprintf(stderr, "ServerWindow %s: Message AS_LAYER_CREATE_ROOT: fCurrentLayer already set!!\n", fTitle); 1083 break; 1084 } 1085 1086 _SetCurrentLayer(_CreateLayerTree(link, NULL)); 1087 fWindowLayer->SetTopLayer(fCurrentLayer); 1088 break; 1089 } 1090 1091 case AS_LAYER_CREATE: 1092 { 1093 STRACE(("ServerWindow %s: Message AS_LAYER_CREATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 1094 1095 ViewLayer* parent = NULL; 1096 ViewLayer* newLayer = _CreateLayerTree(link, &parent); 1097 if (parent != NULL && newLayer != NULL) 1098 parent->AddChild(newLayer); 1099 else 1100 fprintf(stderr, "ServerWindow %s: Message AS_LAYER_CREATE: parent or newLayer NULL!!\n", fTitle); 1101 break; 1102 } 1103 1104 default: 1105 // TODO: when creating a ViewLayer, check for yet non-existing ViewLayer::InitCheck() 1106 // and take appropriate actions, then checking for fCurrentLayer->CurrentState() 1107 // is unnecessary 1108 if (fCurrentLayer == NULL || fCurrentLayer->CurrentState() == NULL) { 1109 printf("ServerWindow %s received unexpected code - message offset %ld before top_view attached.\n", Title(), code - B_OK); 1110 return; 1111 } 1112 1113 _DispatchViewMessage(code, link); 1114 break; 1115 } 1116 } 1117 1118 1119 /*! 1120 Dispatches all view messages that need a valid fCurrentLayer. 1121 */ 1122 void 1123 ServerWindow::_DispatchViewMessage(int32 code, 1124 BPrivate::LinkReceiver &link) 1125 { 1126 if (_DispatchPictureMessage(code, link)) 1127 return; 1128 1129 switch (code) { 1130 case AS_LAYER_SCROLL: 1131 { 1132 DTRACE(("ServerWindow %s: Message AS_LAYER_SCROLL: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 1133 float dh; 1134 float dv; 1135 1136 link.Read<float>(&dh); 1137 link.Read<float>(&dv); 1138 fWindowLayer->ScrollViewBy(fCurrentLayer, dh, dv); 1139 break; 1140 } 1141 case AS_LAYER_COPY_BITS: 1142 { 1143 BRect src; 1144 BRect dst; 1145 1146 link.Read<BRect>(&src); 1147 link.Read<BRect>(&dst); 1148 1149 BRegion contentRegion; 1150 // TODO: avoid copy operation maybe? 1151 fWindowLayer->GetContentRegion(&contentRegion); 1152 fCurrentLayer->CopyBits(src, dst, contentRegion); 1153 break; 1154 } 1155 case AS_LAYER_DELETE: 1156 { 1157 // Received when a view is detached from a window 1158 1159 int32 token; 1160 if (link.Read<int32>(&token) != B_OK) 1161 break; 1162 1163 ViewLayer *view; 1164 if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN, 1165 (void**)&view) == B_OK 1166 && view->Window()->ServerWindow() == this) { 1167 ViewLayer* parent = view->Parent(); 1168 1169 STRACE(("ServerWindow %s: AS_LAYER_DELETE view: %p, parent: %p\n", 1170 fTitle, view, parent)); 1171 1172 if (parent != NULL) { 1173 parent->RemoveChild(view); 1174 1175 if (view->EventMask() != 0) { 1176 fDesktop->EventDispatcher().RemoveListener(EventTarget(), 1177 token); 1178 } 1179 delete view; 1180 } 1181 } 1182 break; 1183 } 1184 case AS_LAYER_SET_STATE: 1185 { 1186 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 1187 1188 fCurrentLayer->CurrentState()->ReadFromLink(link); 1189 // TODO: When is this used?!? 1190 fCurrentLayer->RebuildClipping(true); 1191 break; 1192 } 1193 case AS_LAYER_SET_FONT_STATE: 1194 { 1195 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_FONT_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 1196 fCurrentLayer->CurrentState()->ReadFontFromLink(link); 1197 break; 1198 } 1199 case AS_LAYER_GET_STATE: 1200 { 1201 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 1202 1203 fLink.StartMessage(B_OK); 1204 1205 // attach state data 1206 fCurrentLayer->CurrentState()->WriteToLink(fLink.Sender()); 1207 fLink.Flush(); 1208 break; 1209 } 1210 case AS_LAYER_SET_EVENT_MASK: 1211 { 1212 STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 1213 uint32 eventMask, options; 1214 1215 link.Read<uint32>(&eventMask); 1216 if (link.Read<uint32>(&options) == B_OK) { 1217 fDesktop->UnlockSingleWindow(); 1218 fCurrentLayer->SetEventMask(eventMask, options); 1219 1220 if (eventMask != 0 || options != 0) { 1221 fDesktop->EventDispatcher().AddListener(EventTarget(), 1222 fCurrentLayer->Token(), eventMask, options); 1223 } else { 1224 fDesktop->EventDispatcher().RemoveListener(EventTarget(), 1225 fCurrentLayer->Token()); 1226 } 1227 fDesktop->LockSingleWindow(); 1228 } 1229 break; 1230 } 1231 case AS_LAYER_SET_MOUSE_EVENT_MASK: 1232 { 1233 STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 1234 uint32 eventMask, options; 1235 1236 link.Read<uint32>(&eventMask); 1237 if (link.Read<uint32>(&options) == B_OK) { 1238 fDesktop->UnlockSingleWindow(); 1239 if (eventMask != 0 || options != 0) { 1240 fDesktop->EventDispatcher().AddTemporaryListener(EventTarget(), 1241 fCurrentLayer->Token(), eventMask, options); 1242 } else { 1243 fDesktop->EventDispatcher().RemoveTemporaryListener(EventTarget(), 1244 fCurrentLayer->Token()); 1245 } 1246 fDesktop->LockSingleWindow(); 1247 } 1248 1249 // TODO: support B_LOCK_WINDOW_FOCUS option in Desktop 1250 break; 1251 } 1252 case AS_LAYER_MOVE_TO: 1253 { 1254 STRACE(("ServerWindow %s: Message AS_LAYER_MOVE_TO: ViewLayer name: %s\n", 1255 fTitle, fCurrentLayer->Name())); 1256 1257 float x, y; 1258 link.Read<float>(&x); 1259 link.Read<float>(&y); 1260 1261 float offsetX = x - fCurrentLayer->Frame().left; 1262 float offsetY = y - fCurrentLayer->Frame().top; 1263 1264 BRegion dirty; 1265 fCurrentLayer->MoveBy(offsetX, offsetY, &dirty); 1266 1267 // TODO: think about how to avoid this hack: 1268 // the parent clipping needs to be updated, it is not 1269 // done in ResizeBy() since it would need to avoid 1270 // too much computations when children are resized because 1271 // follow modes 1272 if (ViewLayer* parent = fCurrentLayer->Parent()) 1273 parent->RebuildClipping(false); 1274 1275 fWindowLayer->MarkContentDirty(dirty); 1276 break; 1277 } 1278 case AS_LAYER_RESIZE_TO: 1279 { 1280 STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_TO: ViewLayer name: %s\n", 1281 fTitle, fCurrentLayer->Name())); 1282 1283 float newWidth, newHeight; 1284 link.Read<float>(&newWidth); 1285 link.Read<float>(&newHeight); 1286 1287 float deltaWidth = newWidth - fCurrentLayer->Frame().Width(); 1288 float deltaHeight = newHeight - fCurrentLayer->Frame().Height(); 1289 1290 BRegion dirty; 1291 fCurrentLayer->ResizeBy(deltaWidth, deltaHeight, &dirty); 1292 1293 // TODO: see above 1294 if (ViewLayer* parent = fCurrentLayer->Parent()) 1295 parent->RebuildClipping(false); 1296 1297 fWindowLayer->MarkContentDirty(dirty); 1298 break; 1299 } 1300 case AS_LAYER_GET_COORD: 1301 { 1302 STRACE(("ServerWindow %s: Message AS_LAYER_GET_COORD: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1303 fLink.StartMessage(B_OK); 1304 // our offset in the parent -> will be originX and originY in BView 1305 fLink.Attach<float>(fCurrentLayer->Frame().left); 1306 fLink.Attach<float>(fCurrentLayer->Frame().top); 1307 fLink.Attach<BRect>(fCurrentLayer->Bounds()); 1308 fLink.Flush(); 1309 break; 1310 } 1311 case AS_LAYER_SET_ORIGIN: 1312 { 1313 STRACE(("ServerWindow %s: Message AS_LAYER_SET_ORIGIN: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1314 1315 float x, y; 1316 link.Read<float>(&x); 1317 link.Read<float>(&y); 1318 1319 fCurrentLayer->SetDrawingOrigin(BPoint(x, y)); 1320 break; 1321 } 1322 case AS_LAYER_GET_ORIGIN: 1323 { 1324 STRACE(("ServerWindow %s: Message AS_LAYER_GET_ORIGIN: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1325 fLink.StartMessage(B_OK); 1326 // TODO: rename this where it is used in the BView code! 1327 // (it wants to know scrolling offset, not drawing origin) 1328 fLink.Attach<BPoint>(fCurrentLayer->ScrollingOffset()); 1329 fLink.Flush(); 1330 break; 1331 } 1332 case AS_LAYER_RESIZE_MODE: 1333 { 1334 STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_MODE: ViewLayer: %s\n", 1335 Title(), fCurrentLayer->Name())); 1336 1337 uint32 resizeMode; 1338 if (link.Read<uint32>(&resizeMode) == B_OK) 1339 fCurrentLayer->SetResizeMode(resizeMode); 1340 break; 1341 } 1342 case AS_LAYER_SET_CURSOR: 1343 { 1344 DTRACE(("ServerWindow %s: Message AS_LAYER_CURSOR: ViewLayer: %s\n", Title(), 1345 fCurrentLayer->Name())); 1346 1347 int32 token; 1348 bool sync; 1349 link.Read<int32>(&token); 1350 if (link.Read<bool>(&sync) != B_OK) 1351 break; 1352 1353 if (!fDesktop->GetCursorManager().Lock()) 1354 break; 1355 1356 ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token); 1357 fCurrentLayer->SetCursor(cursor); 1358 1359 fDesktop->GetCursorManager().Unlock(); 1360 1361 if (fWindowLayer->IsFocus()) { 1362 // The cursor might need to be updated now 1363 if (fDesktop->ViewUnderMouse(fWindowLayer) == fCurrentLayer->Token()) 1364 fServerApp->SetCurrentCursor(cursor); 1365 } 1366 if (sync) { 1367 // sync the client (it can now delete the cursor) 1368 fLink.StartMessage(B_OK); 1369 fLink.Flush(); 1370 } 1371 1372 break; 1373 } 1374 case AS_LAYER_SET_FLAGS: 1375 { 1376 uint32 flags; 1377 link.Read<uint32>(&flags); 1378 fCurrentLayer->SetFlags(flags); 1379 1380 STRACE(("ServerWindow %s: Message AS_LAYER_SET_FLAGS: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1381 break; 1382 } 1383 case AS_LAYER_HIDE: 1384 { 1385 STRACE(("ServerWindow %s: Message AS_LAYER_HIDE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1386 fCurrentLayer->SetHidden(true); 1387 break; 1388 } 1389 case AS_LAYER_SHOW: 1390 { 1391 STRACE(("ServerWindow %s: Message AS_LAYER_SHOW: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1392 fCurrentLayer->SetHidden(false); 1393 break; 1394 } 1395 case AS_LAYER_SET_LINE_MODE: 1396 { 1397 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LINE_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1398 int8 lineCap, lineJoin; 1399 float miterLimit; 1400 1401 link.Read<int8>(&lineCap); 1402 link.Read<int8>(&lineJoin); 1403 link.Read<float>(&miterLimit); 1404 1405 fCurrentLayer->CurrentState()->SetLineCapMode((cap_mode)lineCap); 1406 fCurrentLayer->CurrentState()->SetLineJoinMode((join_mode)lineJoin); 1407 fCurrentLayer->CurrentState()->SetMiterLimit(miterLimit); 1408 1409 break; 1410 } 1411 case AS_LAYER_GET_LINE_MODE: 1412 { 1413 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LINE_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1414 fLink.StartMessage(B_OK); 1415 fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->LineCapMode())); 1416 fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->LineJoinMode())); 1417 fLink.Attach<float>(fCurrentLayer->CurrentState()->MiterLimit()); 1418 fLink.Flush(); 1419 1420 break; 1421 } 1422 case AS_LAYER_PUSH_STATE: 1423 { 1424 DTRACE(("ServerWindow %s: Message AS_LAYER_PUSH_STATE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1425 1426 fCurrentLayer->PushState(); 1427 1428 break; 1429 } 1430 case AS_LAYER_POP_STATE: 1431 { 1432 DTRACE(("ServerWindow %s: Message AS_LAYER_POP_STATE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1433 1434 fCurrentLayer->PopState(); 1435 1436 break; 1437 } 1438 case AS_LAYER_SET_SCALE: 1439 { 1440 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_SCALE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1441 float scale; 1442 link.Read<float>(&scale); 1443 1444 fCurrentLayer->SetScale(scale); 1445 break; 1446 } 1447 case AS_LAYER_GET_SCALE: 1448 { 1449 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_SCALE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1450 1451 fLink.StartMessage(B_OK); 1452 fLink.Attach<float>(fCurrentLayer->CurrentState()->Scale()); 1453 fLink.Flush(); 1454 break; 1455 } 1456 case AS_LAYER_SET_PEN_LOC: 1457 { 1458 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_LOC: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1459 float x, y; 1460 1461 link.Read<float>(&x); 1462 link.Read<float>(&y); 1463 1464 fCurrentLayer->CurrentState()->SetPenLocation(BPoint(x, y)); 1465 break; 1466 } 1467 case AS_LAYER_GET_PEN_LOC: 1468 { 1469 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_LOC: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1470 fLink.StartMessage(B_OK); 1471 fLink.Attach<BPoint>(fCurrentLayer->CurrentState()->PenLocation()); 1472 fLink.Flush(); 1473 1474 break; 1475 } 1476 case AS_LAYER_SET_PEN_SIZE: 1477 { 1478 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_SIZE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1479 float penSize; 1480 link.Read<float>(&penSize); 1481 fCurrentLayer->CurrentState()->SetPenSize(penSize); 1482 1483 break; 1484 } 1485 case AS_LAYER_GET_PEN_SIZE: 1486 { 1487 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_SIZE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1488 fLink.StartMessage(B_OK); 1489 fLink.Attach<float>(fCurrentLayer->CurrentState()->PenSize()); 1490 fLink.Flush(); 1491 1492 break; 1493 } 1494 case AS_LAYER_SET_VIEW_COLOR: 1495 { 1496 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_VIEW_COLOR: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1497 rgb_color c; 1498 1499 link.Read(&c, sizeof(rgb_color)); 1500 1501 fCurrentLayer->SetViewColor(RGBColor(c)); 1502 break; 1503 } 1504 1505 case AS_LAYER_GET_HIGH_COLOR: 1506 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_HIGH_COLOR: ViewLayer: %s\n", 1507 Title(), fCurrentLayer->Name())); 1508 1509 fLink.StartMessage(B_OK); 1510 fLink.Attach<rgb_color>(fCurrentLayer->CurrentState()->HighColor().GetColor32()); 1511 fLink.Flush(); 1512 break; 1513 1514 case AS_LAYER_GET_LOW_COLOR: 1515 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LOW_COLOR: ViewLayer: %s\n", 1516 Title(), fCurrentLayer->Name())); 1517 1518 fLink.StartMessage(B_OK); 1519 fLink.Attach<rgb_color>(fCurrentLayer->CurrentState()->LowColor().GetColor32()); 1520 fLink.Flush(); 1521 break; 1522 1523 case AS_LAYER_GET_VIEW_COLOR: 1524 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_VIEW_COLOR: ViewLayer: %s\n", 1525 Title(), fCurrentLayer->Name())); 1526 1527 fLink.StartMessage(B_OK); 1528 fLink.Attach<rgb_color>(fCurrentLayer->ViewColor().GetColor32()); 1529 fLink.Flush(); 1530 break; 1531 1532 case AS_LAYER_SET_BLENDING_MODE: 1533 { 1534 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_BLEND_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1535 int8 srcAlpha, alphaFunc; 1536 1537 link.Read<int8>(&srcAlpha); 1538 link.Read<int8>(&alphaFunc); 1539 1540 fCurrentLayer->CurrentState()->SetBlendingMode((source_alpha)srcAlpha, 1541 (alpha_function)alphaFunc); 1542 1543 break; 1544 } 1545 case AS_LAYER_GET_BLENDING_MODE: 1546 { 1547 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_BLEND_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1548 fLink.StartMessage(B_OK); 1549 fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->AlphaSrcMode())); 1550 fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->AlphaFncMode())); 1551 fLink.Flush(); 1552 1553 break; 1554 } 1555 case AS_LAYER_SET_DRAWING_MODE: 1556 { 1557 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_DRAW_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1558 int8 drawingMode; 1559 1560 link.Read<int8>(&drawingMode); 1561 1562 fCurrentLayer->CurrentState()->SetDrawingMode((drawing_mode)drawingMode); 1563 1564 break; 1565 } 1566 case AS_LAYER_GET_DRAWING_MODE: 1567 { 1568 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_DRAW_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1569 fLink.StartMessage(B_OK); 1570 fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->GetDrawingMode())); 1571 fLink.Flush(); 1572 1573 break; 1574 } 1575 case AS_LAYER_SET_VIEW_BITMAP: 1576 { 1577 int32 bitmapToken, resizingMode, options; 1578 BRect srcRect, dstRect; 1579 1580 link.Read<int32>(&bitmapToken); 1581 link.Read<BRect>(&srcRect); 1582 link.Read<BRect>(&dstRect); 1583 link.Read<int32>(&resizingMode); 1584 status_t status = link.Read<int32>(&options); 1585 1586 rgb_color colorKey = {0}; 1587 1588 if (status == B_OK) { 1589 ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken); 1590 if (bitmapToken == -1 || bitmap != NULL) { 1591 bool wasOverlay = fCurrentLayer->ViewBitmap() != NULL 1592 && fCurrentLayer->ViewBitmap()->Overlay() != NULL; 1593 1594 // TODO: this is a race condition: the bitmap could have been 1595 // deleted in the mean time!! 1596 fCurrentLayer->SetViewBitmap(bitmap, srcRect, dstRect, 1597 resizingMode, options); 1598 1599 // TODO: if we revert the view color overlay handling 1600 // in ViewLayer::Draw() to the R5 version, we never 1601 // need to invalidate the view for overlays. 1602 1603 // invalidate view - but only if this is a non-overlay switch 1604 if (bitmap == NULL || bitmap->Overlay() == NULL || !wasOverlay) { 1605 BRegion dirty(fCurrentLayer->Bounds()); 1606 fWindowLayer->InvalidateView(fCurrentLayer, dirty); 1607 } 1608 1609 if (bitmap != NULL && bitmap->Overlay() != NULL) { 1610 bitmap->Overlay()->SetFlags(options); 1611 colorKey = bitmap->Overlay()->Color().GetColor32(); 1612 } 1613 } else 1614 status = B_BAD_VALUE; 1615 } 1616 1617 fLink.StartMessage(status); 1618 if (status == B_OK && (options & AS_REQUEST_COLOR_KEY) != 0) { 1619 // Attach color key for the overlay bitmap 1620 fLink.Attach<rgb_color>(colorKey); 1621 } 1622 1623 fLink.Flush(); 1624 break; 1625 } 1626 case AS_LAYER_PRINT_ALIASING: 1627 { 1628 DTRACE(("ServerWindow %s: Message AS_LAYER_PRINT_ALIASING: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1629 bool fontAliasing; 1630 if (link.Read<bool>(&fontAliasing) == B_OK) 1631 fCurrentLayer->CurrentState()->SetForceFontAliasing(fontAliasing); 1632 break; 1633 } 1634 case AS_LAYER_CLIP_TO_PICTURE: 1635 { 1636 DTRACE(("ServerWindow %s: Message AS_LAYER_CLIP_TO_PICTURE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1637 // TODO: you are not allowed to use ViewLayer regions here!!! 1638 1639 int32 pictureToken; 1640 BPoint where; 1641 bool inverse = false; 1642 1643 link.Read<int32>(&pictureToken); 1644 link.Read<BPoint>(&where); 1645 link.Read<bool>(&inverse); 1646 1647 // search for a picture with the specified token. 1648 ServerPicture *picture = fServerApp->FindPicture(pictureToken); 1649 // TODO: Increase that picture's reference count.(~ allocate a picture) 1650 if (picture == NULL) 1651 break; 1652 1653 BRegion region; 1654 // TODO: I think we also need the BView's token 1655 // I think PictureToRegion would fit better into the ViewLayer class (?) 1656 if (PictureToRegion(picture, region, inverse, where) < B_OK) 1657 break; 1658 1659 fCurrentLayer->SetUserClipping(®ion); 1660 1661 // TODO: reenable AS_LAYER_CLIP_TO_PICTURE 1662 #if 0 1663 if (rootLayer && !(fCurrentLayer->IsHidden()) && !fWindowLayer->InUpdate()) { 1664 BRegion invalidRegion; 1665 fCurrentLayer->GetOnScreenRegion(invalidRegion); 1666 1667 // TODO: this is broken! a smaller area may be invalidated! 1668 1669 fCurrentLayer->fParent->MarkForRebuild(invalidRegion); 1670 fCurrentLayer->fParent->TriggerRebuild(); 1671 rootLayer->MarkForRedraw(invalidRegion); 1672 rootLayer->TriggerRedraw(); 1673 } 1674 #endif 1675 break; 1676 } 1677 1678 case AS_LAYER_GET_CLIP_REGION: 1679 { 1680 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_CLIP_REGION: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1681 1682 // if this ViewLayer is hidden, it is clear that its visible region is void. 1683 if (fCurrentLayer->IsHidden()) { 1684 fLink.StartMessage(B_OK); 1685 fLink.Attach<int32>(0L); 1686 fLink.Flush(); 1687 } else { 1688 BRegion drawingRegion = fCurrentLayer->LocalClipping(); 1689 int32 rectCount = drawingRegion.CountRects(); 1690 1691 fLink.StartMessage(B_OK); 1692 fLink.Attach<int32>(rectCount); 1693 1694 for (int32 i = 0; i < rectCount; i++) { 1695 fLink.Attach<BRect>(drawingRegion.RectAt(i)); 1696 } 1697 1698 fLink.Flush(); 1699 } 1700 1701 break; 1702 } 1703 case AS_LAYER_SET_CLIP_REGION: 1704 { 1705 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1706 1707 int32 rectCount; 1708 status_t status = link.Read<int32>(&rectCount); 1709 // a negative count means no 1710 // region for the current draw state, 1711 // but an *empty* region is actually valid! 1712 // even if it means no drawing is allowed 1713 BRegion region; 1714 if (status == B_OK && rectCount >= 0) { 1715 for (int32 i = 0; i < rectCount; i++) { 1716 clipping_rect r; 1717 status = link.Read<clipping_rect>(&r); 1718 if (status < B_OK) 1719 break; 1720 // TODO: optimize (use AttachRegion()+ReadRegion()) 1721 region.Include(r); 1722 } 1723 } else 1724 status = B_ERROR; 1725 1726 if (status == B_OK) { 1727 fCurrentLayer->SetUserClipping(®ion); 1728 } else { 1729 // passing NULL sets this states region 1730 // to that of the previous state 1731 fCurrentLayer->SetUserClipping(NULL); 1732 } 1733 1734 break; 1735 } 1736 1737 case AS_LAYER_INVALIDATE_RECT: 1738 { 1739 DTRACE(("ServerWindow %s: Message AS_LAYER_INVALIDATE_RECT: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1740 1741 // NOTE: looks like this call is NOT affected by origin and scale on R5 1742 // so this implementation is "correct" 1743 BRect invalidRect; 1744 if (link.Read<BRect>(&invalidRect) == B_OK) { 1745 BRegion dirty(invalidRect); 1746 fWindowLayer->InvalidateView(fCurrentLayer, dirty); 1747 } 1748 break; 1749 } 1750 case AS_LAYER_INVALIDATE_REGION: 1751 { 1752 DTRACE(("ServerWindow %s: Message AS_LAYER_INVALIDATE_RECT: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1753 1754 // NOTE: looks like this call is NOT affected by origin and scale on R5 1755 // so this implementation is "correct" 1756 BRegion dirty; 1757 int32 rectCount; 1758 BRect rect; 1759 1760 link.Read<int32>(&rectCount); 1761 1762 for (int i = 0; i < rectCount; i++) { 1763 link.Read<BRect>(&rect); 1764 dirty.Include(rect); 1765 } 1766 1767 fWindowLayer->InvalidateView(fCurrentLayer, dirty); 1768 break; 1769 } 1770 1771 case AS_LAYER_SET_HIGH_COLOR: 1772 { 1773 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_HIGH_COLOR: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1774 1775 rgb_color c; 1776 link.Read(&c, sizeof(rgb_color)); 1777 1778 fCurrentLayer->CurrentState()->SetHighColor(RGBColor(c)); 1779 break; 1780 } 1781 case AS_LAYER_SET_LOW_COLOR: 1782 { 1783 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LOW_COLOR: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); 1784 1785 rgb_color c; 1786 link.Read(&c, sizeof(rgb_color)); 1787 1788 fCurrentLayer->CurrentState()->SetLowColor(RGBColor(c)); 1789 break; 1790 } 1791 case AS_LAYER_SET_PATTERN: 1792 { 1793 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PATTERN: ViewLayer: %s\n", fTitle, fCurrentLayer->Name())); 1794 1795 pattern pat; 1796 link.Read(&pat, sizeof(pattern)); 1797 1798 fCurrentLayer->CurrentState()->SetPattern(Pattern(pat)); 1799 break; 1800 } 1801 case AS_SET_FONT: 1802 { 1803 DTRACE(("ServerWindow %s: Message AS_SET_FONT\n", Title())); 1804 // TODO: Implement AS_SET_FONT? 1805 // Confusing!! But it works already! 1806 break; 1807 } 1808 case AS_SET_FONT_SIZE: 1809 { 1810 DTRACE(("ServerWindow %s: Message AS_SET_FONT_SIZE\n", Title())); 1811 // TODO: Implement AS_SET_FONT_SIZE? 1812 break; 1813 } 1814 case AS_SYNC: 1815 { 1816 // TODO: AS_SYNC is a no-op for now, just to get things working 1817 fLink.StartMessage(B_OK); 1818 fLink.Flush(); 1819 break; 1820 } 1821 case AS_LAYER_DRAG_IMAGE: 1822 { 1823 // TODO: flesh out AS_LAYER_DRAG_IMAGE 1824 STRACE(("ServerWindow %s: Message AS_DRAG_IMAGE\n", Title())); 1825 1826 int32 bitmapToken; 1827 drawing_mode dragMode; 1828 BPoint offset; 1829 int32 bufferSize; 1830 1831 link.Read<int32>(&bitmapToken); 1832 link.Read<int32>((int32*)&dragMode); 1833 link.Read<BPoint>(&offset); 1834 link.Read<int32>(&bufferSize); 1835 1836 if (bufferSize > 0) { 1837 char* buffer = new (nothrow) char[bufferSize]; 1838 BMessage dragMessage; 1839 if (link.Read(buffer, bufferSize) == B_OK 1840 && dragMessage.Unflatten(buffer) == B_OK) { 1841 ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken); 1842 fDesktop->EventDispatcher().SetDragMessage(dragMessage, 1843 bitmap, offset); 1844 } 1845 delete[] buffer; 1846 } 1847 // sync the client (it can now delete the bitmap) 1848 fLink.StartMessage(B_OK); 1849 fLink.Flush(); 1850 1851 break; 1852 } 1853 case AS_LAYER_DRAG_RECT: 1854 { 1855 // TODO: flesh out AS_LAYER_DRAG_RECT 1856 STRACE(("ServerWindow %s: Message AS_DRAG_RECT\n", Title())); 1857 1858 BRect dragRect; 1859 BPoint offset; 1860 int32 bufferSize; 1861 1862 link.Read<BRect>(&dragRect); 1863 link.Read<BPoint>(&offset); 1864 link.Read<int32>(&bufferSize); 1865 1866 if (bufferSize > 0) { 1867 char* buffer = new (nothrow) char[bufferSize]; 1868 BMessage dragMessage; 1869 if (link.Read(buffer, bufferSize) == B_OK 1870 && dragMessage.Unflatten(buffer) == B_OK) { 1871 fDesktop->EventDispatcher().SetDragMessage(dragMessage, 1872 NULL /* should be dragRect */, offset); 1873 } 1874 delete[] buffer; 1875 } 1876 1877 break; 1878 } 1879 1880 case AS_LAYER_BEGIN_PICTURE: 1881 { 1882 DTRACE(("ServerWindow %s: Message AS_LAYER_BEGIN_PICTURE\n", Title())); 1883 ServerPicture *picture = App()->CreatePicture(); 1884 picture->SyncState(fCurrentLayer); 1885 fCurrentLayer->SetPicture(picture); 1886 break; 1887 } 1888 1889 case AS_LAYER_APPEND_TO_PICTURE: 1890 { 1891 DTRACE(("ServerWindow %s: Message AS_LAYER_APPEND_TO_PICTURE\n", Title())); 1892 1893 int32 pictureToken; 1894 link.Read<int32>(&pictureToken); 1895 ServerPicture *picture = App()->FindPicture(pictureToken); 1896 if (picture) 1897 picture->SyncState(fCurrentLayer); 1898 fCurrentLayer->SetPicture(picture); 1899 // we don't care if it's NULL 1900 break; 1901 } 1902 1903 case AS_LAYER_END_PICTURE: 1904 { 1905 DTRACE(("ServerWindow %s: Message AS_LAYER_END_PICTURE\n", Title())); 1906 1907 ServerPicture *picture = fCurrentLayer->Picture(); 1908 if (picture != NULL) { 1909 fCurrentLayer->SetPicture(NULL); 1910 fLink.StartMessage(B_OK); 1911 fLink.Attach<int32>(picture->Token()); 1912 } else 1913 fLink.StartMessage(B_ERROR); 1914 1915 fLink.Flush(); 1916 break; 1917 } 1918 1919 default: 1920 _DispatchViewDrawingMessage(code, link); 1921 break; 1922 } 1923 } 1924 1925 1926 /*! 1927 Dispatches all view drawing messages. 1928 The desktop clipping must be read locked when entering this method. 1929 Requires a valid fCurrentLayer. 1930 */ 1931 void 1932 ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &link) 1933 { 1934 if (!fCurrentLayer->IsVisible() || !fWindowLayer->IsVisible()) { 1935 if (link.NeedsReply()) { 1936 printf("ServerWindow::DispatchViewDrawingMessage() got message %ld that needs a reply!\n", code); 1937 // the client is now blocking and waiting for a reply! 1938 fLink.StartMessage(B_ERROR); 1939 fLink.Flush(); 1940 } 1941 return; 1942 } 1943 1944 DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine(); 1945 if (!drawingEngine) { 1946 // ?!? 1947 DTRACE(("ServerWindow %s: no drawing engine!!\n", Title())); 1948 if (link.NeedsReply()) { 1949 // the client is now blocking and waiting for a reply! 1950 fLink.StartMessage(B_ERROR); 1951 fLink.Flush(); 1952 } 1953 return; 1954 } 1955 1956 if (!fCurrentDrawingRegionValid || fWindowLayer->DrawingRegionChanged(fCurrentLayer)) { 1957 fWindowLayer->GetEffectiveDrawingRegion(fCurrentLayer, fCurrentDrawingRegion); 1958 fCurrentDrawingRegionValid = true; 1959 } 1960 1961 if (fCurrentDrawingRegion.CountRects() <= 0) { 1962 if (link.NeedsReply()) { 1963 // the client is now blocking and waiting for a reply! 1964 fLink.StartMessage(B_ERROR); 1965 fLink.Flush(); 1966 } 1967 return; 1968 } 1969 1970 // prevent other ServerWindows from messing with the drawing engine 1971 // as long as each uses the same instance... TODO: remove the locking 1972 // when each has its own 1973 drawingEngine->Lock(); 1974 drawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion); 1975 1976 switch (code) { 1977 case AS_STROKE_LINE: 1978 { 1979 DTRACE(("ServerWindow %s: Message AS_STROKE_LINE\n", Title())); 1980 1981 float x1, y1, x2, y2; 1982 1983 link.Read<float>(&x1); 1984 link.Read<float>(&y1); 1985 link.Read<float>(&x2); 1986 link.Read<float>(&y2); 1987 1988 BPoint p1(x1, y1); 1989 BPoint p2(x2, y2); 1990 BPoint penPos = p2; 1991 fCurrentLayer->ConvertToScreenForDrawing(&p1); 1992 fCurrentLayer->ConvertToScreenForDrawing(&p2); 1993 drawingEngine->StrokeLine(p1, p2, fCurrentLayer->CurrentState()); 1994 1995 // We update the pen here because many DrawingEngine calls which do not update the 1996 // pen position actually call StrokeLine 1997 1998 // TODO: Decide where to put this, for example, it cannot be done 1999 // for DrawString(), also there needs to be a decision, if penlocation 2000 // is in View coordinates (I think it should be) or in screen coordinates. 2001 fCurrentLayer->CurrentState()->SetPenLocation(penPos); 2002 break; 2003 } 2004 case AS_LAYER_INVERT_RECT: 2005 { 2006 DTRACE(("ServerWindow %s: Message AS_INVERT_RECT\n", Title())); 2007 2008 BRect rect; 2009 link.Read<BRect>(&rect); 2010 2011 fCurrentLayer->ConvertToScreenForDrawing(&rect); 2012 drawingEngine->InvertRect(rect); 2013 break; 2014 } 2015 case AS_STROKE_RECT: 2016 { 2017 DTRACE(("ServerWindow %s: Message AS_STROKE_RECT\n", Title())); 2018 2019 float left, top, right, bottom; 2020 link.Read<float>(&left); 2021 link.Read<float>(&top); 2022 link.Read<float>(&right); 2023 link.Read<float>(&bottom); 2024 BRect rect(left,top,right,bottom); 2025 2026 fCurrentLayer->ConvertToScreenForDrawing(&rect); 2027 drawingEngine->StrokeRect(rect, fCurrentLayer->CurrentState()); 2028 break; 2029 } 2030 case AS_FILL_RECT: 2031 { 2032 DTRACE(("ServerWindow %s: Message AS_FILL_RECT\n", Title())); 2033 2034 BRect rect; 2035 link.Read<BRect>(&rect); 2036 2037 fCurrentLayer->ConvertToScreenForDrawing(&rect); 2038 drawingEngine->FillRect(rect, fCurrentLayer->CurrentState()); 2039 break; 2040 } 2041 case AS_LAYER_DRAW_BITMAP: 2042 { 2043 DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); 2044 int32 bitmapToken; 2045 BRect srcRect, dstRect; 2046 2047 link.Read<int32>(&bitmapToken); 2048 link.Read<BRect>(&dstRect); 2049 link.Read<BRect>(&srcRect); 2050 2051 ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken); 2052 if (bitmap) { 2053 fCurrentLayer->ConvertToScreenForDrawing(&dstRect); 2054 2055 drawingEngine->DrawBitmap(bitmap, srcRect, dstRect, fCurrentLayer->CurrentState()); 2056 } 2057 2058 break; 2059 } 2060 case AS_STROKE_ARC: 2061 case AS_FILL_ARC: 2062 { 2063 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ARC\n", Title())); 2064 2065 float angle, span; 2066 BRect r; 2067 2068 link.Read<BRect>(&r); 2069 link.Read<float>(&angle); 2070 link.Read<float>(&span); 2071 2072 fCurrentLayer->ConvertToScreenForDrawing(&r); 2073 drawingEngine->DrawArc(r, angle, span, fCurrentLayer->CurrentState(), 2074 code == AS_FILL_ARC); 2075 break; 2076 } 2077 case AS_STROKE_BEZIER: 2078 case AS_FILL_BEZIER: 2079 { 2080 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n", Title())); 2081 2082 BPoint pts[4]; 2083 for (int32 i = 0; i < 4; i++) { 2084 link.Read<BPoint>(&(pts[i])); 2085 fCurrentLayer->ConvertToScreenForDrawing(&pts[i]); 2086 } 2087 2088 drawingEngine->DrawBezier(pts, fCurrentLayer->CurrentState(), 2089 code == AS_FILL_BEZIER); 2090 break; 2091 } 2092 case AS_STROKE_ELLIPSE: 2093 case AS_FILL_ELLIPSE: 2094 { 2095 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ELLIPSE\n", Title())); 2096 2097 BRect rect; 2098 link.Read<BRect>(&rect); 2099 2100 fCurrentLayer->ConvertToScreenForDrawing(&rect); 2101 drawingEngine->DrawEllipse(rect, fCurrentLayer->CurrentState(), code == AS_FILL_ELLIPSE); 2102 break; 2103 } 2104 case AS_STROKE_ROUNDRECT: 2105 case AS_FILL_ROUNDRECT: 2106 { 2107 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ROUNDRECT\n", Title())); 2108 2109 BRect rect; 2110 float xrad,yrad; 2111 link.Read<BRect>(&rect); 2112 link.Read<float>(&xrad); 2113 link.Read<float>(&yrad); 2114 2115 fCurrentLayer->ConvertToScreenForDrawing(&rect); 2116 drawingEngine->DrawRoundRect(rect, xrad, yrad, fCurrentLayer->CurrentState(), code == AS_FILL_ROUNDRECT); 2117 break; 2118 } 2119 case AS_STROKE_TRIANGLE: 2120 case AS_FILL_TRIANGLE: 2121 { 2122 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n", Title())); 2123 2124 BPoint pts[3]; 2125 BRect rect; 2126 2127 for (int32 i = 0; i < 3; i++) { 2128 link.Read<BPoint>(&(pts[i])); 2129 fCurrentLayer->ConvertToScreenForDrawing(&pts[i]); 2130 } 2131 2132 link.Read<BRect>(&rect); 2133 2134 fCurrentLayer->ConvertToScreenForDrawing(&rect); 2135 drawingEngine->DrawTriangle(pts, rect, fCurrentLayer->CurrentState(), code == AS_FILL_TRIANGLE); 2136 break; 2137 } 2138 case AS_STROKE_POLYGON: 2139 case AS_FILL_POLYGON: 2140 { 2141 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_POLYGON\n", Title())); 2142 2143 BRect polyFrame; 2144 bool isClosed = true; 2145 int32 pointCount; 2146 2147 link.Read<BRect>(&polyFrame); 2148 if (code == AS_STROKE_POLYGON) 2149 link.Read<bool>(&isClosed); 2150 link.Read<int32>(&pointCount); 2151 2152 BPoint* pointList = new(nothrow) BPoint[pointCount]; 2153 if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) { 2154 for (int32 i = 0; i < pointCount; i++) 2155 fCurrentLayer->ConvertToScreenForDrawing(&pointList[i]); 2156 fCurrentLayer->ConvertToScreenForDrawing(&polyFrame); 2157 2158 drawingEngine->DrawPolygon(pointList, pointCount, polyFrame, 2159 fCurrentLayer->CurrentState(), code == AS_FILL_POLYGON, 2160 isClosed && pointCount > 2); 2161 } 2162 delete[] pointList; 2163 break; 2164 } 2165 case AS_STROKE_SHAPE: 2166 case AS_FILL_SHAPE: 2167 { 2168 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_SHAPE\n", Title())); 2169 2170 BRect shapeFrame; 2171 int32 opCount; 2172 int32 ptCount; 2173 2174 link.Read<BRect>(&shapeFrame); 2175 link.Read<int32>(&opCount); 2176 link.Read<int32>(&ptCount); 2177 2178 uint32* opList = new(nothrow) uint32[opCount]; 2179 BPoint* ptList = new(nothrow) BPoint[ptCount]; 2180 if (link.Read(opList, opCount * sizeof(uint32)) >= B_OK && 2181 link.Read(ptList, ptCount * sizeof(BPoint)) >= B_OK) { 2182 2183 for (int32 i = 0; i < ptCount; i++) 2184 fCurrentLayer->ConvertToScreenForDrawing(&ptList[i]); 2185 2186 drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount, ptList, 2187 fCurrentLayer->CurrentState(), code == AS_FILL_SHAPE); 2188 } 2189 2190 delete[] opList; 2191 delete[] ptList; 2192 break; 2193 } 2194 case AS_FILL_REGION: 2195 { 2196 DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title())); 2197 2198 BRegion region; 2199 if (link.ReadRegion(®ion) < B_OK) 2200 break; 2201 2202 fCurrentLayer->ConvertToScreenForDrawing(®ion); 2203 drawingEngine->FillRegion(region, fCurrentLayer->CurrentState()); 2204 2205 break; 2206 } 2207 case AS_STROKE_LINEARRAY: 2208 { 2209 DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n", Title())); 2210 2211 // Attached Data: 2212 // 1) int32 Number of lines in the array 2213 // 2) LineArrayData 2214 2215 int32 lineCount; 2216 2217 link.Read<int32>(&lineCount); 2218 if (lineCount > 0) { 2219 LineArrayData lineData[lineCount]; 2220 2221 for (int32 i = 0; i < lineCount; i++) { 2222 LineArrayData* index = &lineData[i]; 2223 2224 link.Read<float>(&(index->pt1.x)); 2225 link.Read<float>(&(index->pt1.y)); 2226 link.Read<float>(&(index->pt2.x)); 2227 link.Read<float>(&(index->pt2.y)); 2228 link.Read<rgb_color>(&(index->color)); 2229 2230 fCurrentLayer->ConvertToScreenForDrawing(&index->pt1); 2231 fCurrentLayer->ConvertToScreenForDrawing(&index->pt2); 2232 } 2233 drawingEngine->StrokeLineArray(lineCount, lineData, 2234 fCurrentLayer->CurrentState()); 2235 } 2236 break; 2237 } 2238 case AS_DRAW_STRING: 2239 { 2240 DTRACE(("ServerWindow %s: Message AS_DRAW_STRING\n", Title())); 2241 char* string; 2242 int32 length; 2243 BPoint location; 2244 escapement_delta delta; 2245 2246 link.Read<int32>(&length); 2247 link.Read<BPoint>(&location); 2248 link.Read<escapement_delta>(&delta); 2249 link.ReadString(&string); 2250 2251 fCurrentLayer->ConvertToScreenForDrawing(&location); 2252 BPoint penLocation = drawingEngine->DrawString(string, length, location, 2253 fCurrentLayer->CurrentState(), &delta); 2254 2255 fCurrentLayer->ConvertFromScreenForDrawing(&penLocation); 2256 fCurrentLayer->CurrentState()->SetPenLocation(penLocation); 2257 2258 free(string); 2259 break; 2260 } 2261 2262 case AS_LAYER_DRAW_PICTURE: 2263 { 2264 int32 token; 2265 if (link.Read<int32>(&token) == B_OK) { 2266 BPoint where; 2267 link.Read<BPoint>(&where); 2268 2269 ServerPicture *picture = App()->FindPicture(token); 2270 if (picture != NULL) { 2271 fCurrentLayer->ConvertToScreenForDrawing(&where); 2272 fCurrentLayer->CurrentState()->SetPenLocation(where); 2273 // TODO: pass the location to the play method and handle it there 2274 picture->Play(fCurrentLayer); 2275 } 2276 } 2277 break; 2278 } 2279 2280 default: 2281 printf("ServerWindow %s received unexpected code - message offset %ld\n", 2282 Title(), code - B_OK); 2283 2284 if (link.NeedsReply()) { 2285 // the client is now blocking and waiting for a reply! 2286 fLink.StartMessage(B_ERROR); 2287 fLink.Flush(); 2288 } 2289 break; 2290 } 2291 2292 drawingEngine->Unlock(); 2293 } 2294 2295 2296 bool 2297 ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver &link) 2298 { 2299 ServerPicture *picture = fCurrentLayer->Picture(); 2300 if (picture == NULL) 2301 return false; 2302 2303 switch (code) { 2304 case AS_LAYER_SET_ORIGIN: 2305 { 2306 float x, y; 2307 link.Read<float>(&x); 2308 link.Read<float>(&y); 2309 2310 picture->BeginOp(B_PIC_SET_ORIGIN); 2311 picture->AddCoord(BPoint(x, y)); 2312 picture->EndOp(); 2313 break; 2314 } 2315 2316 case AS_LAYER_INVERT_RECT: 2317 { 2318 picture->BeginOp(B_PIC_SET_DRAWING_MODE); 2319 picture->AddInt16((int16)B_OP_INVERT); 2320 picture->EndOp(); 2321 2322 BRect rect; 2323 link.Read<BRect>(&rect); 2324 picture->BeginOp(B_PIC_FILL_RECT); 2325 picture->AddRect(rect); 2326 picture->EndOp(); 2327 2328 picture->BeginOp(B_PIC_SET_DRAWING_MODE); 2329 picture->AddInt16((int16)B_OP_COPY); 2330 picture->EndOp(); 2331 2332 break; 2333 } 2334 case AS_LAYER_PUSH_STATE: 2335 { 2336 picture->BeginOp(B_PIC_PUSH_STATE); 2337 picture->EndOp(); 2338 break; 2339 } 2340 2341 case AS_LAYER_POP_STATE: 2342 { 2343 picture->BeginOp(B_PIC_POP_STATE); 2344 picture->EndOp(); 2345 break; 2346 } 2347 2348 case AS_LAYER_SET_DRAWING_MODE: 2349 { 2350 int8 drawingMode; 2351 link.Read<int8>(&drawingMode); 2352 2353 picture->BeginOp(B_PIC_SET_DRAWING_MODE); 2354 picture->AddInt16((int16)drawingMode); 2355 picture->EndOp(); 2356 break; 2357 } 2358 2359 case AS_LAYER_SET_PEN_SIZE: 2360 { 2361 float penSize; 2362 link.Read<float>(&penSize); 2363 picture->BeginOp(B_PIC_SET_PEN_SIZE); 2364 picture->AddFloat(penSize); 2365 picture->EndOp(); 2366 break; 2367 } 2368 2369 case AS_LAYER_SET_SCALE: 2370 { 2371 float scale; 2372 link.Read<float>(&scale); 2373 picture->BeginOp(B_PIC_SET_SCALE); 2374 picture->AddFloat(scale); 2375 picture->EndOp(); 2376 break; 2377 } 2378 2379 case AS_FILL_RECT: 2380 case AS_STROKE_RECT: 2381 { 2382 BRect rect; 2383 link.Read<BRect>(&rect); 2384 2385 picture->BeginOp(code == AS_FILL_RECT ? B_PIC_FILL_RECT : B_PIC_STROKE_RECT); 2386 picture->AddRect(rect); 2387 picture->EndOp(); 2388 break; 2389 } 2390 2391 case AS_STROKE_ROUNDRECT: 2392 case AS_FILL_ROUNDRECT: 2393 { 2394 BRect rect; 2395 link.Read<BRect>(&rect); 2396 2397 BPoint radii; 2398 link.Read<float>(&radii.x); 2399 link.Read<float>(&radii.y); 2400 2401 picture->BeginOp(code == AS_FILL_ROUNDRECT ? B_PIC_FILL_ROUND_RECT : B_PIC_STROKE_ROUND_RECT); 2402 picture->AddRect(rect); 2403 picture->AddCoord(radii); 2404 picture->EndOp(); 2405 break; 2406 } 2407 case AS_STROKE_ELLIPSE: 2408 case AS_FILL_ELLIPSE: 2409 { 2410 BRect rect; 2411 link.Read<BRect>(&rect); 2412 picture->BeginOp(code == AS_FILL_ELLIPSE ? B_PIC_FILL_ELLIPSE : 2413 B_PIC_STROKE_ELLIPSE); 2414 picture->AddRect(rect); 2415 picture->EndOp(); 2416 2417 break; 2418 } 2419 case AS_STROKE_ARC: 2420 case AS_FILL_ARC: 2421 { 2422 BRect rect; 2423 link.Read<BRect>(&rect); 2424 float startTheta, arcTheta; 2425 link.Read<float>(&startTheta); 2426 link.Read<float>(&arcTheta); 2427 2428 BPoint radii((rect.Width() + 1) / 2, (rect.Height() + 1) / 2); 2429 BPoint center = rect.LeftTop() + radii; 2430 2431 picture->BeginOp(code == AS_FILL_ARC ? B_PIC_FILL_ARC : B_PIC_STROKE_ARC); 2432 picture->AddCoord(center); 2433 picture->AddCoord(radii); 2434 picture->AddFloat(startTheta); 2435 picture->AddFloat(arcTheta); 2436 picture->EndOp(); 2437 break; 2438 } 2439 case AS_STROKE_LINE: 2440 { 2441 float x1, y1, x2, y2; 2442 2443 link.Read<float>(&x1); 2444 link.Read<float>(&y1); 2445 link.Read<float>(&x2); 2446 link.Read<float>(&y2); 2447 2448 picture->BeginOp(B_PIC_STROKE_LINE); 2449 picture->AddCoord(BPoint(x1, y1)); 2450 picture->AddCoord(BPoint(x2, y2)); 2451 picture->EndOp(); 2452 break; 2453 } 2454 2455 case AS_STROKE_LINEARRAY: 2456 { 2457 int32 lineCount; 2458 link.Read<int32>(&lineCount); 2459 if (lineCount <= 0) 2460 break; 2461 2462 picture->BeginOp(B_PIC_PUSH_STATE); 2463 picture->EndOp(); 2464 2465 for (int32 i = 0; i < lineCount; i++) { 2466 float x1, y1, x2, y2; 2467 link.Read<float>(&x1); 2468 link.Read<float>(&y1); 2469 link.Read<float>(&x2); 2470 link.Read<float>(&y2); 2471 2472 rgb_color color; 2473 link.Read<rgb_color>(&color); 2474 2475 picture->BeginOp(B_PIC_SET_FORE_COLOR); 2476 picture->AddColor(color); 2477 picture->EndOp(); 2478 2479 picture->BeginOp(B_PIC_STROKE_LINE); 2480 picture->AddCoord(BPoint(x1, y1)); 2481 picture->AddCoord(BPoint(x2, y2)); 2482 picture->EndOp(); 2483 } 2484 2485 picture->BeginOp(B_PIC_POP_STATE); 2486 picture->EndOp(); 2487 break; 2488 } 2489 2490 case AS_LAYER_SET_LOW_COLOR: 2491 case AS_LAYER_SET_HIGH_COLOR: 2492 { 2493 rgb_color color; 2494 link.Read(&color, sizeof(rgb_color)); 2495 2496 picture->BeginOp(code == AS_LAYER_SET_HIGH_COLOR ? B_PIC_SET_FORE_COLOR : B_PIC_SET_BACK_COLOR); 2497 picture->AddColor(color); 2498 picture->EndOp(); 2499 break; 2500 } 2501 2502 case AS_DRAW_STRING: 2503 { 2504 char* string = NULL; 2505 int32 length; 2506 BPoint location; 2507 escapement_delta delta; 2508 2509 link.Read<int32>(&length); 2510 link.Read<BPoint>(&location); 2511 link.Read<escapement_delta>(&delta); 2512 link.ReadString(&string); 2513 2514 picture->BeginOp(B_PIC_SET_PEN_LOCATION); 2515 picture->AddCoord(location); 2516 picture->EndOp(); 2517 2518 picture->BeginOp(B_PIC_DRAW_STRING); 2519 picture->AddInt32(length); 2520 picture->AddData(string, length); 2521 picture->AddFloat(delta.space); 2522 picture->AddFloat(delta.nonspace); 2523 picture->EndOp(); 2524 2525 free(string); 2526 break; 2527 } 2528 2529 case AS_STROKE_SHAPE: 2530 case AS_FILL_SHAPE: 2531 { 2532 BRect shapeFrame; 2533 int32 opCount; 2534 int32 ptCount; 2535 2536 link.Read<BRect>(&shapeFrame); 2537 link.Read<int32>(&opCount); 2538 link.Read<int32>(&ptCount); 2539 2540 uint32 *opList = new(nothrow) uint32[opCount]; 2541 BPoint *ptList = new(nothrow) BPoint[ptCount]; 2542 if (link.Read(opList, opCount * sizeof(uint32)) >= B_OK && 2543 link.Read(ptList, ptCount * sizeof(BPoint)) >= B_OK) { 2544 2545 picture->BeginOp(code == AS_FILL_SHAPE ? B_PIC_FILL_SHAPE : B_PIC_STROKE_SHAPE); 2546 picture->AddRect(shapeFrame); 2547 picture->AddInt32(opCount); 2548 picture->AddInt32(ptCount); 2549 picture->AddData(opList, opCount * sizeof(uint32)); 2550 picture->AddData(ptList, ptCount * sizeof(BPoint)); 2551 picture->EndOp(); 2552 } 2553 delete[] opList; 2554 delete[] ptList; 2555 2556 break; 2557 } 2558 2559 case AS_LAYER_DRAW_BITMAP: 2560 { 2561 int32 token; 2562 link.Read<int32>(&token); 2563 2564 BRect destRect; 2565 link.Read<BRect>(&destRect); 2566 2567 BRect sourceRect; 2568 link.Read<BRect>(&sourceRect); 2569 2570 ServerBitmap *bitmap = App()->FindBitmap(token); 2571 if (bitmap == NULL) 2572 break; 2573 2574 picture->BeginOp(B_PIC_DRAW_PIXELS); 2575 picture->AddRect(sourceRect); 2576 picture->AddRect(destRect); 2577 picture->AddInt32(bitmap->Width()); 2578 picture->AddInt32(bitmap->Height()); 2579 picture->AddInt32(bitmap->BytesPerRow()); 2580 picture->AddInt32(bitmap->ColorSpace()); 2581 picture->AddInt32(/*bitmap->Flags()*/0); 2582 picture->AddData((void *)bitmap->Bits(), bitmap->BitsLength()); 2583 picture->EndOp(); 2584 2585 break; 2586 } 2587 2588 case AS_LAYER_SET_BLENDING_MODE: 2589 { 2590 int8 srcAlpha, alphaFunc; 2591 2592 link.Read<int8>(&srcAlpha); 2593 link.Read<int8>(&alphaFunc); 2594 2595 picture->BeginOp(B_PIC_SET_BLENDING_MODE); 2596 picture->AddInt16((int16)srcAlpha); 2597 picture->AddInt16((int16)alphaFunc); 2598 picture->EndOp(); 2599 2600 break; 2601 } 2602 default: 2603 return false; 2604 } 2605 2606 if (link.NeedsReply()) { 2607 fLink.StartMessage(B_ERROR); 2608 fLink.Flush(); 2609 } 2610 return true; 2611 } 2612 2613 2614 /*! 2615 \brief Message-dispatching loop for the ServerWindow 2616 2617 Watches the ServerWindow's message port and dispatches as necessary 2618 */ 2619 void 2620 ServerWindow::_MessageLooper() 2621 { 2622 BPrivate::LinkReceiver& receiver = fLink.Receiver(); 2623 bool quitLoop = false; 2624 2625 while (!quitLoop) { 2626 //STRACE(("info: ServerWindow::MonitorWin listening on port %ld.\n", 2627 // fMessagePort)); 2628 2629 int32 code; 2630 status_t status = receiver.GetNextMessage(code); 2631 if (status < B_OK) { 2632 // that shouldn't happen, it's our port 2633 printf("Someone deleted our message port!\n"); 2634 2635 // try to let our client die happily 2636 NotifyQuitRequested(); 2637 break; 2638 } 2639 2640 #ifdef PROFILE_MESSAGE_LOOP 2641 bigtime_t start = system_time(); 2642 #endif 2643 2644 Lock(); 2645 2646 #ifdef PROFILE_MESSAGE_LOOP 2647 bigtime_t diff = system_time() - start; 2648 if (diff > 10000) 2649 printf("ServerWindow %s: lock acquisition took %Ld usecs\n", Title(), diff); 2650 #endif 2651 2652 int32 messagesProcessed = 0; 2653 bool lockedDesktop = false; 2654 2655 while (true) { 2656 if (code == AS_DELETE_WINDOW || code == kMsgQuitLooper) { 2657 // this means the client has been killed 2658 STRACE(("ServerWindow %s received 'AS_DELETE_WINDOW' message code\n", 2659 Title())); 2660 2661 if (code == AS_DELETE_WINDOW) { 2662 fLink.StartMessage(B_OK); 2663 fLink.Flush(); 2664 } 2665 2666 if (lockedDesktop) 2667 fDesktop->UnlockSingleWindow(); 2668 2669 quitLoop = true; 2670 2671 // ServerWindow's destructor takes care of pulling this object off the desktop. 2672 if (!fWindowLayer->IsHidden()) 2673 CRITICAL("ServerWindow: a window must be hidden before it's deleted\n"); 2674 2675 break; 2676 } 2677 2678 if (!lockedDesktop) { 2679 // only lock it once 2680 fDesktop->LockSingleWindow(); 2681 lockedDesktop = true; 2682 } 2683 2684 if (atomic_and(&fRedrawRequested, 0) != 0) 2685 fWindowLayer->RedrawDirtyRegion(); 2686 2687 _DispatchMessage(code, receiver); 2688 2689 #ifdef PROFILE_MESSAGE_LOOP 2690 if (code >= 0 && code < AS_LAST_CODE) { 2691 diff = system_time() - start; 2692 atomic_add(&sMessageProfile[code].count, 1); 2693 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 2694 atomic_add64(&sMessageProfile[code].time, diff); 2695 #else 2696 sMessageProfile[code].time += diff; 2697 #endif 2698 if (diff > 10000) 2699 printf("ServerWindow %s: message %ld took %Ld usecs\n", Title(), code, diff); 2700 } 2701 #endif 2702 2703 // only process up to 70 waiting messages at once (we have the Desktop locked) 2704 if (!receiver.HasMessages() || ++messagesProcessed > 70) { 2705 fDesktop->UnlockSingleWindow(); 2706 break; 2707 } 2708 2709 status_t status = receiver.GetNextMessage(code); 2710 if (status < B_OK) { 2711 // that shouldn't happen, it's our port 2712 printf("Someone deleted our message port!\n"); 2713 fDesktop->UnlockSingleWindow(); 2714 2715 // try to let our client die happily 2716 NotifyQuitRequested(); 2717 break; 2718 } 2719 } 2720 2721 Unlock(); 2722 } 2723 2724 // we were asked to quit the message loop - either on request or because of an error 2725 Quit(); 2726 // does not return 2727 } 2728 2729 2730 status_t 2731 ServerWindow::SendMessageToClient(const BMessage* msg, int32 target) const 2732 { 2733 if (target == B_NULL_TOKEN) 2734 target = fClientToken; 2735 2736 BMessenger reply; 2737 BMessage::Private messagePrivate((BMessage *)msg); 2738 return messagePrivate.SendMessage(fClientLooperPort, target, 0, 2739 false, reply); 2740 } 2741 2742 2743 WindowLayer* 2744 ServerWindow::MakeWindowLayer(BRect frame, const char* name, 2745 window_look look, window_feel feel, uint32 flags, uint32 workspace) 2746 { 2747 // The non-offscreen ServerWindow uses the DrawingEngine instance from the desktop. 2748 return new (nothrow) WindowLayer(frame, name, look, feel, flags, 2749 workspace, this, fDesktop->GetDrawingEngine()); 2750 } 2751 2752 2753 status_t 2754 ServerWindow::_EnableDirectWindowMode() 2755 { 2756 if (fDirectWindowData != NULL) { 2757 // already in direct window mode 2758 return B_ERROR; 2759 } 2760 2761 fDirectWindowData = new (nothrow) direct_window_data; 2762 if (fDirectWindowData == NULL) 2763 return B_NO_MEMORY; 2764 2765 status_t status = fDirectWindowData->InitCheck(); 2766 if (status < B_OK) { 2767 delete fDirectWindowData; 2768 fDirectWindowData = NULL; 2769 2770 return status; 2771 } 2772 2773 return B_OK; 2774 } 2775 2776 2777 void 2778 ServerWindow::HandleDirectConnection(int32 bufferState, int32 driverState) 2779 { 2780 STRACE(("HandleDirectConnection(bufferState = %ld, driverState = %ld)\n", 2781 bufferState, driverState)); 2782 2783 if (fDirectWindowData == NULL 2784 || (!fDirectWindowData->started 2785 && (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START)) 2786 return; 2787 2788 fDirectWindowData->started = true; 2789 2790 if (bufferState != -1) 2791 fDirectWindowData->buffer_info->buffer_state = (direct_buffer_state)bufferState; 2792 2793 if (driverState != -1) 2794 fDirectWindowData->buffer_info->driver_state = (direct_driver_state)driverState; 2795 2796 if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) { 2797 // TODO: Locking ? 2798 RenderingBuffer *buffer = fDesktop->HWInterface()->FrontBuffer(); 2799 fDirectWindowData->buffer_info->bits = buffer->Bits(); 2800 fDirectWindowData->buffer_info->pci_bits = NULL; // TODO 2801 fDirectWindowData->buffer_info->bytes_per_row = buffer->BytesPerRow(); 2802 switch (buffer->ColorSpace()) { 2803 case B_RGB32: 2804 case B_RGBA32: 2805 case B_RGB32_BIG: 2806 case B_RGBA32_BIG: 2807 fDirectWindowData->buffer_info->bits_per_pixel = 32; 2808 break; 2809 case B_RGB24: 2810 case B_RGB24_BIG: 2811 fDirectWindowData->buffer_info->bits_per_pixel = 24; 2812 break; 2813 case B_RGB16: 2814 case B_RGB16_BIG: 2815 case B_RGB15: 2816 case B_RGB15_BIG: 2817 fDirectWindowData->buffer_info->bits_per_pixel = 16; 2818 break; 2819 case B_CMAP8: 2820 fDirectWindowData->buffer_info->bits_per_pixel = 8; 2821 break; 2822 default: 2823 fprintf(stderr, "unkown colorspace in HandleDirectConnection()!\n"); 2824 fDirectWindowData->buffer_info->bits_per_pixel = 0; 2825 break; 2826 } 2827 fDirectWindowData->buffer_info->pixel_format = buffer->ColorSpace(); 2828 fDirectWindowData->buffer_info->layout = B_BUFFER_NONINTERLEAVED; 2829 fDirectWindowData->buffer_info->orientation = B_BUFFER_TOP_TO_BOTTOM; // TODO 2830 2831 fDirectWindowData->buffer_info->window_bounds = to_clipping_rect(fWindowLayer->Frame()); 2832 2833 // TODO: Review this 2834 const int32 kMaxClipRectsCount = (B_PAGE_SIZE - sizeof(direct_buffer_info)) 2835 / sizeof(clipping_rect); 2836 2837 // We just want the region inside the window, border excluded. 2838 BRegion clipRegion = fWindowLayer->VisibleContentRegion(); 2839 2840 fDirectWindowData->buffer_info->clip_list_count = min_c(clipRegion.CountRects(), 2841 kMaxClipRectsCount); 2842 fDirectWindowData->buffer_info->clip_bounds = clipRegion.FrameInt(); 2843 2844 for (uint32 i = 0; i < fDirectWindowData->buffer_info->clip_list_count; i++) 2845 fDirectWindowData->buffer_info->clip_list[i] = clipRegion.RectAtInt(i); 2846 } 2847 2848 // Releasing this sem causes the client to call BDirectWindow::DirectConnected() 2849 release_sem(fDirectWindowData->sem); 2850 2851 // TODO: Waiting half a second in the ServerWindow thread is not a problem, 2852 // but since we are called from the Desktop's thread too, very bad things could happen. 2853 // Find some way to call this method only within ServerWindow's thread (messaging ?) 2854 status_t status; 2855 do { 2856 // TODO: The timeout is 3000000 usecs (3 seconds) on beos. 2857 // Test, but I think half a second is enough. 2858 status = acquire_sem_etc(fDirectWindowData->sem_ack, 1, B_TIMEOUT, 500000); 2859 } while (status == B_INTERRUPTED); 2860 2861 if (status < B_OK) { 2862 // The client application didn't release the semaphore 2863 // within the given timeout. Or something else went wrong. 2864 // Deleting this member should make it crash. 2865 delete fDirectWindowData; 2866 fDirectWindowData = NULL; 2867 } 2868 } 2869 2870 2871 void 2872 ServerWindow::_SetCurrentLayer(ViewLayer* layer) 2873 { 2874 if (fCurrentLayer != layer) { 2875 fCurrentLayer = layer; 2876 fCurrentDrawingRegionValid = false; 2877 #if 0 2878 #if DELAYED_BACKGROUND_CLEARING 2879 if (fCurrentLayer && fCurrentLayer->IsBackgroundDirty() && fWindowLayer->InUpdate()) { 2880 DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine(); 2881 if (drawingEngine->Lock()) { 2882 2883 fWindowLayer->GetEffectiveDrawingRegion(fCurrentLayer, fCurrentDrawingRegion); 2884 fCurrentDrawingRegionValid = true; 2885 BRegion dirty(fCurrentDrawingRegion); 2886 2887 BRegion content; 2888 fWindowLayer->GetContentRegion(&content); 2889 2890 fCurrentLayer->Draw(drawingEngine, &dirty, &content, false); 2891 2892 drawingEngine->Unlock(); 2893 } 2894 } 2895 #endif 2896 #endif // 0 2897 } 2898 } 2899 2900 2901 status_t 2902 ServerWindow::PictureToRegion(ServerPicture *picture, BRegion ®ion, 2903 bool inverse, BPoint where) 2904 { 2905 fprintf(stderr, "ServerWindow::PictureToRegion() not implemented\n"); 2906 region.MakeEmpty(); 2907 return B_ERROR; 2908 } 2909