vfs: check userland buffers before reading them.
[haiku.git] / src / tests / servers / app / newClipping / MyView.cpp
blobac691c42558a09317c76b728ad20d7623c40f7a0
1 #include <Message.h>
2 #include <Messenger.h>
3 #include <Window.h>
5 #include <stdio.h>
6 #include <stack.h>
8 #include "MyView.h"
9 #include "Layer.h"
11 extern BWindow *wind;
12 struct node {
13 node()
15 pointers = NULL;
17 node(const BRect& r, int32 maxPointers)
19 init(r, maxPointers);
21 ~node()
23 delete [] pointers;
26 void init(const BRect& r, int32 maxPointers)
28 rect = r;
29 pointers = new node*[maxPointers];
30 in_degree = 0;
31 next_pointer = 0;
34 void push(node* node)
36 pointers[next_pointer] = node;
37 next_pointer++;
39 node* top()
41 return pointers[next_pointer];
43 node* pop()
45 node* ret = top();
46 next_pointer--;
47 return ret;
50 BRect rect;
51 int32 in_degree;
52 node** pointers;
53 int32 next_pointer;
56 bool
57 is_left_of(const BRect& a, const BRect& b)
59 return (a.right < b.left);
61 bool
62 is_above(const BRect& a, const BRect& b)
64 return (a.bottom < b.top);
67 MyView::MyView(BRect frame, const char *name, uint32 resizingMode, uint32 flags)
68 : BView(frame, name, resizingMode, flags)
70 SetViewColor(B_TRANSPARENT_COLOR);
71 fTracking = false;
72 fIsResize = false;
73 fIs2ndButton= false;
74 fMovingLayer = NULL;
76 rgb_color col;
77 col.red = 49;
78 col.green = 101;
79 col.blue = 156;
80 topLayer = new Layer(Bounds(), "topLayer", B_FOLLOW_ALL, 0, col);
81 topLayer->SetRootLayer(this);
83 topLayer->rebuild_visible_regions(BRegion(Bounds()), BRegion(Bounds()), NULL);
84 fRedrawReg.Set(Bounds());
87 MyView::~MyView()
89 delete topLayer;
92 Layer* MyView::FindLayer(Layer *lay, BPoint &where) const
94 if (lay->Visible()->Contains(where))
95 return lay;
96 else
97 for (Layer *child = lay->BottomChild(); child; child = lay->UpperSibling())
99 Layer *found = FindLayer(child, where);
100 if (found)
101 return found;
103 return NULL;
106 void MyView::MouseDown(BPoint where)
108 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
109 int32 buttons;
110 Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
111 fLastPos = where;
112 if (buttons == B_PRIMARY_MOUSE_BUTTON)
114 fTracking = true;
115 fMovingLayer = FindLayer(topLayer, where);
116 if (fMovingLayer == topLayer)
117 fMovingLayer = NULL;
118 if (fMovingLayer)
120 BRect bounds(fMovingLayer->Bounds());
121 fMovingLayer->ConvertToScreen2(&bounds);
122 BRect resizeRect(bounds.right-10, bounds.bottom-10, bounds.right, bounds.bottom);
123 if (resizeRect.Contains(where))
124 fIsResize = true;
125 else
126 fIsResize = false;
129 else if (buttons == B_SECONDARY_MOUSE_BUTTON)
131 fIs2ndButton = true;
133 else if (buttons == B_TERTIARY_MOUSE_BUTTON)
135 DrawSubTree(topLayer);
139 void MyView::MouseUp(BPoint where)
141 fTracking = false;
142 fIs2ndButton = false;
143 fMovingLayer = NULL;
146 void MyView::MouseMoved(BPoint where, uint32 code, const BMessage *a_message)
148 if (fTracking)
150 float dx, dy;
151 dx = where.x - fLastPos.x;
152 dy = where.y - fLastPos.y;
153 fLastPos = where;
155 if (dx != 0 || dy != 0)
157 if (fMovingLayer)
159 bigtime_t now = system_time();
160 if (fIsResize) {
161 fMovingLayer->ResizeBy(dx, dy);
162 printf("resizing: %lld\n", system_time() - now);
163 } else {
164 fMovingLayer->MoveBy(dx, dy);
165 printf("moving: %lld\n", system_time() - now);
170 else if (fIs2ndButton)
172 SetHighColor(0,0,0);
173 StrokeLine(fLastPos, where);
174 Flush();
175 fLastPos = where;
179 void MyView::MessageReceived(BMessage *msg)
181 switch(msg->what)
183 case B_MOUSE_WHEEL_CHANGED:
185 float dy;
186 msg->FindFloat("be:wheel_delta_y", &dy);
188 BPoint pt;
189 uint32 buttons;
190 Layer *lay;
191 GetMouse(&pt, &buttons, false);
192 if ((lay = FindLayer(topLayer, pt)))
193 lay->ScrollBy(0, dy*5);
194 break;
196 default:
197 BView::MessageReceived(msg);
201 void MyView::CopyRegion(BRegion *region, int32 xOffset, int32 yOffset)
203 wind->Lock();
204 int32 count = region->CountRects();
206 // TODO: make this step unnecessary
207 // (by using different stack impl inside node)
208 node nodes[count];
209 for (int32 i= 0; i < count; i++) {
210 nodes[i].init(region->RectAt(i), count);
213 for (int32 i = 0; i < count; i++) {
214 BRect a = region->RectAt(i);
215 for (int32 k = i + 1; k < count; k++) {
216 BRect b = region->RectAt(k);
217 int cmp = 0;
218 // compare horizontally
219 if (xOffset > 0) {
220 if (is_left_of(a, b)) {
221 cmp -= 1;
222 } else if (is_left_of(b, a)) {
223 cmp += 1;
225 } else if (xOffset < 0) {
226 if (is_left_of(a, b)) {
227 cmp += 1;
228 } else if (is_left_of(b, a)) {
229 cmp -= 1;
232 // compare vertically
233 if (yOffset > 0) {
234 if (is_above(a, b)) {
235 cmp -= 1;
236 } else if (is_above(b, a)) {
237 cmp += 1;
239 } else if (yOffset < 0) {
240 if (is_above(a, b)) {
241 cmp += 1;
242 } else if (is_above(b, a)) {
243 cmp -= 1;
246 // add appropriate node as successor
247 if (cmp > 0) {
248 nodes[i].push(&nodes[k]);
249 nodes[k].in_degree++;
250 } else if (cmp < 0) {
251 nodes[k].push(&nodes[i]);
252 nodes[i].in_degree++;
256 // put all nodes onto a stack that have an "indegree" count of zero
257 stack<node*> inDegreeZeroNodes;
258 for (int32 i = 0; i < count; i++) {
259 if (nodes[i].in_degree == 0) {
260 inDegreeZeroNodes.push(&nodes[i]);
263 // pop the rects from the stack, do the actual copy operation
264 // and decrease the "indegree" count of the other rects not
265 // currently on the stack and to which the current rect pointed
266 // to. If their "indegree" count reaches zero, put them onto the
267 // stack as well.
269 while (!inDegreeZeroNodes.empty()) {
270 node* n = inDegreeZeroNodes.top();
271 inDegreeZeroNodes.pop();
273 CopyBits(n->rect, BRect(n->rect).OffsetByCopy(xOffset, yOffset));
275 for (int32 k = 0; k < n->next_pointer; k++) {
276 n->pointers[k]->in_degree--;
277 if (n->pointers[k]->in_degree == 0)
278 inDegreeZeroNodes.push(n->pointers[k]);
281 wind->Unlock();
284 void MyView::RequestRedraw()
286 wind->Lock();
288 ConstrainClippingRegion(&fRedrawReg);
289 PushState();
290 DrawSubTree(topLayer);
291 PopState();
292 ConstrainClippingRegion(NULL);
294 fRedrawReg.MakeEmpty();
296 wind->Unlock();
299 void MyView::Draw(BRect area)
301 // empty. you can trigger a redraw by clicking the middle mouse button.
304 void MyView::DrawSubTree(Layer* lay)
306 //printf("======== %s =======\n", lay->Name());
307 // lay->Visible()->PrintToStream();
308 // lay->FullVisible()->PrintToStream();
309 for (Layer *child = lay->BottomChild(); child; child = lay->UpperSibling())
310 DrawSubTree(child);
312 ConstrainClippingRegion(lay->Visible());
313 SetHighColor(lay->HighColor());
314 BRegion reg;
315 lay->GetWantedRegion(reg);
316 FillRect(reg.Frame());
317 Flush();
318 ConstrainClippingRegion(NULL);