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