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