2 * Copyright 2001-2015, Haiku.
3 * Distributed under the terms of the MIT License.
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Adrian Oanca <adioanca@gmail.com>
8 * Stephan Aßmus <superstippi@gmx.de>
9 * Stefano Ceccherini <stefano.ceccherini@gmail.com>
10 * Axel Dörfler <axeld@pinc-software.de>
11 * Artur Wyszynski <harakash@gmail.com>
12 * Philippe Saint-Pierre <stpere@gmail.com>
13 * Brecht Machiels <brecht@mos6581.org>
14 * Julian Harnath <julian.harnath@rwth-aachen.de>
15 * Joseph Groover <looncraz@looncraz.net>
19 /*! \class ServerWindow
21 The ServerWindow class handles all BWindow messaging; it forwards all
22 BWindow requests to the corresponding app_server classes, that is Desktop,
24 Furthermore, it also sends app_server requests/notices to its BWindow. There
25 is one ServerWindow per BWindow.
29 #include "ServerWindow.h"
37 #include <DirectWindow.h>
38 #include <TokenSpace.h>
40 #include <GradientLinear.h>
41 #include <GradientRadial.h>
42 #include <GradientRadialFocus.h>
43 #include <GradientDiamond.h>
44 #include <GradientConic.h>
46 #include <MessagePrivate.h>
48 #include <ShapePrivate.h>
49 #include <ServerProtocolStructs.h>
50 #include <ViewPrivate.h>
51 #include <WindowInfo.h>
52 #include <WindowPrivate.h>
55 #include "utf8_functions.h"
57 #include "AlphaMask.h"
58 #include "AppServer.h"
59 #include "AutoDeleter.h"
60 #include "BBitmapBuffer.h"
61 #include "BitmapManager.h"
63 #include "DirectWindowInfo.h"
64 #include "DrawingEngine.h"
65 #include "DrawState.h"
66 #include "HWInterface.h"
69 #include "ProfileMessageSupport.h"
70 #include "RenderingBuffer.h"
71 #include "ServerApp.h"
72 #include "ServerBitmap.h"
73 #include "ServerPicture.h"
74 #include "ServerProtocol.h"
76 #include "WorkspacesView.h"
82 //#define TRACE_SERVER_WINDOW
83 #ifdef TRACE_SERVER_WINDOW
85 # define STRACE(x) debug_printf x
90 //#define TRACE_SERVER_WINDOW_MESSAGES
91 #ifdef TRACE_SERVER_WINDOW_MESSAGES
93 static const char* kDrawingModeMap
[] = {
106 "fix kDrawingModeMap",
107 "fix kDrawingModeMap",
108 "fix kDrawingModeMap",
109 "fix kDrawingModeMap",
110 "fix kDrawingModeMap",
112 # define DTRACE(x) debug_printf x
117 //#define TRACE_SERVER_GRADIENTS
118 #ifdef TRACE_SERVER_GRADIENTS
120 # define GTRACE(x) debug_printf x
125 //#define PROFILE_MESSAGE_LOOP
126 #ifdef PROFILE_MESSAGE_LOOP
127 struct profile
{ int32 code
; int32 count
; bigtime_t time
; };
128 static profile sMessageProfile
[AS_LAST_CODE
];
129 static profile sRedrawProcessingTime
;
130 //static profile sNextMessageTime;
137 #ifdef PROFILE_MESSAGE_LOOP
139 compare_message_profiles(const void* _a
, const void* _b
)
141 profile
* a
= (profile
*)*(void**)_a
;
142 profile
* b
= (profile
*)*(void**)_b
;
143 if (a
->time
< b
->time
)
145 if (a
->time
> b
->time
)
155 /*! Sets up the basic BWindow counterpart - you have to call Init() before
156 you can actually use it, though.
158 ServerWindow::ServerWindow(const char* title
, ServerApp
* app
,
159 port_id clientPort
, port_id looperPort
, int32 clientToken
)
161 MessageLooper(title
&& *title
? title
: "Unnamed Window"),
163 fDesktop(app
->GetDesktop()),
166 fWindowAddedToDesktop(false),
168 fClientTeam(app
->ClientTeam()),
171 fClientReplyPort(clientPort
),
172 fClientLooperPort(looperPort
),
174 fClientToken(clientToken
),
177 fCurrentDrawingRegion(),
178 fCurrentDrawingRegionValid(false),
180 fDirectWindowInfo(NULL
),
181 fIsDirectlyAccessing(false)
183 STRACE(("ServerWindow(%s)::ServerWindow()\n", title
));
186 fServerToken
= BPrivate::gDefaultTokens
.NewToken(B_SERVER_TOKEN
, this);
188 BMessenger::Private(fFocusMessenger
).SetTo(fClientTeam
,
189 looperPort
, B_PREFERRED_TOKEN
);
190 BMessenger::Private(fHandlerMessenger
).SetTo(fClientTeam
,
191 looperPort
, clientToken
);
193 fEventTarget
.SetTo(fFocusMessenger
);
195 fDeathSemaphore
= create_sem(0, "window death");
199 /*! Tears down all connections the main app_server objects, and deletes some
202 ServerWindow::~ServerWindow()
204 STRACE(("ServerWindow(%s@%p):~ServerWindow()\n", fTitle
, this));
206 if (!fWindow
->IsOffscreenWindow()) {
207 fWindowAddedToDesktop
= false;
208 fDesktop
->RemoveWindow(fWindow
);
212 App()->RemoveWindow(this);
219 delete_port(fMessagePort
);
221 BPrivate::gDefaultTokens
.RemoveToken(fServerToken
);
223 delete fDirectWindowInfo
;
224 STRACE(("ServerWindow(%p) will exit NOW\n", this));
226 delete_sem(fDeathSemaphore
);
228 #ifdef PROFILE_MESSAGE_LOOP
230 for (int32 i
= 0; i
< AS_LAST_CODE
; i
++) {
231 if (sMessageProfile
[i
].count
== 0)
233 sMessageProfile
[i
].code
= i
;
234 profiles
.AddItem(&sMessageProfile
[i
]);
237 profiles
.SortItems(compare_message_profiles
);
240 int32 count
= profiles
.CountItems();
241 for (int32 i
= 0; i
< count
; i
++) {
242 profile
* p
= (profile
*)profiles
.ItemAtFast(i
);
243 string_for_message_code(p
->code
, codeName
);
244 printf("[%s] called %" B_PRId32
" times, %g secs (%" B_PRId64
" usecs "
245 "per call)\n", codeName
.String(), p
->count
, p
->time
/ 1000000.0,
248 if (sRedrawProcessingTime
.count
> 0) {
249 printf("average redraw processing time: %g secs, count: %" B_PRId32
" "
250 "(%" B_PRId64
" usecs per call)\n",
251 sRedrawProcessingTime
.time
/ 1000000.0, sRedrawProcessingTime
.count
,
252 sRedrawProcessingTime
.time
/ sRedrawProcessingTime
.count
);
254 // if (sNextMessageTime.count > 0) {
255 // printf("average NextMessage() time: %g secs, count: %ld (%lld usecs per call)\n",
256 // sNextMessageTime.time / 1000000.0, sNextMessageTime.count,
257 // sNextMessageTime.time / sNextMessageTime.count);
264 ServerWindow::Init(BRect frame
, window_look look
, window_feel feel
,
265 uint32 flags
, uint32 workspace
)
267 if (!App()->AddWindow(this)) {
275 // fMessagePort is the port to which the app sends messages for the server
276 fMessagePort
= create_port(100, fTitle
);
277 if (fMessagePort
< B_OK
)
280 fLink
.SetSenderPort(fClientReplyPort
);
281 fLink
.SetReceiverPort(fMessagePort
);
283 // We cannot call MakeWindow in the constructor, since it
284 // is a virtual function!
285 fWindow
= MakeWindow(frame
, fTitle
, look
, feel
, flags
, workspace
);
286 if (!fWindow
|| fWindow
->InitCheck() != B_OK
) {
292 if (!fWindow
->IsOffscreenWindow()) {
293 fDesktop
->AddWindow(fWindow
);
294 fWindowAddedToDesktop
= true;
301 /*! Returns the ServerWindow's Window, if it exists and has been
302 added to the Desktop already.
303 In other words, you cannot assume this method will always give you
307 ServerWindow::Window() const
309 if (!fWindowAddedToDesktop
)
317 ServerWindow::_PrepareQuit()
319 if (fThread
== find_thread(NULL
)) {
320 // make sure we're hidden
321 fDesktop
->LockSingleWindow();
323 fDesktop
->UnlockSingleWindow();
324 } else if (fThread
>= B_OK
)
325 PostMessage(AS_INTERNAL_HIDE_WINDOW
);
330 ServerWindow::_GetLooperName(char* name
, size_t length
)
332 const char *title
= Title();
333 if (title
== NULL
|| !title
[0])
334 title
= "Unnamed Window";
336 snprintf(name
, length
, "w:%" B_PRId32
":%s", ClientTeam(), title
);
340 /*! Shows the window's Window.
343 ServerWindow::_Show()
345 // NOTE: if you do something else, other than sending a port message, PLEASE lock
346 STRACE(("ServerWindow %s: _Show\n", Title()));
348 if (fQuitting
|| fWindow
->IsMinimized() || !fWindow
->IsHidden()
349 || fWindow
->IsOffscreenWindow() || fWindow
->TopView() == NULL
)
352 // TODO: Maybe we need to dispatch a message to the desktop to show/hide us
353 // instead of doing it from this thread.
354 fDesktop
->UnlockSingleWindow();
355 fDesktop
->ShowWindow(fWindow
);
356 if (fDirectWindowInfo
&& fDirectWindowInfo
->IsFullScreen())
357 _ResizeToFullScreen();
359 fDesktop
->LockSingleWindow();
363 /*! Hides the window's Window. You need to have all windows locked when
364 calling this function.
367 ServerWindow::_Hide()
369 STRACE(("ServerWindow %s: _Hide\n", Title()));
371 if (fWindow
->IsHidden() || fWindow
->IsOffscreenWindow())
374 fDesktop
->UnlockSingleWindow();
375 fDesktop
->HideWindow(fWindow
);
376 fDesktop
->LockSingleWindow();
381 ServerWindow::RequestRedraw()
383 PostMessage(AS_REDRAW
, 0);
384 // we don't care if this fails - it's only a notification, and if
385 // it fails, there are obviously enough messages in the queue
388 atomic_add(&fRedrawRequested
, 1);
393 ServerWindow::SetTitle(const char* newTitle
)
395 char* oldTitle
= fTitle
;
397 if (newTitle
== NULL
)
400 fTitle
= strdup(newTitle
);
401 if (fTitle
== NULL
) {
402 // out of memory condition
409 if (Thread() >= B_OK
) {
410 char name
[B_OS_NAME_LENGTH
];
411 _GetLooperName(name
, sizeof(name
));
412 rename_thread(Thread(), name
);
416 fDesktop
->SetWindowTitle(fWindow
, newTitle
);
420 //! Requests that the ServerWindow's BWindow quit
422 ServerWindow::NotifyQuitRequested()
424 // NOTE: if you do something else, other than sending a port message,
426 STRACE(("ServerWindow %s: Quit\n", fTitle
));
428 BMessage
msg(B_QUIT_REQUESTED
);
429 SendMessageToClient(&msg
);
434 ServerWindow::NotifyMinimize(bool minimize
)
436 if (fWindow
->Feel() != B_NORMAL_WINDOW_FEEL
)
439 // The client is responsible for the actual minimization
441 BMessage
msg(B_MINIMIZE
);
442 msg
.AddInt64("when", real_time_clock_usecs());
443 msg
.AddBool("minimize", minimize
);
445 SendMessageToClient(&msg
);
449 //! Sends a message to the client to perform a Zoom
451 ServerWindow::NotifyZoom()
453 // NOTE: if you do something else, other than sending a port message,
455 BMessage
msg(B_ZOOM
);
456 SendMessageToClient(&msg
);
461 ServerWindow::GetInfo(window_info
& info
)
463 info
.team
= ClientTeam();
464 info
.server_token
= ServerToken();
466 info
.thread
= Thread();
467 info
.client_token
= ClientToken();
468 info
.client_port
= fClientLooperPort
;
469 info
.workspaces
= fWindow
->Workspaces();
471 // logic taken from Switcher comments and experiments
472 if (fWindow
->IsHidden())
474 else if (fWindow
->IsVisible()) {
475 if (fWindow
->Feel() == kDesktopWindowFeel
)
477 else if (fWindow
->IsFloating() || fWindow
->IsModal())
484 info
.feel
= fWindow
->Feel();
485 info
.flags
= fWindow
->Flags();
486 info
.window_left
= (int)floor(fWindow
->Frame().left
);
487 info
.window_top
= (int)floor(fWindow
->Frame().top
);
488 info
.window_right
= (int)floor(fWindow
->Frame().right
);
489 info
.window_bottom
= (int)floor(fWindow
->Frame().bottom
);
491 info
.show_hide_level
= fWindow
->ShowLevel();
492 info
.is_mini
= fWindow
->IsMinimized();
497 ServerWindow::ResyncDrawState()
499 _UpdateDrawState(fCurrentView
);
504 ServerWindow::_CreateView(BPrivate::LinkReceiver
& link
, View
** _parent
)
506 // NOTE: no need to check for a lock. This is a private method.
518 BPoint scrollingOffset
;
520 link
.Read
<int32
>(&token
);
521 link
.ReadString(&name
);
522 link
.Read
<BRect
>(&frame
);
523 link
.Read
<BPoint
>(&scrollingOffset
);
524 link
.Read
<uint32
>(&resizeMask
);
525 link
.Read
<uint32
>(&eventMask
);
526 link
.Read
<uint32
>(&eventOptions
);
527 link
.Read
<uint32
>(&flags
);
528 link
.Read
<bool>(&hidden
);
529 link
.Read
<rgb_color
>(&viewColor
);
530 link
.Read
<int32
>(&parentToken
);
532 STRACE(("ServerWindow(%s)::_CreateView()-> view %s, token %" B_PRId32
"\n",
533 fTitle
, name
, token
));
537 if ((flags
& kWorkspacesViewFlag
) != 0) {
538 newView
= new (nothrow
) WorkspacesView(frame
, scrollingOffset
, name
,
539 token
, resizeMask
, flags
);
541 newView
= new (nothrow
) View(frame
, scrollingOffset
, name
, token
,
550 if (newView
->InitCheck() != B_OK
) {
555 // there is no way of setting this, other than manually :-)
556 newView
->SetViewColor(viewColor
);
557 newView
->SetHidden(hidden
);
558 newView
->SetEventMask(eventMask
, eventOptions
);
560 if (eventMask
!= 0 || eventOptions
!= 0) {
561 // fDesktop->UnlockSingleWindow();
562 // fDesktop->LockAllWindows();
563 fDesktop
->UnlockAllWindows();
564 // TODO: possible deadlock
565 fDesktop
->EventDispatcher().AddListener(EventTarget(),
566 newView
->Token(), eventMask
, eventOptions
);
567 fDesktop
->LockAllWindows();
568 // fDesktop->UnlockAllWindows();
569 // fDesktop->LockSingleWindow();
572 // Initialize the view with the current application plain font.
573 // NOTE: This might be out of sync with the global app_server plain
574 // font, but that is so on purpose! The client needs to resync itself
575 // with the app_server fonts upon notification, but if we just use
576 // the current font here, the be_plain_font on the client may still
577 // hold old values. So this needs to be an update initiated by the
578 // client application.
579 newView
->CurrentState()->SetFont(App()->PlainFont());
583 if (App()->ViewTokens().GetToken(parentToken
, B_HANDLER_TOKEN
,
584 (void**)&parent
) != B_OK
585 || parent
->Window()->ServerWindow() != this) {
586 debug_printf("View token not found!\n");
597 /*! Dispatches all window messages, and those view messages that
598 don't need a valid fCurrentView (ie. view creation).
601 ServerWindow::_DispatchMessage(int32 code
, BPrivate::LinkReceiver
& link
)
604 case AS_SHOW_OR_HIDE_WINDOW
:
607 if (link
.Read
<int32
>(&showLevel
) == B_OK
) {
608 DTRACE(("ServerWindow %s: Message AS_SHOW_OR_HIDE_WINDOW, "
609 "show level: %" B_PRId32
"\n", Title(), showLevel
));
611 fWindow
->SetShowLevel(showLevel
);
619 // Only for internal use within this class
620 case AS_INTERNAL_HIDE_WINDOW
:
623 case AS_MINIMIZE_WINDOW
:
626 if (link
.Read
<bool>(&minimize
) == B_OK
) {
627 DTRACE(("ServerWindow %s: Message AS_MINIMIZE_WINDOW, "
628 "minimize: %d\n", Title(), minimize
));
630 fDesktop
->UnlockSingleWindow();
631 fDesktop
->MinimizeWindow(fWindow
, minimize
);
632 fDesktop
->LockSingleWindow();
637 case AS_ACTIVATE_WINDOW
:
639 bool activate
= true;
640 if (link
.Read
<bool>(&activate
) != B_OK
)
643 DTRACE(("ServerWindow %s: Message AS_ACTIVATE_WINDOW: activate: "
644 "%d\n", Title(), activate
));
646 fDesktop
->UnlockSingleWindow();
649 fDesktop
->SelectWindow(fWindow
);
651 fDesktop
->SendWindowBehind(fWindow
, NULL
);
653 fDesktop
->LockSingleWindow();
658 // Has the all-window lock
661 status_t status
= B_ERROR
;
663 link
.Read
<int32
>(&token
);
664 if (link
.Read
<team_id
>(&teamID
) == B_OK
) {
665 ::Window
* behindOf
= fDesktop
->FindWindowByClientToken(token
,
668 DTRACE(("ServerWindow %s: Message AS_SEND_BEHIND %s\n",
669 Title(), behindOf
!= NULL
? behindOf
->Title() : "NULL"));
671 if (behindOf
!= NULL
|| token
== -1) {
672 fDesktop
->SendWindowBehind(fWindow
, behindOf
);
675 status
= B_NAME_NOT_FOUND
;
678 fLink
.StartMessage(status
);
683 case B_QUIT_REQUESTED
:
684 DTRACE(("ServerWindow %s received quit request\n", Title()));
685 NotifyQuitRequested();
688 case AS_ENABLE_UPDATES
:
689 DTRACE(("ServerWindow %s: Message AS_ENABLE_UPDATES\n", Title()));
690 fWindow
->EnableUpdateRequests();
693 case AS_DISABLE_UPDATES
:
694 DTRACE(("ServerWindow %s: Message AS_DISABLE_UPDATES\n", Title()));
695 fWindow
->DisableUpdateRequests();
698 case AS_NEEDS_UPDATE
:
699 DTRACE(("ServerWindow %s: Message AS_NEEDS_UPDATE: %d\n",
700 Title(), fWindow
->NeedsUpdate()));
701 if (fWindow
->NeedsUpdate())
702 fLink
.StartMessage(B_OK
);
704 fLink
.StartMessage(B_ERROR
);
708 case AS_SET_WINDOW_TITLE
:
711 if (link
.ReadString(&newTitle
) == B_OK
) {
712 DTRACE(("ServerWindow %s: Message AS_SET_WINDOW_TITLE: %s\n",
721 case AS_ADD_TO_SUBSET
:
723 // Has the all-window lock
724 DTRACE(("ServerWindow %s: Message AS_ADD_TO_SUBSET\n", Title()));
725 status_t status
= B_ERROR
;
728 if (link
.Read
<int32
>(&token
) == B_OK
) {
729 ::Window
* window
= fDesktop
->FindWindowByClientToken(token
,
730 App()->ClientTeam());
731 if (window
== NULL
|| window
->Feel() != B_NORMAL_WINDOW_FEEL
) {
732 status
= B_BAD_VALUE
;
734 status
= fDesktop
->AddWindowToSubset(fWindow
, window
)
735 ? B_OK
: B_NO_MEMORY
;
739 fLink
.StartMessage(status
);
743 case AS_REMOVE_FROM_SUBSET
:
745 // Has the all-window lock
746 DTRACE(("ServerWindow %s: Message AS_REM_FROM_SUBSET\n", Title()));
747 status_t status
= B_ERROR
;
750 if (link
.Read
<int32
>(&token
) == B_OK
) {
751 ::Window
* window
= fDesktop
->FindWindowByClientToken(token
,
752 App()->ClientTeam());
753 if (window
!= NULL
) {
754 fDesktop
->RemoveWindowFromSubset(fWindow
, window
);
757 status
= B_BAD_VALUE
;
760 fLink
.StartMessage(status
);
767 // Has the all-window look
768 DTRACE(("ServerWindow %s: Message AS_SET_LOOK\n", Title()));
770 status_t status
= B_ERROR
;
772 if (link
.Read
<int32
>(&look
) == B_OK
) {
773 // test if look is valid
774 status
= Window::IsValidLook((window_look
)look
)
775 ? B_OK
: B_BAD_VALUE
;
778 if (status
== B_OK
&& !fWindow
->IsOffscreenWindow())
779 fDesktop
->SetWindowLook(fWindow
, (window_look
)look
);
781 fLink
.StartMessage(status
);
787 // Has the all-window look
788 DTRACE(("ServerWindow %s: Message AS_SET_FEEL\n", Title()));
790 status_t status
= B_ERROR
;
792 if (link
.Read
<int32
>(&feel
) == B_OK
) {
793 // test if feel is valid
794 status
= Window::IsValidFeel((window_feel
)feel
)
795 ? B_OK
: B_BAD_VALUE
;
798 if (status
== B_OK
&& !fWindow
->IsOffscreenWindow())
799 fDesktop
->SetWindowFeel(fWindow
, (window_feel
)feel
);
801 fLink
.StartMessage(status
);
807 // Has the all-window look
808 DTRACE(("ServerWindow %s: Message AS_SET_FLAGS\n", Title()));
810 status_t status
= B_ERROR
;
812 if (link
.Read
<uint32
>(&flags
) == B_OK
) {
813 // test if flags are valid
814 status
= (flags
& ~Window::ValidWindowFlags()) == 0
815 ? B_OK
: B_BAD_VALUE
;
818 if (status
== B_OK
&& !fWindow
->IsOffscreenWindow())
819 fDesktop
->SetWindowFlags(fWindow
, flags
);
821 fLink
.StartMessage(status
);
826 case AS_SET_ALIGNMENT
:
828 // TODO: Implement AS_SET_ALIGNMENT
829 DTRACE(("ServerWindow %s: Message Set_Alignment unimplemented\n",
833 case AS_GET_ALIGNMENT
:
835 // TODO: Implement AS_GET_ALIGNMENT
836 DTRACE(("ServerWindow %s: Message Get_Alignment unimplemented\n",
841 case AS_IS_FRONT_WINDOW
:
843 bool isFront
= fDesktop
->FrontWindow() == fWindow
;
844 DTRACE(("ServerWindow %s: Message AS_IS_FRONT_WINDOW: %d\n",
846 fLink
.StartMessage(isFront
? B_OK
: B_ERROR
);
851 case AS_GET_WORKSPACES
:
853 DTRACE(("ServerWindow %s: Message AS_GET_WORKSPACES\n", Title()));
854 fLink
.StartMessage(B_OK
);
855 fLink
.Attach
<uint32
>(fWindow
->Workspaces());
859 case AS_SET_WORKSPACES
:
861 // Has the all-window lock (but would actually not need to lock at
863 uint32 newWorkspaces
;
864 if (link
.Read
<uint32
>(&newWorkspaces
) != B_OK
)
867 DTRACE(("ServerWindow %s: Message AS_SET_WORKSPACES %" B_PRIx32
"\n",
868 Title(), newWorkspaces
));
870 fDesktop
->SetWindowWorkspaces(fWindow
, newWorkspaces
);
873 case AS_WINDOW_RESIZE
:
875 // Has the all-window look
878 link
.Read
<float>(&xResizeTo
);
879 if (link
.Read
<float>(&yResizeTo
) != B_OK
)
882 DTRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n",
883 Title(), xResizeTo
, yResizeTo
));
885 // comment this code for the time being, as some apps rely
886 // on the programmatically resize behavior during user resize
887 // if (fWindow->IsResizing()) {
888 // While the user resizes the window, we ignore
889 // pragmatically set window bounds
890 // fLink.StartMessage(B_BUSY);
892 fDesktop
->ResizeWindowBy(fWindow
,
893 xResizeTo
- fWindow
->Frame().Width(),
894 yResizeTo
- fWindow
->Frame().Height());
895 fLink
.StartMessage(B_OK
);
902 // Has the all-window look
905 link
.Read
<float>(&xMoveTo
);
906 if (link
.Read
<float>(&yMoveTo
) != B_OK
)
909 DTRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n",
910 Title(), xMoveTo
, yMoveTo
));
912 if (fWindow
->IsDragging()) {
913 // While the user moves the window, we ignore
914 // pragmatically set window positions
915 fLink
.StartMessage(B_BUSY
);
917 fDesktop
->MoveWindowBy(fWindow
, xMoveTo
- fWindow
->Frame().left
,
918 yMoveTo
- fWindow
->Frame().top
);
919 fLink
.StartMessage(B_OK
);
924 case AS_SET_SIZE_LIMITS
:
926 // Has the all-window look
929 // 1) float minimum width
930 // 2) float maximum width
931 // 3) float minimum height
932 // 4) float maximum height
934 // TODO: for now, move the client to int32 as well!
935 int32 minWidth
, maxWidth
, minHeight
, maxHeight
;
937 link
.Read
<float>(&value
); minWidth
= (int32
)value
;
938 link
.Read
<float>(&value
); maxWidth
= (int32
)value
;
939 link
.Read
<float>(&value
); minHeight
= (int32
)value
;
940 link
.Read
<float>(&value
); maxHeight
= (int32
)value
;
942 link.Read<int32>(&minWidth);
943 link.Read<int32>(&maxWidth);
944 link.Read<int32>(&minHeight);
945 link.Read<int32>(&maxHeight);
947 DTRACE(("ServerWindow %s: Message AS_SET_SIZE_LIMITS: "
948 "x: %" B_PRId32
"-%" B_PRId32
", y: %" B_PRId32
"-%" B_PRId32
949 "\n", Title(), minWidth
, maxWidth
, minHeight
, maxHeight
));
951 fWindow
->SetSizeLimits(minWidth
, maxWidth
, minHeight
, maxHeight
);
953 // and now, sync the client to the limits that we were able to enforce
954 fWindow
->GetSizeLimits(&minWidth
, &maxWidth
,
955 &minHeight
, &maxHeight
);
957 fLink
.StartMessage(B_OK
);
958 fLink
.Attach
<BRect
>(fWindow
->Frame());
959 fLink
.Attach
<float>((float)minWidth
);
960 fLink
.Attach
<float>((float)maxWidth
);
961 fLink
.Attach
<float>((float)minHeight
);
962 fLink
.Attach
<float>((float)maxHeight
);
966 fDesktop
->NotifySizeLimitsChanged(fWindow
, minWidth
, maxWidth
,
967 minHeight
, maxHeight
);
971 case AS_SET_DECORATOR_SETTINGS
:
973 // Has the all-window look
974 DTRACE(("ServerWindow %s: Message AS_SET_DECORATOR_SETTINGS\n",
978 if (fWindow
&& link
.Read
<int32
>(&size
) == B_OK
) {
980 if (link
.Read(buffer
, size
) == B_OK
) {
982 if (settings
.Unflatten(buffer
) == B_OK
)
983 fDesktop
->SetWindowDecoratorSettings(fWindow
, settings
);
989 case AS_GET_DECORATOR_SETTINGS
:
991 DTRACE(("ServerWindow %s: Message AS_GET_DECORATOR_SETTINGS\n",
994 bool success
= false;
997 if (fWindow
->GetDecoratorSettings(&settings
)) {
998 int32 size
= settings
.FlattenedSize();
1000 if (settings
.Flatten(buffer
, size
) == B_OK
) {
1002 fLink
.StartMessage(B_OK
);
1003 fLink
.Attach
<int32
>(size
);
1004 fLink
.Attach(buffer
, size
);
1009 fLink
.StartMessage(B_ERROR
);
1015 case AS_SYSTEM_FONT_CHANGED
:
1017 // Has the all-window look
1018 fDesktop
->FontsChanged(fWindow
);
1022 // Forward to client
1023 case B_FONTS_UPDATED
:
1025 // TODO: would knowing which font was changed be useful?
1026 BMessage
message(code
);
1027 SendMessageToClient(&message
);
1032 // Nothing to do here - the redraws are actually handled by looking
1033 // at the fRedrawRequested member variable in _MessageLooper().
1037 DTRACE(("ServerWindow %s: Message AS_SYNC\n", Title()));
1038 // the synchronisation works by the fact that the client
1039 // window is waiting for this reply, after having received it,
1040 // client and server queues are in sync (earlier, the client
1041 // may have pushed drawing commands at the server and now it
1042 // knows they have all been carried out)
1043 fLink
.StartMessage(B_OK
);
1047 case AS_BEGIN_UPDATE
:
1048 DTRACE(("ServerWindow %s: Message AS_BEGIN_UPDATE\n", Title()));
1049 fWindow
->BeginUpdate(fLink
);
1053 DTRACE(("ServerWindow %s: Message AS_END_UPDATE\n", Title()));
1054 fWindow
->EndUpdate();
1059 // Has the all-window look
1060 DTRACE(("ServerWindow %s: Message AS_GET_MOUSE\n", fTitle
));
1063 // 1) BPoint mouse location
1064 // 2) int32 button state
1068 fDesktop
->GetLastMouseState(&where
, &buttons
);
1070 fLink
.StartMessage(B_OK
);
1071 fLink
.Attach
<BPoint
>(where
);
1072 fLink
.Attach
<int32
>(buttons
);
1077 // BDirectWindow communication
1079 case AS_DIRECT_WINDOW_GET_SYNC_DATA
:
1081 status_t status
= _EnableDirectWindowMode();
1083 fLink
.StartMessage(status
);
1084 if (status
== B_OK
) {
1085 struct direct_window_sync_data syncData
;
1086 fDirectWindowInfo
->GetSyncData(syncData
);
1088 fLink
.Attach(&syncData
, sizeof(syncData
));
1094 case AS_DIRECT_WINDOW_SET_FULLSCREEN
:
1096 // Has the all-window look
1098 link
.Read
<bool>(&enable
);
1100 status_t status
= B_OK
;
1101 if (fDirectWindowInfo
!= NULL
)
1102 _DirectWindowSetFullScreen(enable
);
1104 status
= B_BAD_TYPE
;
1106 fLink
.StartMessage(status
);
1111 // View creation and destruction (don't need a valid fCurrentView)
1113 case AS_SET_CURRENT_VIEW
:
1116 if (link
.Read
<int32
>(&token
) != B_OK
)
1120 if (App()->ViewTokens().GetToken(token
, B_HANDLER_TOKEN
,
1121 (void**)¤t
) != B_OK
1122 || current
->Window()->ServerWindow() != this) {
1123 // TODO: if this happens, we probably want to kill the app and
1125 debug_printf("ServerWindow %s: Message "
1126 "\n\n\nAS_SET_CURRENT_VIEW: view not found, token %"
1127 B_PRId32
"\n", fTitle
, token
);
1130 DTRACE(("\n\n\nServerWindow %s: Message AS_SET_CURRENT_VIEW: %s, "
1131 "token %" B_PRId32
"\n", fTitle
, current
->Name(), token
));
1132 _SetCurrentView(current
);
1137 case AS_VIEW_CREATE_ROOT
:
1139 DTRACE(("ServerWindow %s: Message AS_VIEW_CREATE_ROOT\n", fTitle
));
1141 // Start receiving top_view data -- pass NULL as the parent view.
1142 // This should be the *only* place where this happens.
1143 if (fCurrentView
!= NULL
) {
1144 debug_printf("ServerWindow %s: Message "
1145 "AS_VIEW_CREATE_ROOT: fCurrentView already set!!\n",
1150 _SetCurrentView(_CreateView(link
, NULL
));
1151 fWindow
->SetTopView(fCurrentView
);
1155 case AS_VIEW_CREATE
:
1157 DTRACE(("ServerWindow %s: Message AS_VIEW_CREATE: View name: "
1158 "%s\n", fTitle
, fCurrentView
->Name()));
1160 View
* parent
= NULL
;
1161 View
* newView
= _CreateView(link
, &parent
);
1162 if (parent
!= NULL
&& newView
!= NULL
)
1163 parent
->AddChild(newView
);
1166 debug_printf("ServerWindow %s: Message AS_VIEW_CREATE: "
1167 "parent or newView NULL!!\n", fTitle
);
1172 case AS_TALK_TO_DESKTOP_LISTENER
:
1174 if (fDesktop
->MessageForListener(fWindow
, fLink
.Receiver(),
1177 // unhandled message at least send an error if needed
1178 if (link
.NeedsReply()) {
1179 fLink
.StartMessage(B_ERROR
);
1186 if (fCurrentView
== NULL
) {
1188 string_for_message_code(code
, codeName
);
1189 debug_printf("ServerWindow %s received unexpected code - "
1190 "message '%s' before top_view attached.\n",
1191 Title(), codeName
.String());
1192 if (link
.NeedsReply()) {
1193 fLink
.StartMessage(B_ERROR
);
1199 _DispatchViewMessage(code
, link
);
1206 Dispatches all view messages that need a valid fCurrentView.
1209 ServerWindow::_DispatchViewMessage(int32 code
,
1210 BPrivate::LinkReceiver
&link
)
1212 if (_DispatchPictureMessage(code
, link
))
1216 case AS_VIEW_SCROLL
:
1220 link
.Read
<float>(&dh
);
1221 if (link
.Read
<float>(&dv
) != B_OK
)
1224 DTRACE(("ServerWindow %s: Message AS_VIEW_SCROLL: View name: "
1225 "%s, %.1f x %.1f\n", fTitle
, fCurrentView
->Name(), dh
, dv
));
1226 fWindow
->ScrollViewBy(fCurrentView
, dh
, dv
);
1229 case AS_VIEW_COPY_BITS
:
1234 link
.Read
<BRect
>(&src
);
1235 if (link
.Read
<BRect
>(&dst
) != B_OK
)
1238 DTRACE(("ServerWindow %s: Message AS_VIEW_COPY_BITS: View name: "
1239 "%s, BRect(%.1f, %.1f, %.1f, %.1f) -> "
1240 "BRect(%.1f, %.1f, %.1f, %.1f)\n", fTitle
,
1241 fCurrentView
->Name(), src
.left
, src
.top
, src
.right
, src
.bottom
,
1242 dst
.left
, dst
.top
, dst
.right
, dst
.bottom
));
1244 BRegion contentRegion
;
1245 // TODO: avoid copy operation maybe?
1246 fWindow
->GetContentRegion(&contentRegion
);
1247 fCurrentView
->CopyBits(src
, dst
, contentRegion
);
1250 case AS_VIEW_DELETE
:
1252 // Received when a view is detached from a window
1255 if (link
.Read
<int32
>(&token
) != B_OK
)
1259 if (App()->ViewTokens().GetToken(token
, B_HANDLER_TOKEN
,
1260 (void**)&view
) == B_OK
1261 && view
->Window()->ServerWindow() == this) {
1262 View
* parent
= view
->Parent();
1264 DTRACE(("ServerWindow %s: AS_VIEW_DELETE view: %p, "
1265 "parent: %p\n", fTitle
, view
, parent
));
1267 if (parent
!= NULL
) {
1268 parent
->RemoveChild(view
);
1270 if (view
->EventMask() != 0) {
1271 // TODO: possible deadlock (event dispatcher already
1272 // locked itself, waits for Desktop write lock, but
1273 // we have it, now we are trying to lock the event
1274 // dispatcher -> deadlock)
1275 fDesktop
->UnlockSingleWindow();
1276 fDesktop
->EventDispatcher().RemoveListener(
1277 EventTarget(), token
);
1278 fDesktop
->LockSingleWindow();
1281 if (fCurrentView
== view
|| fCurrentView
->HasParent(view
))
1282 _SetCurrentView(parent
);
1285 } // else we don't delete the root view
1289 case AS_VIEW_SET_STATE
:
1291 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_STATE: "
1292 "View name: %s\n", fTitle
, fCurrentView
->Name()));
1294 fCurrentView
->CurrentState()->ReadFromLink(link
);
1295 // TODO: When is this used?!?
1296 fCurrentView
->RebuildClipping(true);
1297 _UpdateDrawState(fCurrentView
);
1301 case AS_VIEW_SET_FONT_STATE
:
1303 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FONT_STATE: "
1304 "View name: %s\n", fTitle
, fCurrentView
->Name()));
1306 fCurrentView
->CurrentState()->ReadFontFromLink(link
);
1307 fWindow
->GetDrawingEngine()->SetFont(
1308 fCurrentView
->CurrentState());
1311 case AS_VIEW_GET_STATE
:
1313 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_STATE: "
1314 "View name: %s\n", fTitle
, fCurrentView
->Name()));
1316 fLink
.StartMessage(B_OK
);
1318 // attach state data
1319 fCurrentView
->CurrentState()->WriteToLink(fLink
.Sender());
1323 case AS_VIEW_SET_EVENT_MASK
:
1325 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_EVENT_MASK: "
1326 "View name: %s\n", fTitle
, fCurrentView
->Name()));
1327 uint32 eventMask
, options
;
1329 link
.Read
<uint32
>(&eventMask
);
1330 if (link
.Read
<uint32
>(&options
) == B_OK
) {
1331 fCurrentView
->SetEventMask(eventMask
, options
);
1333 fDesktop
->UnlockSingleWindow();
1334 // TODO: possible deadlock!
1335 if (eventMask
!= 0 || options
!= 0) {
1336 fDesktop
->EventDispatcher().AddListener(EventTarget(),
1337 fCurrentView
->Token(), eventMask
, options
);
1339 fDesktop
->EventDispatcher().RemoveListener(EventTarget(),
1340 fCurrentView
->Token());
1342 fDesktop
->LockSingleWindow();
1346 case AS_VIEW_SET_MOUSE_EVENT_MASK
:
1348 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_MOUSE_EVENT_MASK: "
1349 "View name: %s\n", fTitle
, fCurrentView
->Name()));
1350 uint32 eventMask
, options
;
1352 link
.Read
<uint32
>(&eventMask
);
1353 if (link
.Read
<uint32
>(&options
) == B_OK
) {
1354 fDesktop
->UnlockSingleWindow();
1355 // TODO: possible deadlock
1356 if (eventMask
!= 0 || options
!= 0) {
1357 if (options
& B_LOCK_WINDOW_FOCUS
)
1358 fDesktop
->SetFocusLocked(fWindow
);
1359 fDesktop
->EventDispatcher().AddTemporaryListener(EventTarget(),
1360 fCurrentView
->Token(), eventMask
, options
);
1362 fDesktop
->EventDispatcher().RemoveTemporaryListener(EventTarget(),
1363 fCurrentView
->Token());
1365 fDesktop
->LockSingleWindow();
1368 // TODO: support B_LOCK_WINDOW_FOCUS option in Desktop
1371 case AS_VIEW_MOVE_TO
:
1374 link
.Read
<float>(&x
);
1375 if (link
.Read
<float>(&y
) != B_OK
)
1378 DTRACE(("ServerWindow %s: Message AS_VIEW_MOVE_TO: View name: "
1379 "%s, x: %.1f, y: %.1f\n", fTitle
, fCurrentView
->Name(), x
, y
));
1381 float offsetX
= x
- fCurrentView
->Frame().left
;
1382 float offsetY
= y
- fCurrentView
->Frame().top
;
1385 fCurrentView
->MoveBy(offsetX
, offsetY
, &dirty
);
1387 // TODO: think about how to avoid this hack:
1388 // the parent clipping needs to be updated, it is not
1389 // done in MoveBy() since it would cause
1390 // too much computations when children are resized because
1392 if (View
* parent
= fCurrentView
->Parent())
1393 parent
->RebuildClipping(false);
1395 fWindow
->MarkContentDirty(dirty
);
1398 case AS_VIEW_RESIZE_TO
:
1400 float newWidth
, newHeight
;
1401 link
.Read
<float>(&newWidth
);
1402 if (link
.Read
<float>(&newHeight
) != B_OK
)
1405 DTRACE(("ServerWindow %s: Message AS_VIEW_RESIZE_TO: View name: "
1406 "%s, width: %.1f, height: %.1f\n", fTitle
,
1407 fCurrentView
->Name(), newWidth
, newHeight
));
1409 float deltaWidth
= newWidth
- fCurrentView
->Frame().Width();
1410 float deltaHeight
= newHeight
- fCurrentView
->Frame().Height();
1413 fCurrentView
->ResizeBy(deltaWidth
, deltaHeight
, &dirty
);
1416 if (View
* parent
= fCurrentView
->Parent())
1417 parent
->RebuildClipping(false);
1419 fWindow
->MarkContentDirty(dirty
);
1422 case AS_VIEW_GET_COORD
:
1424 // our offset in the parent -> will be originX and originY
1426 BPoint parentOffset
= fCurrentView
->Frame().LeftTop();
1428 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_COORD: "
1429 "View: %s -> x: %.1f, y: %.1f\n", Title(),
1430 fCurrentView
->Name(), parentOffset
.x
, parentOffset
.y
));
1432 fLink
.StartMessage(B_OK
);
1433 fLink
.Attach
<BPoint
>(parentOffset
);
1434 fLink
.Attach
<BRect
>(fCurrentView
->Bounds());
1438 case AS_VIEW_SET_ORIGIN
:
1441 link
.Read
<float>(&x
);
1442 if (link
.Read
<float>(&y
) != B_OK
)
1445 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_ORIGIN: "
1446 "View: %s -> x: %.1f, y: %.1f\n", Title(),
1447 fCurrentView
->Name(), x
, y
));
1449 fCurrentView
->SetDrawingOrigin(BPoint(x
, y
));
1450 _UpdateDrawState(fCurrentView
);
1453 case AS_VIEW_GET_ORIGIN
:
1455 BPoint drawingOrigin
= fCurrentView
->DrawingOrigin();
1457 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_ORIGIN: "
1458 "View: %s -> x: %.1f, y: %.1f\n", Title(),
1459 fCurrentView
->Name(), drawingOrigin
.x
, drawingOrigin
.y
));
1461 fLink
.StartMessage(B_OK
);
1462 fLink
.Attach
<BPoint
>(drawingOrigin
);
1466 case AS_VIEW_RESIZE_MODE
:
1469 if (link
.Read
<uint32
>(&resizeMode
) != B_OK
)
1472 DTRACE(("ServerWindow %s: Message AS_VIEW_RESIZE_MODE: "
1473 "View: %s -> %" B_PRId32
"\n", Title(), fCurrentView
->Name(),
1476 fCurrentView
->SetResizeMode(resizeMode
);
1479 case AS_VIEW_SET_FLAGS
:
1482 link
.Read
<uint32
>(&flags
);
1484 // The views clipping changes when the B_DRAW_ON_CHILDREN flag is
1486 bool updateClipping
= (flags
& B_DRAW_ON_CHILDREN
)
1487 ^ (fCurrentView
->Flags() & B_DRAW_ON_CHILDREN
);
1489 fCurrentView
->SetFlags(flags
);
1490 _UpdateDrawState(fCurrentView
);
1492 if (updateClipping
) {
1493 fCurrentView
->RebuildClipping(false);
1494 fCurrentDrawingRegionValid
= false;
1497 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FLAGS: "
1498 "View: %s -> flags: %" B_PRIu32
"\n", Title(),
1499 fCurrentView
->Name(), flags
));
1503 DTRACE(("ServerWindow %s: Message AS_VIEW_HIDE: View: %s\n",
1504 Title(), fCurrentView
->Name()));
1505 fCurrentView
->SetHidden(true);
1509 DTRACE(("ServerWindow %s: Message AS_VIEW_SHOW: View: %s\n",
1510 Title(), fCurrentView
->Name()));
1511 fCurrentView
->SetHidden(false);
1514 case AS_VIEW_SET_LINE_MODE
:
1516 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_LINE_MODE: "
1517 "View: %s\n", Title(), fCurrentView
->Name()));
1518 ViewSetLineModeInfo info
;
1519 if (link
.Read
<ViewSetLineModeInfo
>(&info
) != B_OK
)
1522 fCurrentView
->CurrentState()->SetLineCapMode(info
.lineCap
);
1523 fCurrentView
->CurrentState()->SetLineJoinMode(info
.lineJoin
);
1524 fCurrentView
->CurrentState()->SetMiterLimit(info
.miterLimit
);
1526 fWindow
->GetDrawingEngine()->SetStrokeMode(info
.lineCap
,
1527 info
.lineJoin
, info
.miterLimit
);
1531 case AS_VIEW_GET_LINE_MODE
:
1533 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LINE_MODE: "
1534 "View: %s\n", Title(), fCurrentView
->Name()));
1535 ViewSetLineModeInfo info
;
1536 info
.lineJoin
= fCurrentView
->CurrentState()->LineJoinMode();
1537 info
.lineCap
= fCurrentView
->CurrentState()->LineCapMode();
1538 info
.miterLimit
= fCurrentView
->CurrentState()->MiterLimit();
1540 fLink
.StartMessage(B_OK
);
1541 fLink
.Attach
<ViewSetLineModeInfo
>(info
);
1546 case AS_VIEW_SET_FILL_RULE
:
1548 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FILL_RULE: "
1549 "View: %s\n", Title(), fCurrentView
->Name()));
1551 if (link
.Read
<int32
>(&fillRule
) != B_OK
)
1554 fCurrentView
->CurrentState()->SetFillRule(fillRule
);
1555 fWindow
->GetDrawingEngine()->SetFillRule(fillRule
);
1559 case AS_VIEW_GET_FILL_RULE
:
1561 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_FILL_RULE: "
1562 "View: %s\n", Title(), fCurrentView
->Name()));
1563 int32 fillRule
= fCurrentView
->CurrentState()->FillRule();
1565 fLink
.StartMessage(B_OK
);
1566 fLink
.Attach
<int32
>(fillRule
);
1571 case AS_VIEW_PUSH_STATE
:
1573 DTRACE(("ServerWindow %s: Message AS_VIEW_PUSH_STATE: View: "
1574 "%s\n", Title(), fCurrentView
->Name()));
1576 fCurrentView
->PushState();
1577 // TODO: is this necessary?
1578 // _UpdateDrawState(fCurrentView);
1581 case AS_VIEW_POP_STATE
:
1583 DTRACE(("ServerWindow %s: Message AS_VIEW_POP_STATE: View: %s\n",
1584 Title(), fCurrentView
->Name()));
1586 fCurrentView
->PopState();
1587 _UpdateDrawState(fCurrentView
);
1590 case AS_VIEW_SET_SCALE
:
1593 if (link
.Read
<float>(&scale
) != B_OK
)
1596 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_SCALE: "
1597 "View: %s -> scale: %.2f\n", Title(), fCurrentView
->Name(),
1600 fCurrentView
->SetScale(scale
);
1601 _UpdateDrawState(fCurrentView
);
1604 case AS_VIEW_GET_SCALE
:
1606 float scale
= fCurrentView
->CurrentState()->Scale();
1608 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_SCALE: "
1609 "View: %s -> scale: %.2f\n",
1610 Title(), fCurrentView
->Name(), scale
));
1612 fLink
.StartMessage(B_OK
);
1613 fLink
.Attach
<float>(scale
);
1617 case AS_VIEW_SET_TRANSFORM
:
1619 BAffineTransform transform
;
1620 if (link
.Read
<BAffineTransform
>(&transform
) != B_OK
)
1623 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_TRANSFORM: "
1624 "View: %s -> transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
1625 Title(), fCurrentView
->Name(), transform
.sx
, transform
.shy
,
1626 transform
.shx
, transform
.sy
, transform
.tx
, transform
.ty
));
1628 fCurrentView
->CurrentState()->SetTransform(transform
);
1629 _UpdateDrawState(fCurrentView
);
1632 case AS_VIEW_GET_TRANSFORM
:
1634 BAffineTransform transform
1635 = fCurrentView
->CurrentState()->Transform();
1637 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_TRANSFORM: "
1638 "View: %s -> transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
1639 Title(), fCurrentView
->Name(), transform
.sx
, transform
.shy
,
1640 transform
.shx
, transform
.sy
, transform
.tx
, transform
.ty
));
1642 fLink
.StartMessage(B_OK
);
1643 fLink
.Attach
<BAffineTransform
>(transform
);
1647 case AS_VIEW_AFFINE_TRANSLATE
:
1650 link
.Read
<double>(&x
);
1651 link
.Read
<double>(&y
);
1652 BAffineTransform current
=
1653 fCurrentView
->CurrentState()->Transform();
1654 current
.PreTranslateBy(x
, y
);
1655 fCurrentView
->CurrentState()->SetTransform(current
);
1656 _UpdateDrawState(fCurrentView
);
1660 case AS_VIEW_AFFINE_SCALE
:
1663 link
.Read
<double>(&x
);
1664 link
.Read
<double>(&y
);
1665 BAffineTransform current
=
1666 fCurrentView
->CurrentState()->Transform();
1667 current
.PreScaleBy(x
, y
);
1668 fCurrentView
->CurrentState()->SetTransform(current
);
1669 _UpdateDrawState(fCurrentView
);
1673 case AS_VIEW_AFFINE_ROTATE
:
1675 double angleRadians
;
1676 link
.Read
<double>(&angleRadians
);
1677 BAffineTransform current
=
1678 fCurrentView
->CurrentState()->Transform();
1679 current
.PreRotateBy(angleRadians
);
1680 fCurrentView
->CurrentState()->SetTransform(current
);
1681 _UpdateDrawState(fCurrentView
);
1685 case AS_VIEW_SET_PEN_LOC
:
1688 if (link
.Read
<BPoint
>(&location
) != B_OK
)
1691 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PEN_LOC: "
1692 "View: %s -> BPoint(%.1f, %.1f)\n", Title(),
1693 fCurrentView
->Name(), location
.x
, location
.y
));
1695 fCurrentView
->CurrentState()->SetPenLocation(location
);
1698 case AS_VIEW_GET_PEN_LOC
:
1700 BPoint location
= fCurrentView
->CurrentState()->PenLocation();
1702 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_PEN_LOC: "
1703 "View: %s -> BPoint(%.1f, %.1f)\n", Title(),
1704 fCurrentView
->Name(), location
.x
, location
.y
));
1706 fLink
.StartMessage(B_OK
);
1707 fLink
.Attach
<BPoint
>(location
);
1712 case AS_VIEW_SET_PEN_SIZE
:
1715 if (link
.Read
<float>(&penSize
) != B_OK
)
1718 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PEN_SIZE: "
1719 "View: %s -> %.1f\n", Title(), fCurrentView
->Name(), penSize
));
1721 fCurrentView
->CurrentState()->SetPenSize(penSize
);
1722 fWindow
->GetDrawingEngine()->SetPenSize(
1723 fCurrentView
->CurrentState()->PenSize());
1726 case AS_VIEW_GET_PEN_SIZE
:
1728 float penSize
= fCurrentView
->CurrentState()->UnscaledPenSize();
1730 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_PEN_SIZE: "
1731 "View: %s -> %.1f\n", Title(), fCurrentView
->Name(), penSize
));
1733 fLink
.StartMessage(B_OK
);
1734 fLink
.Attach
<float>(penSize
);
1739 case AS_VIEW_SET_VIEW_COLOR
:
1742 if (link
.Read(&color
, sizeof(rgb_color
)) != B_OK
)
1745 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_VIEW_COLOR: "
1746 "View: %s -> rgb_color(%d, %d, %d, %d)\n", Title(),
1747 fCurrentView
->Name(), color
.red
, color
.green
, color
.blue
,
1750 fCurrentView
->SetViewColor(color
);
1753 case AS_VIEW_GET_VIEW_COLOR
:
1755 rgb_color color
= fCurrentView
->ViewColor();
1757 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_VIEW_COLOR: "
1758 "View: %s -> rgb_color(%d, %d, %d, %d)\n",
1759 Title(), fCurrentView
->Name(), color
.red
, color
.green
,
1760 color
.blue
, color
.alpha
));
1762 fLink
.StartMessage(B_OK
);
1763 fLink
.Attach
<rgb_color
>(color
);
1767 case AS_VIEW_SET_HIGH_COLOR
:
1770 if (link
.Read(&color
, sizeof(rgb_color
)) != B_OK
)
1773 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_HIGH_COLOR: "
1774 "View: %s -> rgb_color(%d, %d, %d, %d)\n",
1775 Title(), fCurrentView
->Name(), color
.red
, color
.green
,
1776 color
.blue
, color
.alpha
));
1778 fCurrentView
->CurrentState()->SetHighColor(color
);
1779 fWindow
->GetDrawingEngine()->SetHighColor(color
);
1783 case AS_VIEW_SET_HIGH_UI_COLOR
:
1785 color_which which
= B_NO_COLOR
;
1786 float tint
= B_NO_TINT
;
1788 if (link
.Read
<color_which
>(&which
) != B_OK
1789 || link
.Read
<float>(&tint
) != B_OK
)
1792 fCurrentView
->CurrentState()->SetHighUIColor(which
, tint
);
1794 // TODO: should we do more color_which validity checking?
1795 if (which
!= B_NO_COLOR
) {
1796 DesktopSettings
settings(fDesktop
);
1797 rgb_color color
= tint_color(settings
.UIColor(which
), tint
);
1799 fCurrentView
->CurrentState()->SetHighColor(color
);
1800 fWindow
->GetDrawingEngine()->SetHighColor(color
);
1804 case AS_VIEW_SET_LOW_UI_COLOR
:
1806 color_which which
= B_NO_COLOR
;
1807 float tint
= B_NO_TINT
;
1809 if (link
.Read
<color_which
>(&which
) != B_OK
1810 || link
.Read
<float>(&tint
) != B_OK
)
1813 fCurrentView
->CurrentState()->SetLowUIColor(which
, tint
);
1815 // TODO: should we do more color_which validity checking?
1816 if (which
!= B_NO_COLOR
) {
1817 DesktopSettings
settings(fDesktop
);
1818 rgb_color color
= tint_color(settings
.UIColor(which
), tint
);
1820 fCurrentView
->CurrentState()->SetLowColor(color
);
1821 fWindow
->GetDrawingEngine()->SetLowColor(color
);
1825 case AS_VIEW_SET_VIEW_UI_COLOR
:
1827 color_which which
= B_NO_COLOR
;
1828 float tint
= B_NO_TINT
;
1830 if (link
.Read
<color_which
>(&which
) != B_OK
1831 || link
.Read
<float>(&tint
) != B_OK
)
1834 // TODO: should we do more color_which validity checking?
1835 fCurrentView
->SetViewUIColor(which
, tint
);
1838 case AS_VIEW_GET_HIGH_UI_COLOR
:
1841 color_which which
= fCurrentView
->CurrentState()->HighUIColor(&tint
);
1842 rgb_color color
= fCurrentView
->CurrentState()->HighColor();
1844 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_HIGH_UI_COLOR: "
1845 "View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1846 " %i, %i)\n", Title(), fCurrentView
->Name(), which
, tint
,
1847 color
.red
, color
.green
, color
.blue
, color
.alpha
));
1849 fLink
.StartMessage(B_OK
);
1850 fLink
.Attach
<color_which
>(which
);
1851 fLink
.Attach
<float>(tint
);
1852 fLink
.Attach
<rgb_color
>(color
);
1856 case AS_VIEW_GET_LOW_UI_COLOR
:
1859 color_which which
= fCurrentView
->CurrentState()->LowUIColor(&tint
);
1860 rgb_color color
= fCurrentView
->CurrentState()->LowColor();
1862 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LOW_UI_COLOR: "
1863 "View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1864 " %i, %i)\n", Title(), fCurrentView
->Name(), which
, tint
,
1865 color
.red
, color
.green
, color
.blue
, color
.alpha
));
1867 fLink
.StartMessage(B_OK
);
1868 fLink
.Attach
<color_which
>(which
);
1869 fLink
.Attach
<float>(tint
);
1870 fLink
.Attach
<rgb_color
>(color
);
1874 case AS_VIEW_GET_VIEW_UI_COLOR
:
1877 color_which which
= fCurrentView
->ViewUIColor(&tint
);
1878 rgb_color color
= fCurrentView
->ViewColor();
1880 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_VIEW_UI_COLOR: "
1881 "View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1882 " %i, %i)\n", Title(), fCurrentView
->Name(), which
, tint
,
1883 color
.red
, color
.green
, color
.blue
, color
.alpha
));
1885 fLink
.StartMessage(B_OK
);
1886 fLink
.Attach
<color_which
>(which
);
1887 fLink
.Attach
<float>(tint
);
1888 fLink
.Attach
<rgb_color
>(color
);
1892 case AS_VIEW_GET_HIGH_COLOR
:
1894 rgb_color color
= fCurrentView
->CurrentState()->HighColor();
1896 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_HIGH_COLOR: "
1897 "View: %s -> rgb_color(%d, %d, %d, %d)\n",
1898 Title(), fCurrentView
->Name(), color
.red
, color
.green
,
1899 color
.blue
, color
.alpha
));
1901 fLink
.StartMessage(B_OK
);
1902 fLink
.Attach
<rgb_color
>(color
);
1906 case AS_VIEW_SET_LOW_COLOR
:
1909 if (link
.Read(&color
, sizeof(rgb_color
)) != B_OK
)
1912 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_LOW_COLOR: "
1913 "View: %s -> rgb_color(%d, %d, %d, %d)\n",
1914 Title(), fCurrentView
->Name(), color
.red
, color
.green
,
1915 color
.blue
, color
.alpha
));
1917 fCurrentView
->CurrentState()->SetLowColor(color
);
1918 fWindow
->GetDrawingEngine()->SetLowColor(color
);
1921 case AS_VIEW_GET_LOW_COLOR
:
1923 rgb_color color
= fCurrentView
->CurrentState()->LowColor();
1925 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LOW_COLOR: "
1926 "View: %s -> rgb_color(%d, %d, %d, %d)\n",
1927 Title(), fCurrentView
->Name(), color
.red
, color
.green
,
1928 color
.blue
, color
.alpha
));
1930 fLink
.StartMessage(B_OK
);
1931 fLink
.Attach
<rgb_color
>(color
);
1935 case AS_VIEW_SET_PATTERN
:
1937 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PATTERN: "
1938 "View: %s\n", fTitle
, fCurrentView
->Name()));
1941 if (link
.Read(&pat
, sizeof(pattern
)) != B_OK
)
1944 fCurrentView
->CurrentState()->SetPattern(Pattern(pat
));
1945 fWindow
->GetDrawingEngine()->SetPattern(pat
);
1949 case AS_VIEW_SET_BLENDING_MODE
:
1951 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_BLEND_MODE: "
1952 "View: %s\n", Title(), fCurrentView
->Name()));
1954 ViewBlendingModeInfo info
;
1955 if (link
.Read
<ViewBlendingModeInfo
>(&info
) != B_OK
)
1958 fCurrentView
->CurrentState()->SetBlendingMode(
1959 info
.sourceAlpha
, info
.alphaFunction
);
1960 fWindow
->GetDrawingEngine()->SetBlendingMode(
1961 info
.sourceAlpha
, info
.alphaFunction
);
1964 case AS_VIEW_GET_BLENDING_MODE
:
1966 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_BLEND_MODE: "
1967 "View: %s\n", Title(), fCurrentView
->Name()));
1969 ViewBlendingModeInfo info
;
1970 info
.sourceAlpha
= fCurrentView
->CurrentState()->AlphaSrcMode();
1971 info
.alphaFunction
= fCurrentView
->CurrentState()->AlphaFncMode();
1973 fLink
.StartMessage(B_OK
);
1974 fLink
.Attach
<ViewBlendingModeInfo
>(info
);
1979 case AS_VIEW_SET_DRAWING_MODE
:
1982 if (link
.Read
<int8
>(&drawingMode
) != B_OK
)
1985 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_DRAW_MODE: "
1986 "View: %s -> %s\n", Title(), fCurrentView
->Name(),
1987 kDrawingModeMap
[drawingMode
]));
1989 fCurrentView
->CurrentState()->SetDrawingMode(
1990 (drawing_mode
)drawingMode
);
1991 fWindow
->GetDrawingEngine()->SetDrawingMode(
1992 (drawing_mode
)drawingMode
);
1995 case AS_VIEW_GET_DRAWING_MODE
:
1998 = (int8
)(fCurrentView
->CurrentState()->GetDrawingMode());
2000 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_DRAW_MODE: "
2001 "View: %s -> %s\n", Title(), fCurrentView
->Name(),
2002 kDrawingModeMap
[drawingMode
]));
2004 fLink
.StartMessage(B_OK
);
2005 fLink
.Attach
<int8
>(drawingMode
);
2010 case AS_VIEW_SET_VIEW_BITMAP
:
2012 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_VIEW_BITMAP: "
2013 "View: %s\n", Title(), fCurrentView
->Name()));
2015 int32 bitmapToken
, resizingMode
, options
;
2016 BRect srcRect
, dstRect
;
2018 link
.Read
<int32
>(&bitmapToken
);
2019 link
.Read
<BRect
>(&srcRect
);
2020 link
.Read
<BRect
>(&dstRect
);
2021 link
.Read
<int32
>(&resizingMode
);
2022 status_t status
= link
.Read
<int32
>(&options
);
2024 rgb_color colorKey
= {0};
2026 if (status
== B_OK
) {
2027 ServerBitmap
* bitmap
= fServerApp
->GetBitmap(bitmapToken
);
2028 if (bitmapToken
== -1 || bitmap
!= NULL
) {
2029 bool wasOverlay
= fCurrentView
->ViewBitmap() != NULL
2030 && fCurrentView
->ViewBitmap()->Overlay() != NULL
;
2032 fCurrentView
->SetViewBitmap(bitmap
, srcRect
, dstRect
,
2033 resizingMode
, options
);
2035 // TODO: if we revert the view color overlay handling
2036 // in View::Draw() to the BeOS version, we never
2037 // need to invalidate the view for overlays.
2039 // Invalidate view - but only if this is a non-overlay
2041 if (bitmap
== NULL
|| bitmap
->Overlay() == NULL
2043 BRegion
dirty((BRect
)fCurrentView
->Bounds());
2044 fWindow
->InvalidateView(fCurrentView
, dirty
);
2047 if (bitmap
!= NULL
&& bitmap
->Overlay() != NULL
) {
2048 bitmap
->Overlay()->SetFlags(options
);
2049 colorKey
= bitmap
->Overlay()->Color();
2053 bitmap
->ReleaseReference();
2055 status
= B_BAD_VALUE
;
2058 fLink
.StartMessage(status
);
2059 if (status
== B_OK
&& (options
& AS_REQUEST_COLOR_KEY
) != 0) {
2060 // Attach color key for the overlay bitmap
2061 fLink
.Attach
<rgb_color
>(colorKey
);
2067 case AS_VIEW_PRINT_ALIASING
:
2069 DTRACE(("ServerWindow %s: Message AS_VIEW_PRINT_ALIASING: "
2070 "View: %s\n", Title(), fCurrentView
->Name()));
2073 if (link
.Read
<bool>(&fontAliasing
) == B_OK
) {
2074 fCurrentView
->CurrentState()->SetForceFontAliasing(fontAliasing
);
2075 _UpdateDrawState(fCurrentView
);
2079 case AS_VIEW_CLIP_TO_PICTURE
:
2081 DTRACE(("ServerWindow %s: Message AS_VIEW_CLIP_TO_PICTURE: "
2082 "View: %s\n", Title(), fCurrentView
->Name()));
2086 bool inverse
= false;
2088 link
.Read
<int32
>(&pictureToken
);
2089 if (pictureToken
< 0) {
2090 fCurrentView
->SetAlphaMask(NULL
);
2091 _UpdateDrawState(fCurrentView
);
2095 link
.Read
<BPoint
>(&where
);
2096 if (link
.Read
<bool>(&inverse
) != B_OK
)
2099 ServerPicture
* picture
= fServerApp
->GetPicture(pictureToken
);
2100 if (picture
== NULL
)
2103 AlphaMask
* const mask
= new(std::nothrow
) PictureAlphaMask(
2104 fCurrentView
->GetAlphaMask(), picture
,
2105 *fCurrentView
->CurrentState(), where
, inverse
);
2106 fCurrentView
->SetAlphaMask(mask
);
2108 mask
->ReleaseReference();
2110 _UpdateDrawState(fCurrentView
);
2112 picture
->ReleaseReference();
2116 case AS_VIEW_GET_CLIP_REGION
:
2118 DTRACE(("ServerWindow %s: Message AS_VIEW_GET_CLIP_REGION: "
2119 "View: %s\n", Title(), fCurrentView
->Name()));
2121 // if this view is hidden, it has no visible region
2122 fLink
.StartMessage(B_OK
);
2123 if (!fWindow
->IsVisible() || !fCurrentView
->IsVisible()) {
2125 fLink
.AttachRegion(empty
);
2127 _UpdateCurrentDrawingRegion();
2128 BRegion
region(fCurrentDrawingRegion
);
2129 fCurrentView
->ScreenToLocalTransform().Apply(®ion
);
2130 fLink
.AttachRegion(region
);
2136 case AS_VIEW_SET_CLIP_REGION
:
2139 status_t status
= link
.Read
<int32
>(&rectCount
);
2140 // a negative count means no
2141 // region for the current draw state,
2142 // but an *empty* region is actually valid!
2143 // even if it means no drawing is allowed
2148 if (rectCount
>= 0) {
2149 // we are supposed to set the clipping region
2151 if (rectCount
> 0 && link
.ReadRegion(®ion
) < B_OK
)
2154 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_CLIP_REGION: "
2155 "View: %s -> rect count: %" B_PRId32
", frame = "
2156 "BRect(%.1f, %.1f, %.1f, %.1f)\n",
2157 Title(), fCurrentView
->Name(), rectCount
,
2158 region
.Frame().left
, region
.Frame().top
,
2159 region
.Frame().right
, region
.Frame().bottom
));
2161 fCurrentView
->SetUserClipping(®ion
);
2163 // we are supposed to unset the clipping region
2164 // passing NULL sets this states region to that
2165 // of the previous state
2167 DTRACE(("ServerWindow %s: Message AS_VIEW_SET_CLIP_REGION: "
2168 "View: %s -> unset\n", Title(), fCurrentView
->Name()));
2170 fCurrentView
->SetUserClipping(NULL
);
2172 fCurrentDrawingRegionValid
= false;
2177 case AS_VIEW_CLIP_TO_RECT
:
2182 link
.Read
<bool>(&inverse
);
2183 link
.Read
<BRect
>(&rect
);
2185 bool needDrawStateUpdate
= fCurrentView
->ClipToRect(
2187 fCurrentDrawingRegionValid
= false;
2189 if (needDrawStateUpdate
)
2190 _UpdateDrawState(fCurrentView
);
2192 _UpdateCurrentDrawingRegion();
2194 BRegion
region(fCurrentDrawingRegion
);
2195 fCurrentView
->ScreenToLocalTransform().Apply(®ion
);
2200 case AS_VIEW_CLIP_TO_SHAPE
:
2203 link
.Read
<bool>(&inverse
);
2206 link
.Read
<int32
>(&shape
.opCount
);
2207 link
.Read
<int32
>(&shape
.ptCount
);
2208 shape
.opSize
= shape
.opCount
* sizeof(uint32
);
2209 shape
.ptSize
= shape
.ptCount
* sizeof(BPoint
);
2210 shape
.opList
= new(nothrow
) uint32
[shape
.opCount
];
2211 shape
.ptList
= new(nothrow
) BPoint
[shape
.ptCount
];
2212 if (link
.Read(shape
.opList
, shape
.opSize
) >= B_OK
2213 && link
.Read(shape
.ptList
, shape
.ptSize
) >= B_OK
) {
2214 fCurrentView
->ClipToShape(&shape
, inverse
);
2215 _UpdateDrawState(fCurrentView
);
2218 delete[] shape
.opList
;
2219 delete[] shape
.ptList
;
2223 case AS_VIEW_INVALIDATE_RECT
:
2225 // NOTE: looks like this call is NOT affected by origin and scale
2226 // on R5 so this implementation is "correct"
2228 if (link
.Read
<BRect
>(&invalidRect
) == B_OK
) {
2229 DTRACE(("ServerWindow %s: Message AS_VIEW_INVALIDATE_RECT: "
2230 "View: %s -> BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2231 fCurrentView
->Name(), invalidRect
.left
, invalidRect
.top
,
2232 invalidRect
.right
, invalidRect
.bottom
));
2235 if (link
.Read
<View
*>(&view
) != B_OK
)
2236 view
= fCurrentView
;
2238 // make sure the view is still available!
2239 if (view
!= fCurrentView
2240 && !fWindow
->TopView()->HasView(view
))
2243 BRegion
dirty(invalidRect
);
2244 fWindow
->InvalidateView(view
, dirty
);
2249 case AS_VIEW_DELAYED_INVALIDATE_RECT
:
2253 if (link
.Read
<bigtime_t
>(&time
) == B_OK
2254 && link
.Read
<BRect
>(&invalidRect
) == B_OK
) {
2255 DTRACE(("ServerWindow %s: Message "
2256 "AS_VIEW_DELAYED_INVALIDATE_RECT: "
2257 "View: %s -> BRect(%.1f, %.1f, %.1f, %.1f) at time %llu\n",
2258 Title(), fCurrentView
->Name(), invalidRect
.left
,
2259 invalidRect
.top
, invalidRect
.right
, invalidRect
.bottom
,
2262 DelayedMessage
delayed(AS_VIEW_INVALIDATE_RECT
, time
, true);
2263 delayed
.AddTarget(MessagePort());
2264 delayed
.SetMerge(DM_MERGE_DUPLICATES
);
2266 if (delayed
.Attach
<BRect
>(invalidRect
) == B_OK
2267 && delayed
.Attach
<View
*>(fCurrentView
) == B_OK
)
2273 case AS_VIEW_INVALIDATE_REGION
:
2275 // NOTE: looks like this call is NOT affected by origin and scale
2276 // on R5 so this implementation is "correct"
2278 if (link
.ReadRegion(®ion
) < B_OK
)
2281 DTRACE(("ServerWindow %s: Message AS_VIEW_INVALIDATE_REGION: "
2282 "View: %s -> rect count: %" B_PRId32
", frame: BRect(%.1f, "
2283 "%.1f, %.1f, %.1f)\n", Title(),
2284 fCurrentView
->Name(), region
.CountRects(),
2285 region
.Frame().left
, region
.Frame().top
,
2286 region
.Frame().right
, region
.Frame().bottom
));
2288 fWindow
->InvalidateView(fCurrentView
, region
);
2292 case AS_VIEW_DRAG_IMAGE
:
2294 // TODO: flesh out AS_VIEW_DRAG_IMAGE
2295 DTRACE(("ServerWindow %s: Message AS_DRAG_IMAGE\n", Title()));
2298 drawing_mode dragMode
;
2302 link
.Read
<int32
>(&bitmapToken
);
2303 link
.Read
<int32
>((int32
*)&dragMode
);
2304 link
.Read
<BPoint
>(&offset
);
2305 link
.Read
<int32
>(&bufferSize
);
2307 if (bufferSize
> 0) {
2308 char* buffer
= new (nothrow
) char[bufferSize
];
2309 BMessage dragMessage
;
2310 if (link
.Read(buffer
, bufferSize
) == B_OK
2311 && dragMessage
.Unflatten(buffer
) == B_OK
) {
2312 ServerBitmap
* bitmap
2313 = fServerApp
->GetBitmap(bitmapToken
);
2314 // TODO: possible deadlock
2315 fDesktop
->UnlockSingleWindow();
2316 fDesktop
->EventDispatcher().SetDragMessage(dragMessage
,
2318 fDesktop
->LockSingleWindow();
2320 bitmap
->ReleaseReference();
2324 // sync the client (it can now delete the bitmap)
2325 fLink
.StartMessage(B_OK
);
2330 case AS_VIEW_DRAG_RECT
:
2332 // TODO: flesh out AS_VIEW_DRAG_RECT
2333 DTRACE(("ServerWindow %s: Message AS_DRAG_RECT\n", Title()));
2339 link
.Read
<BRect
>(&dragRect
);
2340 link
.Read
<BPoint
>(&offset
);
2341 link
.Read
<int32
>(&bufferSize
);
2343 if (bufferSize
> 0) {
2344 char* buffer
= new (nothrow
) char[bufferSize
];
2345 BMessage dragMessage
;
2346 if (link
.Read(buffer
, bufferSize
) == B_OK
2347 && dragMessage
.Unflatten(buffer
) == B_OK
) {
2348 // TODO: possible deadlock
2349 fDesktop
->UnlockSingleWindow();
2350 fDesktop
->EventDispatcher().SetDragMessage(dragMessage
,
2351 NULL
/* should be dragRect */, offset
);
2352 fDesktop
->LockSingleWindow();
2359 case AS_VIEW_BEGIN_RECT_TRACK
:
2361 DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_RECT_TRACK\n",
2366 link
.Read
<BRect
>(&dragRect
);
2367 link
.Read
<uint32
>(&style
);
2369 // TODO: implement rect tracking (used sometimes for selecting
2370 // a group of things, also sometimes used to appear to drag
2371 // something, but without real drag message)
2374 case AS_VIEW_END_RECT_TRACK
:
2376 DTRACE(("ServerWindow %s: Message AS_VIEW_END_RECT_TRACK\n",
2378 // TODO: implement rect tracking
2382 case AS_VIEW_BEGIN_PICTURE
:
2384 DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_PICTURE\n",
2386 ServerPicture
* picture
= App()->CreatePicture();
2387 if (picture
!= NULL
) {
2388 picture
->SyncState(fCurrentView
);
2389 fCurrentView
->SetPicture(picture
);
2394 case AS_VIEW_APPEND_TO_PICTURE
:
2396 DTRACE(("ServerWindow %s: Message AS_VIEW_APPEND_TO_PICTURE\n",
2400 link
.Read
<int32
>(&token
);
2402 ServerPicture
* picture
= App()->GetPicture(token
);
2403 if (picture
!= NULL
)
2404 picture
->SyncState(fCurrentView
);
2406 fCurrentView
->SetPicture(picture
);
2408 if (picture
!= NULL
)
2409 picture
->ReleaseReference();
2413 case AS_VIEW_END_PICTURE
:
2415 DTRACE(("ServerWindow %s: Message AS_VIEW_END_PICTURE\n",
2418 ServerPicture
* picture
= fCurrentView
->Picture();
2419 if (picture
!= NULL
) {
2420 fCurrentView
->SetPicture(NULL
);
2421 fLink
.StartMessage(B_OK
);
2422 fLink
.Attach
<int32
>(picture
->Token());
2424 fLink
.StartMessage(B_ERROR
);
2430 case AS_VIEW_BEGIN_LAYER
:
2432 DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_LAYER\n",
2436 link
.Read
<uint8
>(&opacity
);
2438 Layer
* layer
= new(std::nothrow
) Layer(opacity
);
2442 if (opacity
!= 255) {
2443 fCurrentView
->CurrentState()->SetDrawingMode(B_OP_ALPHA
);
2444 fCurrentView
->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA
,
2446 fCurrentView
->CurrentState()->SetDrawingModeLocked(true);
2449 fCurrentView
->SetPicture(layer
);
2454 _DispatchViewDrawingMessage(code
, link
);
2460 /*! Dispatches all view drawing messages.
2461 The desktop clipping must be read locked when entering this method.
2462 Requires a valid fCurrentView.
2465 ServerWindow::_DispatchViewDrawingMessage(int32 code
,
2466 BPrivate::LinkReceiver
&link
)
2468 if (!fCurrentView
->IsVisible() || !fWindow
->IsVisible()) {
2469 if (link
.NeedsReply()) {
2470 debug_printf("ServerWindow::DispatchViewDrawingMessage() got "
2471 "message %" B_PRId32
" that needs a reply!\n", code
);
2472 // the client is now blocking and waiting for a reply!
2473 fLink
.StartMessage(B_ERROR
);
2479 DrawingEngine
* drawingEngine
= fWindow
->GetDrawingEngine();
2480 if (!drawingEngine
) {
2482 debug_printf("ServerWindow %s: no drawing engine!!\n", Title());
2483 if (link
.NeedsReply()) {
2484 // the client is now blocking and waiting for a reply!
2485 fLink
.StartMessage(B_ERROR
);
2491 _UpdateCurrentDrawingRegion();
2492 if (fCurrentDrawingRegion
.CountRects() <= 0 && code
!= AS_VIEW_END_LAYER
) {
2493 // If the command is AS_VIEW_END_LAYER, then we continue even if
2494 // the clipping region is empty. The layer itself might set a valid
2495 // clipping while its contents are drawn, and even if it doesn't,
2496 // we must still play back its picture so that we don't leak
2497 // nested layer instances.
2499 DTRACE(("ServerWindow %s: _DispatchViewDrawingMessage(): View: %s, "
2500 "INVALID CLIPPING!\n", Title(), fCurrentView
->Name()));
2501 if (link
.NeedsReply()) {
2502 // the client is now blocking and waiting for a reply!
2503 fLink
.StartMessage(B_ERROR
);
2509 drawingEngine
->LockParallelAccess();
2510 // NOTE: the region is not copied, Painter keeps a pointer,
2511 // that's why you need to use the clipping only for as long
2512 // as you have it locked
2513 drawingEngine
->ConstrainClippingRegion(&fCurrentDrawingRegion
);
2516 case AS_STROKE_LINE
:
2518 ViewStrokeLineInfo info
;
2519 if (link
.Read
<ViewStrokeLineInfo
>(&info
) != B_OK
)
2522 DTRACE(("ServerWindow %s: Message AS_STROKE_LINE: View: %s -> "
2523 "BPoint(%.1f, %.1f) - BPoint(%.1f, %.1f)\n", Title(),
2524 fCurrentView
->Name(),
2525 info
.startPoint
.x
, info
.startPoint
.y
,
2526 info
.endPoint
.x
, info
.endPoint
.y
));
2528 BPoint penPos
= info
.endPoint
;
2529 const SimpleTransform transform
=
2530 fCurrentView
->PenToScreenTransform();
2531 transform
.Apply(&info
.startPoint
);
2532 transform
.Apply(&info
.endPoint
);
2533 drawingEngine
->StrokeLine(info
.startPoint
, info
.endPoint
);
2535 // We update the pen here because many DrawingEngine calls which
2536 // do not update the pen position actually call StrokeLine
2538 // TODO: Decide where to put this, for example, it cannot be done
2539 // for DrawString(), also there needs to be a decision, if the pen
2540 // location is in View coordinates (I think it should be) or in
2541 // screen coordinates.
2542 fCurrentView
->CurrentState()->SetPenLocation(penPos
);
2545 case AS_VIEW_INVERT_RECT
:
2548 if (link
.Read
<BRect
>(&rect
) != B_OK
)
2551 DTRACE(("ServerWindow %s: Message AS_INVERT_RECT: View: %s -> "
2552 "BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2553 fCurrentView
->Name(), rect
.left
, rect
.top
, rect
.right
,
2556 fCurrentView
->PenToScreenTransform().Apply(&rect
);
2557 drawingEngine
->InvertRect(rect
);
2560 case AS_STROKE_RECT
:
2563 if (link
.Read
<BRect
>(&rect
) != B_OK
)
2566 DTRACE(("ServerWindow %s: Message AS_STROKE_RECT: View: %s -> "
2567 "BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2568 fCurrentView
->Name(), rect
.left
, rect
.top
, rect
.right
,
2571 fCurrentView
->PenToScreenTransform().Apply(&rect
);
2572 drawingEngine
->StrokeRect(rect
);
2578 if (link
.Read
<BRect
>(&rect
) != B_OK
)
2581 DTRACE(("ServerWindow %s: Message AS_FILL_RECT: View: %s -> "
2582 "BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2583 fCurrentView
->Name(), rect
.left
, rect
.top
, rect
.right
,
2586 fCurrentView
->PenToScreenTransform().Apply(&rect
);
2587 drawingEngine
->FillRect(rect
);
2590 case AS_FILL_RECT_GRADIENT
:
2593 link
.Read
<BRect
>(&rect
);
2594 BGradient
* gradient
;
2595 if (link
.ReadGradient(&gradient
) != B_OK
)
2598 GTRACE(("ServerWindow %s: Message AS_FILL_RECT_GRADIENT: View: %s "
2599 "-> BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2600 fCurrentView
->Name(), rect
.left
, rect
.top
, rect
.right
,
2603 const SimpleTransform transform
=
2604 fCurrentView
->PenToScreenTransform();
2605 transform
.Apply(&rect
);
2606 transform
.Apply(gradient
);
2607 drawingEngine
->FillRect(rect
, *gradient
);
2611 case AS_VIEW_DRAW_BITMAP
:
2613 ViewDrawBitmapInfo info
;
2614 if (link
.Read
<ViewDrawBitmapInfo
>(&info
) != B_OK
)
2618 if (strcmp(fServerApp
->SignatureLeaf(), "x-vnd.videolan-vlc") == 0)
2619 info
.options
|= B_FILTER_BITMAP_BILINEAR
;
2622 ServerBitmap
* bitmap
= fServerApp
->GetBitmap(info
.bitmapToken
);
2623 if (bitmap
!= NULL
) {
2624 DTRACE(("ServerWindow %s: Message AS_VIEW_DRAW_BITMAP: "
2625 "View: %s, bitmap: %" B_PRId32
" (size %" B_PRId32
" x "
2626 "%" B_PRId32
"), BRect(%.1f, %.1f, %.1f, %.1f) -> "
2627 "BRect(%.1f, %.1f, %.1f, %.1f)\n",
2628 fTitle
, fCurrentView
->Name(), info
.bitmapToken
,
2629 bitmap
->Width(), bitmap
->Height(),
2630 info
.bitmapRect
.left
, info
.bitmapRect
.top
,
2631 info
.bitmapRect
.right
, info
.bitmapRect
.bottom
,
2632 info
.viewRect
.left
, info
.viewRect
.top
,
2633 info
.viewRect
.right
, info
.viewRect
.bottom
));
2635 fCurrentView
->PenToScreenTransform().Apply(&info
.viewRect
);
2638 // if ((info.options & B_WAIT_FOR_RETRACE) != 0)
2639 // fDesktop->HWInterface()->WaitForRetrace(20000);
2641 drawingEngine
->DrawBitmap(bitmap
, info
.bitmapRect
,
2642 info
.viewRect
, info
.options
);
2644 bitmap
->ReleaseReference();
2651 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ARC\n", Title()));
2656 link
.Read
<BRect
>(&r
);
2657 link
.Read
<float>(&angle
);
2658 if (link
.Read
<float>(&span
) != B_OK
)
2661 fCurrentView
->PenToScreenTransform().Apply(&r
);
2662 drawingEngine
->DrawArc(r
, angle
, span
, code
== AS_FILL_ARC
);
2665 case AS_FILL_ARC_GRADIENT
:
2667 GTRACE(("ServerWindow %s: Message AS_FILL_ARC_GRADIENT\n",
2672 link
.Read
<BRect
>(&r
);
2673 link
.Read
<float>(&angle
);
2674 link
.Read
<float>(&span
);
2675 BGradient
* gradient
;
2676 if (link
.ReadGradient(&gradient
) != B_OK
)
2678 const SimpleTransform transform
=
2679 fCurrentView
->PenToScreenTransform();
2680 transform
.Apply(&r
);
2681 transform
.Apply(gradient
);
2682 drawingEngine
->FillArc(r
, angle
, span
, *gradient
);
2686 case AS_STROKE_BEZIER
:
2687 case AS_FILL_BEZIER
:
2689 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n",
2692 const SimpleTransform transform
=
2693 fCurrentView
->PenToScreenTransform();
2696 for (int32 i
= 0; i
< 4; i
++) {
2697 status
= link
.Read
<BPoint
>(&(pts
[i
]));
2698 transform
.Apply(&pts
[i
]);
2703 drawingEngine
->DrawBezier(pts
, code
== AS_FILL_BEZIER
);
2706 case AS_FILL_BEZIER_GRADIENT
:
2708 GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n",
2711 const SimpleTransform transform
=
2712 fCurrentView
->PenToScreenTransform();
2714 for (int32 i
= 0; i
< 4; i
++) {
2715 link
.Read
<BPoint
>(&(pts
[i
]));
2716 transform
.Apply(&pts
[i
]);
2718 BGradient
* gradient
;
2719 if (link
.ReadGradient(&gradient
) != B_OK
)
2721 transform
.Apply(gradient
);
2722 drawingEngine
->FillBezier(pts
, *gradient
);
2726 case AS_STROKE_ELLIPSE
:
2727 case AS_FILL_ELLIPSE
:
2729 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ELLIPSE\n",
2733 if (link
.Read
<BRect
>(&rect
) != B_OK
)
2736 fCurrentView
->PenToScreenTransform().Apply(&rect
);
2737 drawingEngine
->DrawEllipse(rect
, code
== AS_FILL_ELLIPSE
);
2740 case AS_FILL_ELLIPSE_GRADIENT
:
2742 GTRACE(("ServerWindow %s: Message AS_FILL_ELLIPSE_GRADIENT\n",
2746 link
.Read
<BRect
>(&rect
);
2747 BGradient
* gradient
;
2748 if (link
.ReadGradient(&gradient
) != B_OK
)
2750 const SimpleTransform transform
=
2751 fCurrentView
->PenToScreenTransform();
2752 transform
.Apply(&rect
);
2753 transform
.Apply(gradient
);
2754 drawingEngine
->FillEllipse(rect
, *gradient
);
2758 case AS_STROKE_ROUNDRECT
:
2759 case AS_FILL_ROUNDRECT
:
2761 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ROUNDRECT\n",
2767 link
.Read
<BRect
>(&rect
);
2768 link
.Read
<float>(&xRadius
);
2769 if (link
.Read
<float>(&yRadius
) != B_OK
)
2772 fCurrentView
->PenToScreenTransform().Apply(&rect
);
2773 float scale
= fCurrentView
->CurrentState()->CombinedScale();
2774 drawingEngine
->DrawRoundRect(rect
, xRadius
* scale
, yRadius
* scale
,
2775 code
== AS_FILL_ROUNDRECT
);
2778 case AS_FILL_ROUNDRECT_GRADIENT
:
2780 GTRACE(("ServerWindow %s: Message AS_FILL_ROUNDRECT_GRADIENT\n",
2785 link
.Read
<BRect
>(&rect
);
2786 link
.Read
<float>(&xrad
);
2787 link
.Read
<float>(&yrad
);
2788 BGradient
* gradient
;
2789 if (link
.ReadGradient(&gradient
) != B_OK
)
2791 const SimpleTransform transform
=
2792 fCurrentView
->PenToScreenTransform();
2793 transform
.Apply(&rect
);
2794 transform
.Apply(gradient
);
2795 drawingEngine
->FillRoundRect(rect
, xrad
, yrad
, *gradient
);
2799 case AS_STROKE_TRIANGLE
:
2800 case AS_FILL_TRIANGLE
:
2802 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n",
2805 const SimpleTransform transform
=
2806 fCurrentView
->PenToScreenTransform();
2810 for (int32 i
= 0; i
< 3; i
++) {
2811 link
.Read
<BPoint
>(&(pts
[i
]));
2812 transform
.Apply(&pts
[i
]);
2815 if (link
.Read
<BRect
>(&rect
) != B_OK
)
2818 transform
.Apply(&rect
);
2819 drawingEngine
->DrawTriangle(pts
, rect
, code
== AS_FILL_TRIANGLE
);
2822 case AS_FILL_TRIANGLE_GRADIENT
:
2824 DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n",
2827 const SimpleTransform transform
=
2828 fCurrentView
->PenToScreenTransform();
2831 for (int32 i
= 0; i
< 3; i
++) {
2832 link
.Read
<BPoint
>(&(pts
[i
]));
2833 transform
.Apply(&pts
[i
]);
2835 link
.Read
<BRect
>(&rect
);
2836 BGradient
* gradient
;
2837 if (link
.ReadGradient(&gradient
) != B_OK
)
2839 transform
.Apply(&rect
);
2840 transform
.Apply(gradient
);
2841 drawingEngine
->FillTriangle(pts
, rect
, *gradient
);
2845 case AS_STROKE_POLYGON
:
2846 case AS_FILL_POLYGON
:
2848 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_POLYGON\n",
2852 bool isClosed
= true;
2855 link
.Read
<BRect
>(&polyFrame
);
2856 if (code
== AS_STROKE_POLYGON
)
2857 link
.Read
<bool>(&isClosed
);
2858 link
.Read
<int32
>(&pointCount
);
2860 const SimpleTransform transform
=
2861 fCurrentView
->PenToScreenTransform();
2862 BPoint
* pointList
= new(nothrow
) BPoint
[pointCount
];
2863 if (link
.Read(pointList
, pointCount
* sizeof(BPoint
)) >= B_OK
) {
2864 for (int32 i
= 0; i
< pointCount
; i
++)
2865 transform
.Apply(&pointList
[i
]);
2866 transform
.Apply(&polyFrame
);
2868 drawingEngine
->DrawPolygon(pointList
, pointCount
, polyFrame
,
2869 code
== AS_FILL_POLYGON
, isClosed
&& pointCount
> 2);
2874 case AS_FILL_POLYGON_GRADIENT
:
2876 DTRACE(("ServerWindow %s: Message AS_FILL_POLYGON_GRADIENT\n",
2880 bool isClosed
= true;
2882 link
.Read
<BRect
>(&polyFrame
);
2883 link
.Read
<int32
>(&pointCount
);
2885 const SimpleTransform transform
=
2886 fCurrentView
->PenToScreenTransform();
2887 BPoint
* pointList
= new(nothrow
) BPoint
[pointCount
];
2888 BGradient
* gradient
;
2889 if (link
.Read(pointList
, pointCount
* sizeof(BPoint
)) == B_OK
2890 && link
.ReadGradient(&gradient
) == B_OK
) {
2891 for (int32 i
= 0; i
< pointCount
; i
++)
2892 transform
.Apply(&pointList
[i
]);
2893 transform
.Apply(&polyFrame
);
2894 transform
.Apply(gradient
);
2896 drawingEngine
->FillPolygon(pointList
, pointCount
,
2897 polyFrame
, *gradient
, isClosed
&& pointCount
> 2);
2903 case AS_STROKE_SHAPE
:
2906 DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_SHAPE\n",
2913 link
.Read
<BRect
>(&shapeFrame
);
2914 link
.Read
<int32
>(&opCount
);
2915 link
.Read
<int32
>(&ptCount
);
2917 uint32
* opList
= new(nothrow
) uint32
[opCount
];
2918 BPoint
* ptList
= new(nothrow
) BPoint
[ptCount
];
2919 if (link
.Read(opList
, opCount
* sizeof(uint32
)) >= B_OK
&&
2920 link
.Read(ptList
, ptCount
* sizeof(BPoint
)) >= B_OK
) {
2922 // this might seem a bit weird, but under R5, the shapes
2923 // are always offset by the current pen location
2925 = fCurrentView
->CurrentState()->PenLocation();
2926 shapeFrame
.OffsetBy(screenOffset
);
2928 const SimpleTransform transform
=
2929 fCurrentView
->PenToScreenTransform();
2930 transform
.Apply(&screenOffset
);
2931 transform
.Apply(&shapeFrame
);
2933 drawingEngine
->DrawShape(shapeFrame
, opCount
, opList
, ptCount
,
2934 ptList
, code
== AS_FILL_SHAPE
, screenOffset
,
2935 fCurrentView
->Scale());
2942 case AS_FILL_SHAPE_GRADIENT
:
2944 DTRACE(("ServerWindow %s: Message AS_FILL_SHAPE_GRADIENT\n",
2951 link
.Read
<BRect
>(&shapeFrame
);
2952 link
.Read
<int32
>(&opCount
);
2953 link
.Read
<int32
>(&ptCount
);
2955 uint32
* opList
= new(nothrow
) uint32
[opCount
];
2956 BPoint
* ptList
= new(nothrow
) BPoint
[ptCount
];
2957 BGradient
* gradient
;
2958 if (link
.Read(opList
, opCount
* sizeof(uint32
)) == B_OK
2959 && link
.Read(ptList
, ptCount
* sizeof(BPoint
)) == B_OK
2960 && link
.ReadGradient(&gradient
) == B_OK
) {
2962 // this might seem a bit weird, but under R5, the shapes
2963 // are always offset by the current pen location
2965 = fCurrentView
->CurrentState()->PenLocation();
2966 shapeFrame
.OffsetBy(screenOffset
);
2968 const SimpleTransform transform
=
2969 fCurrentView
->PenToScreenTransform();
2970 transform
.Apply(&screenOffset
);
2971 transform
.Apply(&shapeFrame
);
2972 transform
.Apply(gradient
);
2973 drawingEngine
->FillShape(shapeFrame
, opCount
, opList
,
2974 ptCount
, ptList
, *gradient
, screenOffset
,
2975 fCurrentView
->Scale());
2983 case AS_FILL_REGION
:
2985 DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title()));
2988 if (link
.ReadRegion(®ion
) < B_OK
)
2991 fCurrentView
->PenToScreenTransform().Apply(®ion
);
2992 drawingEngine
->FillRegion(region
);
2996 case AS_FILL_REGION_GRADIENT
:
2998 DTRACE(("ServerWindow %s: Message AS_FILL_REGION_GRADIENT\n",
3002 link
.ReadRegion(®ion
);
3004 BGradient
* gradient
;
3005 if (link
.ReadGradient(&gradient
) != B_OK
)
3008 const SimpleTransform transform
=
3009 fCurrentView
->PenToScreenTransform();
3010 transform
.Apply(®ion
);
3011 transform
.Apply(gradient
);
3012 drawingEngine
->FillRegion(region
, *gradient
);
3016 case AS_STROKE_LINEARRAY
:
3018 DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n",
3022 // 1) int32 Number of lines in the array
3026 if (link
.Read
<int32
>(&lineCount
) != B_OK
|| lineCount
<= 0)
3029 // To speed things up, try to use a stack allocation and only
3030 // fall back to the heap if there are enough lines...
3031 ViewLineArrayInfo
* lineData
;
3032 const int32 kStackBufferLineDataCount
= 64;
3033 ViewLineArrayInfo lineDataStackBuffer
[kStackBufferLineDataCount
];
3034 if (lineCount
> kStackBufferLineDataCount
) {
3035 lineData
= new(std::nothrow
) ViewLineArrayInfo
[lineCount
];
3036 if (lineData
== NULL
)
3039 lineData
= lineDataStackBuffer
;
3041 // Read them all in one go
3042 size_t dataSize
= lineCount
* sizeof(ViewLineArrayInfo
);
3043 if (link
.Read(lineData
, dataSize
) != B_OK
) {
3044 if (lineData
!= lineDataStackBuffer
)
3049 // Convert to screen coords and draw
3050 const SimpleTransform transform
=
3051 fCurrentView
->PenToScreenTransform();
3052 for (int32 i
= 0; i
< lineCount
; i
++) {
3053 transform
.Apply(&lineData
[i
].startPoint
);
3054 transform
.Apply(&lineData
[i
].endPoint
);
3056 drawingEngine
->StrokeLineArray(lineCount
, lineData
);
3058 if (lineData
!= lineDataStackBuffer
)
3062 case AS_DRAW_STRING
:
3063 case AS_DRAW_STRING_WITH_DELTA
:
3065 ViewDrawStringInfo info
;
3066 if (link
.Read
<ViewDrawStringInfo
>(&info
) != B_OK
3067 || info
.stringLength
<= 0) {
3071 const ssize_t kMaxStackStringSize
= 4096;
3072 char stackString
[kMaxStackStringSize
];
3073 char* string
= stackString
;
3074 if (info
.stringLength
>= kMaxStackStringSize
) {
3075 // NOTE: Careful, the + 1 is for termination!
3076 string
= (char*)malloc((info
.stringLength
+ 1 + 63) / 64 * 64);
3081 escapement_delta
* delta
= NULL
;
3082 if (code
== AS_DRAW_STRING_WITH_DELTA
) {
3083 // In this case, info.delta will contain valid values.
3084 delta
= &info
.delta
;
3087 if (link
.Read(string
, info
.stringLength
) != B_OK
) {
3088 if (string
!= stackString
)
3092 // Terminate the string, if nothing else, it's important
3093 // for the DTRACE call below...
3094 string
[info
.stringLength
] = '\0';
3096 DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s "
3097 "-> %s\n", Title(), fCurrentView
->Name(), string
));
3099 fCurrentView
->PenToScreenTransform().Apply(&info
.location
);
3100 BPoint penLocation
= drawingEngine
->DrawString(string
,
3101 info
.stringLength
, info
.location
, delta
);
3103 fCurrentView
->ScreenToPenTransform().Apply(&penLocation
);
3104 fCurrentView
->CurrentState()->SetPenLocation(penLocation
);
3106 if (string
!= stackString
)
3110 case AS_DRAW_STRING_WITH_OFFSETS
:
3113 if (link
.Read
<int32
>(&stringLength
) != B_OK
|| stringLength
<= 0)
3117 if (link
.Read
<int32
>(&glyphCount
) != B_OK
|| glyphCount
<= 0)
3120 const ssize_t kMaxStackStringSize
= 512;
3121 char stackString
[kMaxStackStringSize
];
3122 char* string
= stackString
;
3123 BPoint stackLocations
[kMaxStackStringSize
];
3124 BPoint
* locations
= stackLocations
;
3125 MemoryDeleter stringDeleter
;
3126 MemoryDeleter locationsDeleter
;
3127 if (stringLength
>= kMaxStackStringSize
) {
3128 // NOTE: Careful, the + 1 is for termination!
3129 string
= (char*)malloc((stringLength
+ 1 + 63) / 64 * 64);
3132 stringDeleter
.SetTo(string
);
3134 if (glyphCount
> kMaxStackStringSize
) {
3135 locations
= (BPoint
*)malloc(
3136 ((glyphCount
* sizeof(BPoint
)) + 63) / 64 * 64);
3137 if (locations
== NULL
)
3139 locationsDeleter
.SetTo(locations
);
3142 if (link
.Read(string
, stringLength
) != B_OK
)
3144 // Count UTF8 glyphs and make sure we have enough locations
3145 if ((int32
)UTF8CountChars(string
, stringLength
) > glyphCount
)
3147 if (link
.Read(locations
, glyphCount
* sizeof(BPoint
)) != B_OK
)
3149 // Terminate the string, if nothing else, it's important
3150 // for the DTRACE call below...
3151 string
[stringLength
] = '\0';
3153 DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s "
3154 "-> %s\n", Title(), fCurrentView
->Name(), string
));
3156 const SimpleTransform transform
=
3157 fCurrentView
->PenToScreenTransform();
3158 for (int32 i
= 0; i
< glyphCount
; i
++)
3159 transform
.Apply(&locations
[i
]);
3161 BPoint penLocation
= drawingEngine
->DrawString(string
,
3162 stringLength
, locations
);
3164 fCurrentView
->ScreenToPenTransform().Apply(&penLocation
);
3165 fCurrentView
->CurrentState()->SetPenLocation(penLocation
);
3170 case AS_VIEW_DRAW_PICTURE
:
3173 link
.Read
<int32
>(&token
);
3176 if (link
.Read
<BPoint
>(&where
) == B_OK
) {
3177 ServerPicture
* picture
= App()->GetPicture(token
);
3178 if (picture
!= NULL
) {
3179 // Setting the drawing origin outside of the
3180 // state makes sure that everything the picture
3181 // does is relative to the global picture offset.
3182 fCurrentView
->PushState();
3183 fCurrentView
->SetDrawingOrigin(where
);
3185 fCurrentView
->PushState();
3186 picture
->Play(fCurrentView
);
3187 fCurrentView
->PopState();
3189 fCurrentView
->PopState();
3191 picture
->ReleaseReference();
3197 case AS_VIEW_END_LAYER
:
3199 DTRACE(("ServerWindow %s: Message AS_VIEW_END_LAYER\n",
3202 fCurrentView
->BlendAllLayers();
3203 fCurrentView
->SetPicture(NULL
);
3204 fCurrentView
->CurrentState()->SetDrawingModeLocked(false);
3210 string_for_message_code(code
, codeString
);
3211 debug_printf("ServerWindow %s received unexpected code: %s\n",
3212 Title(), codeString
.String());
3214 if (link
.NeedsReply()) {
3215 // the client is now blocking and waiting for a reply!
3216 fLink
.StartMessage(B_ERROR
);
3222 drawingEngine
->UnlockParallelAccess();
3227 ServerWindow::_DispatchPictureMessage(int32 code
, BPrivate::LinkReceiver
& link
)
3229 ServerPicture
* picture
= fCurrentView
->Picture();
3230 if (picture
== NULL
)
3234 case AS_VIEW_SET_ORIGIN
:
3237 link
.Read
<float>(&x
);
3238 link
.Read
<float>(&y
);
3240 picture
->WriteSetOrigin(BPoint(x
, y
));
3244 case AS_VIEW_INVERT_RECT
:
3247 link
.Read
<BRect
>(&rect
);
3248 picture
->WriteInvertRect(rect
);
3252 case AS_VIEW_PUSH_STATE
:
3254 picture
->WritePushState();
3258 case AS_VIEW_POP_STATE
:
3260 picture
->WritePopState();
3264 case AS_VIEW_SET_DRAWING_MODE
:
3267 link
.Read
<int8
>(&drawingMode
);
3269 picture
->WriteSetDrawingMode((drawing_mode
)drawingMode
);
3271 fCurrentView
->CurrentState()->SetDrawingMode(
3272 (drawing_mode
)drawingMode
);
3273 fWindow
->GetDrawingEngine()->SetDrawingMode(
3274 (drawing_mode
)drawingMode
);
3278 case AS_VIEW_SET_PEN_LOC
:
3281 link
.Read
<BPoint
>(&location
);
3282 picture
->WriteSetPenLocation(location
);
3284 fCurrentView
->CurrentState()->SetPenLocation(location
);
3287 case AS_VIEW_SET_PEN_SIZE
:
3290 link
.Read
<float>(&penSize
);
3291 picture
->WriteSetPenSize(penSize
);
3293 fCurrentView
->CurrentState()->SetPenSize(penSize
);
3294 fWindow
->GetDrawingEngine()->SetPenSize(
3295 fCurrentView
->CurrentState()->PenSize());
3299 case AS_VIEW_SET_LINE_MODE
:
3302 ViewSetLineModeInfo info
;
3303 link
.Read
<ViewSetLineModeInfo
>(&info
);
3305 picture
->WriteSetLineMode(info
.lineCap
, info
.lineJoin
,
3308 fCurrentView
->CurrentState()->SetLineCapMode(info
.lineCap
);
3309 fCurrentView
->CurrentState()->SetLineJoinMode(info
.lineJoin
);
3310 fCurrentView
->CurrentState()->SetMiterLimit(info
.miterLimit
);
3312 fWindow
->GetDrawingEngine()->SetStrokeMode(info
.lineCap
,
3313 info
.lineJoin
, info
.miterLimit
);
3316 case AS_VIEW_SET_SCALE
:
3319 if (link
.Read
<float>(&scale
) != B_OK
)
3322 picture
->WriteSetScale(scale
);
3324 fCurrentView
->SetScale(scale
);
3325 _UpdateDrawState(fCurrentView
);
3328 case AS_VIEW_SET_TRANSFORM
:
3330 BAffineTransform transform
;
3331 if (link
.Read
<BAffineTransform
>(&transform
) != B_OK
)
3334 picture
->WriteSetTransform(transform
);
3338 case AS_VIEW_AFFINE_TRANSLATE
:
3341 link
.Read
<double>(&x
);
3342 link
.Read
<double>(&y
);
3344 picture
->WriteTranslateBy(x
, y
);
3348 case AS_VIEW_AFFINE_SCALE
:
3351 link
.Read
<double>(&x
);
3352 link
.Read
<double>(&y
);
3354 picture
->WriteScaleBy(x
, y
);
3358 case AS_VIEW_AFFINE_ROTATE
:
3360 double angleRadians
;
3361 link
.Read
<double>(&angleRadians
);
3363 picture
->WriteRotateBy(angleRadians
);
3368 case AS_VIEW_SET_PATTERN
:
3371 link
.Read(&pat
, sizeof(pattern
));
3372 picture
->WriteSetPattern(pat
);
3376 case AS_VIEW_SET_FONT_STATE
:
3378 picture
->SetFontFromLink(link
);
3383 case AS_STROKE_RECT
:
3386 link
.Read
<BRect
>(&rect
);
3388 picture
->WriteDrawRect(rect
, code
== AS_FILL_RECT
);
3392 case AS_FILL_REGION
:
3394 // There is no B_PIC_FILL_REGION op, we have to
3395 // implement it using B_PIC_FILL_RECT
3397 if (link
.ReadRegion(®ion
) < B_OK
)
3399 for (int32 i
= 0; i
< region
.CountRects(); i
++)
3400 picture
->WriteDrawRect(region
.RectAt(i
), true);
3404 case AS_STROKE_ROUNDRECT
:
3405 case AS_FILL_ROUNDRECT
:
3408 link
.Read
<BRect
>(&rect
);
3411 link
.Read
<float>(&radii
.x
);
3412 link
.Read
<float>(&radii
.y
);
3414 picture
->WriteDrawRoundRect(rect
, radii
, code
== AS_FILL_ROUNDRECT
);
3418 case AS_STROKE_ELLIPSE
:
3419 case AS_FILL_ELLIPSE
:
3422 link
.Read
<BRect
>(&rect
);
3423 picture
->WriteDrawEllipse(rect
, code
== AS_FILL_ELLIPSE
);
3431 link
.Read
<BRect
>(&rect
);
3432 float startTheta
, arcTheta
;
3433 link
.Read
<float>(&startTheta
);
3434 link
.Read
<float>(&arcTheta
);
3436 BPoint
radii((rect
.Width() + 1) / 2, (rect
.Height() + 1) / 2);
3437 BPoint center
= rect
.LeftTop() + radii
;
3439 picture
->WriteDrawArc(center
, radii
, startTheta
, arcTheta
,
3440 code
== AS_FILL_ARC
);
3444 case AS_STROKE_TRIANGLE
:
3445 case AS_FILL_TRIANGLE
:
3447 // There is no B_PIC_FILL/STROKE_TRIANGLE op,
3448 // we implement it using B_PIC_FILL/STROKE_POLYGON
3451 for (int32 i
= 0; i
< 3; i
++) {
3452 link
.Read
<BPoint
>(&(points
[i
]));
3456 link
.Read
<BRect
>(&rect
);
3458 picture
->WriteDrawPolygon(3, points
,
3459 true, code
== AS_FILL_TRIANGLE
);
3462 case AS_STROKE_POLYGON
:
3463 case AS_FILL_POLYGON
:
3466 bool isClosed
= true;
3468 const bool fill
= (code
== AS_FILL_POLYGON
);
3470 link
.Read
<BRect
>(&polyFrame
);
3471 if (code
== AS_STROKE_POLYGON
)
3472 link
.Read
<bool>(&isClosed
);
3473 link
.Read
<int32
>(&pointCount
);
3475 BPoint
* pointList
= new(nothrow
) BPoint
[pointCount
];
3476 if (link
.Read(pointList
, pointCount
* sizeof(BPoint
)) >= B_OK
) {
3477 picture
->WriteDrawPolygon(pointCount
, pointList
,
3478 isClosed
&& pointCount
> 2, fill
);
3484 case AS_STROKE_BEZIER
:
3485 case AS_FILL_BEZIER
:
3488 for (int32 i
= 0; i
< 4; i
++) {
3489 link
.Read
<BPoint
>(&(points
[i
]));
3491 picture
->WriteDrawBezier(points
, code
== AS_FILL_BEZIER
);
3495 case AS_STROKE_LINE
:
3497 ViewStrokeLineInfo info
;
3498 link
.Read
<ViewStrokeLineInfo
>(&info
);
3500 picture
->WriteStrokeLine(info
.startPoint
, info
.endPoint
);
3504 case AS_STROKE_LINEARRAY
:
3507 if (link
.Read
<int32
>(&lineCount
) != B_OK
|| lineCount
<= 0)
3510 // To speed things up, try to use a stack allocation and only
3511 // fall back to the heap if there are enough lines...
3512 ViewLineArrayInfo
* lineData
;
3513 const int32 kStackBufferLineDataCount
= 64;
3514 ViewLineArrayInfo lineDataStackBuffer
[kStackBufferLineDataCount
];
3515 if (lineCount
> kStackBufferLineDataCount
) {
3516 lineData
= new(std::nothrow
) ViewLineArrayInfo
[lineCount
];
3517 if (lineData
== NULL
)
3520 lineData
= lineDataStackBuffer
;
3522 // Read them all in one go
3523 size_t dataSize
= lineCount
* sizeof(ViewLineArrayInfo
);
3524 if (link
.Read(lineData
, dataSize
) != B_OK
) {
3525 if (lineData
!= lineDataStackBuffer
)
3530 picture
->WritePushState();
3532 for (int32 i
= 0; i
< lineCount
; i
++) {
3533 picture
->WriteSetHighColor(lineData
[i
].color
);
3534 picture
->WriteStrokeLine(lineData
[i
].startPoint
,
3535 lineData
[i
].endPoint
);
3538 picture
->WritePopState();
3540 if (lineData
!= lineDataStackBuffer
)
3545 case AS_VIEW_SET_LOW_COLOR
:
3546 case AS_VIEW_SET_HIGH_COLOR
:
3549 link
.Read(&color
, sizeof(rgb_color
));
3551 if (code
== AS_VIEW_SET_HIGH_COLOR
) {
3552 picture
->WriteSetHighColor(color
);
3553 fCurrentView
->CurrentState()->SetHighColor(color
);
3554 fWindow
->GetDrawingEngine()->SetHighColor(color
);
3556 picture
->WriteSetLowColor(color
);
3557 fCurrentView
->CurrentState()->SetLowColor(color
);
3558 fWindow
->GetDrawingEngine()->SetLowColor(color
);
3562 case AS_DRAW_STRING
:
3563 case AS_DRAW_STRING_WITH_DELTA
:
3565 ViewDrawStringInfo info
;
3566 if (link
.Read
<ViewDrawStringInfo
>(&info
) != B_OK
)
3569 char* string
= (char*)malloc(info
.stringLength
+ 1);
3573 if (code
!= AS_DRAW_STRING_WITH_DELTA
) {
3574 // In this case, info.delta will NOT contain valid values.
3575 info
.delta
= (escapement_delta
){ 0, 0 };
3578 if (link
.Read(string
, info
.stringLength
) != B_OK
) {
3582 // Terminate the string
3583 string
[info
.stringLength
] = '\0';
3585 picture
->WriteDrawString(info
.location
, string
, info
.stringLength
,
3592 case AS_STROKE_SHAPE
:
3599 link
.Read
<BRect
>(&shapeFrame
);
3600 link
.Read
<int32
>(&opCount
);
3601 link
.Read
<int32
>(&ptCount
);
3603 uint32
* opList
= new(std::nothrow
) uint32
[opCount
];
3604 BPoint
* ptList
= new(std::nothrow
) BPoint
[ptCount
];
3605 if (opList
!= NULL
&& ptList
!= NULL
3606 && link
.Read(opList
, opCount
* sizeof(uint32
)) >= B_OK
3607 && link
.Read(ptList
, ptCount
* sizeof(BPoint
)) >= B_OK
) {
3608 // This might seem a bit weird, but under BeOS, the shapes
3609 // are always offset by the current pen location
3611 = fCurrentView
->CurrentState()->PenLocation();
3612 for (int32 i
= 0; i
< ptCount
; i
++) {
3613 ptList
[i
] += penLocation
;
3615 const bool fill
= (code
== AS_FILL_SHAPE
);
3616 picture
->WriteDrawShape(opCount
, opList
, ptCount
, ptList
, fill
);
3624 case AS_VIEW_DRAW_BITMAP
:
3626 ViewDrawBitmapInfo info
;
3627 link
.Read
<ViewDrawBitmapInfo
>(&info
);
3629 ServerBitmap
* bitmap
= App()->GetBitmap(info
.bitmapToken
);
3633 picture
->WriteDrawBitmap(info
.bitmapRect
, info
.viewRect
,
3634 bitmap
->Width(), bitmap
->Height(), bitmap
->BytesPerRow(),
3635 bitmap
->ColorSpace(), info
.options
, bitmap
->Bits(),
3636 bitmap
->BitsLength());
3638 bitmap
->ReleaseReference();
3642 case AS_VIEW_DRAW_PICTURE
:
3645 link
.Read
<int32
>(&token
);
3648 if (link
.Read
<BPoint
>(&where
) == B_OK
) {
3649 ServerPicture
* pictureToDraw
= App()->GetPicture(token
);
3650 if (pictureToDraw
!= NULL
) {
3651 // We need to make a copy of the picture, since it can
3652 // change after it has been drawn
3653 ServerPicture
* copy
= App()->CreatePicture(pictureToDraw
);
3654 picture
->NestPicture(copy
);
3655 picture
->WriteDrawPicture(where
, copy
->Token());
3657 pictureToDraw
->ReleaseReference();
3663 case AS_VIEW_SET_CLIP_REGION
:
3666 status_t status
= link
.Read
<int32
>(&rectCount
);
3667 // a negative count means no
3668 // region for the current draw state,
3669 // but an *empty* region is actually valid!
3670 // even if it means no drawing is allowed
3675 if (rectCount
>= 0) {
3676 // we are supposed to set the clipping region
3678 if (rectCount
> 0 && link
.ReadRegion(®ion
) < B_OK
)
3680 picture
->WriteSetClipping(region
);
3682 // we are supposed to clear the clipping region
3683 picture
->WriteClearClipping();
3688 case AS_VIEW_CLIP_TO_PICTURE
:
3692 bool inverse
= false;
3694 link
.Read
<int32
>(&pictureToken
);
3695 if (pictureToken
< 0)
3698 link
.Read
<BPoint
>(&where
);
3699 if (link
.Read
<bool>(&inverse
) != B_OK
)
3702 ServerPicture
* picture
= fServerApp
->GetPicture(pictureToken
);
3703 if (picture
== NULL
)
3706 picture
->WriteClipToPicture(picture
->Token(), where
, inverse
);
3708 picture
->ReleaseReference();
3712 case AS_VIEW_CLIP_TO_RECT
:
3716 link
.Read
<bool>(&inverse
);
3717 link
.Read
<BRect
>(&rect
);
3718 picture
->WriteClipToRect(rect
, inverse
);
3723 case AS_VIEW_CLIP_TO_SHAPE
:
3726 link
.Read
<bool>(&inverse
);
3729 link
.Read
<int32
>(&shape
.opCount
);
3730 link
.Read
<int32
>(&shape
.ptCount
);
3731 shape
.opSize
= shape
.opCount
* sizeof(uint32
);
3732 shape
.ptSize
= shape
.ptCount
* sizeof(BPoint
);
3733 shape
.opList
= new(nothrow
) uint32
[shape
.opCount
];
3734 shape
.ptList
= new(nothrow
) BPoint
[shape
.ptCount
];
3735 if (link
.Read(shape
.opList
, shape
.opSize
) >= B_OK
3736 && link
.Read(shape
.ptList
, shape
.ptSize
) >= B_OK
) {
3737 picture
->WriteClipToShape(shape
.opCount
, shape
.opList
,
3738 shape
.ptCount
, shape
.ptList
, inverse
);
3741 delete[] shape
.opList
;
3742 delete[] shape
.ptList
;
3746 case AS_VIEW_BEGIN_PICTURE
:
3748 ServerPicture
* newPicture
= App()->CreatePicture();
3749 if (newPicture
!= NULL
) {
3750 newPicture
->PushPicture(picture
);
3751 newPicture
->SyncState(fCurrentView
);
3752 fCurrentView
->SetPicture(newPicture
);
3757 case AS_VIEW_APPEND_TO_PICTURE
:
3760 link
.Read
<int32
>(&token
);
3762 ServerPicture
* appendPicture
= App()->GetPicture(token
);
3763 if (appendPicture
!= NULL
) {
3764 //picture->SyncState(fCurrentView);
3765 appendPicture
->AppendPicture(picture
);
3768 fCurrentView
->SetPicture(appendPicture
);
3770 if (appendPicture
!= NULL
)
3771 appendPicture
->ReleaseReference();
3775 case AS_VIEW_END_PICTURE
:
3777 ServerPicture
* poppedPicture
= picture
->PopPicture();
3778 fCurrentView
->SetPicture(poppedPicture
);
3779 if (poppedPicture
!= NULL
)
3780 poppedPicture
->ReleaseReference();
3782 fLink
.StartMessage(B_OK
);
3783 fLink
.Attach
<int32
>(picture
->Token());
3788 case AS_VIEW_BEGIN_LAYER
:
3791 link
.Read
<uint8
>(&opacity
);
3793 Layer
* layer
= dynamic_cast<Layer
*>(picture
);
3797 Layer
* nextLayer
= new(std::nothrow
) Layer(opacity
);
3798 if (nextLayer
== NULL
)
3801 if (opacity
!= 255) {
3802 fCurrentView
->CurrentState()->SetDrawingMode(B_OP_ALPHA
);
3803 fCurrentView
->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA
,
3805 fCurrentView
->CurrentState()->SetDrawingModeLocked(true);
3808 nextLayer
->PushLayer(layer
);
3809 fCurrentView
->SetPicture(nextLayer
);
3813 case AS_VIEW_END_LAYER
:
3815 Layer
* layer
= dynamic_cast<Layer
*>(picture
);
3819 Layer
* previousLayer
= layer
->PopLayer();
3820 if (previousLayer
== NULL
) {
3824 fCurrentView
->SetPicture(previousLayer
);
3826 previousLayer
->WriteBlendLayer(layer
);
3831 case AS_VIEW_SET_BLENDING_MODE:
3833 ViewBlendingModeInfo info;
3834 link.Read<ViewBlendingModeInfo>(&info);
3836 picture->BeginOp(B_PIC_SET_BLENDING_MODE);
3837 picture->AddInt16((int16)info.sourceAlpha);
3838 picture->AddInt16((int16)info.alphaFunction);
3841 fCurrentView->CurrentState()->SetBlendingMode(info.sourceAlpha,
3842 info.alphaFunction);
3843 fWindow->GetDrawingEngine()->SetBlendingMode(info.sourceAlpha,
3844 info.alphaFunction);
3851 if (link
.NeedsReply()) {
3852 fLink
.StartMessage(B_ERROR
);
3859 /*! \brief Message-dispatching loop for the ServerWindow
3861 Watches the ServerWindow's message port and dispatches as necessary
3864 ServerWindow::_MessageLooper()
3866 // Send a reply to our window - it is expecting fMessagePort
3867 // port and some other info.
3869 fLink
.StartMessage(B_OK
);
3870 fLink
.Attach
<port_id
>(fMessagePort
);
3872 int32 minWidth
, maxWidth
, minHeight
, maxHeight
;
3873 fWindow
->GetSizeLimits(&minWidth
, &maxWidth
, &minHeight
, &maxHeight
);
3875 fLink
.Attach
<BRect
>(fWindow
->Frame());
3876 fLink
.Attach
<float>((float)minWidth
);
3877 fLink
.Attach
<float>((float)maxWidth
);
3878 fLink
.Attach
<float>((float)minHeight
);
3879 fLink
.Attach
<float>((float)maxHeight
);
3882 BPrivate::LinkReceiver
& receiver
= fLink
.Receiver();
3883 bool quitLoop
= false;
3886 //STRACE(("info: ServerWindow::MonitorWin listening on port %ld.\n",
3890 status_t status
= receiver
.GetNextMessage(code
);
3891 if (status
!= B_OK
) {
3892 // that shouldn't happen, it's our port
3893 printf("Someone deleted our message port!\n");
3895 // try to let our client die happily
3896 NotifyQuitRequested();
3900 #ifdef PROFILE_MESSAGE_LOOP
3901 bigtime_t start
= system_time();
3906 #ifdef PROFILE_MESSAGE_LOOP
3907 bigtime_t diff
= system_time() - start
;
3909 printf("ServerWindow %s: lock acquisition took %" B_PRId64
" usecs\n",
3914 int32 messagesProcessed
= 0;
3915 bigtime_t processingStart
= system_time();
3916 bool lockedDesktopSingleWindow
= false;
3919 if (code
== AS_DELETE_WINDOW
|| code
== kMsgQuitLooper
) {
3920 // this means the client has been killed
3921 DTRACE(("ServerWindow %s received 'AS_DELETE_WINDOW' message "
3922 "code\n", Title()));
3924 if (code
== AS_DELETE_WINDOW
) {
3925 fLink
.StartMessage(B_OK
);
3929 if (lockedDesktopSingleWindow
)
3930 fDesktop
->UnlockSingleWindow();
3934 // ServerWindow's destructor takes care of pulling this object
3936 ASSERT(fWindow
->IsHidden());
3940 // Acquire the appropriate lock
3941 bool needsAllWindowsLocked
= _MessageNeedsAllWindowsLocked(code
);
3942 if (needsAllWindowsLocked
) {
3943 // We may already still hold the read-lock from the previous
3944 // inner-loop iteration.
3945 if (lockedDesktopSingleWindow
) {
3946 fDesktop
->UnlockSingleWindow();
3947 lockedDesktopSingleWindow
= false;
3949 fDesktop
->LockAllWindows();
3951 // We never keep the write-lock across inner-loop iterations,
3952 // so there is nothing else to do besides read-locking unless
3953 // we already have the read-lock from the previous iteration.
3954 if (!lockedDesktopSingleWindow
) {
3955 fDesktop
->LockSingleWindow();
3956 lockedDesktopSingleWindow
= true;
3960 if (atomic_and(&fRedrawRequested
, 0) != 0) {
3961 #ifdef PROFILE_MESSAGE_LOOP
3962 bigtime_t redrawStart
= system_time();
3964 fWindow
->RedrawDirtyRegion();
3965 #ifdef PROFILE_MESSAGE_LOOP
3966 diff
= system_time() - redrawStart
;
3967 atomic_add(&sRedrawProcessingTime
.count
, 1);
3968 # ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
3969 atomic_add64(&sRedrawProcessingTime
.time
, diff
);
3971 sRedrawProcessingTime
.time
+= diff
;
3976 #ifdef PROFILE_MESSAGE_LOOP
3977 bigtime_t dispatchStart
= system_time();
3979 _DispatchMessage(code
, receiver
);
3981 #ifdef PROFILE_MESSAGE_LOOP
3982 if (code
>= 0 && code
< AS_LAST_CODE
) {
3983 diff
= system_time() - dispatchStart
;
3984 atomic_add(&sMessageProfile
[code
].count
, 1);
3985 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
3986 atomic_add64(&sMessageProfile
[code
].time
, diff
);
3988 sMessageProfile
[code
].time
+= diff
;
3991 printf("ServerWindow %s: message %" B_PRId32
" took %"
3992 B_PRId64
" usecs\n", Title(), code
, diff
);
3997 if (needsAllWindowsLocked
)
3998 fDesktop
->UnlockAllWindows();
4000 // Only process up to 70 waiting messages at once (we have the
4001 // Desktop locked), but don't hold the lock longer than 10 ms
4002 if (!receiver
.HasMessages() || ++messagesProcessed
> 70
4003 || system_time() - processingStart
> 10000) {
4004 if (lockedDesktopSingleWindow
)
4005 fDesktop
->UnlockSingleWindow();
4010 status_t status
= receiver
.GetNextMessage(code
);
4011 if (status
!= B_OK
) {
4012 // that shouldn't happen, it's our port
4013 printf("Someone deleted our message port!\n");
4014 if (lockedDesktopSingleWindow
)
4015 fDesktop
->UnlockSingleWindow();
4017 // try to let our client die happily
4018 NotifyQuitRequested();
4026 // We were asked to quit the message loop - either on request or because of
4034 ServerWindow::ScreenChanged(const BMessage
* message
)
4036 SendMessageToClient(message
);
4038 if (fDirectWindowInfo
!= NULL
&& fDirectWindowInfo
->IsFullScreen())
4039 _ResizeToFullScreen();
4044 ServerWindow::SendMessageToClient(const BMessage
* msg
, int32 target
) const
4046 if (target
== B_NULL_TOKEN
)
4047 target
= fClientToken
;
4050 BMessage::Private
messagePrivate((BMessage
*)msg
);
4051 return messagePrivate
.SendMessage(fClientLooperPort
, fClientTeam
, target
,
4057 ServerWindow::MakeWindow(BRect frame
, const char* name
,
4058 window_look look
, window_feel feel
, uint32 flags
, uint32 workspace
)
4060 // The non-offscreen ServerWindow uses the DrawingEngine instance from
4062 return new(std::nothrow
) ::Window(frame
, name
, look
, feel
, flags
,
4063 workspace
, this, fDesktop
->HWInterface()->CreateDrawingEngine());
4068 ServerWindow::HandleDirectConnection(int32 bufferState
, int32 driverState
)
4070 ASSERT_MULTI_LOCKED(fDesktop
->WindowLocker());
4072 if (fDirectWindowInfo
== NULL
)
4075 STRACE(("HandleDirectConnection(bufferState = %" B_PRId32
", driverState = "
4076 "%" B_PRId32
")\n", bufferState
, driverState
));
4078 status_t status
= fDirectWindowInfo
->SetState(
4079 (direct_buffer_state
)bufferState
, (direct_driver_state
)driverState
,
4080 fDesktop
->HWInterface()->FrontBuffer(), fWindow
->Frame(),
4081 fWindow
->VisibleContentRegion());
4083 if (status
!= B_OK
) {
4084 char errorString
[256];
4085 snprintf(errorString
, sizeof(errorString
),
4086 "%s killed for a problem in DirectConnected(): %s",
4087 App()->Signature(), strerror(status
));
4088 syslog(LOG_ERR
, errorString
);
4090 // The client application didn't release the semaphore
4091 // within the given timeout. Or something else went wrong.
4092 // Deleting this member should make it crash.
4093 delete fDirectWindowInfo
;
4094 fDirectWindowInfo
= NULL
;
4095 } else if ((bufferState
& B_DIRECT_MODE_MASK
) == B_DIRECT_START
)
4096 fIsDirectlyAccessing
= true;
4097 else if ((bufferState
& B_DIRECT_MODE_MASK
) == B_DIRECT_STOP
)
4098 fIsDirectlyAccessing
= false;
4103 ServerWindow::_SetCurrentView(View
* view
)
4105 if (fCurrentView
== view
)
4108 fCurrentView
= view
;
4109 fCurrentDrawingRegionValid
= false;
4110 _UpdateDrawState(fCurrentView
);
4113 #if DELAYED_BACKGROUND_CLEARING
4114 if (fCurrentView
&& fCurrentView
->IsBackgroundDirty()
4115 && fWindow
->InUpdate()) {
4116 DrawingEngine
* drawingEngine
= fWindow
->GetDrawingEngine();
4117 if (drawingEngine
->LockParallelAccess()) {
4118 fWindow
->GetEffectiveDrawingRegion(fCurrentView
,
4119 fCurrentDrawingRegion
);
4120 fCurrentDrawingRegionValid
= true;
4121 BRegion
dirty(fCurrentDrawingRegion
);
4124 fWindow
->GetContentRegion(&content
);
4126 fCurrentView
->Draw(drawingEngine
, &dirty
, &content
, false);
4128 drawingEngine
->UnlockParallelAccess();
4137 ServerWindow::_UpdateDrawState(View
* view
)
4139 // switch the drawing state
4140 // TODO: is it possible to scroll a view while it
4141 // is being drawn? probably not... otherwise the
4142 // "offsets" passed below would need to be updated again
4143 DrawingEngine
* drawingEngine
= fWindow
->GetDrawingEngine();
4144 if (view
!= NULL
&& drawingEngine
!= NULL
) {
4145 BPoint
leftTop(0, 0);
4146 if (view
->GetAlphaMask() != NULL
) {
4147 view
->LocalToScreenTransform().Apply(&leftTop
);
4148 view
->GetAlphaMask()->SetCanvasGeometry(leftTop
, view
->Bounds());
4149 leftTop
= BPoint(0, 0);
4151 view
->PenToScreenTransform().Apply(&leftTop
);
4152 drawingEngine
->SetDrawState(view
->CurrentState(), leftTop
.x
, leftTop
.y
);
4158 ServerWindow::_UpdateCurrentDrawingRegion()
4160 if (!fCurrentDrawingRegionValid
4161 || fWindow
->DrawingRegionChanged(fCurrentView
)) {
4162 fWindow
->GetEffectiveDrawingRegion(fCurrentView
, fCurrentDrawingRegion
);
4163 fCurrentDrawingRegionValid
= true;
4169 ServerWindow::_MessageNeedsAllWindowsLocked(uint32 code
) const
4172 case AS_SET_WINDOW_TITLE
:
4173 case AS_ADD_TO_SUBSET
:
4174 case AS_REMOVE_FROM_SUBSET
:
4175 case AS_VIEW_CREATE_ROOT
:
4176 case AS_VIEW_CREATE
:
4177 case AS_SEND_BEHIND
:
4181 case AS_SET_WORKSPACES
:
4182 case AS_WINDOW_MOVE
:
4183 case AS_WINDOW_RESIZE
:
4184 case AS_SET_SIZE_LIMITS
:
4185 case AS_SYSTEM_FONT_CHANGED
:
4186 case AS_SET_DECORATOR_SETTINGS
:
4188 case AS_DIRECT_WINDOW_SET_FULLSCREEN
:
4189 // case AS_VIEW_SET_EVENT_MASK:
4190 // case AS_VIEW_SET_MOUSE_EVENT_MASK:
4191 case AS_TALK_TO_DESKTOP_LISTENER
:
4200 ServerWindow::_ResizeToFullScreen()
4205 AutoReadLocker
_(fDesktop
->ScreenLocker());
4206 const Screen
* screen
= fWindow
->Screen();
4210 screenFrame
= fWindow
->Screen()->Frame();
4213 fDesktop
->MoveWindowBy(fWindow
,
4214 screenFrame
.left
- fWindow
->Frame().left
,
4215 screenFrame
.top
- fWindow
->Frame().top
);
4216 fDesktop
->ResizeWindowBy(fWindow
,
4217 screenFrame
.Width() - fWindow
->Frame().Width(),
4218 screenFrame
.Height() - fWindow
->Frame().Height());
4223 ServerWindow::_EnableDirectWindowMode()
4225 if (fDirectWindowInfo
!= NULL
) {
4226 // already in direct window mode
4230 if (fDesktop
->HWInterface()->FrontBuffer() == NULL
) {
4231 // direct window mode not supported
4232 return B_UNSUPPORTED
;
4235 fDirectWindowInfo
= new(std::nothrow
) DirectWindowInfo
;
4236 if (fDirectWindowInfo
== NULL
)
4239 status_t status
= fDirectWindowInfo
->InitCheck();
4240 if (status
!= B_OK
) {
4241 delete fDirectWindowInfo
;
4242 fDirectWindowInfo
= NULL
;
4252 ServerWindow::_DirectWindowSetFullScreen(bool enable
)
4254 window_feel feel
= kWindowScreenFeel
;
4257 fDesktop
->HWInterface()->SetCursorVisible(false);
4259 fDirectWindowInfo
->EnableFullScreen(fWindow
->Frame(), fWindow
->Feel());
4260 _ResizeToFullScreen();
4262 const BRect
& originalFrame
= fDirectWindowInfo
->OriginalFrame();
4264 fDirectWindowInfo
->DisableFullScreen();
4266 // Resize window back to its original size
4267 fDesktop
->MoveWindowBy(fWindow
,
4268 originalFrame
.left
- fWindow
->Frame().left
,
4269 originalFrame
.top
- fWindow
->Frame().top
);
4270 fDesktop
->ResizeWindowBy(fWindow
,
4271 originalFrame
.Width() - fWindow
->Frame().Width(),
4272 originalFrame
.Height() - fWindow
->Frame().Height());
4274 fDesktop
->HWInterface()->SetCursorVisible(true);
4277 fDesktop
->SetWindowFeel(fWindow
, feel
);