1 #include <sys/syscalls.h>
7 using namespace os::gui
;
9 Window::Window(int id
, int eventPort
, Renderer
*renderer
)
16 fFlags(WINDOW_FLAG_NONE
),
18 fEventPort(eventPort
),
23 // I am being attached directly to a renderer. My clip
24 // region is the bounds of the renderer.
25 fGC
.SetRenderer(renderer
);
26 fFrame
= renderer
->Bounds();
27 fVisibleRegion
.Clear();
28 fVisibleRegion
.Include(fFrame
);
29 fClipRegion
= fVisibleRegion
;
30 fGC
.SetClipRegion(fClipRegion
);
37 fParent
->RemoveChild(this);
40 Window
* Window::ChildAtPoint(int x
, int y
)
42 // See what child is covering me at this point
43 for (Window
*child
= fChildList
; child
; child
= child
->fNextSibling
) {
44 if (child
->Frame().Contains(x
, y
))
45 return child
->ChildAtPoint(x
- child
->Frame().left
, y
- child
->Frame().top
);
48 return this; // I guess that's me!
51 void Window::UpdateClipRegion()
53 Region newClipRegion
= fVisibleRegion
;
54 Rect myScreenFrame
= LocalToScreen(Bounds());
56 // Walk the child list. It is ordered from front to back.
57 for (Window
*child
= fChildList
; child
; child
= child
->fNextSibling
) {
58 // Ship hidden children (and effectively all their descendents).
59 if (!child
->IsVisible()) {
61 child
->SetVisibleRegion(empty
);
65 // My children are obscured both by my siblings and theirs.
66 // Create a new region. Note that fClipRegion is initialized as
67 // my visible region (that is, parts of me that aren't clipped by
68 // my siblings). With iteration, each child window is excluded
69 // from it, so this clips my children against each other.
70 Region childClipRegion
= newClipRegion
;
71 Rect childScreenFrame
= LocalToScreen(child
->Frame());
72 childClipRegion
.ConstrainTo(childScreenFrame
);
73 child
->SetVisibleRegion(childClipRegion
);
75 // I am obscured by my child windows, remove them from my clip
77 newClipRegion
.Exclude(childScreenFrame
);
81 // 1. Invert the old clipping region to find
82 // which parts of the window were previously hidden.
83 // 2. Intersect that with the new clipping region to find areas
84 // that have become visible.
85 Region exposedRegion
= fClipRegion
;
86 exposedRegion
.Invert();
87 exposedRegion
.Intersect(newClipRegion
);
89 if (exposedRegion
.Valid())
90 Invalidate(exposedRegion
);
92 // Now set the new clip region for this window.
93 fClipRegion
= newClipRegion
;
94 fGC
.SetClipRegion(fClipRegion
);
95 fGC
.SetOrigin(myScreenFrame
.left
, myScreenFrame
.top
);
98 void Window::AddChild(const Rect
&frame
, Window
*child
, window_flags flags
)
100 child
->fFrame
= frame
;
101 child
->fGC
.SetRenderer(fGC
.GetRenderer());
102 child
->fFlags
= flags
;
104 if(flags
& WINDOW_FLAG_TOPLEVEL
)
105 child
->fToplevelWindow
= child
;
107 child
->fToplevelWindow
= fToplevelWindow
;
109 child
->fNextSibling
= fChildList
;
110 child
->fPreviousSibling
= &fChildList
;
112 fChildList
->fPreviousSibling
= &child
->fNextSibling
;
115 child
->fParent
= this;
116 if (child
->IsVisible())
120 void Window::RemoveChild(Window
*window
)
122 ASSERT(window
->parent
== this);
123 ASSERT(window
->fPreviousSibling
);
125 *window
->fPreviousSibling
= window
->fNextSibling
;
128 // Should remove all of its children
133 void Window::MoveToFront()
135 fParent
->RemoveChild(this);
136 fParent
->AddChild(fFrame
, this);
140 void Window::SetVisibleRegion(const Region
®ion
)
142 fVisibleRegion
= region
;
146 Region drawRegion
= fCurrentRedrawRegion
;
147 drawRegion
.Intersect(fClipRegion
);
148 fGC
.SetClipRegion(drawRegion
);
150 fGC
.SetClipRegion(fClipRegion
);
153 const Region
& Window::ClipRegion() const
158 void Window::MoveTo(long x
, long y
)
160 fFrame
.OffsetTo(x
, y
);
162 fParent
->UpdateClipRegion();
165 void Window::MoveBy(long x
, long y
)
167 fFrame
.OffsetBy(x
, y
);
169 fParent
->UpdateClipRegion();
172 void Window::ResizeTo(long width
, long height
)
174 fFrame
.right
= fFrame
.left
+ width
;
175 fFrame
.bottom
= fFrame
.top
+ height
;
177 fParent
->UpdateClipRegion();
180 void Window::Invalidate(const Region
®ion
)
183 for (int rect
= 0; rect
< region
.CountRects(); rect
++) {
184 const Rect
&clipRect
= region
.RectAt(rect
);
185 fGC
.GetRenderer()->FillRect(clipRect
.left
, clipRect
.top
, clipRect
.right
,
186 clipRect
.bottom
, Color(), CSPACE_RGB888
);
189 fInvalidRegion
.Include(region
);
190 if (!fPaintMsgSent
) {
192 paintEvent
.what
= EVT_PAINT
;
193 PostEvent(&paintEvent
);
194 fPaintMsgSent
= true;
198 void Window::Invalidate(const Rect
&rect
)
200 if (!fClipRegion
.Intersects(rect
))
201 return; // this region isn't even visible, dont bother
204 Region
eraseRegion(fClipRegion
);
206 invalRegion
.Include(rect
);
207 eraseRegion
.Intersect(invalRegion
);
208 for (int index
= 0; index
< eraseRegion
.CountRects(); index
++) {
209 const Rect
&clipRect
= eraseRegion
.RectAt(index
);
210 fGC
.GetRenderer()->FillRect(clipRect
.left
, clipRect
.top
, clipRect
.right
,
211 clipRect
.bottom
, Color(), CSPACE_RGB888
);
214 // The rect is assumed to be in window coordinates
215 fInvalidRegion
.Include(rect
);
216 if (!fPaintMsgSent
) {
218 paintEvent
.what
= EVT_PAINT
;
219 PostEvent(&paintEvent
);
220 fPaintMsgSent
= true;
224 // walk my children and invalidate them if necessary
225 for (Window
*child
= fChildList
; child
; child
= child
->fNextSibling
) {
226 child
->Invalidate(rect
);
231 GraphicsContext
& Window::GC()
236 void Window::BeginPaint(Rect
&out_invalidRect
)
238 fPaintMsgSent
= false;
240 fCurrentRedrawRegion
= fInvalidRegion
;
241 fInvalidRegion
.Clear();
243 Region drawRegion
= fCurrentRedrawRegion
;
244 drawRegion
.Intersect(fClipRegion
);
245 out_invalidRect
= ScreenToLocal(drawRegion
.Bounds());
246 fGC
.SetClipRegion(drawRegion
);
249 void Window::EndPaint()
254 bool Window::IsVisible() const
259 color888
Window::Color() const
264 void Window::SetColor(color888 c
)
274 fParent
->UpdateClipRegion();
283 fParent
->UpdateClipRegion();
287 void Window::PostEvent(Event
*event
)
294 printf("Window::PostEvent: port %d ID %d, event->what %d\n", fEventPort
, fID
, event
->what
);
296 _kern_port_write(fEventPort
, 0, event
, sizeof(Event
));
299 Rect
Window::LocalToScreen(const Rect
&inRect
) const
301 Rect outRect
= inRect
;
302 for (const Window
*window
= this; window
; window
= window
->fParent
)
303 outRect
.OffsetBy(window
->fFrame
.left
, window
->fFrame
.top
);
308 Rect
Window::ScreenToLocal(const Rect
&inRect
) const
310 Rect outRect
= inRect
;
311 for (const Window
*window
= this; window
; window
= window
->fParent
)
312 outRect
.OffsetBy(-window
->fFrame
.left
, -window
->fFrame
.top
);
317 void Window::DumpChildList(int level
)
319 for (int i
= 0; i
< level
; i
++)
322 Rect frame
= Frame();
323 printf(" + %d %d %d %d\n", frame
.left
, frame
.top
, frame
.right
, frame
.bottom
);
324 for (Window
*child
= fChildList
; child
; child
= child
->fNextSibling
)
325 child
->DumpChildList(level
+ 1);