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