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