more x86_64 work. started to put the mmu bits together in the (former) stage2 loader.
[newos.git] / apps / window_server / Window.cpp
blob7cc41e1285486c13621fbe807c4c27f5cd2d385d
1 #include <sys/syscalls.h>
2 #include <stdio.h>
3 #include <win/Event.h>
4 #include "assert.h"
5 #include "Window.h"
7 using namespace os::gui;
9 Window::Window(int id, int eventPort, Renderer *renderer)
10 : fID(id),
11 fNextSibling(0),
12 fPreviousSibling(0),
13 fChildList(0),
14 fParent(0),
15 fToplevelWindow(0),
16 fFlags(WINDOW_FLAG_NONE),
17 fIsVisible(false),
18 fEventPort(eventPort),
19 fPaintMsgSent(false),
20 fColor(0)
22 if (renderer) {
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);
34 Window::~Window()
36 if (fParent)
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()) {
60 Region empty;
61 child->SetVisibleRegion(empty);
62 continue;
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
76 // region.
77 newClipRegion.Exclude(childScreenFrame);
80 // Handle exposures.
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;
106 else
107 child->fToplevelWindow = fToplevelWindow;
109 child->fNextSibling = fChildList;
110 child->fPreviousSibling = &fChildList;
111 if (fChildList)
112 fChildList->fPreviousSibling = &child->fNextSibling;
114 fChildList = child;
115 child->fParent = this;
116 if (child->IsVisible())
117 UpdateClipRegion();
120 void Window::RemoveChild(Window *window)
122 ASSERT(window->parent == this);
123 ASSERT(window->fPreviousSibling);
125 *window->fPreviousSibling = window->fNextSibling;
126 fParent = 0;
128 // Should remove all of its children
130 UpdateClipRegion();
133 void Window::MoveToFront()
135 fParent->RemoveChild(this);
136 fParent->AddChild(fFrame, this);
137 UpdateClipRegion();
140 void Window::SetVisibleRegion(const Region &region)
142 fVisibleRegion = region;
143 UpdateClipRegion();
145 if (fInRedraw) {
146 Region drawRegion = fCurrentRedrawRegion;
147 drawRegion.Intersect(fClipRegion);
148 fGC.SetClipRegion(drawRegion);
149 } else
150 fGC.SetClipRegion(fClipRegion);
153 const Region& Window::ClipRegion() const
155 return fClipRegion;
158 void Window::MoveTo(long x, long y)
160 fFrame.OffsetTo(x, y);
161 if(fParent)
162 fParent->UpdateClipRegion();
165 void Window::MoveBy(long x, long y)
167 fFrame.OffsetBy(x, y);
168 if(fParent)
169 fParent->UpdateClipRegion();
172 void Window::ResizeTo(long width, long height)
174 fFrame.right = fFrame.left + width;
175 fFrame.bottom = fFrame.top + height;
176 if(fParent)
177 fParent->UpdateClipRegion();
180 void Window::Invalidate(const Region &region)
182 // Erase background
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) {
191 Event paintEvent;
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
203 // Erase background
204 Region eraseRegion(fClipRegion);
205 Region invalRegion;
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) {
217 Event paintEvent;
218 paintEvent.what = EVT_PAINT;
219 PostEvent(&paintEvent);
220 fPaintMsgSent = true;
223 #if 0
224 // walk my children and invalidate them if necessary
225 for (Window *child = fChildList; child; child = child->fNextSibling) {
226 child->Invalidate(rect);
228 #endif
231 GraphicsContext& Window::GC()
233 return fGC;
236 void Window::BeginPaint(Rect &out_invalidRect)
238 fPaintMsgSent = false;
239 fInRedraw = true;
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()
251 fInRedraw = false;
254 bool Window::IsVisible() const
256 return fIsVisible;
259 color888 Window::Color() const
261 return fColor;
264 void Window::SetColor(color888 c)
266 fColor = c;
269 void Window::Show()
271 if (!fIsVisible) {
272 fIsVisible = true;
273 if (fParent)
274 fParent->UpdateClipRegion();
278 void Window::Hide()
280 if (fIsVisible) {
281 fIsVisible = false;
282 if (fParent)
283 fParent->UpdateClipRegion();
287 void Window::PostEvent(Event *event)
289 if(fEventPort < 0)
290 return;
292 event->target = fID;
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);
305 return outRect;
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);
314 return outRect;
317 void Window::DumpChildList(int level)
319 for (int i = 0; i < level; i++)
320 printf(" | ");
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);