2 * Copyright 2009-2014, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
9 #include "NetReceiver.h"
10 #include "NetSender.h"
11 #include "RemoteMessage.h"
12 #include "RemoteView.h"
13 #include "StreamingRingBuffer.h"
15 #include <Application.h>
19 #include <NetEndpoint.h>
23 #include <utf8_functions.h>
29 static const uint8 kCursorData
[] = { 16 /* size, 16x16 */,
30 1 /* depth, 1 bit per pixel */, 0, 0, /* hot spot at 0, 0 */
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
42 #define TRACE(x...) /*printf("RemoteView: " x)*/
43 #define TRACE_ALWAYS(x...) printf("RemoteView: " x)
44 #define TRACE_ERROR(x...) printf("RemoteView: " x)
47 typedef struct engine_state
{
51 BRegion clipping_region
;
57 RemoteView::RemoteView(BRect frame
, const char *remoteHost
, uint16 remotePort
)
59 BView(frame
, "RemoteView", B_FOLLOW_NONE
, B_WILL_DRAW
),
60 fInitStatus(B_NO_INIT
),
68 fOffscreenBitmap(NULL
),
70 fViewCursor(kCursorData
),
74 fReceiveBuffer
= new(std::nothrow
) StreamingRingBuffer(16 * 1024);
75 if (fReceiveBuffer
== NULL
) {
76 fInitStatus
= B_NO_MEMORY
;
77 TRACE_ERROR("no memory available\n");
81 fInitStatus
= fReceiveBuffer
->InitCheck();
82 if (fInitStatus
!= B_OK
)
85 fSendBuffer
= new(std::nothrow
) StreamingRingBuffer(16 * 1024);
86 if (fSendBuffer
== NULL
) {
87 fInitStatus
= B_NO_MEMORY
;
88 TRACE_ERROR("no memory available\n");
92 fInitStatus
= fSendBuffer
->InitCheck();
93 if (fInitStatus
!= B_OK
)
96 fEndpoint
= new(std::nothrow
) BNetEndpoint();
97 if (fEndpoint
== NULL
) {
98 fInitStatus
= B_NO_MEMORY
;
99 TRACE_ERROR("no memory available\n");
103 fInitStatus
= fEndpoint
->Connect(remoteHost
, remotePort
);
104 if (fInitStatus
!= B_OK
) {
105 TRACE_ERROR("failed to connect to %s:%" B_PRIu16
"\n",
106 remoteHost
, remotePort
);
110 fSender
= new(std::nothrow
) NetSender(fEndpoint
, fSendBuffer
);
111 if (fSender
== NULL
) {
112 fInitStatus
= B_NO_MEMORY
;
113 TRACE_ERROR("no memory available\n");
117 fReceiver
= new(std::nothrow
) NetReceiver(fEndpoint
, fReceiveBuffer
);
118 if (fReceiver
== NULL
) {
119 fInitStatus
= B_NO_MEMORY
;
120 TRACE_ERROR("no memory available\n");
124 BRect bounds
= frame
.OffsetToCopy(0, 0);
125 fOffscreenBitmap
= new(std::nothrow
) BBitmap(bounds
, B_BITMAP_ACCEPTS_VIEWS
,
127 if (fOffscreenBitmap
== NULL
) {
128 fInitStatus
= B_NO_MEMORY
;
129 TRACE_ERROR("no memory available\n");
133 fOffscreen
= new(std::nothrow
) BView(bounds
, "offscreen remote view",
134 B_FOLLOW_NONE
, B_WILL_DRAW
);
135 if (fOffscreen
== NULL
) {
136 fInitStatus
= B_NO_MEMORY
;
137 TRACE_ERROR("no memory available\n");
141 fOffscreenBitmap
->AddChild(fOffscreen
);
142 fOffscreen
->SetDrawingMode(B_OP_COPY
);
144 fDrawThread
= spawn_thread(&_DrawEntry
, "draw thread", B_NORMAL_PRIORITY
,
146 if (fDrawThread
< 0) {
147 fInitStatus
= fDrawThread
;
149 TRACE_ERROR("failed to start _DrawThread()\n");
150 TRACE_ERROR("status = %" B_PRIx32
"\n", fInitStatus
);
155 resume_thread(fDrawThread
);
159 RemoteView::~RemoteView()
164 delete fReceiveBuffer
;
171 delete fOffscreenBitmap
;
172 delete fCursorBitmap
;
175 wait_for_thread(fDrawThread
, &result
);
180 RemoteView::InitCheck()
187 RemoteView::AttachedToWindow()
189 SetViewColor(B_TRANSPARENT_COLOR
);
190 SetViewCursor(&fViewCursor
);
195 RemoteView::Draw(BRect updateRect
)
197 SetDrawingMode(B_OP_COPY
);
198 fOffscreenBitmap
->Lock();
201 DrawBitmap(fOffscreenBitmap
, updateRect
, updateRect
);
203 if (fCursorVisible
&& fCursorBitmap
!= NULL
204 && fCursorFrame
.Intersects(updateRect
)) {
205 DrawBitmap(fOffscreenBitmap
, fCursorFrame
, fCursorFrame
);
206 SetDrawingMode(B_OP_ALPHA
);
207 DrawBitmap(fCursorBitmap
, fCursorFrame
.LeftTop());
210 fOffscreenBitmap
->Unlock();
215 RemoteView::MouseMoved(BPoint where
, uint32 code
, const BMessage
*dragMessage
)
220 _SendMouseMessage(RP_MOUSE_MOVED
, where
);
225 RemoteView::MouseDown(BPoint where
)
230 _SendMouseMessage(RP_MOUSE_DOWN
, where
);
235 RemoteView::MouseUp(BPoint where
)
240 _SendMouseMessage(RP_MOUSE_UP
, where
);
245 RemoteView::KeyDown(const char *bytes
, int32 numBytes
)
250 _SendKeyMessage(RP_KEY_DOWN
, bytes
, numBytes
);
255 RemoteView::KeyUp(const char *bytes
, int32 numBytes
)
260 _SendKeyMessage(RP_KEY_UP
, bytes
, numBytes
);
265 RemoteView::MessageReceived(BMessage
*message
)
268 BView::MessageReceived(message
);
272 switch (message
->what
) {
273 case B_UNMAPPED_KEY_DOWN
:
274 case B_UNMAPPED_KEY_UP
:
275 // these are easily repeated and then cause a flood of messages
276 // so we might not want them.
279 case B_MODIFIERS_CHANGED
:
281 uint32 modifiers
= 0;
282 message
->FindInt32("modifiers", (int32
*)&modifiers
);
283 RemoteMessage
message(NULL
, fSendBuffer
);
284 message
.Start(RP_MODIFIERS_CHANGED
);
285 message
.Add(modifiers
);
289 case B_MOUSE_WHEEL_CHANGED
:
291 float xDelta
, yDelta
;
292 if (message
->FindFloat("be:wheel_delta_x", &xDelta
) != B_OK
)
294 if (message
->FindFloat("be:wheel_delta_y", &yDelta
) != B_OK
)
297 RemoteMessage
message(NULL
, fSendBuffer
);
298 message
.Start(RP_MOUSE_WHEEL_CHANGED
);
305 BView::MessageReceived(message
);
310 RemoteView::_SendMouseMessage(uint16 code
, BPoint where
)
312 RemoteMessage
message(NULL
, fSendBuffer
);
316 if (code
== RP_MOUSE_MOVED
)
319 BMessage
*event
= Window()->CurrentMessage();
322 event
->FindInt32("buttons", &buttons
);
323 message
.Add(buttons
);
325 if (code
== RP_MOUSE_DOWN
)
329 event
->FindInt32("clicks", &clicks
);
335 RemoteView::_SendKeyMessage(uint16 code
, const char *bytes
, int32 numBytes
)
337 RemoteMessage
message(NULL
, fSendBuffer
);
339 message
.Add(numBytes
);
340 message
.AddList(bytes
, numBytes
);
342 BMessage
*event
= Window()->CurrentMessage();
345 event
->FindInt32("raw_char", &rawChar
);
346 event
->FindInt32("key", &key
);
348 message
.Add(rawChar
);
354 RemoteView::_StateCompareByKey(const uint32
*key
, const engine_state
*state
)
356 if (state
->token
== *key
)
359 if (state
->token
< *key
)
367 RemoteView::_CreateState(uint32 token
)
369 int32 index
= fStates
.BinarySearchIndexByKey(token
, &_StateCompareByKey
);
371 TRACE_ERROR("state for token %" B_PRIu32
" already in list\n", token
);
375 engine_state
*state
= new(std::nothrow
) engine_state
;
377 TRACE_ERROR("failed to allocate engine state\n");
381 fOffscreenBitmap
->Lock();
382 BView
*offscreen
= new(std::nothrow
) BView(fOffscreenBitmap
->Bounds(),
383 "offscreen remote view", B_FOLLOW_NONE
, B_WILL_DRAW
);
384 if (offscreen
== NULL
) {
385 TRACE_ERROR("failed to allocate offscreen view\n");
386 fOffscreenBitmap
->Unlock();
391 fOffscreenBitmap
->AddChild(offscreen
);
392 fOffscreenBitmap
->Unlock();
394 state
->token
= token
;
395 state
->view
= offscreen
;
396 state
->pattern
= B_SOLID_HIGH
;
397 state
->clipping_region
.MakeEmpty();
399 state
->sync_drawing
= true;
401 fStates
.AddItem(state
, -index
- 1);
407 RemoteView::_DeleteState(uint32 token
)
409 int32 index
= fStates
.BinarySearchIndexByKey(token
, &_StateCompareByKey
);
413 engine_state
*state
= fStates
.RemoveItemAt(index
);
415 fOffscreenBitmap
->RemoveChild(state
->view
);
422 RemoteView::_FindState(uint32 token
)
424 return fStates
.BinarySearchByKey(token
, &_StateCompareByKey
);
429 RemoteView::_DrawEntry(void *data
)
431 ((RemoteView
*)data
)->_DrawThread();
437 RemoteView::_DrawThread()
439 RemoteMessage
reply(NULL
, fSendBuffer
);
440 RemoteMessage
message(fReceiveBuffer
, NULL
);
443 BPoint
cursorHotSpot(0, 0);
445 reply
.Start(RP_INIT_CONNECTION
);
448 while (!fStopThread
) {
450 status_t status
= message
.NextMessage(code
);
452 if (status
!= B_OK
) {
453 if (status
== B_TIMED_OUT
|| status
== -1) {
454 TRACE_ERROR("could not connect to device\n");
456 TRACE_ERROR("failed to read message from receiver\n");
461 TRACE("code %u with %ld bytes data\n", code
, message
.DataLeft());
463 BAutolock
locker(this->Looper());
464 if (!locker
.IsLocked())
467 // handle stuff that doesn't go to a specific engine
469 case RP_INIT_CONNECTION
:
471 BRect bounds
= fOffscreenBitmap
->Bounds();
472 reply
.Start(RP_UPDATE_DISPLAY_MODE
);
473 reply
.Add(bounds
.IntegerWidth() + 1);
474 reply
.Add(bounds
.IntegerHeight() + 1);
475 if (reply
.Flush() == B_OK
)
481 case RP_CLOSE_CONNECTION
:
483 be_app
->PostMessage(B_QUIT_REQUESTED
);
487 case RP_CREATE_STATE
:
488 case RP_DELETE_STATE
:
493 if (code
== RP_CREATE_STATE
)
504 BPoint oldHotSpot
= cursorHotSpot
;
505 message
.Read(cursorHotSpot
);
506 if (message
.ReadBitmap(&bitmap
) != B_OK
)
509 delete fCursorBitmap
;
510 fCursorBitmap
= bitmap
;
512 Invalidate(fCursorFrame
);
514 BRect bounds
= fCursorBitmap
->Bounds();
515 fCursorFrame
.right
= fCursorFrame
.left
516 + bounds
.IntegerWidth() + 1;
517 fCursorFrame
.bottom
= fCursorFrame
.bottom
518 + bounds
.IntegerHeight() + 1;
520 fCursorFrame
.OffsetBy(oldHotSpot
- cursorHotSpot
);
522 Invalidate(fCursorFrame
);
526 case RP_SET_CURSOR_VISIBLE
:
528 bool wasVisible
= fCursorVisible
;
529 message
.Read(fCursorVisible
);
530 if (wasVisible
!= fCursorVisible
)
531 Invalidate(fCursorFrame
);
535 case RP_MOVE_CURSOR_TO
:
538 message
.Read(position
);
541 Invalidate(fCursorFrame
);
543 fCursorFrame
.OffsetTo(position
- cursorHotSpot
);
545 Invalidate(fCursorFrame
);
549 case RP_INVALIDATE_RECT
:
552 if (message
.Read(rect
) != B_OK
)
559 case RP_INVALIDATE_REGION
:
562 if (message
.ReadRegion(region
) != B_OK
)
569 case RP_FILL_REGION_COLOR_NO_CLIPPING
:
574 message
.ReadRegion(region
);
575 if (message
.Read(color
) != B_OK
)
578 fOffscreen
->LockLooper();
579 fOffscreen
->SetHighColor(color
);
580 fOffscreen
->FillRegion(®ion
);
581 fOffscreen
->UnlockLooper();
586 case RP_COPY_RECT_NO_CLIPPING
:
588 int32 xOffset
, yOffset
;
591 message
.Read(xOffset
);
592 message
.Read(yOffset
);
593 if (message
.Read(rect
) != B_OK
)
596 BRect dest
= rect
.OffsetByCopy(xOffset
, yOffset
);
597 fOffscreen
->LockLooper();
598 fOffscreen
->CopyBits(rect
, dest
);
599 fOffscreen
->UnlockLooper();
607 engine_state
*state
= _FindState(token
);
609 TRACE_ERROR("didn't find state for token %" B_PRIu32
"\n", token
);
610 state
= _CreateState(token
);
612 TRACE_ERROR("failed to create state for unknown token\n");
617 BView
*offscreen
= state
->view
;
618 ::pattern
&pattern
= state
->pattern
;
619 BRegion
&clippingRegion
= state
->clipping_region
;
620 float &penSize
= state
->pen_size
;
621 bool &syncDrawing
= state
->sync_drawing
;
622 BRegion invalidRegion
;
624 BAutolock
offscreenLocker(offscreen
->Looper());
625 if (!offscreenLocker
.IsLocked())
629 case RP_ENABLE_SYNC_DRAWING
:
633 case RP_DISABLE_SYNC_DRAWING
:
639 int32 xOffset
, yOffset
;
640 message
.Read(xOffset
);
641 if (message
.Read(yOffset
) != B_OK
)
644 offscreen
->MovePenTo(xOffset
, yOffset
);
648 case RP_SET_HIGH_COLOR
:
649 case RP_SET_LOW_COLOR
:
652 if (message
.Read(color
) != B_OK
)
655 if (code
== RP_SET_HIGH_COLOR
)
656 offscreen
->SetHighColor(color
);
658 offscreen
->SetLowColor(color
);
663 case RP_SET_PEN_SIZE
:
666 if (message
.Read(newPenSize
) != B_OK
)
669 offscreen
->SetPenSize(newPenSize
);
670 penSize
= newPenSize
/ 2;
674 case RP_SET_STROKE_MODE
:
680 message
.Read(capMode
);
681 message
.Read(joinMode
);
682 if (message
.Read(miterLimit
) != B_OK
)
685 offscreen
->SetLineMode(capMode
, joinMode
, miterLimit
);
689 case RP_SET_BLENDING_MODE
:
691 source_alpha sourceAlpha
;
692 alpha_function alphaFunction
;
694 message
.Read(sourceAlpha
);
695 if (message
.Read(alphaFunction
) != B_OK
)
698 offscreen
->SetBlendingMode(sourceAlpha
, alphaFunction
);
702 case RP_SET_TRANSFORM
:
704 BAffineTransform transform
;
705 if (message
.ReadTransform(transform
) != B_OK
)
708 offscreen
->SetTransform(transform
);
714 if (message
.Read(pattern
) != B_OK
)
719 case RP_SET_DRAWING_MODE
:
721 drawing_mode drawingMode
;
722 if (message
.Read(drawingMode
) != B_OK
)
725 offscreen
->SetDrawingMode(drawingMode
);
732 if (message
.ReadFontState(font
) != B_OK
)
735 offscreen
->SetFont(&font
);
739 case RP_CONSTRAIN_CLIPPING_REGION
:
741 if (message
.ReadRegion(clippingRegion
) != B_OK
)
744 offscreen
->ConstrainClippingRegion(&clippingRegion
);
751 if (message
.Read(rect
) != B_OK
)
754 offscreen
->InvertRect(rect
);
755 invalidRegion
.Include(rect
);
762 BRect bitmapRect
, viewRect
;
765 message
.Read(bitmapRect
);
766 message
.Read(viewRect
);
767 message
.Read(options
);
768 if (message
.ReadBitmap(&bitmap
) != B_OK
|| bitmap
== NULL
)
771 offscreen
->DrawBitmap(bitmap
, bitmapRect
, viewRect
, options
);
772 invalidRegion
.Include(viewRect
);
777 case RP_DRAW_BITMAP_RECTS
:
779 color_space colorSpace
;
781 uint32 flags
, options
;
783 message
.Read(options
);
784 message
.Read(colorSpace
);
786 message
.Read(rectCount
);
787 for (int32 i
= 0; i
< rectCount
; i
++) {
791 message
.Read(viewRect
);
792 if (message
.ReadBitmap(&bitmap
, true, colorSpace
,
793 flags
) != B_OK
|| bitmap
== NULL
) {
797 offscreen
->DrawBitmap(bitmap
, bitmap
->Bounds(), viewRect
,
799 invalidRegion
.Include(viewRect
);
808 case RP_FILL_ARC_GRADIENT
:
815 if (message
.Read(span
) != B_OK
)
818 if (code
== RP_STROKE_ARC
) {
819 offscreen
->StrokeArc(rect
, angle
, span
, pattern
);
820 rect
.InsetBy(-penSize
, -penSize
);
821 } else if (code
== RP_FILL_ARC
)
822 offscreen
->FillArc(rect
, angle
, span
, pattern
);
825 if (message
.ReadGradient(&gradient
) != B_OK
)
828 offscreen
->FillArc(rect
, angle
, span
, *gradient
);
832 invalidRegion
.Include(rect
);
836 case RP_STROKE_BEZIER
:
838 case RP_FILL_BEZIER_GRADIENT
:
841 if (message
.ReadList(points
, 4) != B_OK
)
844 BRect bounds
= _BuildInvalidateRect(points
, 4);
845 if (code
== RP_STROKE_BEZIER
) {
846 offscreen
->StrokeBezier(points
, pattern
);
847 bounds
.InsetBy(-penSize
, -penSize
);
848 } else if (code
== RP_FILL_BEZIER
)
849 offscreen
->FillBezier(points
, pattern
);
852 if (message
.ReadGradient(&gradient
) != B_OK
)
855 offscreen
->FillBezier(points
, *gradient
);
859 invalidRegion
.Include(bounds
);
863 case RP_STROKE_ELLIPSE
:
864 case RP_FILL_ELLIPSE
:
865 case RP_FILL_ELLIPSE_GRADIENT
:
868 if (message
.Read(rect
) != B_OK
)
871 if (code
== RP_STROKE_ELLIPSE
) {
872 offscreen
->StrokeEllipse(rect
, pattern
);
873 rect
.InsetBy(-penSize
, -penSize
);
874 } else if (code
== RP_FILL_ELLIPSE
)
875 offscreen
->FillEllipse(rect
, pattern
);
878 if (message
.ReadGradient(&gradient
) != B_OK
)
881 offscreen
->FillEllipse(rect
, *gradient
);
885 invalidRegion
.Include(rect
);
889 case RP_STROKE_POLYGON
:
890 case RP_FILL_POLYGON
:
891 case RP_FILL_POLYGON_GRADIENT
:
897 message
.Read(bounds
);
898 message
.Read(closed
);
899 if (message
.Read(numPoints
) != B_OK
)
902 BPoint points
[numPoints
];
903 for (int32 i
= 0; i
< numPoints
; i
++)
904 message
.Read(points
[i
]);
906 if (code
== RP_STROKE_POLYGON
) {
907 offscreen
->StrokePolygon(points
, numPoints
, bounds
, closed
,
909 bounds
.InsetBy(-penSize
, -penSize
);
910 } else if (code
== RP_FILL_POLYGON
)
911 offscreen
->FillPolygon(points
, numPoints
, bounds
, pattern
);
914 if (message
.ReadGradient(&gradient
) != B_OK
)
917 offscreen
->FillPolygon(points
, numPoints
, bounds
,
922 invalidRegion
.Include(bounds
);
928 case RP_FILL_RECT_GRADIENT
:
931 if (message
.Read(rect
) != B_OK
)
934 if (code
== RP_STROKE_RECT
) {
935 offscreen
->StrokeRect(rect
, pattern
);
936 rect
.InsetBy(-penSize
, -penSize
);
937 } else if (code
== RP_FILL_RECT
)
938 offscreen
->FillRect(rect
, pattern
);
941 if (message
.ReadGradient(&gradient
) != B_OK
)
944 offscreen
->FillRect(rect
, *gradient
);
948 invalidRegion
.Include(rect
);
952 case RP_STROKE_ROUND_RECT
:
953 case RP_FILL_ROUND_RECT
:
954 case RP_FILL_ROUND_RECT_GRADIENT
:
957 float xRadius
, yRadius
;
960 message
.Read(xRadius
);
961 if (message
.Read(yRadius
) != B_OK
)
964 if (code
== RP_STROKE_ROUND_RECT
) {
965 offscreen
->StrokeRoundRect(rect
, xRadius
, yRadius
,
967 rect
.InsetBy(-penSize
, -penSize
);
968 } else if (code
== RP_FILL_ROUND_RECT
)
969 offscreen
->FillRoundRect(rect
, xRadius
, yRadius
, pattern
);
972 if (message
.ReadGradient(&gradient
) != B_OK
)
975 offscreen
->FillRoundRect(rect
, xRadius
, yRadius
,
980 invalidRegion
.Include(rect
);
984 case RP_STROKE_SHAPE
:
986 case RP_FILL_SHAPE_GRADIENT
:
989 int32 opCount
, pointCount
;
991 message
.Read(bounds
);
992 if (message
.Read(opCount
) != B_OK
)
996 for (int32 i
= 0; i
< opCount
; i
++) {
999 archive
.AddInt32("ops", op
);
1002 if (message
.Read(pointCount
) != B_OK
)
1005 for (int32 i
= 0; i
< pointCount
; i
++) {
1007 message
.Read(point
);
1008 archive
.AddPoint("pts", point
);
1012 message
.Read(offset
);
1015 if (message
.Read(scale
) != B_OK
)
1018 offscreen
->PushState();
1019 offscreen
->MovePenTo(offset
);
1020 offscreen
->SetScale(scale
);
1022 BShape
shape(&archive
);
1023 if (code
== RP_STROKE_SHAPE
) {
1024 offscreen
->StrokeShape(&shape
, pattern
);
1025 bounds
.InsetBy(-penSize
, -penSize
);
1026 } else if (code
== RP_FILL_SHAPE
)
1027 offscreen
->FillShape(&shape
, pattern
);
1029 BGradient
*gradient
;
1030 if (message
.ReadGradient(&gradient
) != B_OK
) {
1031 offscreen
->PopState();
1035 offscreen
->FillShape(&shape
, *gradient
);
1039 offscreen
->PopState();
1040 invalidRegion
.Include(bounds
);
1044 case RP_STROKE_TRIANGLE
:
1045 case RP_FILL_TRIANGLE
:
1046 case RP_FILL_TRIANGLE_GRADIENT
:
1051 message
.ReadList(points
, 3);
1052 if (message
.Read(bounds
) != B_OK
)
1055 if (code
== RP_STROKE_TRIANGLE
) {
1056 offscreen
->StrokeTriangle(points
[0], points
[1], points
[2],
1058 bounds
.InsetBy(-penSize
, -penSize
);
1059 } else if (code
== RP_FILL_TRIANGLE
) {
1060 offscreen
->FillTriangle(points
[0], points
[1], points
[2],
1063 BGradient
*gradient
;
1064 if (message
.ReadGradient(&gradient
) != B_OK
)
1067 offscreen
->FillTriangle(points
[0], points
[1], points
[2],
1072 invalidRegion
.Include(bounds
);
1076 case RP_STROKE_LINE
:
1079 if (message
.ReadList(points
, 2) != B_OK
)
1082 offscreen
->StrokeLine(points
[0], points
[1], pattern
);
1084 BRect bounds
= _BuildInvalidateRect(points
, 2);
1085 invalidRegion
.Include(bounds
.InsetBySelf(-penSize
, -penSize
));
1089 case RP_STROKE_LINE_ARRAY
:
1092 if (message
.Read(numLines
) != B_OK
)
1096 offscreen
->BeginLineArray(numLines
);
1097 for (int32 i
= 0; i
< numLines
; i
++) {
1100 message
.ReadArrayLine(start
, end
, color
);
1101 offscreen
->AddLine(start
, end
, color
);
1103 bounds
.left
= min_c(bounds
.left
, min_c(start
.x
, end
.x
));
1104 bounds
.top
= min_c(bounds
.top
, min_c(start
.y
, end
.y
));
1105 bounds
.right
= max_c(bounds
.right
, max_c(start
.x
, end
.x
));
1106 bounds
.bottom
= max_c(bounds
.bottom
, max_c(start
.y
, end
.y
));
1109 offscreen
->EndLineArray();
1110 invalidRegion
.Include(bounds
);
1114 case RP_FILL_REGION
:
1115 case RP_FILL_REGION_GRADIENT
:
1118 if (message
.ReadRegion(region
) != B_OK
)
1121 if (code
== RP_FILL_REGION
)
1122 offscreen
->FillRegion(®ion
, pattern
);
1124 BGradient
*gradient
;
1125 if (message
.ReadGradient(&gradient
) != B_OK
)
1128 offscreen
->FillRegion(®ion
, *gradient
);
1132 invalidRegion
.Include(®ion
);
1136 case RP_STROKE_POINT_COLOR
:
1141 message
.Read(point
);
1142 if (message
.Read(color
) != B_OK
)
1145 rgb_color oldColor
= offscreen
->HighColor();
1146 offscreen
->SetHighColor(color
);
1147 offscreen
->StrokeLine(point
, point
);
1148 offscreen
->SetHighColor(oldColor
);
1150 invalidRegion
.Include(
1151 BRect(point
, point
).InsetBySelf(-penSize
, -penSize
));
1155 case RP_STROKE_LINE_1PX_COLOR
:
1160 message
.ReadList(points
, 2);
1161 if (message
.Read(color
) != B_OK
)
1164 float oldSize
= offscreen
->PenSize();
1165 rgb_color oldColor
= offscreen
->HighColor();
1166 drawing_mode oldMode
= offscreen
->DrawingMode();
1167 offscreen
->SetPenSize(1);
1168 offscreen
->SetHighColor(color
);
1169 offscreen
->SetDrawingMode(B_OP_OVER
);
1171 offscreen
->StrokeLine(points
[0], points
[1]);
1173 offscreen
->SetDrawingMode(oldMode
);
1174 offscreen
->SetHighColor(oldColor
);
1175 offscreen
->SetPenSize(oldSize
);
1177 invalidRegion
.Include(_BuildInvalidateRect(points
, 2));
1181 case RP_STROKE_RECT_1PX_COLOR
:
1182 case RP_FILL_RECT_COLOR
:
1188 if (message
.Read(color
) != B_OK
)
1191 rgb_color oldColor
= offscreen
->HighColor();
1192 offscreen
->SetHighColor(color
);
1194 if (code
== RP_STROKE_RECT_1PX_COLOR
) {
1195 float oldSize
= PenSize();
1196 offscreen
->SetPenSize(1);
1197 offscreen
->StrokeRect(rect
);
1198 offscreen
->SetPenSize(oldSize
);
1200 offscreen
->FillRect(rect
);
1202 offscreen
->SetHighColor(oldColor
);
1203 invalidRegion
.Include(rect
);
1207 case RP_DRAW_STRING
:
1214 message
.Read(point
);
1215 message
.ReadString(&string
, length
);
1216 if (message
.Read(hasDelta
) != B_OK
) {
1222 escapement_delta delta
[length
];
1223 message
.ReadList(delta
, length
);
1224 offscreen
->DrawString(string
, point
, delta
);
1226 offscreen
->DrawString(string
, point
);
1229 reply
.Start(RP_DRAW_STRING_RESULT
);
1231 reply
.Add(offscreen
->PenLocation());
1235 offscreen
->GetFontHeight(&height
);
1237 BRect
bounds(point
, offscreen
->PenLocation());
1238 bounds
.top
-= height
.ascent
;
1239 bounds
.bottom
+= height
.descent
;
1240 invalidRegion
.Include(bounds
);
1244 case RP_DRAW_STRING_WITH_OFFSETS
:
1248 message
.ReadString(&string
, length
);
1249 int32 count
= UTF8CountChars(string
, length
);
1251 BPoint offsets
[count
];
1252 if (message
.ReadList(offsets
, count
) != B_OK
) {
1257 offscreen
->DrawString(string
, offsets
, count
);
1260 reply
.Start(RP_DRAW_STRING_RESULT
);
1262 reply
.Add(offscreen
->PenLocation());
1266 offscreen
->GetFont(&font
);
1269 font
.GetBoundingBoxesAsGlyphs(string
, count
, B_SCREEN_METRIC
,
1273 offscreen
->GetFontHeight(&height
);
1275 for (int32 i
= 0; i
< count
; i
++) {
1277 boxes
[i
].OffsetBy(offsets
[i
] + BPoint(0, -height
.ascent
));
1278 invalidRegion
.Include(boxes
[i
]);
1284 case RP_READ_BITMAP
:
1289 message
.Read(bounds
);
1290 if (message
.Read(drawCursor
) != B_OK
)
1293 // TODO: support the drawCursor flag
1294 BBitmap
bitmap(bounds
, B_BITMAP_NO_SERVER_LINK
, B_RGB32
);
1295 bitmap
.ImportBits(fOffscreenBitmap
, bounds
.LeftTop(),
1296 BPoint(0, 0), bounds
.IntegerWidth() + 1,
1297 bounds
.IntegerHeight() + 1);
1299 reply
.Start(RP_READ_BITMAP_RESULT
);
1301 reply
.AddBitmap(&bitmap
);
1307 TRACE_ERROR("unknown protocol code: %u\n", code
);
1313 Invalidate(&invalidRegion
);
1320 RemoteView::_BuildInvalidateRect(BPoint
*points
, int32 pointCount
)
1322 BRect
bounds(1000000, 1000000, 0, 0);
1323 for (int32 i
= 0; i
< pointCount
; i
++) {
1324 bounds
.left
= min_c(bounds
.left
, points
[i
].x
);
1325 bounds
.top
= min_c(bounds
.top
, points
[i
].y
);
1326 bounds
.right
= max_c(bounds
.right
, points
[i
].x
);
1327 bounds
.bottom
= max_c(bounds
.bottom
, points
[i
].y
);