1 /* 2 * Copyright 2001-2005, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * Adrian Oanca <adioanca@cotty.iren.ro> 8 * Stephan Aßmus <superstippi@gmx.de> 9 * Stefano Ceccherini (burton666@libero.it) 10 * Axel Dörfler, axeld@pinc-software.de 11 */ 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 WinBorder half with its messaging half, dispatching 20 mouse and key events from the server to its window, and other such things. 21 */ 22 23 #include <new> 24 25 #include <AppDefs.h> 26 #include <DirectWindow.h> 27 #include <GraphicsDefs.h> 28 #include <Message.h> 29 #include <PortLink.h> 30 #include <Rect.h> 31 #include <View.h> 32 #include <ViewAux.h> 33 #include <Autolock.h> 34 #include <TokenSpace.h> 35 #include <WindowInfo.h> 36 #include <WindowPrivate.h> 37 38 #include "AppServer.h" 39 #include "BGet++.h" 40 #include "DebugInfoManager.h" 41 #include "Desktop.h" 42 #include "DisplayDriver.h" 43 #include "HWInterface.h" 44 #include "Layer.h" 45 #include "MessagePrivate.h" 46 #include "RAMLinkMsgReader.h" 47 #include "RenderingBuffer.h" 48 #include "RootLayer.h" 49 #include "ServerApp.h" 50 #include "ServerBitmap.h" 51 #include "ServerPicture.h" 52 #include "ServerProtocol.h" 53 #include "TokenHandler.h" 54 #include "Utils.h" 55 #include "WinBorder.h" 56 #include "Workspace.h" 57 #include "WorkspacesLayer.h" 58 59 #include "ServerWindow.h" 60 61 #include "clipping.h" 62 63 //#define DEBUG_SERVERWINDOW 64 //#define DEBUG_SERVERWINDOW_GRAPHICS 65 66 67 #ifdef DEBUG_SERVERWINDOW 68 # include <stdio.h> 69 # define STRACE(x) printf x 70 #else 71 # define STRACE(x) ; 72 #endif 73 74 #ifdef DEBUG_SERVERWINDOW_GRAPHICS 75 # include <stdio.h> 76 # define DTRACE(x) printf x 77 #else 78 # define DTRACE(x) ; 79 #endif 80 81 struct dw_data { 82 sem_id direct_sem; 83 sem_id direct_sem_ack; 84 area_id direct_area; 85 direct_buffer_info *direct_info; 86 87 dw_data() : 88 direct_sem(-1), 89 direct_sem_ack(-1), 90 direct_area(-1), 91 direct_info(NULL) 92 { 93 direct_area = create_area("direct area", (void **)&direct_info, 94 B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_WRITE); 95 96 direct_sem = create_sem(1, "direct sem"); 97 direct_sem_ack = create_sem(1, "direct sem ack"); 98 } 99 100 ~dw_data() 101 { 102 if (direct_area >= 0) 103 delete_area(direct_area); 104 if (direct_sem >= 0) 105 delete_sem(direct_sem); 106 if (direct_sem_ack >= 0) 107 delete_sem(direct_sem_ack); 108 } 109 110 bool IsValid() const 111 { 112 return (direct_area >= 0) && (direct_sem >= 0) 113 && (direct_sem_ack >= 0) && (direct_info != NULL); 114 } 115 }; 116 117 118 // TODO: Copied from DirectWindow.cpp: Move to a common header 119 struct dw_sync_data { 120 area_id area; 121 sem_id disableSem; 122 sem_id disableSemAck; 123 }; 124 125 /*! 126 \brief Constructor 127 128 Does a lot of stuff to set up for the window - new decorator, new winborder, spawn a 129 monitor thread. 130 */ 131 ServerWindow::ServerWindow(const char *title, ServerApp *app, 132 port_id clientPort, port_id looperPort, int32 handlerID) 133 : MessageLooper(title && *title ? title : "Unnamed Window"), 134 fTitle(title), 135 fDesktop(app->GetDesktop()), 136 fServerApp(app), 137 fWinBorder(NULL), 138 fClientTeam(app->ClientTeam()), 139 fMessagePort(-1), 140 fClientReplyPort(clientPort), 141 fClientLooperPort(looperPort), 142 fClientViewsWithInvalidCoords(B_VIEW_RESIZED), 143 fHandlerToken(handlerID), 144 fCurrentLayer(NULL), 145 fDirectWindowData(NULL) 146 { 147 STRACE(("ServerWindow(%s)::ServerWindow()\n", title)); 148 149 fServerToken = BPrivate::gDefaultTokens.NewToken(B_SERVER_TOKEN, this); 150 } 151 152 153 //!Tears down all connections the main app_server objects, and deletes some internals. 154 ServerWindow::~ServerWindow() 155 { 156 STRACE(("*ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this)); 157 158 if (!fWinBorder->IsOffscreenWindow()) 159 fDesktop->RemoveWinBorder(fWinBorder); 160 161 delete fWinBorder; 162 163 free(const_cast<char *>(fTitle)); 164 delete_port(fMessagePort); 165 166 BPrivate::gDefaultTokens.RemoveToken(fServerToken); 167 168 delete fDirectWindowData; 169 STRACE(("#ServerWindow(%p) will exit NOW\n", this)); 170 } 171 172 173 status_t 174 ServerWindow::Init(BRect frame, uint32 look, uint32 feel, uint32 flags, uint32 workspace) 175 { 176 if (fTitle == NULL) 177 fTitle = strdup("Unnamed Window"); 178 if (fTitle == NULL) 179 return B_NO_MEMORY; 180 181 // fMessagePort is the port to which the app sends messages for the server 182 fMessagePort = create_port(100, fTitle); 183 if (fMessagePort < B_OK) 184 return fMessagePort; 185 186 fLink.SetSenderPort(fClientReplyPort); 187 fLink.SetReceiverPort(fMessagePort); 188 189 // We cannot call MakeWinBorder in the constructor, since it 190 fWinBorder = MakeWinBorder(frame, fTitle, look, feel, flags, workspace); 191 if (!fWinBorder) 192 return B_NO_MEMORY; 193 194 if (!fWinBorder->IsOffscreenWindow()) 195 fDesktop->AddWinBorder(fWinBorder); 196 197 return B_OK; 198 } 199 200 201 bool 202 ServerWindow::Run() 203 { 204 if (!MessageLooper::Run()) 205 return false; 206 207 // Send a reply to our window - it is expecting fMessagePort 208 // port and some other info 209 210 fLink.StartMessage(SERVER_TRUE); 211 fLink.Attach<port_id>(fMessagePort); 212 213 float minWidth, maxWidth, minHeight, maxHeight; 214 fWinBorder->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); 215 216 fLink.Attach<BRect>(fWinBorder->Frame()); 217 fLink.Attach<float>(minWidth); 218 fLink.Attach<float>(maxWidth); 219 fLink.Attach<float>(minHeight); 220 fLink.Attach<float>(maxHeight); 221 fLink.Flush(); 222 223 return true; 224 } 225 226 227 void 228 ServerWindow::_PrepareQuit() 229 { 230 if (fThread == find_thread(NULL)) { 231 // make sure we're hidden 232 Hide(); 233 234 App()->RemoveWindow(this); 235 } else if (fThread >= B_OK) 236 PostMessage(AS_HIDE_WINDOW); 237 } 238 239 240 void 241 ServerWindow::_GetLooperName(char* name, size_t length) 242 { 243 snprintf(name, length, "w:%ld:%s", ClientTeam(), Title()); 244 } 245 246 247 //! Forces the window border to update its decorator 248 void 249 ServerWindow::ReplaceDecorator() 250 { 251 if (!IsLocked()) 252 debugger("you must lock a ServerWindow object before calling ::ReplaceDecorator()\n"); 253 254 STRACE(("ServerWindow %s: Replace Decorator\n", fTitle)); 255 fWinBorder->UpdateDecorator(); 256 } 257 258 259 //! Shows the window's WinBorder 260 void 261 ServerWindow::Show() 262 { 263 // NOTE: if you do something else, other than sending a port message, PLEASE lock 264 STRACE(("ServerWindow %s: Show\n", Title())); 265 266 if (fQuitting || !fWinBorder->IsHidden()) 267 return; 268 269 RootLayer* rootLayer = fWinBorder->GetRootLayer(); 270 if (rootLayer && rootLayer->Lock()) { 271 rootLayer->ShowWinBorder(fWinBorder); 272 rootLayer->Unlock(); 273 } 274 275 // TODO: This doesn't work: Here we aren't shown yet as RootLayer::ShowWinBorder() 276 // does its work asynchronously. As we lock the rootlayer, I think it could be synchronous. 277 // Otherwise, we need a "Shown()" hook or something like that. 278 if (fDirectWindowData != NULL) 279 _HandleDirectConnection(B_DIRECT_START); 280 } 281 282 283 //! Hides the window's WinBorder 284 void 285 ServerWindow::Hide() 286 { 287 // NOTE: if you do something else, other than sending a port message, PLEASE lock 288 STRACE(("ServerWindow %s: Hide\n", Title())); 289 290 if (fWinBorder->IsHidden()) 291 return; 292 293 if (fDirectWindowData != NULL) 294 _HandleDirectConnection(B_DIRECT_STOP); 295 296 RootLayer* rootLayer = fWinBorder->GetRootLayer(); 297 if (rootLayer && rootLayer->Lock()) { 298 rootLayer->HideWinBorder(fWinBorder); 299 rootLayer->Unlock(); 300 } 301 } 302 303 304 void 305 ServerWindow::SetTitle(const char* newTitle) 306 { 307 const char* oldTitle = fTitle; 308 309 if (newTitle == NULL || !newTitle[0]) 310 fTitle = strdup("Unnamed Window"); 311 else 312 fTitle = strdup(newTitle); 313 314 if (fTitle == NULL) { 315 fTitle = oldTitle; 316 return; 317 } 318 319 free(const_cast<char*>(oldTitle)); 320 321 if (Thread() >= B_OK) { 322 char name[B_OS_NAME_LENGTH]; 323 snprintf(name, sizeof(name), "w:%ld:%s", ClientTeam(), fTitle); 324 rename_thread(Thread(), name); 325 } 326 327 if (fWinBorder != NULL) 328 fWinBorder->SetName(newTitle); 329 } 330 331 332 //! Requests that the ServerWindow's BWindow quit 333 void 334 ServerWindow::NotifyQuitRequested() 335 { 336 // NOTE: if you do something else, other than sending a port message, PLEASE lock 337 STRACE(("ServerWindow %s: Quit\n", fTitle)); 338 339 BMessage msg(B_QUIT_REQUESTED); 340 SendMessageToClient(&msg); 341 } 342 343 344 void 345 ServerWindow::NotifyMinimize(bool minimize) 346 { 347 // NOTE: if you do something else, other than sending a port message, PLEASE lock 348 // This function doesn't need much -- check to make sure that we should and 349 // send the message to the client. According to the BeBook, the BWindow hook function 350 // does all the heavy lifting for us. :) 351 bool sendMessages = false; 352 353 if (minimize) { 354 if (!fWinBorder->IsHidden()) { 355 Hide(); 356 sendMessages = true; 357 } 358 } else { 359 if (fWinBorder->IsHidden()) { 360 Show(); 361 sendMessages = true; 362 } 363 } 364 365 if (sendMessages) { 366 BMessage msg(B_MINIMIZE); 367 msg.AddInt64("when", real_time_clock_usecs()); 368 msg.AddBool("minimize", minimize); 369 370 SendMessageToClient(&msg); 371 } 372 } 373 374 //! Sends a message to the client to perform a Zoom 375 void 376 ServerWindow::NotifyZoom() 377 { 378 // NOTE: if you do something else, other than sending a port message, PLEASE lock 379 BMessage msg(B_ZOOM); 380 SendMessageToClient(&msg); 381 } 382 383 /*! 384 \brief Notifies window of a change in screen resolution 385 \param frame Size of the new resolution 386 \param color_space Color space of the new screen mode 387 */ 388 void 389 ServerWindow::NotifyScreenModeChanged(const BRect frame, const color_space colorSpace) 390 { 391 STRACE(("ServerWindow %s: ScreenModeChanged\n", fTitle)); 392 393 BMessage msg(B_SCREEN_CHANGED); 394 msg.AddRect("frame", frame); 395 msg.AddInt32("mode", (int32)colorSpace); 396 397 SendMessageToClient(&msg); 398 } 399 400 401 void 402 ServerWindow::GetInfo(window_info& info) 403 { 404 info.team = ClientTeam(); 405 info.server_token = ServerToken(); 406 407 info.thread = Thread(); 408 info.client_token = ClientToken(); 409 info.client_port = fClientLooperPort; 410 info.workspaces = fWinBorder->Workspaces(); 411 412 info.layer = 0; // ToDo: what is this??? 413 info.feel = fWinBorder->Feel(); 414 info.flags = fWinBorder->WindowFlags(); 415 info.window_left = (int)floor(fWinBorder->Frame().left); 416 info.window_top = (int)floor(fWinBorder->Frame().top); 417 info.window_right = (int)floor(fWinBorder->Frame().right); 418 info.window_bottom = (int)floor(fWinBorder->Frame().bottom); 419 420 info.show_hide_level = fWinBorder->IsHidden() ? 1 : -1; // ??? 421 info.is_mini = fWinBorder->IsHidden(); 422 } 423 424 425 /*! 426 \brief Sets the font state for a layer 427 \param layer The layer to set the font 428 */ 429 inline void 430 ServerWindow::SetLayerFontState(Layer *layer, BPrivate::LinkReceiver &link) 431 { 432 STRACE(("ServerWindow %s: SetLayerFontStateMessage for layer %s\n", 433 fTitle, layer->Name())); 434 // NOTE: no need to check for a lock. This is a private method. 435 436 layer->fLayerData->ReadFontFromLink(link); 437 } 438 439 440 inline void 441 ServerWindow::SetLayerState(Layer *layer, BPrivate::LinkReceiver &link) 442 { 443 STRACE(("ServerWindow %s: SetLayerState for layer %s\n", Title(), 444 layer->Name())); 445 // NOTE: no need to check for a lock. This is a private method. 446 447 layer->fLayerData->ReadFromLink(link); 448 // TODO: Rebuild clipping here? 449 } 450 451 452 inline Layer* 453 ServerWindow::CreateLayerTree(BPrivate::LinkReceiver &link, Layer **_parent) 454 { 455 // NOTE: no need to check for a lock. This is a private method. 456 457 int32 token; 458 BRect frame; 459 uint32 resizeMask; 460 uint32 eventMask; 461 uint32 eventOptions; 462 uint32 flags; 463 bool hidden; 464 int32 parentToken; 465 char *name = NULL; 466 rgb_color viewColor; 467 468 link.Read<int32>(&token); 469 link.ReadString(&name); 470 link.Read<BRect>(&frame); 471 link.Read<uint32>(&resizeMask); 472 link.Read<uint32>(&eventMask); 473 link.Read<uint32>(&eventOptions); 474 link.Read<uint32>(&flags); 475 link.Read<bool>(&hidden); 476 link.Read<rgb_color>(&viewColor); 477 link.Read<int32>(&parentToken); 478 479 STRACE(("ServerWindow(%s)::CreateLayerTree()-> layer %s, token %ld\n", 480 fTitle, name, token)); 481 482 Layer *newLayer; 483 484 if (link.Code() == AS_LAYER_CREATE_ROOT 485 && (fWinBorder->WindowFlags() & kWorkspacesWindowFlag) != 0) { 486 // this is a workspaces window! 487 newLayer = new WorkspacesLayer(frame, name, token, resizeMask, 488 flags, fWinBorder->GetDisplayDriver()); 489 } else { 490 newLayer = new Layer(frame, name, token, resizeMask, 491 flags, fDesktop->GetDisplayDriver()); 492 } 493 494 free(name); 495 496 // there is no way of setting this, other than manually :-) 497 newLayer->fViewColor = viewColor; 498 newLayer->fHidden = hidden; 499 newLayer->fEventMask = eventMask; 500 newLayer->fEventOptions = eventOptions; 501 newLayer->fOwner = fWinBorder; 502 503 // TODO: rework the clipping stuff to remove RootLayer dependency and then 504 // remove this hack: 505 if (fWinBorder->IsOffscreenWindow()) { 506 #ifndef NEW_CLIPPING 507 newLayer->fVisible.Set(newLayer->fFrame); 508 #else 509 newLayer->fVisible2.Set(newLayer->fFrame); 510 #endif 511 } 512 513 if (_parent) { 514 Layer *parent = fWinBorder->FindLayer(parentToken); 515 if (parent == NULL) 516 CRITICAL("View token not found!\n"); 517 518 *_parent = parent; 519 } 520 521 return newLayer; 522 } 523 524 525 void 526 ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) 527 { 528 if (fCurrentLayer == NULL && code != AS_LAYER_CREATE_ROOT && code != AS_LAYER_CREATE) { 529 printf("ServerWindow %s received unexpected code - message offset %ld before top_view attached.\n", Title(), code - SERVER_TRUE); 530 return; 531 } 532 533 RootLayer *myRootLayer = fWinBorder->GetRootLayer(); 534 // NOTE: is NULL when fWinBorder is offscreen! 535 if (myRootLayer) 536 myRootLayer->Lock(); 537 538 switch (code) { 539 //--------- BView Messages ----------------- 540 case AS_LAYER_SCROLL: 541 { 542 DTRACE(("ServerWindow %s: Message AS_LAYER_SCROLL: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 543 float dh; 544 float dv; 545 546 link.Read<float>(&dh); 547 link.Read<float>(&dv); 548 #ifndef NEW_CLIPPING 549 // scroll visually by using the CopyBits() implementation 550 // this will also take care of invalidating previously invisible 551 // areas (areas scrolled into view) 552 BRect src = fCurrentLayer->Bounds(); 553 BRect dst = src; 554 // NOTE: if we scroll down, the contents are moved *up* 555 dst.OffsetBy(-dh, -dv); 556 557 // TODO: Are origin and scale handled in this conversion? 558 src = fCurrentLayer->ConvertToTop(src); 559 dst = fCurrentLayer->ConvertToTop(dst); 560 561 int32 xOffset = (int32)(dst.left - src.left); 562 int32 yOffset = (int32)(dst.top - src.top); 563 564 // this little detail is where it differs from CopyBits() 565 // -> it will invalidate areas previously out of screen 566 dst = dst | src; 567 568 fCurrentLayer->fLayerData->OffsetOrigin(BPoint(dh, dv)); 569 570 fCurrentLayer->CopyBits(src, dst, xOffset, yOffset); 571 #else 572 fCurrentLayer->ScrollBy(dh, dv); 573 #endif 574 575 break; 576 } 577 case AS_LAYER_COPY_BITS: 578 { 579 BRect src; 580 BRect dst; 581 582 link.Read<BRect>(&src); 583 link.Read<BRect>(&dst); 584 585 // TODO: Are origin and scale handled in this conversion? 586 src = fCurrentLayer->ConvertToTop(src); 587 dst = fCurrentLayer->ConvertToTop(dst); 588 589 int32 xOffset = (int32)(dst.left - src.left); 590 int32 yOffset = (int32)(dst.top - src.top); 591 592 fCurrentLayer->CopyBits(src, dst, xOffset, yOffset); 593 594 break; 595 } 596 case AS_SET_CURRENT_LAYER: 597 { 598 int32 token; 599 600 link.Read<int32>(&token); 601 602 Layer *current = fWinBorder->FindLayer(token); 603 if (current) { 604 DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token)); 605 } else { 606 DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: layer not found, token %ld\n", fTitle, token)); 607 } 608 609 if (current) 610 fCurrentLayer = current; 611 else // hope this NEVER happens! :-) 612 CRITICAL("Server PANIC: window cannot find Layer with ID\n"); 613 // ToDo: if this happens, we probably want to kill the app and clean up 614 break; 615 } 616 617 case AS_LAYER_CREATE_ROOT: 618 { 619 STRACE(("ServerWindow %s: Message AS_LAYER_CREATE_ROOT\n", fTitle)); 620 621 // Start receiving top_view data -- pass NULL as the parent view. 622 // This should be the *only* place where this happens. 623 if (fCurrentLayer != NULL) 624 break; 625 626 fWinBorder->SetTopLayer(CreateLayerTree(link, NULL)); 627 fCurrentLayer = fWinBorder->TopLayer(); 628 break; 629 } 630 631 case AS_LAYER_CREATE: 632 { 633 STRACE(("ServerWindow %s: Message AS_LAYER_CREATE: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 634 635 Layer* parent = NULL; 636 Layer* newLayer = CreateLayerTree(link, &parent); 637 if (parent != NULL) 638 parent->AddChild(newLayer, this); 639 640 if (myRootLayer && !newLayer->IsHidden() && parent) 641 #ifndef NEW_CLIPPING 642 myRootLayer->GoInvalidate(newLayer, newLayer->fFull); 643 #else 644 { 645 BRegion invalidRegion; 646 newLayer->GetWantedRegion(invalidRegion); 647 myRootLayer->GoInvalidate(newLayer, invalidRegion); 648 } 649 #endif 650 break; 651 } 652 case AS_LAYER_DELETE: 653 { 654 // Received when a view is detached from a window. This is definitely 655 // the less taxing operation - we call PruneTree() on the removed 656 // layer, detach the layer itself, delete it, and invalidate the 657 // area assuming that the view was visible when removed 658 659 STRACE(("ServerWindow %s: AS_LAYER_DELETE(self)...\n", fTitle)); 660 661 Layer *parent = fCurrentLayer->fParent; 662 BRegion *invalidRegion = NULL; 663 664 if (!fCurrentLayer->IsHidden() && parent) { 665 #ifndef NEW_CLIPPING 666 if (fCurrentLayer->fFullVisible.CountRects() > 0) 667 invalidRegion = new BRegion(fCurrentLayer->fFullVisible); 668 #else 669 if (fCurrentLayer->FullVisible().Frame().IsValid()) 670 invalidRegion = new BRegion(fCurrentLayer->FullVisible()); 671 #endif 672 } 673 674 // here we remove current layer from list. 675 fCurrentLayer->RemoveSelf(); 676 fCurrentLayer->PruneTree(); 677 678 if (myRootLayer) { 679 680 myRootLayer->LayerRemoved(fCurrentLayer); 681 682 // trigger update 683 if (invalidRegion) { 684 myRootLayer->GoInvalidate(parent, *invalidRegion); 685 delete invalidRegion; 686 } 687 } 688 689 #ifdef DEBUG_SERVERWINDOW 690 parent->PrintTree(); 691 #endif 692 STRACE(("DONE: ServerWindow %s: Message AS_DELETE_LAYER: Parent: %s Layer: %s\n", fTitle, parent->Name(), fCurrentLayer->Name())); 693 694 delete fCurrentLayer; 695 // TODO: It is necessary to do this, but I find it very obscure. 696 fCurrentLayer = parent; 697 break; 698 } 699 case AS_LAYER_SET_STATE: 700 { 701 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_STATE: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 702 // SetLayerState(fCurrentLayer); 703 SetLayerState(fCurrentLayer, link); 704 // TODO: should this be moved into SetLayerState? 705 // If it _always_ needs to be done afterwards, then yes! 706 #ifndef NEW_CLIPPING 707 fCurrentLayer->RebuildFullRegion(); 708 #endif 709 break; 710 } 711 case AS_LAYER_SET_FONT_STATE: 712 { 713 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_FONT_STATE: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 714 // SetLayerFontState(fCurrentLayer); 715 SetLayerFontState(fCurrentLayer, link); 716 #ifndef NEW_CLIPPING 717 fCurrentLayer->RebuildFullRegion(); 718 #endif 719 break; 720 } 721 case AS_LAYER_GET_STATE: 722 { 723 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_STATE: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 724 725 fLink.StartMessage(SERVER_TRUE); 726 727 // attach state data 728 fCurrentLayer->fLayerData->WriteToLink(fLink.Sender()); 729 fLink.Flush(); 730 break; 731 } 732 case AS_LAYER_SET_EVENT_MASK: 733 { 734 STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 735 736 uint32 mask; 737 uint32 options; 738 739 link.Read<uint32>(&mask); 740 link.Read<uint32>(&options); 741 742 fCurrentLayer->QuietlySetEventMask(mask); 743 fCurrentLayer->QuietlySetEventOptions(options); 744 745 if (myRootLayer) 746 myRootLayer->AddToInputNotificationLists(fCurrentLayer, mask, options); 747 } 748 case AS_LAYER_SET_MOUSE_EVENT_MASK: 749 { 750 STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 751 752 uint32 mask; 753 uint32 options; 754 755 link.Read<uint32>(&mask); 756 link.Read<uint32>(&options); 757 758 if (myRootLayer) 759 myRootLayer->SetNotifyLayer(fCurrentLayer, mask, options); 760 break; 761 } 762 case AS_LAYER_MOVE_TO: 763 { 764 STRACE(("ServerWindow %s: Message AS_LAYER_MOVE_TO: Layer name: %s\n", 765 fTitle, fCurrentLayer->Name())); 766 767 float x, y; 768 link.Read<float>(&x); 769 link.Read<float>(&y); 770 771 float offsetX = x - fCurrentLayer->fFrame.left; 772 float offsetY = y - fCurrentLayer->fFrame.top; 773 774 fCurrentLayer->MoveBy(offsetX, offsetY); 775 break; 776 } 777 case AS_LAYER_RESIZE_TO: 778 { 779 STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_TO: Layer name: %s\n", 780 fTitle, fCurrentLayer->Name())); 781 782 float newWidth, newHeight; 783 link.Read<float>(&newWidth); 784 link.Read<float>(&newHeight); 785 786 // TODO: If fCurrentLayer is a window, check for minimum size allowed. 787 // Need WinBorder::GetSizeLimits 788 float deltaWidth = newWidth - fCurrentLayer->fFrame.Width(); 789 float deltaHeight = newHeight - fCurrentLayer->fFrame.Height(); 790 791 fCurrentLayer->ResizeBy(deltaWidth, deltaHeight); 792 break; 793 } 794 case AS_LAYER_GET_COORD: 795 { 796 STRACE(("ServerWindow %s: Message AS_LAYER_GET_COORD: Layer: %s\n", Title(), fCurrentLayer->Name())); 797 fLink.StartMessage(SERVER_TRUE); 798 // our offset in the parent -> will be originX and originY in BView 799 fLink.Attach<float>(fCurrentLayer->fFrame.left); 800 fLink.Attach<float>(fCurrentLayer->fFrame.top); 801 // convert frame to bounds 802 fLink.Attach<BRect>(fCurrentLayer->fFrame.OffsetToCopy(fCurrentLayer->BoundsOrigin())); 803 fLink.Flush(); 804 break; 805 } 806 case AS_LAYER_SET_ORIGIN: 807 { 808 STRACE(("ServerWindow %s: Message AS_LAYER_SET_ORIGIN: Layer: %s\n", Title(), fCurrentLayer->Name())); 809 float x, y; 810 811 link.Read<float>(&x); 812 link.Read<float>(&y); 813 814 fCurrentLayer->fLayerData->SetOrigin(BPoint(x, y)); 815 break; 816 } 817 case AS_LAYER_GET_ORIGIN: 818 { 819 STRACE(("ServerWindow %s: Message AS_LAYER_GET_ORIGIN: Layer: %s\n", Title(), fCurrentLayer->Name())); 820 fLink.StartMessage(SERVER_TRUE); 821 fLink.Attach<BPoint>(fCurrentLayer->fLayerData->Origin()); 822 fLink.Flush(); 823 break; 824 } 825 case AS_LAYER_RESIZE_MODE: 826 { 827 STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_MODE: Layer: %s\n", Title(), fCurrentLayer->Name())); 828 link.Read<uint32>(&(fCurrentLayer->fResizeMode)); 829 break; 830 } 831 case AS_LAYER_CURSOR: 832 { 833 DTRACE(("ServerWindow %s: Message AS_LAYER_CURSOR: Layer: %s - NOT IMPLEMENTED\n", Title(), fCurrentLayer->Name())); 834 int32 token; 835 836 link.Read<int32>(&token); 837 838 // TODO: implement; I think each Layer should have a member pointing 839 // to this requested cursor. 840 841 break; 842 } 843 case AS_LAYER_SET_FLAGS: 844 { 845 uint32 flags; 846 link.Read<uint32>(&flags); 847 fCurrentLayer->SetFlags(flags); 848 849 STRACE(("ServerWindow %s: Message AS_LAYER_SET_FLAGS: Layer: %s\n", Title(), fCurrentLayer->Name())); 850 break; 851 } 852 case AS_LAYER_HIDE: 853 { 854 STRACE(("ServerWindow %s: Message AS_LAYER_HIDE: Layer: %s\n", Title(), fCurrentLayer->Name())); 855 fCurrentLayer->Hide(); 856 break; 857 } 858 case AS_LAYER_SHOW: 859 { 860 STRACE(("ServerWindow %s: Message AS_LAYER_SHOW: Layer: %s\n", Title(), fCurrentLayer->Name())); 861 fCurrentLayer->Show(); 862 break; 863 } 864 case AS_LAYER_SET_LINE_MODE: 865 { 866 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LINE_MODE: Layer: %s\n", Title(), fCurrentLayer->Name())); 867 int8 lineCap, lineJoin; 868 float miterLimit; 869 870 // TODO: Look into locking scheme relating to Layers and modifying redraw-related members 871 872 link.Read<int8>(&lineCap); 873 link.Read<int8>(&lineJoin); 874 link.Read<float>(&miterLimit); 875 876 fCurrentLayer->fLayerData->SetLineCapMode((cap_mode)lineCap); 877 fCurrentLayer->fLayerData->SetLineJoinMode((join_mode)lineJoin); 878 fCurrentLayer->fLayerData->SetMiterLimit(miterLimit); 879 880 break; 881 } 882 case AS_LAYER_GET_LINE_MODE: 883 { 884 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LINE_MODE: Layer: %s\n", Title(), fCurrentLayer->Name())); 885 fLink.StartMessage(SERVER_TRUE); 886 fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->LineCapMode())); 887 fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->LineJoinMode())); 888 fLink.Attach<float>(fCurrentLayer->fLayerData->MiterLimit()); 889 fLink.Flush(); 890 891 break; 892 } 893 case AS_LAYER_PUSH_STATE: 894 { 895 DTRACE(("ServerWindow %s: Message AS_LAYER_PUSH_STATE: Layer: %s\n", Title(), fCurrentLayer->Name())); 896 897 fCurrentLayer->PushState(); 898 #ifndef NEW_CLIPPING 899 fCurrentLayer->RebuildFullRegion(); 900 #endif 901 break; 902 } 903 case AS_LAYER_POP_STATE: 904 { 905 DTRACE(("ServerWindow %s: Message AS_LAYER_POP_STATE: Layer: %s\n", Title(), fCurrentLayer->Name())); 906 907 fCurrentLayer->PopState(); 908 #ifndef NEW_CLIPPING 909 fCurrentLayer->RebuildFullRegion(); 910 #endif 911 break; 912 } 913 case AS_LAYER_SET_SCALE: 914 { 915 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_SCALE: Layer: %s\n", Title(), fCurrentLayer->Name())); 916 float scale; 917 link.Read<float>(&scale); 918 // TODO: The BeBook says, if you call SetScale() it will be 919 // multiplied with the scale from all previous states on the stack 920 fCurrentLayer->fLayerData->SetScale(scale); 921 break; 922 } 923 case AS_LAYER_GET_SCALE: 924 { 925 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_SCALE: Layer: %s\n", Title(), fCurrentLayer->Name())); 926 LayerData *ld = fCurrentLayer->fLayerData; 927 928 // TODO: And here, we're taking that into account, but not above 929 // -> refactor put scale into Layer, or better yet, when the 930 // state stack is within Layer, PushState() should multiply 931 // by the previous last states scale. Would fix the problem above too. 932 float scale = ld->Scale(); 933 934 while ((ld = ld->prevState)) 935 scale *= ld->Scale(); 936 937 fLink.StartMessage(SERVER_TRUE); 938 fLink.Attach<float>(scale); 939 fLink.Flush(); 940 941 break; 942 } 943 case AS_LAYER_SET_PEN_LOC: 944 { 945 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_LOC: Layer: %s\n", Title(), fCurrentLayer->Name())); 946 float x, y; 947 948 link.Read<float>(&x); 949 link.Read<float>(&y); 950 951 fCurrentLayer->fLayerData->SetPenLocation(BPoint(x, y)); 952 953 break; 954 } 955 case AS_LAYER_GET_PEN_LOC: 956 { 957 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_LOC: Layer: %s\n", Title(), fCurrentLayer->Name())); 958 fLink.StartMessage(SERVER_TRUE); 959 fLink.Attach<BPoint>(fCurrentLayer->fLayerData->PenLocation()); 960 fLink.Flush(); 961 962 break; 963 } 964 case AS_LAYER_SET_PEN_SIZE: 965 { 966 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_SIZE: Layer: %s\n", Title(), fCurrentLayer->Name())); 967 float penSize; 968 link.Read<float>(&penSize); 969 fCurrentLayer->fLayerData->SetPenSize(penSize); 970 971 break; 972 } 973 case AS_LAYER_GET_PEN_SIZE: 974 { 975 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_SIZE: Layer: %s\n", Title(), fCurrentLayer->Name())); 976 fLink.StartMessage(SERVER_TRUE); 977 fLink.Attach<float>(fCurrentLayer->fLayerData->PenSize()); 978 fLink.Flush(); 979 980 break; 981 } 982 case AS_LAYER_SET_VIEW_COLOR: 983 { 984 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_VIEW_COLOR: Layer: %s\n", Title(), fCurrentLayer->Name())); 985 rgb_color c; 986 987 link.Read(&c, sizeof(rgb_color)); 988 myRootLayer->Lock(); 989 fCurrentLayer->SetViewColor(RGBColor(c)); 990 991 #ifndef NEW_CLIPPING 992 if (myRootLayer) 993 myRootLayer->GoRedraw(fCurrentLayer, fCurrentLayer->fVisible); 994 #else 995 myRootLayer->GoRedraw(fCurrentLayer, fCurrentLayer->VisibleRegion()); 996 #endif 997 myRootLayer->Unlock(); 998 break; 999 } 1000 1001 case AS_LAYER_GET_HIGH_COLOR: 1002 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_HIGH_COLOR: Layer: %s\n", 1003 Title(), fCurrentLayer->Name())); 1004 1005 fLink.StartMessage(SERVER_TRUE); 1006 fLink.Attach<rgb_color>(fCurrentLayer->fLayerData->HighColor().GetColor32()); 1007 fLink.Flush(); 1008 break; 1009 1010 case AS_LAYER_GET_LOW_COLOR: 1011 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LOW_COLOR: Layer: %s\n", 1012 Title(), fCurrentLayer->Name())); 1013 1014 fLink.StartMessage(SERVER_TRUE); 1015 fLink.Attach<rgb_color>(fCurrentLayer->fLayerData->LowColor().GetColor32()); 1016 fLink.Flush(); 1017 break; 1018 1019 case AS_LAYER_GET_VIEW_COLOR: 1020 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_VIEW_COLOR: Layer: %s\n", 1021 Title(), fCurrentLayer->Name())); 1022 1023 fLink.StartMessage(SERVER_TRUE); 1024 fLink.Attach<rgb_color>(fCurrentLayer->ViewColor().GetColor32()); 1025 fLink.Flush(); 1026 break; 1027 1028 case AS_LAYER_SET_BLEND_MODE: 1029 { 1030 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_BLEND_MODE: Layer: %s\n", Title(), fCurrentLayer->Name())); 1031 int8 srcAlpha, alphaFunc; 1032 1033 link.Read<int8>(&srcAlpha); 1034 link.Read<int8>(&alphaFunc); 1035 1036 fCurrentLayer->fLayerData->SetBlendingMode((source_alpha)srcAlpha, 1037 (alpha_function)alphaFunc); 1038 1039 break; 1040 } 1041 case AS_LAYER_GET_BLEND_MODE: 1042 { 1043 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_BLEND_MODE: Layer: %s\n", Title(), fCurrentLayer->Name())); 1044 fLink.StartMessage(SERVER_TRUE); 1045 fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->AlphaSrcMode())); 1046 fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->AlphaFncMode())); 1047 fLink.Flush(); 1048 1049 break; 1050 } 1051 case AS_LAYER_SET_DRAW_MODE: 1052 { 1053 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_DRAW_MODE: Layer: %s\n", Title(), fCurrentLayer->Name())); 1054 int8 drawingMode; 1055 1056 link.Read<int8>(&drawingMode); 1057 1058 fCurrentLayer->fLayerData->SetDrawingMode((drawing_mode)drawingMode); 1059 1060 break; 1061 } 1062 case AS_LAYER_GET_DRAW_MODE: 1063 { 1064 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_DRAW_MODE: Layer: %s\n", Title(), fCurrentLayer->Name())); 1065 fLink.StartMessage(SERVER_TRUE); 1066 fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->GetDrawingMode())); 1067 fLink.Flush(); 1068 1069 break; 1070 } 1071 case AS_LAYER_PRINT_ALIASING: 1072 { 1073 DTRACE(("ServerWindow %s: Message AS_LAYER_PRINT_ALIASING: Layer: %s\n", Title(), fCurrentLayer->Name())); 1074 bool fontAliasing; 1075 link.Read<bool>(&fontAliasing); 1076 fCurrentLayer->fLayerData->SetForceFontAliasing(fontAliasing); 1077 1078 break; 1079 } 1080 case AS_LAYER_CLIP_TO_PICTURE: 1081 { 1082 DTRACE(("ServerWindow %s: Message AS_LAYER_CLIP_TO_PICTURE: Layer: %s\n", Title(), fCurrentLayer->Name())); 1083 // TODO: you are not allowed to use Layer regions here!!! 1084 // If there is no other way, then first lock RootLayer object first. 1085 1086 int32 pictureToken; 1087 BPoint where; 1088 bool inverse = false; 1089 1090 link.Read<int32>(&pictureToken); 1091 link.Read<BPoint>(&where); 1092 link.Read<bool>(&inverse); 1093 1094 // search for a picture with the specified token. 1095 ServerPicture *picture = fServerApp->FindPicture(pictureToken); 1096 // TODO: Increase that picture's reference count.(~ allocate a picture) 1097 if (picture == NULL) 1098 break; 1099 1100 BRegion region; 1101 // TODO: I think we also need the BView's token 1102 // I think PictureToRegion would fit better into the Layer class (?) 1103 if (PictureToRegion(picture, region, inverse, where) < B_OK) 1104 break; 1105 1106 fCurrentLayer->fLayerData->SetClippingRegion(region); 1107 1108 #ifndef NEW_CLIPPING 1109 fCurrentLayer->RebuildFullRegion(); 1110 #endif 1111 if (myRootLayer && !(fCurrentLayer->IsHidden()) && !fWinBorder->InUpdate()) 1112 #ifndef NEW_CLIPPING 1113 myRootLayer->GoInvalidate(fCurrentLayer, fCurrentLayer->fFull); 1114 #else 1115 { 1116 BRegion invalidRegion; 1117 fCurrentLayer->GetWantedRegion(invalidRegion); 1118 myRootLayer->GoInvalidate(fCurrentLayer, invalidRegion); 1119 } 1120 #endif 1121 1122 break; 1123 } 1124 1125 case AS_LAYER_GET_CLIP_REGION: 1126 { 1127 DTRACE(("ServerWindow %s: Message AS_LAYER_GET_CLIP_REGION: Layer: %s\n", Title(), fCurrentLayer->Name())); 1128 1129 // if this Layer is hidden, it is clear that its visible region is void. 1130 if (fCurrentLayer->IsHidden()) { 1131 fLink.StartMessage(SERVER_TRUE); 1132 fLink.Attach<int32>(0L); 1133 fLink.Flush(); 1134 } else { 1135 // TODO: Watch out for the coordinate system in AS_LAYER_GET_CLIP_REGION 1136 #ifndef NEW_CLIPPING 1137 int32 rectCount = fCurrentLayer->fVisible.CountRects(); 1138 #else 1139 int32 rectCount = fCurrentLayer->fVisible2.CountRects(); 1140 #endif 1141 1142 fLink.StartMessage(SERVER_TRUE); 1143 fLink.Attach<int32>(rectCount); 1144 1145 for (int32 i = 0; i < rectCount; i++) 1146 #ifndef NEW_CLIPPING 1147 fLink.Attach<BRect>(fCurrentLayer->ConvertFromTop(fCurrentLayer->fVisible.RectAt(i))); 1148 #else 1149 fLink.Attach<BRect>(fCurrentLayer->ConvertFromTop(fCurrentLayer->fVisible2.RectAt(i))); 1150 #endif 1151 1152 fLink.Flush(); 1153 } 1154 1155 break; 1156 } 1157 case AS_LAYER_SET_CLIP_REGION: 1158 { 1159 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: Layer: %s\n", Title(), fCurrentLayer->Name())); 1160 1161 // TODO: Watch out for the coordinate system in AS_LAYER_SET_CLIP_REGION 1162 int32 noOfRects; 1163 BRect r; 1164 1165 link.Read<int32>(&noOfRects); 1166 1167 BRegion region; 1168 for (int i = 0; i < noOfRects; i++) { 1169 link.Read<BRect>(&r); 1170 region.Include(fCurrentLayer->ConvertToTop(r)); 1171 } 1172 // TODO: Turned off user clipping for now (will probably not harm anything but performance right now) 1173 // We need to integrate user clipping more, in Layer::PopState, the clipping needs to be 1174 // restored too. "AS_LAYER_SET_CLIP_REGION" is irritating, as I think it should be 1175 // "AS_LAYER_CONSTRAIN_CLIP_REGION", since it means to "add" to the current clipping, not "set" it. 1176 // fCurrentLayer->fLayerData->SetClippingRegion(region); 1177 #ifndef NEW_CLIPPING 1178 // TODO: set the clipping 1179 // fCurrentLayer->fVisible.IntersectWith(®ion); 1180 #endif 1181 /* 1182 #ifndef NEW_CLIPPING 1183 fCurrentLayer->RebuildFullRegion(); 1184 if (myRootLayer && !(fCurrentLayer->IsHidden()) && !fWinBorder->InUpdate()) 1185 myRootLayer->GoInvalidate(fCurrentLayer, fCurrentLayer->fFull); 1186 #else 1187 if (myRootLayer && !(fCurrentLayer->IsHidden()) && !fWinBorder->InUpdate()) 1188 myRootLayer->GoInvalidate(fCurrentLayer, fCurrentLayer->Frame()); 1189 #endif 1190 */ 1191 break; 1192 } 1193 case AS_LAYER_INVAL_RECT: 1194 { 1195 DTRACE(("ServerWindow %s: Message AS_LAYER_INVAL_RECT: Layer: %s\n", Title(), fCurrentLayer->Name())); 1196 1197 // TODO: handle transformation (origin and scale) prior to converting to top 1198 BRect invalRect; 1199 1200 link.Read<BRect>(&invalRect); 1201 1202 if (myRootLayer) { 1203 BRect converted(fCurrentLayer->ConvertToTop(invalRect.LeftTop()), 1204 fCurrentLayer->ConvertToTop(invalRect.RightBottom())); 1205 BRegion invalidRegion(converted); 1206 #ifdef NEW_CLIPPING 1207 invalidRegion.IntersectWith(&fCurrentLayer->fVisible2); 1208 #endif 1209 myRootLayer->GoRedraw(fWinBorder, invalidRegion); 1210 // myRootLayer->RequestDraw(invalidRegion, fWinBorder); 1211 } 1212 break; 1213 } 1214 case AS_LAYER_INVAL_REGION: 1215 { 1216 DTRACE(("ServerWindow %s: Message AS_LAYER_INVAL_RECT: Layer: %s\n", Title(), fCurrentLayer->Name())); 1217 1218 // TODO: handle transformation (origin and scale) prior to converting to top 1219 // TODO: Handle conversion to top 1220 BRegion invalReg; 1221 int32 noOfRects; 1222 BRect rect; 1223 1224 link.Read<int32>(&noOfRects); 1225 1226 for (int i = 0; i < noOfRects; i++) { 1227 link.Read<BRect>(&rect); 1228 invalReg.Include(rect); 1229 } 1230 1231 if (myRootLayer) 1232 myRootLayer->GoRedraw(fCurrentLayer, invalReg); 1233 1234 break; 1235 } 1236 case AS_BEGIN_UPDATE: 1237 { 1238 DTRACE(("ServerWindowo %s: AS_BEGIN_UPDATE\n", Title())); 1239 fWinBorder->UpdateStart(); 1240 break; 1241 } 1242 case AS_END_UPDATE: 1243 { 1244 DTRACE(("ServerWindowo %s: AS_END_UPDATE\n", Title())); 1245 fWinBorder->UpdateEnd(); 1246 break; 1247 } 1248 1249 // ********** END: BView Messages *********** 1250 1251 // ********* BWindow Messages *********** 1252 case AS_LAYER_DELETE_ROOT: 1253 { 1254 // Received when a window deletes its internal top view 1255 1256 // TODO: Implement AS_LAYER_DELETE_ROOT 1257 STRACE(("ServerWindow %s: Message Delete_Layer_Root unimplemented\n", Title())); 1258 break; 1259 } 1260 case AS_SHOW_WINDOW: 1261 { 1262 STRACE(("ServerWindow %s: Message AS_SHOW_WINDOW\n", Title())); 1263 Show(); 1264 break; 1265 } 1266 case AS_HIDE_WINDOW: 1267 { 1268 STRACE(("ServerWindow %s: Message AS_HIDE_WINDOW\n", Title())); 1269 Hide(); 1270 break; 1271 } 1272 case AS_SEND_BEHIND: 1273 { 1274 STRACE(("ServerWindow %s: Message Send_Behind unimplemented\n", Title())); 1275 int32 token; 1276 team_id teamID; 1277 status_t status = B_NAME_NOT_FOUND; 1278 1279 link.Read<int32>(&token); 1280 link.Read<team_id>(&teamID); 1281 1282 WinBorder *behindOf; 1283 if ((behindOf = fDesktop->FindWinBorderByClientToken(token, teamID)) != NULL) { 1284 fWinBorder->GetRootLayer()->Lock(); 1285 // TODO: move to back ATM. Fix this later! 1286 fWinBorder->GetRootLayer()->SetActive(fWinBorder, false); 1287 fWinBorder->GetRootLayer()->Unlock(); 1288 status = B_OK; 1289 } 1290 1291 fLink.StartMessage(status); 1292 fLink.Flush(); 1293 break; 1294 } 1295 case AS_ENABLE_UPDATES: 1296 { 1297 STRACE(("ServerWindow %s: Message Enable_Updates unimplemented\n", Title())); 1298 fWinBorder->EnableUpdateRequests(); 1299 if (fWinBorder->CulmulatedUpdateRegion().Frame().IsValid()) { 1300 BRegion reg(fWinBorder->CulmulatedUpdateRegion()); 1301 fWinBorder->RequestDraw(reg, NULL); 1302 } 1303 break; 1304 } 1305 case AS_DISABLE_UPDATES: 1306 { 1307 STRACE(("ServerWindow %s: Message Disable_Updates unimplemented\n", Title())); 1308 fWinBorder->DisableUpdateRequests(); 1309 break; 1310 } 1311 case AS_NEEDS_UPDATE: 1312 { 1313 STRACE(("ServerWindow %s: Message Needs_Update unimplemented\n", Title())); 1314 if (fWinBorder->CulmulatedUpdateRegion().Frame().IsValid()) 1315 fLink.StartMessage(B_OK); 1316 else 1317 fLink.StartMessage(B_ERROR); 1318 fLink.Flush(); 1319 break; 1320 } 1321 case AS_SET_WINDOW_TITLE: 1322 { 1323 char* newTitle; 1324 if (link.ReadString(&newTitle) == B_OK) { 1325 SetTitle(newTitle); 1326 free(newTitle); 1327 } 1328 break; 1329 } 1330 1331 case AS_ADD_TO_SUBSET: 1332 { 1333 STRACE(("ServerWindow %s: Message AS_ADD_TO_SUBSET\n", Title())); 1334 WinBorder *windowBorder; 1335 int32 mainToken; 1336 team_id teamID; 1337 1338 link.Read<int32>(&mainToken); 1339 link.Read(&teamID, sizeof(team_id)); 1340 1341 windowBorder = fDesktop->FindWinBorderByClientToken(mainToken, teamID); 1342 if (windowBorder) { 1343 fLink.StartMessage(SERVER_TRUE); 1344 fLink.Flush(); 1345 1346 fWinBorder->GetRootLayer()->Lock(); 1347 fDesktop->AddWinBorderToSubset(fWinBorder, windowBorder); 1348 fWinBorder->GetRootLayer()->Unlock(); 1349 } else { 1350 fLink.StartMessage(SERVER_FALSE); 1351 fLink.Flush(); 1352 } 1353 break; 1354 } 1355 case AS_REM_FROM_SUBSET: 1356 { 1357 STRACE(("ServerWindow %s: Message AS_REM_FROM_SUBSET\n", Title())); 1358 WinBorder *windowBorder; 1359 int32 mainToken; 1360 team_id teamID; 1361 1362 link.Read<int32>(&mainToken); 1363 link.Read(&teamID, sizeof(team_id)); 1364 1365 windowBorder = fDesktop->FindWinBorderByClientToken(mainToken, teamID); 1366 if (windowBorder) { 1367 fLink.StartMessage(SERVER_TRUE); 1368 fLink.Flush(); 1369 1370 fWinBorder->GetRootLayer()->Lock(); 1371 fDesktop->RemoveWinBorderFromSubset(fWinBorder, windowBorder); 1372 fWinBorder->GetRootLayer()->Unlock(); 1373 } else { 1374 fLink.StartMessage(SERVER_FALSE); 1375 fLink.Flush(); 1376 } 1377 break; 1378 } 1379 #if 0 1380 case AS_SET_LOOK: 1381 { 1382 // TODO: Implement AS_SET_LOOK 1383 STRACE(("ServerWindow %s: Message Set_Look unimplemented\n", Title())); 1384 break; 1385 } 1386 case AS_SET_FLAGS: 1387 { 1388 // TODO: Implement AS_SET_FLAGS 1389 STRACE(("ServerWindow %s: Message Set_Flags unimplemented\n", Title())); 1390 break; 1391 } 1392 case AS_SET_FEEL: 1393 { 1394 STRACE(("ServerWindow %s: Message AS_SET_FEEL\n", Title())); 1395 int32 newFeel; 1396 link.Read<int32>(&newFeel); 1397 1398 fWinBorder->GetRootLayer()->GoChangeWinBorderFeel(winBorder, newFeel); 1399 break; 1400 } 1401 case AS_SET_ALIGNMENT: 1402 { 1403 // TODO: Implement AS_SET_ALIGNMENT 1404 STRACE(("ServerWindow %s: Message Set_Alignment unimplemented\n", Title())); 1405 break; 1406 } 1407 case AS_GET_ALIGNMENT: 1408 { 1409 // TODO: Implement AS_GET_ALIGNMENT 1410 STRACE(("ServerWindow %s: Message Get_Alignment unimplemented\n", Title())); 1411 break; 1412 } 1413 #endif 1414 case AS_GET_WORKSPACES: 1415 { 1416 STRACE(("ServerWindow %s: Message Get_Workspaces unimplemented\n", Title())); 1417 fLink.StartMessage(SERVER_TRUE); 1418 fLink.Attach<uint32>(fWinBorder->Workspaces()); 1419 fLink.Flush(); 1420 break; 1421 } 1422 case AS_SET_WORKSPACES: 1423 { 1424 STRACE(("ServerWindow %s: Message Set_Workspaces unimplemented\n", Title())); 1425 uint32 newWorkspaces; 1426 link.Read<uint32>(&newWorkspaces); 1427 1428 fWinBorder->GetRootLayer()->Lock(); 1429 fWinBorder->GetRootLayer()->SetWinBorderWorskpaces( fWinBorder, 1430 fWinBorder->Workspaces(), 1431 newWorkspaces); 1432 fWinBorder->GetRootLayer()->Unlock(); 1433 break; 1434 } 1435 case AS_WINDOW_RESIZE: 1436 { 1437 float xResizeBy; 1438 float yResizeBy; 1439 1440 link.Read<float>(&xResizeBy); 1441 link.Read<float>(&yResizeBy); 1442 1443 STRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n", Title(), xResizeBy, yResizeBy)); 1444 1445 fWinBorder->ResizeBy(xResizeBy, yResizeBy); 1446 break; 1447 } 1448 case AS_WINDOW_MOVE: 1449 { 1450 float xMoveBy; 1451 float yMoveBy; 1452 1453 link.Read<float>(&xMoveBy); 1454 link.Read<float>(&yMoveBy); 1455 1456 STRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n", Title(), xMoveBy, yMoveBy)); 1457 1458 fWinBorder->MoveBy(xMoveBy, yMoveBy); 1459 break; 1460 } 1461 case AS_SET_SIZE_LIMITS: 1462 { 1463 // Attached Data: 1464 // 1) float minimum width 1465 // 2) float maximum width 1466 // 3) float minimum height 1467 // 4) float maximum height 1468 1469 float minWidth; 1470 float maxWidth; 1471 float minHeight; 1472 float maxHeight; 1473 1474 link.Read<float>(&minWidth); 1475 link.Read<float>(&maxWidth); 1476 link.Read<float>(&minHeight); 1477 link.Read<float>(&maxHeight); 1478 1479 fWinBorder->SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight); 1480 1481 // and now, sync the client to the limits that we were able to enforce 1482 fWinBorder->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); 1483 1484 fLink.StartMessage(SERVER_TRUE); 1485 fLink.Attach<BRect>(fWinBorder->Frame()); 1486 fLink.Attach<float>(minWidth); 1487 fLink.Attach<float>(maxWidth); 1488 fLink.Attach<float>(minHeight); 1489 fLink.Attach<float>(maxHeight); 1490 1491 fLink.Flush(); 1492 break; 1493 } 1494 case AS_ACTIVATE_WINDOW: 1495 { 1496 DTRACE(("ServerWindow %s: Message AS_ACTIVATE_WINDOW: Layer: %s\n", Title(), fCurrentLayer->Name())); 1497 bool activate = true; 1498 1499 link.Read<bool>(&activate); 1500 1501 if (myRootLayer && myRootLayer->Lock()) { 1502 myRootLayer->SetActive(fWinBorder, activate); 1503 myRootLayer->Unlock(); 1504 } 1505 break; 1506 } 1507 // Some BView drawing messages, but which don't need clipping 1508 case AS_LAYER_SET_HIGH_COLOR: 1509 { 1510 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_HIGH_COLOR: Layer: %s\n", Title(), fCurrentLayer->Name())); 1511 rgb_color c; 1512 1513 link.Read(&c, sizeof(rgb_color)); 1514 1515 fCurrentLayer->fLayerData->SetHighColor(RGBColor(c)); 1516 1517 break; 1518 } 1519 case AS_LAYER_SET_LOW_COLOR: 1520 { 1521 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LOW_COLOR: Layer: %s\n", Title(), fCurrentLayer->Name())); 1522 rgb_color c; 1523 1524 link.Read(&c, sizeof(rgb_color)); 1525 1526 fCurrentLayer->fLayerData->SetLowColor(RGBColor(c)); 1527 1528 break; 1529 } 1530 case AS_LAYER_SET_PATTERN: 1531 { 1532 DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PATTERN: Layer: %s\n", fTitle, fCurrentLayer->Name())); 1533 pattern pat; 1534 1535 link.Read(&pat, sizeof(pattern)); 1536 1537 fCurrentLayer->fLayerData->SetPattern(Pattern(pat)); 1538 1539 break; 1540 } 1541 case AS_MOVEPENTO: 1542 { 1543 DTRACE(("ServerWindow %s: Message AS_MOVEPENTO\n", Title())); 1544 1545 float x,y; 1546 1547 link.Read<float>(&x); 1548 link.Read<float>(&y); 1549 if (fCurrentLayer && fCurrentLayer->fLayerData) 1550 fCurrentLayer->fLayerData->SetPenLocation(BPoint(x, y)); 1551 1552 break; 1553 } 1554 case AS_SETPENSIZE: 1555 { 1556 DTRACE(("ServerWindow %s: Message AS_SETPENSIZE\n", Title())); 1557 float size; 1558 1559 link.Read<float>(&size); 1560 if (fCurrentLayer && fCurrentLayer->fLayerData) 1561 fCurrentLayer->fLayerData->SetPenSize(size); 1562 1563 break; 1564 } 1565 case AS_SET_FONT: 1566 { 1567 DTRACE(("ServerWindow %s: Message AS_SET_FONT\n", Title())); 1568 // TODO: Implement AS_SET_FONT? 1569 // Confusing!! But it works already! 1570 break; 1571 } 1572 case AS_SET_FONT_SIZE: 1573 { 1574 DTRACE(("ServerWindow %s: Message AS_SET_FONT_SIZE\n", Title())); 1575 // TODO: Implement AS_SET_FONT_SIZE? 1576 break; 1577 } 1578 case AS_AREA_MESSAGE: 1579 { 1580 STRACE(("ServerWindow %s: Message AS_AREA_MESSAGE\n", Title())); 1581 // This occurs in only one kind of case: a message is too big to send over a port. This 1582 // is really an edge case, so this shouldn't happen *too* often 1583 1584 // Attached Data: 1585 // 1) area_id id of an area already owned by the server containing the message 1586 // 2) size_t offset of the pointer in the area 1587 // 3) size_t size of the message 1588 1589 area_id area; 1590 size_t offset; 1591 size_t msgsize; 1592 area_info ai; 1593 int8 *msgpointer; 1594 1595 link.Read<area_id>(&area); 1596 link.Read<size_t>(&offset); 1597 link.Read<size_t>(&msgsize); 1598 1599 // Part sanity check, part get base pointer :) 1600 if(get_area_info(area,&ai)!=B_OK) 1601 break; 1602 1603 msgpointer = (int8*)ai.address + offset; 1604 1605 RAMLinkMsgReader mlink(msgpointer); 1606 _DispatchMessage(mlink.Code(), mlink); 1607 1608 // This is a very special case in the sense that when ServerMemIO is used for this 1609 // purpose, it will be set to NOT automatically free the memory which it had 1610 // requested. This is the server's job once the message has been dispatched. 1611 fServerApp->AppAreaPool()->ReleaseBuffer(msgpointer); 1612 break; 1613 } 1614 case AS_SYNC: 1615 { 1616 // TODO: AS_SYNC is a no-op for now, just to get things working 1617 fLink.StartMessage(SERVER_TRUE); 1618 fLink.Flush(); 1619 break; 1620 } 1621 case AS_LAYER_DRAG_IMAGE: 1622 { 1623 // TODO: Implement AS_LAYER_DRAG_IMAGE 1624 STRACE(("ServerWindow %s: Message AS_DRAG_IMAGE unimplemented\n", Title())); 1625 DTRACE(("ServerWindow %s: Message AS_DRAG_IMAGE unimplemented\n", Title())); 1626 break; 1627 } 1628 case AS_LAYER_DRAG_RECT: 1629 { 1630 // TODO: Implement AS_LAYER_DRAG_RECT 1631 STRACE(("ServerWindow %s: Message AS_DRAG_RECT unimplemented\n", Title())); 1632 DTRACE(("ServerWindow %s: Message AS_DRAG_RECT unimplemented\n", Title())); 1633 break; 1634 } 1635 case AS_LAYER_GET_MOUSE_COORDS: 1636 { 1637 DTRACE(("ServerWindow %s: Message AS_GET_MOUSE_COORDS\n", fTitle)); 1638 1639 fLink.StartMessage(SERVER_TRUE); 1640 1641 // Returns 1642 // 1) BPoint mouse location 1643 // 2) int32 button state 1644 1645 fLink.Attach<BPoint>(fDesktop->GetHWInterface()->GetCursorPosition()); 1646 fLink.Attach<int32>(fDesktop->ActiveRootLayer()->Buttons()); 1647 1648 fLink.Flush(); 1649 break; 1650 } 1651 1652 case AS_DW_GET_SYNC_DATA: 1653 { 1654 // TODO: Use token or get rid of it. 1655 int32 serverToken; 1656 link.Read<int32>(&serverToken); 1657 1658 if (_EnableDirectWindowMode() == B_OK) { 1659 fLink.StartMessage(SERVER_TRUE); 1660 struct dw_sync_data syncData = { 1661 fDirectWindowData->direct_area, 1662 fDirectWindowData->direct_sem, 1663 fDirectWindowData->direct_sem_ack 1664 }; 1665 1666 fLink.Attach(&syncData, sizeof(syncData)); 1667 1668 } else 1669 fLink.StartMessage(SERVER_FALSE); 1670 1671 fLink.Flush(); 1672 1673 break; 1674 } 1675 1676 default: 1677 _DispatchGraphicsMessage(code, link); 1678 break; 1679 } 1680 1681 if (myRootLayer) 1682 myRootLayer->Unlock(); 1683 } 1684 1685 // -------------------- Graphics messages ---------------------------------- 1686 1687 void 1688 ServerWindow::_DispatchGraphicsMessage(int32 code, BPrivate::LinkReceiver &link) 1689 { 1690 #ifndef NEW_CLIPPING 1691 BRegion rreg(fCurrentLayer->fVisible); 1692 #else 1693 BRegion rreg(fCurrentLayer->fVisible2); 1694 #endif 1695 1696 if (fWinBorder->InUpdate()) 1697 rreg.IntersectWith(&fWinBorder->RegionToBeUpdated()); 1698 1699 DisplayDriver* driver = fWinBorder->GetDisplayDriver(); 1700 1701 driver->ConstrainClippingRegion(&rreg); 1702 // rgb_color rrr = fCurrentLayer->fLayerData->viewcolor.GetColor32(); 1703 // RGBColor c(rand()%255,rand()%255,rand()%255); 1704 // driver->FillRect(BRect(0,0,639,479), c); 1705 1706 switch (code) { 1707 case AS_STROKE_LINE: 1708 { 1709 DTRACE(("ServerWindow %s: Message AS_STROKE_LINE\n", Title())); 1710 1711 float x1, y1, x2, y2; 1712 1713 link.Read<float>(&x1); 1714 link.Read<float>(&y1); 1715 link.Read<float>(&x2); 1716 link.Read<float>(&y2); 1717 1718 if (fCurrentLayer && fCurrentLayer->fLayerData) { 1719 1720 BPoint p1(x1,y1); 1721 BPoint p2(x2,y2); 1722 driver->StrokeLine(fCurrentLayer->ConvertToTop(p1), 1723 fCurrentLayer->ConvertToTop(p2), 1724 fCurrentLayer->fLayerData); 1725 1726 // We update the pen here because many DisplayDriver calls which do not update the 1727 // pen position actually call StrokeLine 1728 1729 // TODO: Decide where to put this, for example, it cannot be done 1730 // for DrawString(), also there needs to be a decision, if penlocation 1731 // is in View coordinates (I think it should be) or in screen coordinates. 1732 fCurrentLayer->fLayerData->SetPenLocation(p2); 1733 } 1734 break; 1735 } 1736 case AS_LAYER_INVERT_RECT: 1737 { 1738 DTRACE(("ServerWindow %s: Message AS_INVERT_RECT\n", Title())); 1739 1740 BRect rect; 1741 link.Read<BRect>(&rect); 1742 1743 if (fCurrentLayer && fCurrentLayer->fLayerData) 1744 driver->InvertRect(fCurrentLayer->ConvertToTop(rect)); 1745 break; 1746 } 1747 case AS_STROKE_RECT: 1748 { 1749 DTRACE(("ServerWindow %s: Message AS_STROKE_RECT\n", Title())); 1750 1751 float left, top, right, bottom; 1752 link.Read<float>(&left); 1753 link.Read<float>(&top); 1754 link.Read<float>(&right); 1755 link.Read<float>(&bottom); 1756 BRect rect(left,top,right,bottom); 1757 1758 if (fCurrentLayer && fCurrentLayer->fLayerData) 1759 driver->StrokeRect(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData); 1760 break; 1761 } 1762 case AS_FILL_RECT: 1763 { 1764 DTRACE(("ServerWindow %s: Message AS_FILL_RECT\n", Title())); 1765 1766 BRect rect; 1767 link.Read<BRect>(&rect); 1768 if (fCurrentLayer && fCurrentLayer->fLayerData) 1769 driver->FillRect(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData); 1770 break; 1771 } 1772 case AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT: 1773 { 1774 DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 1775 int32 bitmapToken; 1776 BPoint point; 1777 1778 link.Read<int32>(&bitmapToken); 1779 link.Read<BPoint>(&point); 1780 1781 ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken); 1782 if (sbmp) { 1783 BRect src = sbmp->Bounds(); 1784 BRect dst = src.OffsetToCopy(point); 1785 dst = fCurrentLayer->ConvertToTop(dst); 1786 1787 driver->DrawBitmap(sbmp, src, dst, fCurrentLayer->fLayerData); 1788 } 1789 1790 // TODO: Adi -- shouldn't AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT sync with the client? 1791 break; 1792 } 1793 case AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT: 1794 { 1795 DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 1796 int32 bitmapToken; 1797 BPoint point; 1798 1799 link.Read<int32>(&bitmapToken); 1800 link.Read<BPoint>(&point); 1801 1802 ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken); 1803 if (sbmp) { 1804 BRect src = sbmp->Bounds(); 1805 BRect dst = src.OffsetToCopy(point); 1806 dst = fCurrentLayer->ConvertToTop(dst); 1807 1808 driver->DrawBitmap(sbmp, src, dst, fCurrentLayer->fLayerData); 1809 } 1810 break; 1811 } 1812 case AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT: 1813 { 1814 DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 1815 int32 bitmapToken; 1816 BRect srcRect, dstRect; 1817 1818 link.Read<int32>(&bitmapToken); 1819 link.Read<BRect>(&dstRect); 1820 link.Read<BRect>(&srcRect); 1821 1822 ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken); 1823 if (sbmp) { 1824 dstRect = fCurrentLayer->ConvertToTop(dstRect); 1825 1826 driver->DrawBitmap(sbmp, srcRect, dstRect, fCurrentLayer->fLayerData); 1827 } 1828 1829 // TODO: Adi -- shouldn't AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT sync with the client? 1830 break; 1831 } 1832 case AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT: 1833 { 1834 DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT: Layer name: %s\n", fTitle, fCurrentLayer->Name())); 1835 int32 bitmapToken; 1836 BRect srcRect, dstRect; 1837 1838 link.Read<int32>(&bitmapToken); 1839 link.Read<BRect>(&dstRect); 1840 link.Read<BRect>(&srcRect); 1841 1842 ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken); 1843 if (sbmp) { 1844 dstRect = fCurrentLayer->ConvertToTop(dstRect); 1845 1846 driver->DrawBitmap(sbmp, srcRect, dstRect, fCurrentLayer->fLayerData); 1847 } 1848 break; 1849 } 1850 case AS_STROKE_ARC: 1851 { 1852 DTRACE(("ServerWindow %s: Message AS_STROKE_ARC\n", Title())); 1853 1854 float angle, span; 1855 BRect r; 1856 1857 link.Read<BRect>(&r); 1858 link.Read<float>(&angle); 1859 link.Read<float>(&span); 1860 if (fCurrentLayer && fCurrentLayer->fLayerData) 1861 driver->StrokeArc(fCurrentLayer->ConvertToTop(r),angle,span, fCurrentLayer->fLayerData); 1862 break; 1863 } 1864 case AS_FILL_ARC: 1865 { 1866 DTRACE(("ServerWindow %s: Message AS_FILL_ARC\n", Title())); 1867 1868 float angle, span; 1869 BRect r; 1870 1871 link.Read<BRect>(&r); 1872 link.Read<float>(&angle); 1873 link.Read<float>(&span); 1874 if (fCurrentLayer && fCurrentLayer->fLayerData) 1875 driver->FillArc(fCurrentLayer->ConvertToTop(r),angle,span, fCurrentLayer->fLayerData); 1876 break; 1877 } 1878 case AS_STROKE_BEZIER: 1879 { 1880 DTRACE(("ServerWindow %s: Message AS_STROKE_BEZIER\n", Title())); 1881 1882 BPoint *pts; 1883 int i; 1884 pts = new BPoint[4]; 1885 1886 for (i=0; i<4; i++) 1887 link.Read<BPoint>(&(pts[i])); 1888 1889 if (fCurrentLayer && fCurrentLayer->fLayerData) 1890 { 1891 for (i=0; i<4; i++) 1892 pts[i]=fCurrentLayer->ConvertToTop(pts[i]); 1893 1894 driver->StrokeBezier(pts, fCurrentLayer->fLayerData); 1895 } 1896 delete [] pts; 1897 break; 1898 } 1899 case AS_FILL_BEZIER: 1900 { 1901 DTRACE(("ServerWindow %s: Message AS_FILL_BEZIER\n", Title())); 1902 1903 BPoint *pts; 1904 int i; 1905 pts = new BPoint[4]; 1906 1907 for (i=0; i<4; i++) 1908 link.Read<BPoint>(&(pts[i])); 1909 1910 if (fCurrentLayer && fCurrentLayer->fLayerData) 1911 { 1912 for (i=0; i<4; i++) 1913 pts[i]=fCurrentLayer->ConvertToTop(pts[i]); 1914 1915 driver->FillBezier(pts, fCurrentLayer->fLayerData); 1916 } 1917 delete [] pts; 1918 break; 1919 } 1920 case AS_STROKE_ELLIPSE: 1921 { 1922 DTRACE(("ServerWindow %s: Message AS_STROKE_ELLIPSE\n", Title())); 1923 1924 BRect rect; 1925 link.Read<BRect>(&rect); 1926 if (fCurrentLayer && fCurrentLayer->fLayerData) 1927 driver->StrokeEllipse(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData); 1928 break; 1929 } 1930 case AS_FILL_ELLIPSE: 1931 { 1932 DTRACE(("ServerWindow %s: Message AS_FILL_ELLIPSE\n", Title())); 1933 1934 BRect rect; 1935 link.Read<BRect>(&rect); 1936 if (fCurrentLayer && fCurrentLayer->fLayerData) 1937 driver->FillEllipse(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData); 1938 break; 1939 } 1940 case AS_STROKE_ROUNDRECT: 1941 { 1942 DTRACE(("ServerWindow %s: Message AS_STROKE_ROUNDRECT\n", Title())); 1943 1944 BRect rect; 1945 float xrad,yrad; 1946 link.Read<BRect>(&rect); 1947 link.Read<float>(&xrad); 1948 link.Read<float>(&yrad); 1949 1950 if (fCurrentLayer && fCurrentLayer->fLayerData) 1951 driver->StrokeRoundRect(fCurrentLayer->ConvertToTop(rect),xrad,yrad, fCurrentLayer->fLayerData); 1952 break; 1953 } 1954 case AS_FILL_ROUNDRECT: 1955 { 1956 DTRACE(("ServerWindow %s: Message AS_FILL_ROUNDRECT\n", Title())); 1957 1958 BRect rect; 1959 float xrad,yrad; 1960 link.Read<BRect>(&rect); 1961 link.Read<float>(&xrad); 1962 link.Read<float>(&yrad); 1963 1964 if (fCurrentLayer && fCurrentLayer->fLayerData) 1965 driver->FillRoundRect(fCurrentLayer->ConvertToTop(rect),xrad,yrad, fCurrentLayer->fLayerData); 1966 break; 1967 } 1968 case AS_STROKE_TRIANGLE: 1969 { 1970 DTRACE(("ServerWindow %s: Message AS_STROKE_TRIANGLE\n", Title())); 1971 1972 BPoint pts[3]; 1973 BRect rect; 1974 1975 for (int i = 0; i < 3; i++) 1976 link.Read<BPoint>(&(pts[i])); 1977 1978 link.Read<BRect>(&rect); 1979 1980 if (fCurrentLayer && fCurrentLayer->fLayerData) { 1981 for (int i = 0;i < 3; i++) 1982 pts[i] = fCurrentLayer->ConvertToTop(pts[i]); 1983 1984 driver->StrokeTriangle(pts, fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData); 1985 } 1986 break; 1987 } 1988 case AS_FILL_TRIANGLE: 1989 { 1990 DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE\n", Title())); 1991 1992 BPoint pts[3]; 1993 BRect rect; 1994 1995 for (int i = 0; i < 3; i++) 1996 link.Read<BPoint>(&(pts[i])); 1997 1998 link.Read<BRect>(&rect); 1999 2000 if (fCurrentLayer && fCurrentLayer->fLayerData) { 2001 for (int i = 0; i < 3; i++) 2002 pts[i] = fCurrentLayer->ConvertToTop(pts[i]); 2003 2004 driver->FillTriangle(pts, fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData); 2005 } 2006 break; 2007 } 2008 // TODO: get rid of all this code duplication!! 2009 case AS_STROKE_POLYGON: 2010 { 2011 DTRACE(("ServerWindow %s: Message AS_STROKE_POLYGON\n", Title())); 2012 2013 BRect polyframe; 2014 bool isclosed; 2015 int32 pointcount; 2016 BPoint *pointlist; 2017 2018 link.Read<BRect>(&polyframe); 2019 link.Read<bool>(&isclosed); 2020 link.Read<int32>(&pointcount); 2021 2022 pointlist = new BPoint[pointcount]; 2023 2024 link.Read(pointlist, sizeof(BPoint)*pointcount); 2025 2026 for (int32 i = 0; i < pointcount; i++) 2027 pointlist[i] = fCurrentLayer->ConvertToTop(pointlist[i]); 2028 2029 driver->StrokePolygon(pointlist,pointcount,polyframe, 2030 fCurrentLayer->fLayerData,isclosed); 2031 2032 delete [] pointlist; 2033 break; 2034 } 2035 case AS_FILL_POLYGON: 2036 { 2037 DTRACE(("ServerWindow %s: Message AS_FILL_POLYGON\n", Title())); 2038 2039 BRect polyframe; 2040 int32 pointcount; 2041 BPoint *pointlist; 2042 2043 link.Read<BRect>(&polyframe); 2044 link.Read<int32>(&pointcount); 2045 2046 pointlist = new BPoint[pointcount]; 2047 2048 link.Read(pointlist, sizeof(BPoint) * pointcount); 2049 2050 for (int32 i = 0; i < pointcount; i++) 2051 pointlist[i] = fCurrentLayer->ConvertToTop(pointlist[i]); 2052 2053 driver->FillPolygon(pointlist,pointcount,polyframe, fCurrentLayer->fLayerData); 2054 2055 delete [] pointlist; 2056 break; 2057 } 2058 case AS_STROKE_SHAPE: 2059 { 2060 DTRACE(("ServerWindow %s: Message AS_STROKE_SHAPE\n", Title())); 2061 2062 BRect shaperect; 2063 int32 opcount; 2064 int32 ptcount; 2065 int32 *oplist; 2066 BPoint *ptlist; 2067 2068 link.Read<BRect>(&shaperect); 2069 link.Read<int32>(&opcount); 2070 link.Read<int32>(&ptcount); 2071 2072 oplist = new int32[opcount]; 2073 ptlist = new BPoint[ptcount]; 2074 2075 link.Read(oplist, sizeof(int32) * opcount); 2076 link.Read(ptlist, sizeof(BPoint) * ptcount); 2077 2078 for (int32 i = 0; i < ptcount; i++) 2079 ptlist[i] = fCurrentLayer->ConvertToTop(ptlist[i]); 2080 2081 driver->StrokeShape(shaperect, opcount, oplist, ptcount, ptlist, fCurrentLayer->fLayerData); 2082 delete[] oplist; 2083 delete[] ptlist; 2084 break; 2085 } 2086 case AS_FILL_SHAPE: 2087 { 2088 DTRACE(("ServerWindow %s: Message AS_FILL_SHAPE\n", Title())); 2089 2090 BRect shaperect; 2091 int32 opcount; 2092 int32 ptcount; 2093 int32 *oplist; 2094 BPoint *ptlist; 2095 2096 link.Read<BRect>(&shaperect); 2097 link.Read<int32>(&opcount); 2098 link.Read<int32>(&ptcount); 2099 2100 oplist = new int32[opcount]; 2101 ptlist = new BPoint[ptcount]; 2102 2103 link.Read(oplist, sizeof(int32) * opcount); 2104 link.Read(ptlist, sizeof(BPoint) * ptcount); 2105 2106 for (int32 i = 0; i < ptcount; i++) 2107 ptlist[i] = fCurrentLayer->ConvertToTop(ptlist[i]); 2108 2109 driver->FillShape(shaperect, opcount, oplist, ptcount, ptlist, fCurrentLayer->fLayerData); 2110 2111 delete[] oplist; 2112 delete[] ptlist; 2113 break; 2114 } 2115 case AS_FILL_REGION: 2116 { 2117 DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title())); 2118 2119 int32 count; 2120 link.Read<int32>(&count); 2121 2122 BRect *rects = new BRect[count]; 2123 if (link.Read(rects, sizeof(BRect) * count) != B_OK) { 2124 delete[] rects; 2125 break; 2126 } 2127 2128 // Between the client-side conversion to BRects from clipping_rects to the overhead 2129 // in repeatedly calling FillRect(), this is definitely in need of optimization. At 2130 // least it works for now. :) 2131 BRegion region; 2132 for (int32 i = 0; i < count; i++) { 2133 region.Include(fCurrentLayer->ConvertToTop(rects[i])); 2134 } 2135 driver->FillRegion(region, fCurrentLayer->fLayerData); 2136 2137 delete[] rects; 2138 2139 // TODO: create support for clipping_rect usage for faster BRegion display. 2140 // Tweaks to DisplayDriver are necessary along with conversion routines in Layer 2141 break; 2142 } 2143 case AS_STROKE_LINEARRAY: 2144 { 2145 DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n", Title())); 2146 2147 // Attached Data: 2148 // 1) int32 Number of lines in the array 2149 // 2) array of struct _array_data_ objects, as defined in ViewAux.h 2150 2151 int32 linecount; 2152 2153 link.Read<int32>(&linecount); 2154 if (linecount > 0) { 2155 LineArrayData linedata[linecount], *index; 2156 2157 for (int32 i = 0; i < linecount; i++) { 2158 index = &linedata[i]; 2159 2160 link.Read<float>(&(index->pt1.x)); 2161 link.Read<float>(&(index->pt1.y)); 2162 link.Read<float>(&(index->pt2.x)); 2163 link.Read<float>(&(index->pt2.y)); 2164 link.Read<rgb_color>(&(index->color)); 2165 2166 index->pt1 = fCurrentLayer->ConvertToTop(index->pt1); 2167 index->pt2 = fCurrentLayer->ConvertToTop(index->pt2); 2168 } 2169 driver->StrokeLineArray(linecount,linedata,fCurrentLayer->fLayerData); 2170 } 2171 break; 2172 } 2173 case AS_DRAW_STRING: 2174 { 2175 DTRACE(("ServerWindow %s: Message AS_DRAW_STRING\n", Title())); 2176 char *string; 2177 int32 length; 2178 BPoint location; 2179 escapement_delta delta; 2180 2181 link.Read<int32>(&length); 2182 link.Read<BPoint>(&location); 2183 link.Read<escapement_delta>(&delta); 2184 link.ReadString(&string); 2185 2186 if (fCurrentLayer && fCurrentLayer->fLayerData) 2187 driver->DrawString(string, length, 2188 fCurrentLayer->ConvertToTop(location), 2189 fCurrentLayer->fLayerData, &delta); 2190 2191 free(string); 2192 break; 2193 } 2194 case AS_LAYER_BEGIN_PICTURE: 2195 CRITICAL("AS_LAYER_BEGIN_PICTURE not implemented\n"); 2196 break; 2197 case AS_LAYER_APPEND_TO_PICTURE: 2198 CRITICAL("AS_LAYER_APPEND_TO_PICTURE not implemented\n"); 2199 break; 2200 case AS_LAYER_END_PICTURE: 2201 CRITICAL("AS_LAYER_END_PICTURE not implemented\n"); 2202 break; 2203 2204 default: 2205 printf("ServerWindow %s received unexpected code - message offset %ld\n", 2206 Title(), code - SERVER_TRUE); 2207 2208 if (link.NeedsReply()) { 2209 // the client is now blocking and waiting for a reply! 2210 fLink.StartMessage(SERVER_FALSE); 2211 fLink.Flush(); 2212 } 2213 break; 2214 } 2215 2216 driver->ConstrainClippingRegion(NULL); 2217 } 2218 2219 2220 /*! 2221 \brief Message-dispatching loop for the ServerWindow 2222 2223 Watches the ServerWindow's message port and dispatches as necessary 2224 */ 2225 void 2226 ServerWindow::_MessageLooper() 2227 { 2228 BPrivate::LinkReceiver& receiver = fLink.Receiver(); 2229 bool quitLoop = false; 2230 2231 while (!quitLoop) { 2232 //STRACE(("info: ServerWindow::MonitorWin listening on port %ld.\n", 2233 // fMessagePort)); 2234 2235 int32 code; 2236 status_t status = receiver.GetNextMessage(code); 2237 if (status < B_OK) { 2238 // that shouldn't happen, it's our port 2239 printf("Someone deleted our message port!\n"); 2240 2241 // try to let our client die happily 2242 NotifyQuitRequested(); 2243 break; 2244 } 2245 2246 Lock(); 2247 2248 switch (code) { 2249 case AS_DELETE_WINDOW: 2250 case kMsgQuitLooper: 2251 // this means the client has been killed 2252 STRACE(("ServerWindow %s received 'AS_DELETE_WINDOW' message code\n", 2253 Title())); 2254 2255 quitLoop = true; 2256 2257 // ToDo: what's this? 2258 //RootLayer *rootLayer = fWinBorder->GetRootLayer(); 2259 2260 // we are preparing to delete a ServerWindow, RootLayer should be aware 2261 // of that and stop for a moment. 2262 // also we must wait a bit for the associated WinBorder to become hidden 2263 //while(1) { 2264 // myRootLayer->Lock(); 2265 // if (IsHidden()) 2266 // break; 2267 // else 2268 // rootLayer->Unlock(); 2269 //} 2270 2271 // ServerWindow's destructor takes care of pulling this object off the desktop. 2272 if (!fWinBorder->IsHidden()) 2273 CRITICAL("ServerWindow: a window must be hidden before it's deleted\n"); 2274 break; 2275 2276 case B_QUIT_REQUESTED: 2277 STRACE(("ServerWindow %s received quit request\n", Title())); 2278 NotifyQuitRequested(); 2279 break; 2280 2281 default: 2282 _DispatchMessage(code, receiver); 2283 break; 2284 } 2285 2286 Unlock(); 2287 } 2288 2289 // we were asked to quit the message loop - either on request or because of an error 2290 Quit(); 2291 // does not return 2292 } 2293 2294 /* 2295 void 2296 ServerWindow::_CopyBits(RootLayer* rootLayer, Layer* layer, 2297 BRect& src, BRect& dst, 2298 int32 xOffset, int32 yOffset) const 2299 { 2300 // NOTE: The correct behaviour is this: 2301 // * The region that is copied is the 2302 // src rectangle, no matter if it fits 2303 // into the dst rectangle. It is copied 2304 // by the offset dst.LeftTop() - src.LeftTop() 2305 // * The dst rectangle is used for invalidation: 2306 // Any area in the dst rectangle that could 2307 // not be copied from src (because either the 2308 // src rectangle was not big enough, or because there 2309 // were parts cut off by the current layer clipping), 2310 // are triggering BView::Draw() to be called 2311 // and for these parts only. 2312 2313 #ifndef NEW_CLIPPING 2314 2315 // the region that is going to be copied 2316 BRegion copyRegion(src); 2317 // apply the current clipping of the layer 2318 2319 copyRegion.IntersectWith(&layer->fVisible); 2320 2321 // offset the region to the destination 2322 // and apply the current clipping there as well 2323 copyRegion.OffsetBy(xOffset, yOffset); 2324 copyRegion.IntersectWith(&layer->fVisible); 2325 2326 // the region at the destination that needs invalidation 2327 BRegion invalidRegion(dst); 2328 // exclude the region drawn by the copy operation 2329 invalidRegion.Exclude(©Region); 2330 // apply the current clipping as well 2331 invalidRegion.IntersectWith(&layer->fVisible); 2332 2333 // move the region back for the actual operation 2334 copyRegion.OffsetBy(-xOffset, -yOffset); 2335 2336 layer->GetDisplayDriver()->CopyRegion(©Region, xOffset, yOffset); 2337 2338 // trigger the redraw 2339 if (rootLayer) { 2340 // the following code solves a "concurrency" problem: 2341 // since the scrolling might happen more often 2342 // than redrawing, we need to keep track of the region 2343 // pending for redraw that might fall into the area 2344 // that is scrolled. 2345 BRegion scrolledInvalid(fWinBorder->CulmulatedUpdateRegion()); 2346 scrolledInvalid.IntersectWith(&layer->fVisible); 2347 if (scrolledInvalid.Frame().IsValid()) { 2348 //printf("the layer has pending updates that will be scrolled\n"); 2349 scrolledInvalid.OffsetBy(xOffset, yOffset); 2350 invalidRegion.Include(&scrolledInvalid); 2351 } 2352 2353 rootLayer->GoRedraw(fWinBorder, invalidRegion); 2354 } 2355 2356 #endif 2357 }*/ 2358 2359 2360 status_t 2361 ServerWindow::SendMessageToClient(const BMessage* msg, int32 target, bool usePreferred) const 2362 { 2363 ssize_t size = msg->FlattenedSize(); 2364 char* buffer = new char[size]; 2365 status_t ret; 2366 2367 if ((ret = msg->Flatten(buffer, size)) == B_OK) { 2368 ret = BMessage::Private::SendFlattenedMessage(buffer, size, 2369 fClientLooperPort, target, usePreferred, 100000); 2370 if (ret < B_OK) 2371 fprintf(stderr, "ServerWindow::SendMessageToClient(): %s\n", strerror(ret)); 2372 } else 2373 printf("PANIC: ServerWindow %s: can't flatten message in 'SendMessageToClient()'\n", fTitle); 2374 2375 delete[] buffer; 2376 2377 return ret; 2378 } 2379 2380 // MakeWinBorder 2381 WinBorder* 2382 ServerWindow::MakeWinBorder(BRect frame, const char* name, 2383 uint32 look, uint32 feel, uint32 flags, 2384 uint32 workspace) 2385 { 2386 // The non-offscreen ServerWindow uses the DisplayDriver instance from the desktop. 2387 return new(nothrow) WinBorder(frame, name, look, feel, flags, 2388 workspace, this, fDesktop->GetDisplayDriver()); 2389 } 2390 2391 2392 status_t 2393 ServerWindow::_EnableDirectWindowMode() 2394 { 2395 if (fDirectWindowData != NULL) 2396 return B_ERROR; // already in direct window mode 2397 2398 fDirectWindowData = new (nothrow) dw_data; 2399 if (fDirectWindowData == NULL) 2400 return B_NO_MEMORY; 2401 2402 if (!fDirectWindowData->IsValid()) { 2403 delete fDirectWindowData; 2404 fDirectWindowData = NULL; 2405 return B_ERROR; 2406 } 2407 2408 return B_OK; 2409 } 2410 2411 2412 void 2413 ServerWindow::_HandleDirectConnection(direct_buffer_state state) 2414 { 2415 if (fDirectWindowData == NULL) 2416 return; 2417 2418 fDirectWindowData->direct_info->buffer_state = state; 2419 2420 if ((state & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) { 2421 // TODO: Locking ? 2422 RenderingBuffer *buffer = fDesktop->GetHWInterface()->FrontBuffer(); 2423 fDirectWindowData->direct_info->bits = buffer->Bits(); 2424 fDirectWindowData->direct_info->pci_bits = NULL; // TODO 2425 fDirectWindowData->direct_info->bytes_per_row = buffer->BytesPerRow(); 2426 fDirectWindowData->direct_info->bits_per_pixel = buffer->BytesPerRow() / buffer->Width() * 8; 2427 fDirectWindowData->direct_info->pixel_format = buffer->ColorSpace(); 2428 fDirectWindowData->direct_info->layout = B_BUFFER_NONINTERLEAVED; 2429 fDirectWindowData->direct_info->orientation = B_BUFFER_TOP_TO_BOTTOM; // TODO 2430 2431 WinBorder *border = const_cast<WinBorder *>(GetWinBorder()); 2432 fDirectWindowData->direct_info->window_bounds = to_clipping_rect(border->Frame()); 2433 2434 // TODO: Review this 2435 const int32 kMaxClipRectsCount = (B_PAGE_SIZE - sizeof(direct_buffer_info)) / sizeof(clipping_rect); 2436 2437 // TODO: Is this the correct region to take into account ? 2438 BRegion clipRegion = const_cast<BRegion &>(border->VisibleRegion()); 2439 border->ConvertToTop(&clipRegion); 2440 fDirectWindowData->direct_info->clip_list_count = min_c(clipRegion.CountRects(), kMaxClipRectsCount); 2441 fDirectWindowData->direct_info->clip_bounds = clipRegion.FrameInt(); 2442 2443 for (uint32 i = 0; i < fDirectWindowData->direct_info->clip_list_count; i++) 2444 fDirectWindowData->direct_info->clip_list[i] = clipRegion.RectAtInt(i); 2445 } 2446 2447 // Releasing this sem causes the client to call BDirectWindow::DirectConnected() 2448 release_sem(fDirectWindowData->direct_sem); 2449 2450 // TODO: Waiting 3 seconds in this thread could cause weird things: test 2451 status_t status = acquire_sem_etc(fDirectWindowData->direct_sem_ack, 1, B_TIMEOUT, 3000000); 2452 if (status == B_TIMED_OUT) { 2453 // The client application didn't release the semaphore 2454 // within the given timeout. Deleting this member should make it crash. 2455 // TODO: Actually, it will not. At least, not always. Find a better way to 2456 // crash the client application. 2457 delete fDirectWindowData; 2458 fDirectWindowData = NULL; 2459 } 2460 } 2461 2462 2463 status_t 2464 ServerWindow::PictureToRegion(ServerPicture *picture, BRegion ®ion, 2465 bool inverse, BPoint where) 2466 { 2467 fprintf(stderr, "ServerWindow::PictureToRegion() not implemented\n"); 2468 region.MakeEmpty(); 2469 return B_ERROR; 2470 } 2471