1 | | #include "SnowView.h" |
2 | | |
3 | | #include <stdio.h> |
4 | | #include <stdlib.h> |
5 | | #include <string.h> |
6 | | #include <math.h> |
7 | | |
8 | | #include <Alert.h> |
9 | | #include <Catalog.h> |
10 | | #include <Debug.h> |
11 | | #include <Message.h> |
12 | | #include <MessageRunner.h> |
13 | | #include <MessageFilter.h> |
14 | | #include <OS.h> |
15 | | #include <Region.h> |
16 | | #include <Screen.h> |
17 | | |
18 | | #include "Flakes.h" |
19 | | |
20 | | |
21 | | #define FORWARD_TO_PARENT |
22 | | #undef B_TRANSLATION_CONTEXT |
23 | | #define B_TRANSLATION_CONTEXT "BSnow" |
24 | | |
25 | | |
26 | | SnowView::SnowView() |
27 | | : |
28 | | BView(BRect(SNOW_VIEW_RECT), "BSnow", B_FOLLOW_NONE, |
29 | | B_WILL_DRAW | B_PULSE_NEEDED) |
30 | | { |
31 | | fAttached = false; |
32 | | fMsgRunner = NULL; |
33 | | fCachedParent = NULL; |
34 | | fFallenBmp = NULL; |
35 | | fFallenView = NULL; |
36 | | fFallenReg = NULL; |
37 | | fInvalidator = -1; |
38 | | fShowClickMe = false; |
39 | | for (int i = 0; i < WORKSPACES_COUNT; i++) |
40 | | fFlakes[i] = NULL; |
41 | | for (int i = 0; i < NUM_PATTERNS; i++) |
42 | | fFlakeBitmaps[i] = NULL; |
43 | | BRect r(Frame()); |
44 | | r.left = r.right - 7; |
45 | | r.top = r.bottom - 7; |
46 | | fDragger = new BDragger(r, this); |
47 | | AddChild(fDragger); |
48 | | SetHighColor(255,255,255); |
49 | | } |
50 | | |
51 | | #ifdef DEBUG |
52 | | filter_result msgfilter(BMessage *message, BHandler **target, BMessageFilter *filter) |
53 | | { |
54 | | switch (message->what) { |
55 | | case B_MOUSE_DOWN: |
56 | | case B_MOUSE_UP: |
57 | | case B_MOUSE_MOVED: |
58 | | case '_EVP': |
59 | | case '_UPD': |
60 | | case '_PUL': |
61 | | case 'NTCH': |
62 | | case 'NMDN': |
63 | | break; |
64 | | default: |
65 | | printf("For: %p: %s\n", *target, (*target)->Name()); |
66 | | message->PrintToStream(); |
67 | | } |
68 | | return B_DISPATCH_MESSAGE; |
69 | | } |
70 | | #endif |
71 | | |
72 | | SnowView::SnowView(BMessage *archive) |
73 | | : BView(archive) |
74 | | { |
75 | | system_info si; |
76 | | PRINT(("SnowView()\n")); |
77 | | #ifdef DEBUG |
78 | | archive->PrintToStream(); |
79 | | #endif |
80 | | fDragger = NULL; |
81 | | fAttached = false; |
82 | | fMsgRunner = NULL; |
83 | | fFallenBmp = NULL; |
84 | | fFallenView = NULL; |
85 | | fFallenReg = NULL; |
86 | | fCachedParent = NULL; |
87 | | fShowClickMe = false; |
88 | | SetFlags(Flags() & ~B_PULSE_NEEDED); /* it's only used when in the app */ |
89 | | get_system_info(&si); |
90 | | fNumFlakes = 1000 * si.cpu_count / 3; |
91 | | printf("BSnow: using %ld flakes\n", fNumFlakes); |
92 | | for (int i = 0; i < WORKSPACES_COUNT; i++) { |
93 | | fFlakes[i] = new flake[fNumFlakes]; |
94 | | memset(fFlakes[i], 0, fNumFlakes * sizeof(flake)); |
95 | | } |
96 | | for (int i = 0; i < NUM_PATTERNS; i++) { |
97 | | fFlakeBitmaps[i] = new BBitmap(BRect(0,0,7,7), B_CMAP8); |
98 | | fFlakeBitmaps[i]->SetBits(gFlakeBits[i], 8*8, 0, B_CMAP8); |
99 | | } |
100 | | fCurrentWorkspace = 0; |
101 | | SetHighColor(255,255,255); |
102 | | SetDrawingMode(B_OP_OVER); |
103 | | } |
104 | | |
105 | | SnowView::~SnowView() |
106 | | { |
107 | | for (int i = 0; i < WORKSPACES_COUNT; i++) |
108 | | if (fFlakes[i]) |
109 | | delete [] fFlakes[i]; |
110 | | if (fFallenBmp) |
111 | | delete fFallenBmp; /* the view goes away with it */ |
112 | | } |
113 | | |
114 | | BArchivable *SnowView::Instantiate(BMessage *data) |
115 | | { |
116 | | return new SnowView(data); |
117 | | } |
118 | | |
119 | | status_t SnowView::Archive(BMessage *data, bool deep) const |
120 | | { |
121 | | status_t err; |
122 | | err = BView::Archive(data, deep); |
123 | | if (err < B_OK) |
124 | | return err; |
125 | | data->AddString("add_on", APP_SIG); |
126 | | return B_OK; |
127 | | } |
128 | | |
129 | | void SnowView::AttachedToWindow() |
130 | | { |
131 | | BView *p; |
132 | | rgb_color col; |
133 | | fAttached = true; |
134 | | /* if (!fMsgRunner) |
135 | | fMsgRunner = new BMessageRunner(BMessenger(this), |
136 | | new BMessage(MSG_PULSE_ME), |
137 | | INTERVAL); |
138 | | */ |
139 | | p = Parent(); |
140 | | if (p) |
141 | | col = B_TRANSPARENT_32_BIT;//Parent()->ViewColor(); |
142 | | else |
143 | | col = ui_color(B_PANEL_BACKGROUND_COLOR); |
144 | | SetViewColor(col); |
145 | | // BScreen bs; |
146 | | // fCachedWsWidth = bs.Frame().IntegerWidth(); |
147 | | // fCachedWsHeight = bs.Frame().IntegerHeight(); |
148 | | fDragger = dynamic_cast<BDragger *>(FindView("_dragger_")); |
149 | | if (fDragger && p) { |
150 | | fCachedParent = p; |
151 | | fCachedWsWidth = p->Frame().IntegerWidth(); |
152 | | fCachedWsHeight = p->Frame().IntegerHeight(); |
153 | | fDragger->SetViewColor(col); |
154 | | if (fDragger->InShelf()) { |
155 | | p->SetFlags(p->Flags() | B_DRAW_ON_CHILDREN); |
156 | | #ifdef B_BEOS_VERSION_DANO |
157 | | p->SetDoubleBuffering(p->DoubleBuffering() | B_UPDATE_EXPOSED); |
158 | | #endif |
159 | | ResizeTo(p->Bounds().Width(), p->Bounds().Height()); |
160 | | MoveTo(0,0); |
161 | | fDragger->MoveTo(p->Bounds().Width()-7, p->Bounds().Height()-7); |
162 | | } |
163 | | BRect fallenRect(p->Bounds()); |
164 | | fallenRect.top = fallenRect.bottom - FALLEN_HEIGHT; |
165 | | fFallenBmp = new BBitmap(fallenRect, B_BITMAP_ACCEPTS_VIEWS, B_CMAP8); |
166 | | memset(fFallenBmp->Bits(), B_TRANSPARENT_MAGIC_CMAP8, (size_t)(fallenRect.Height()*fFallenBmp->BytesPerRow())); |
167 | | fFallenView = new BView(fallenRect, "offscreen fallen snow", B_FOLLOW_NONE, 0); |
168 | | fFallenBmp->AddChild(fFallenView); |
169 | | fFallenReg = new BRegion; |
170 | | fInvalidator = spawn_thread(SnowMakerThread, INVALIDATOR_THREAD_NAME, B_LOW_PRIORITY, (void *)this); |
171 | | resume_thread(fInvalidator); |
172 | | printf("BSnow: OK: ws = %" B_PRId32 " x %" B_PRId32 "\n", fCachedWsWidth, fCachedWsHeight); |
173 | | #ifdef DEBUG |
174 | | Window()->AddCommonFilter(new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, msgfilter)); |
175 | | #endif |
176 | | } |
177 | | } |
178 | | |
179 | | void SnowView::DetachedFromWindow() |
180 | | { |
181 | | fAttached = false; |
182 | | /* |
183 | | if (Parent()) { |
184 | | Parent()->Invalidate(Parent()->Bounds()); |
185 | | } |
186 | | */ |
187 | | if (fMsgRunner) |
188 | | delete fMsgRunner; |
189 | | fMsgRunner = NULL; |
190 | | status_t err; |
191 | | fCachedParent = NULL; |
192 | | if (fInvalidator > B_OK) |
193 | | wait_for_thread(fInvalidator, &err); |
194 | | fInvalidator = -1; |
195 | | if (fFallenReg) |
196 | | delete fFallenReg; |
197 | | } |
198 | | |
199 | | void SnowView::MessageReceived(BMessage *msg) |
200 | | { |
201 | | BAlert *info; |
202 | | //msg->PrintToStream(); |
203 | | switch (msg->what) { |
204 | | case MSG_PULSE_ME: |
205 | | if (Parent()) { |
206 | | Calc(); |
207 | | InvalFlakes(); |
208 | | } |
209 | | break; |
210 | | case B_ABOUT_REQUESTED: |
211 | | info = new BAlert("BSnow info", |
212 | | "BSnow, just in case you don't have real one...\n" |
213 | | "" B_UTF8_COPYRIGHT " 2003, François Revol.", |
214 | | "Where is Santa ??"); |
215 | | info->SetFeel(B_NORMAL_WINDOW_FEEL); |
216 | | info->SetLook(B_FLOATING_WINDOW_LOOK); |
217 | | info->SetFlags(info->Flags()|B_NOT_ZOOMABLE|B_CLOSE_ON_ESCAPE); |
218 | | info->Go(NULL); |
219 | | break; |
220 | | default: |
221 | | //#ifdef FORWARD_TO_PARENT |
222 | | /* |
223 | | if (fAttached && Parent()) |
224 | | Parent()->MessageReceived(msg); |
225 | | else |
226 | | */ |
227 | | //#endif |
228 | | BView::MessageReceived(msg); |
229 | | } |
230 | | } |
231 | | |
232 | | void SnowView::Draw(BRect ur) |
233 | | { |
234 | | int i; |
235 | | if (!fCachedParent) { |
236 | | if (!fShowClickMe) { /* show "drag me" */ |
237 | | SetLowColor(ViewColor()); |
238 | | SetHighColor(0,0,0); |
239 | | SetFontSize(12); |
240 | | DrawString(B_TRANSLATE("Drag me on your desktop" B_UTF8_ELLIPSIS), |
241 | | BPoint(15,25)); |
242 | | BPoint arrowHead(Bounds().RightBottom() + BPoint(-10,-10)); |
243 | | StrokeLine(arrowHead, arrowHead - BPoint(7,0)); |
244 | | StrokeLine(arrowHead, arrowHead - BPoint(0,7)); |
245 | | StrokeLine(arrowHead, arrowHead - BPoint(12,12)); |
246 | | return; |
247 | | } else { |
248 | | SetLowColor(ViewColor()); |
249 | | SetHighColor(0,0,0); |
250 | | SetFontSize(12); |
251 | | DrawString(B_TRANSLATE("Click me to remove BSnow" B_UTF8_ELLIPSIS), |
252 | | BPoint(15,25)); |
253 | | return; |
254 | | } |
255 | | } |
256 | | //printf("Draw()\n"); |
257 | | uint32 cw = fCurrentWorkspace; |
258 | | if (fFlakes[cw] == NULL) |
259 | | return; |
260 | | /* draw the snow already fallen */ |
261 | | // BRect fallenRect(Bounds()); |
262 | | // fallenRect.top = fallenRect.bottom - FALLEN_HEIGHT; |
263 | | // if (ur.Intersects(fallenRect)) { |
264 | | //if (fFallenBmp->Lock()) { |
265 | | // DrawBitmap(fFallenBmp, fallenRect); |
266 | | // fFallenBmp->Unlock(); |
267 | | //} |
268 | | int32 cnt = fFallenReg->CountRects(); |
269 | | // drawing_mode oldmode = DrawingMode(); |
270 | | // SetDrawingMode(B_OP_ADD); |
271 | | |
272 | | for (i=0; i<cnt; i++) { |
273 | | BRect r = fFallenReg->RectAt(i); |
274 | | // SetHighColor(245, 245, 245, 200); |
275 | | // FillRect(r); |
276 | | // SetHighColor(255, 255, 255, 255); |
277 | | // r.InsetBy(1,1); |
278 | | FillRect(r); |
279 | | } |
280 | | // SetDrawingMode(oldmode); |
281 | | // } |
282 | | /* draw our flakes */ |
283 | | for (i=0; i<fNumFlakes; i++) { |
284 | | int pat; |
285 | | if (!ur.Contains(BRect(fFlakes[cw][i].pos-BPoint(4,4), fFlakes[cw][i].pos+BPoint(4,4)))) |
286 | | continue; |
287 | | if (fFlakes[cw][i].weight == 0) |
288 | | continue; |
289 | | pat = (fFlakes[cw][i].weight>3)?1:0; |
290 | | //FillRect(BRect(fFlakes[cw][i].pos-BPoint(PAT_HOTSPOT),fFlakes[cw][i].pos-BPoint(PAT_HOTSPOT)+BPoint(7,7)), gFlakePatterns[pat]); |
291 | | /* |
292 | | StrokeLine(fFlakes[cw][i].pos+BPoint(-1,-1), |
293 | | fFlakes[cw][i].pos+BPoint(1,1)); |
294 | | StrokeLine(fFlakes[cw][i].pos+BPoint(-1,1), |
295 | | fFlakes[cw][i].pos+BPoint(1,-1)); |
296 | | */ |
297 | | DrawBitmap(fFlakeBitmaps[pat], fFlakes[cw][i].pos-BPoint(PAT_HOTSPOT)); |
298 | | } |
299 | | } |
300 | | |
301 | | void SnowView::Pulse() |
302 | | { |
303 | | if (fShowClickMe) |
304 | | return; /* done */ |
305 | | if (fCachedParent) |
306 | | return; /* we are in Tracker! */ |
307 | | BMessenger msgr("application/x-vnd.Be-TRAK"); |
308 | | BMessage msg(B_GET_PROPERTY), reply; |
309 | | msg.AddSpecifier("Frame"); |
310 | | msg.AddSpecifier("View", "BSnow"); |
311 | | msg.AddSpecifier("Window", 1); /* 0 is Twitcher */ |
312 | | if (msgr.SendMessage(&msg, &reply) == B_OK && reply.what == B_REPLY) { |
313 | | //reply.PrintToStream(); |
314 | | Invalidate(Bounds()); |
315 | | fShowClickMe = true; |
316 | | } |
317 | | } |
318 | | |
319 | | void SnowView::Calc() |
320 | | { |
321 | | int i; |
322 | | uint32 cw = fCurrentWorkspace; |
323 | | |
324 | | /* check if the parent changed size */ |
325 | | BRect pFrame = fCachedParent->Frame(); |
326 | | if (fCachedWsWidth != pFrame.Width() || fCachedWsHeight != pFrame.Height()) { |
327 | | fCachedWsWidth = pFrame.IntegerWidth(); |
328 | | fCachedWsHeight = pFrame.IntegerHeight(); |
329 | | printf("BSnow: Parent resized to %" B_PRId32 " %" B_PRId32 "\n", fCachedWsWidth, fCachedWsHeight); |
330 | | fFallenReg->MakeEmpty(); /* remove all the fallen snow */ |
331 | | ResizeTo(pFrame.IntegerWidth(), pFrame.IntegerHeight()); |
332 | | fDragger->MoveTo(pFrame.IntegerWidth()-7, pFrame.IntegerHeight()-7); |
333 | | } |
334 | | |
335 | | /* make new flakes */ |
336 | | for (i=0; i<fNumFlakes; i++) { |
337 | | if (fFlakes[cw][i].weight == 0) { |
338 | | fFlakes[cw][i].weight = ((float)(rand() % WEIGHT_SPAN)) / WEIGHT_GRAN; |
339 | | fFlakes[cw][i].weight = MAX(fFlakes[cw][i].weight, 0.5); |
340 | | fFlakes[cw][i].pos.y = rand() % 5 - 2; |
341 | | fFlakes[cw][i].pos.x = (rand()%(fCachedWsWidth+2*fCachedWsHeight))-fCachedWsHeight; |
342 | | if (fFlakes[cw][i].pos.x < -10) { |
343 | | fFlakes[cw][i].pos.y = -fFlakes[cw][i].pos.x; |
344 | | if (fWind > 0) |
345 | | fFlakes[cw][i].pos.x = 0; |
346 | | else |
347 | | fFlakes[cw][i].pos.x = fCachedWsWidth; |
348 | | } |
349 | | if (fFlakes[cw][i].pos.x > fCachedWsWidth+10) { |
350 | | fFlakes[cw][i].pos.y = fFlakes[cw][i].pos.x - fCachedWsWidth; |
351 | | if (fWind > 0) |
352 | | fFlakes[cw][i].pos.x = 0; |
353 | | else |
354 | | fFlakes[cw][i].pos.x = fCachedWsWidth; |
355 | | } |
356 | | } |
357 | | } |
358 | | |
359 | | /* like a candle in the wind... */ |
360 | | if (fWindDuration < system_time()) { |
361 | | fWindDuration = system_time() + ((((bigtime_t)rand())*1000) % WIND_MAX_DURATION); |
362 | | fWind = (rand() % WIND_SPAN) - WIND_SPAN/2; |
363 | | printf("BSnow: wind change: %f\n", fWind); |
364 | | } |
365 | | |
366 | | |
367 | | // if (fFallenView->LockLooperWithTimeout(5000)) { |
368 | | // if (fFallenBmp) { |
369 | | // uint8 *fallenBits = (uint8 *)fFallenBmp->Bits(); |
370 | | |
371 | | BRegion desktopReg; |
372 | | GetClippingRegion(&desktopReg); |
373 | | |
374 | | /* let's add some gravity and wind */ |
375 | | for (i=0; i<fNumFlakes; i++) { |
376 | | float yinc; |
377 | | if (fFlakes[cw][i].weight == 0) |
378 | | continue; |
379 | | fFlakes[cw][i].opos = fFlakes[cw][i].pos; |
380 | | |
381 | | yinc = fFlakes[cw][i].weight - (rand() % 3); |
382 | | yinc = MAX(yinc, 0.5); |
383 | | fFlakes[cw][i].pos.y += yinc; |
384 | | |
385 | | // if (fFlakes[cw][i].pos.y > (fCachedWsHeight-FALLEN_HEIGHT)) { |
386 | | |
387 | | bool fallen = false; |
388 | | bool keepfalling = false; |
389 | | |
390 | | /* fallen on the flour */ |
391 | | if (fFlakes[cw][i].pos.y > fCachedWsHeight-2) |
392 | | fallen = true; |
393 | | /* fallon on another fallen flake */ |
394 | | else if (fFallenReg->Intersects(BRect(fFlakes[cw][i].pos - BPoint(0,1), |
395 | | fFlakes[cw][i].pos + BPoint(0,1)))) { |
396 | | /* don't accumulate too much */ |
397 | | if ((fFlakes[cw][i].pos.y > fCachedWsHeight-30) || |
398 | | !desktopReg.Intersects( |
399 | | BRect(fFlakes[cw][i].pos + BPoint(0,6), |
400 | | fFlakes[cw][i].pos + BPoint(0,10)))) |
401 | | fallen = true; |
402 | | /* fallen on a window */ |
403 | | } else if (!desktopReg.Intersects( |
404 | | BRect(fFlakes[cw][i].pos + BPoint(-1,-1-2), |
405 | | fFlakes[cw][i].pos + BPoint(1,1-1))) && |
406 | | desktopReg.Intersects( |
407 | | BRect(fFlakes[cw][i].pos + BPoint(-1,-1-3), |
408 | | fFlakes[cw][i].pos + BPoint(1,1-3)))) { |
409 | | //printf("fallen3 @ %f %f\n", fFlakes[cw][i].pos.x, fFlakes[cw][i].pos.y); |
410 | | fFlakes[cw][i].pos = fFlakes[cw][i].opos; |
411 | | fallen = true; |
412 | | keepfalling = true; /* but keep one falling */ |
413 | | } |
414 | | |
415 | | /* else if (fallenBits[ (long)(fFlakes[cw][i].pos.y |
416 | | * fFallenBmp->BytesPerRow() |
417 | | + fFlakes[cw][i].pos.y |
418 | | - (fCachedWsHeight-FALLEN_HEIGHT)) ] != B_TRANSPARENT_MAGIC_CMAP8) { |
419 | | fallen = true; |
420 | | }*/ |
421 | | |
422 | | // if (fallen) { |
423 | | // int pat = (fFlakes[cw][i].weight>3)?1:0; |
424 | | // if (fFlakes[cw][i].pos.y > fCachedWsHeight-1) |
425 | | // fFlakes[cw][i].pos.y = fCachedWsHeight-(rand()%4); |
426 | | //fFallenView->DrawBitmap(fFlakeBitmaps[pat], fFlakes[cw][i].pos-BPoint(PAT_HOTSPOT)); |
427 | | // fallenBits[ (long)(fFlakes[cw][i].pos.y * fFallenBmp->BytesPerRow() |
428 | | // + fFlakes[cw][i].pos.y-(fCachedWsHeight-FALLEN_HEIGHT)) ] = 0x56; |
429 | | // printf("fallen @ %f, %f\n", fFlakes[cw][i].pos.x, fFlakes[cw][i].pos.y); |
430 | | // } |
431 | | if (fallen) { |
432 | | if (!keepfalling) |
433 | | fFlakes[cw][i].weight = 0; |
434 | | fFallenReg->Include(BRect(fFlakes[cw][i].pos - BPoint(2,0), |
435 | | fFlakes[cw][i].pos + BPoint(2,2))); |
436 | | if (keepfalling) { |
437 | | fFlakes[cw][i].pos += BPoint(0,10); |
438 | | /* except if under the desktop */ |
439 | | if (fFlakes[cw][i].pos.y > fCachedWsHeight-1) |
440 | | fFlakes[cw][i].weight = 0; |
441 | | } |
442 | | } |
443 | | |
444 | | /* cleanup, when a window hides the snow */ |
445 | | fFallenReg->IntersectWith(&desktopReg); |
446 | | |
447 | | /* cleanup, when a window is moved */ |
448 | | /* seems to lockup Tracker */ |
449 | | /* |
450 | | int32 cnt = fFallenReg->CountRects(); |
451 | | for (i=0; i<cnt; i++) { |
452 | | BRect r = fFallenReg->RectAt(i); |
453 | | if (desktopReg.Intersects(r.OffsetByCopy(0,15))) { |
454 | | fFallenReg->Exclude(r); |
455 | | cnt--; |
456 | | } |
457 | | } |
458 | | */ |
459 | | /* add the effect of the wind */ |
460 | | fFlakes[cw][i].pos.x += fWind + (rand() % 6 - 3); |
461 | | if ((fFlakes[cw][i].pos.x > fCachedWsWidth+50)||(fFlakes[cw][i].pos.x < -50)) |
462 | | fFlakes[cw][i].weight = 0; |
463 | | } |
464 | | // fFallenView->UnlockLooper(); |
465 | | // } |
466 | | #if 0 |
467 | | for (i=0; i<10; i++) |
468 | | printf("f[%d] = {%f, %f}, {%f, %f}, %d\n", i, |
469 | | fFlakes[cw][i].opos.x, fFlakes[cw][i].opos.y, |
470 | | fFlakes[cw][i].pos.x, fFlakes[cw][i].pos.y, |
471 | | fFlakes[cw][i].weight); |
472 | | #endif |
473 | | } |
474 | | |
475 | | void SnowView::InvalFlakes() |
476 | | { |
477 | | int i; |
478 | | BView *p = Parent(); |
479 | | if (!p) |
480 | | return; |
481 | | //printf("InvalFlakes()\n"); |
482 | | uint32 cw = fCurrentWorkspace; |
483 | | |
484 | | for (i=0; i<fNumFlakes; i++) { |
485 | | if (fFlakes[cw][i].weight) |
486 | | Invalidate(BRect(fFlakes[cw][i].opos-BPoint(PAT_HOTSPOT), fFlakes[cw][i].opos-BPoint(PAT_HOTSPOT)+BPoint(7,7))); |
487 | | } |
488 | | } |
489 | | |
490 | | void SnowView::MouseDown(BPoint where) |
491 | | { |
492 | | #ifdef FORWARD_TO_PARENT |
493 | | if (fAttached && Parent()) |
494 | | Parent()->MouseDown(where); |
495 | | #endif |
496 | | } |
497 | | |
498 | | void SnowView::MouseUp(BPoint where) |
499 | | { |
500 | | #ifdef FORWARD_TO_PARENT |
501 | | if (fAttached && Parent()) |
502 | | Parent()->MouseUp(where); |
503 | | #endif |
504 | | if (fCachedParent) |
505 | | return; /* we are *inside* the Tracker, |
506 | | * don't even try talking to ourselve |
507 | | * with the window locked |
508 | | */ |
509 | | BMessenger msgr("application/x-vnd.Be-TRAK"); |
510 | | BMessage msg(B_DELETE_PROPERTY), reply; |
511 | | msg.AddSpecifier("Replicant", "BSnow"); |
512 | | msg.AddSpecifier("Shelf"); |
513 | | msg.AddSpecifier("View", "PoseView"); |
514 | | msg.AddSpecifier("Window", 1); /* 0 is Tracker Status */ |
515 | | if ((msgr.SendMessage(&msg, &reply) == B_OK) && |
516 | | (reply.what == B_NO_REPLY || reply.what == B_REPLY)) { |
517 | | //reply.PrintToStream(); |
518 | | fShowClickMe = false; |
519 | | Invalidate(Bounds()); |
520 | | } |
521 | | /* |
522 | | BMessage: what = JAHA (0x4a414841, or 1245792321) |
523 | | entry index, type='LONG', c=1, size= 4, data[0]: 0x2 (2, '') |
524 | | entry when, type='LLNG', c=1, size= 8, data[0]: 0xf6a1b09ac (66204666284, '') |
525 | | entry source, type='PNTR', c=1, size= 4, |
526 | | entry be:sender, type='MSNG', c=1, size=24, |
527 | | */ |
528 | | } |
529 | | |
530 | | void SnowView::MouseMoved(BPoint where, uint32 code, const BMessage *a_message) |
531 | | { |
532 | | #ifdef FORWARD_TO_PARENT |
533 | | if (fAttached && Parent()) |
534 | | Parent()->MouseMoved(where, code, a_message); |
535 | | #endif |
536 | | } |
537 | | |
538 | | void SnowView::KeyDown(const char *bytes, int32 numBytes) |
539 | | { |
540 | | #ifdef FORWARD_TO_PARENT |
541 | | if (fAttached && Parent()) |
542 | | Parent()->KeyDown(bytes, numBytes); |
543 | | #endif |
544 | | } |
545 | | |
546 | | void SnowView::KeyUp(const char *bytes, int32 numBytes) |
547 | | { |
548 | | #ifdef FORWARD_TO_PARENT |
549 | | if (fAttached && Parent()) |
550 | | Parent()->KeyUp(bytes, numBytes); |
551 | | #endif |
552 | | } |
553 | | |
554 | | #define PORTION_GRAN 20 |
555 | | |
556 | | int32 SnowView::SnowMakerThread(void *p_this) |
557 | | { |
558 | | SnowView *_this = (SnowView *)p_this; |
559 | | BView *p = _this->Parent(); |
560 | | BRect portion(0,0,(_this->fCachedWsWidth/PORTION_GRAN)-1, (_this->fCachedWsHeight/PORTION_GRAN)-1); |
561 | | int nf = _this->fNumFlakes; |
562 | | BRegion reg(BRect(-1,-1,-1,-1)); |
563 | | while (p && _this->fAttached) { |
564 | | snooze(INTERVAL/(10*(nf?nf:1))); |
565 | | int32 cw = _this->fCurrentWorkspace; |
566 | | bool drawThisOne = false; |
567 | | //printf("processing flake %d...\n", current); |
568 | | //for (; (current%(fNumFlakes/4); current++) |
569 | | if (reg.Intersects(portion)) { |
570 | | for (int i = 0; !drawThisOne && i < nf; i++) { |
571 | | /* if we find at least one flake in this rect, draw it */ |
572 | | if ((_this->fFlakes[cw][i].weight) && ( |
573 | | portion.Intersects(BRect(_this->fFlakes[cw][i].opos - BPoint(4,4), _this->fFlakes[cw][i].opos + BPoint(4,4))) || |
574 | | portion.Intersects(BRect(_this->fFlakes[cw][i].pos - BPoint(4,4), _this->fFlakes[cw][i].pos + BPoint(4,4))))) { |
575 | | drawThisOne = true; |
576 | | } |
577 | | } |
578 | | } |
579 | | //if (!drawThisOne) |
580 | | //printf("!Invalidate(%f, %f, %f, %f)\n", portion.left, portion.top, portion.right, portion.bottom); |
581 | | /* avoid deadlock on exit */ |
582 | | if (drawThisOne && (_this->LockLooperWithTimeout(2000) == B_OK)) { |
583 | | // printf("Invalidate(%f, %f, %f, %f)\n", portion.left, portion.top, portion.right, portion.bottom); |
584 | | p->Invalidate(portion); |
585 | | _this->UnlockLooper(); |
586 | | } |
587 | | portion.OffsetBy(_this->fCachedWsWidth/PORTION_GRAN, 0); |
588 | | if (portion.left >= _this->fCachedWsWidth) { /* right wrap */ |
589 | | //printf("rigth wrap to %ld\n", _this->fCachedWsWidth); |
590 | | portion.OffsetTo(0, portion.top+(_this->fCachedWsHeight/PORTION_GRAN)); |
591 | | } |
592 | | if (portion.top >= _this->fCachedWsHeight) { |
593 | | portion.OffsetTo(0,0); |
594 | | /* avoid deadlock on exit */ |
595 | | if (_this->LockLooperWithTimeout(5000) == B_OK) { |
596 | | //printf("calculating flakes...\n"); |
597 | | _this->Calc(); |
598 | | //printf("done calculating flakes.\n"); |
599 | | _this->GetClippingRegion(®); |
600 | | //printf("Region:\n"); |
601 | | //reg.PrintToStream(); |
602 | | _this->UnlockLooper(); |
603 | | } |
604 | | } |
605 | | } |
606 | | #if 0 |
607 | | BView *p = _this->Parent(); |
608 | | while (p && _this->fAttached) { |
609 | | snooze(INTERVAL/_this->fNumFlakes); |
610 | | //printf("processing flake %d...\n", current); |
611 | | //for (; (current%(fNumFlakes/4); current++) |
612 | | /* avoid deadlock on exit */ |
613 | | if (_this->LockLooperWithTimeout(2000) == B_OK) { |
614 | | if (_this->fFlakes[_this->fCurrentWorkspace][current].weight) { |
615 | | p->Invalidate(BRect(_this->fFlakes[_this->fCurrentWorkspace][current].opos - BPoint(4,4), |
616 | | _this->fFlakes[_this->fCurrentWorkspace][current].opos + BPoint(4,4))); |
617 | | p->Invalidate(BRect(_this->fFlakes[_this->fCurrentWorkspace][current].pos - BPoint(4,4), |
618 | | _this->fFlakes[_this->fCurrentWorkspace][current].pos + BPoint(4,4))); |
619 | | } |
620 | | _this->UnlockLooper(); |
621 | | current++; |
622 | | current %= _this->fNumFlakes; |
623 | | if (!current) { |
624 | | /* avoid deadlock on exit */ |
625 | | if (_this->LockLooperWithTimeout(2000) == B_OK) { |
626 | | printf("calculating flakes...\n"); |
627 | | _this->Calc(); |
628 | | printf("done calculating flakes.\n"); |
629 | | _this->UnlockLooper(); |
630 | | } |
631 | | } |
632 | | } |
633 | | } |
634 | | #endif |
635 | | return B_OK; |
636 | | } |