1 #include "CtrlCore.h"
2
3 namespace Upp {
4
5 #define LLOG(x) // DLOG(x)
6
7 Ptr<Ctrl> Ctrl::eventCtrl;
8 Ptr<Ctrl> Ctrl::mouseCtrl;
9 Ptr<Ctrl> Ctrl::captureCtrl;
10 Ptr<Ctrl> Ctrl::repeatTopCtrl;
11 Point Ctrl::repeatMousePos;
12 bool Ctrl::ignoreclick;
13 bool Ctrl::ignoremouseup;
14 bool Ctrl::mouseinframe;
15 bool Ctrl::mouseinview;
16 Point Ctrl::mousepos;
17 Point Ctrl::leftmousepos = Null;
18 Point Ctrl::rightmousepos = Null;
19 Point Ctrl::middlemousepos = Null;
20
GetMouseFlags()21 dword GetMouseFlags() {
22 dword style = 0;
23 if(GetAlt()) style |= K_ALT;
24 if(GetCtrl()) style |= K_CTRL;
25 if(GetShift()) style |= K_SHIFT;
26 if(GetMouseLeft()) style |= K_MOUSELEFT;
27 if(GetMouseRight()) style |= K_MOUSERIGHT;
28 if(GetMouseMiddle()) style |= K_MOUSEMIDDLE;
29 return style;
30 }
31
LogMouseEvent(const char * f,const Ctrl * ctrl,int event,Point p,int zdelta,dword keyflags)32 void Ctrl::LogMouseEvent(const char *f, const Ctrl *ctrl, int event, Point p, int zdelta, dword keyflags)
33 {
34 if(!Ini::user_log)
35 return;
36 String txt = f;
37 txt += (event & BUTTON) == RIGHT ? "RIGHT" : (event & BUTTON) == MIDDLE ? "MIDDLE" : "LEFT";
38 switch(event & ACTION) {
39 case DOWN: txt << "DOWN"; break;
40 case UP: txt << "UP"; break;
41 case DOUBLE: txt << "DOUBLE"; break;
42 case MOUSEWHEEL: txt << "WHEEL"; break;
43 default:
44 return;
45 }
46 txt << ' ' << p << " (";
47 if(keyflags & K_ALT)
48 txt << " ALT";
49 if(keyflags & K_CTRL)
50 txt << " CTRL";
51 if(keyflags & K_SHIFT)
52 txt << " SHIFT";
53 if(keyflags & K_MOUSELEFT)
54 txt << " LEFT";
55 if(keyflags & K_MOUSERIGHT)
56 txt << " RIGHT";
57 if(keyflags & K_MOUSEMIDDLE)
58 txt << " MIDDLE";
59 txt << " ) " << Desc(ctrl);
60 USRLOG(txt);
61 LLOG(txt);
62 }
63
FrameMouseEventH(int event,Point p,int zdelta,dword keyflags)64 Image Ctrl::FrameMouseEventH(int event, Point p, int zdelta, dword keyflags)
65 {
66 GuiLock __;
67 Ptr<Ctrl> this_ = this;
68 for(int i = 0; i < mousehook().GetCount(); i++)
69 if(this_ && (*mousehook()[i])(this, true, event, p, zdelta, keyflags))
70 return Image::Arrow();
71 if(this_)
72 LogMouseEvent("FRAME ", this, event, p, zdelta, keyflags);
73 eventCtrl = this_;
74 if(parent && this_)
75 parent->ChildFrameMouseEvent(this, event, p, zdelta, keyflags);
76 return this_ ? FrameMouseEvent(event, p, zdelta, keyflags) : Image();
77 }
78
FrameMouseEvent(int event,Point p,int zdelta,dword keyflags)79 Image Ctrl::FrameMouseEvent(int event, Point p, int zdelta, dword keyflags)
80 {
81 return Image::Arrow();
82 }
83
84 static bool sPropagated;
85
MouseEvent0(int event,Point p,int zdelta,dword keyflags)86 Image Ctrl::MouseEvent0(int event, Point p, int zdelta, dword keyflags)
87 {
88 GuiLock __;
89 Ptr<Ctrl> this_ = this;
90 bool pb = sPropagated;
91 sPropagated = false;
92 Image m = this_ ? MouseEvent(event, p, zdelta, keyflags) : Image();
93 if(event == MOUSEWHEEL && !sPropagated && this_ && parent)
94 parent->ChildMouseEvent(this, event, p, zdelta, keyflags);
95 sPropagated = pb;
96 return m;
97 }
98
MouseEventH(int event,Point p,int zdelta,dword keyflags)99 Image Ctrl::MouseEventH(int event, Point p, int zdelta, dword keyflags)
100 {
101 GuiLock __;
102 Ptr<Ctrl> this_ = this;
103 for(int i = 0; i < mousehook().GetCount(); i++)
104 if(this_ && (*mousehook()[i])(this, false, event, p, zdelta, keyflags))
105 return Image::Arrow();
106 if(this_)
107 LogMouseEvent(NULL, this, event, p, zdelta, keyflags);
108 if(this_ && parent && event != MOUSEWHEEL)
109 parent->ChildMouseEvent(this, event, p, zdelta, keyflags);
110 return MouseEvent0(event, p, zdelta, keyflags);
111 }
112
MouseWheel(Point p,int zd,dword kf)113 void Ctrl::MouseWheel(Point p, int zd, dword kf)
114 {
115 if(parent) {
116 p += GetScreenView().TopLeft();
117 Rect r = parent->GetScreenView();
118 if(r.Contains(p)) {
119 parent->MouseEvent0(MOUSEWHEEL, p - r.TopLeft(), zd, kf);
120 sPropagated = true;
121 }
122 }
123 }
124
ChildFrameMouseEvent(Ctrl * child,int event,Point p,int zdelta,dword keyflags)125 void Ctrl::ChildFrameMouseEvent(Ctrl *child, int event, Point p, int zdelta, dword keyflags)
126 {
127 GuiLock __;
128 if(parent)
129 parent->ChildFrameMouseEvent(child, event, p, zdelta, keyflags);
130 }
131
ChildMouseEvent(Ctrl * child,int event,Point p,int zdelta,dword keyflags)132 void Ctrl::ChildMouseEvent(Ctrl *child, int event, Point p, int zdelta, dword keyflags)
133 {
134 GuiLock __;
135 if(parent)
136 parent->ChildMouseEvent(child, event, p, zdelta, keyflags);
137 }
138
MouseEvent(int event,Point p,int zdelta,dword keyflags)139 Image Ctrl::MouseEvent(int event, Point p, int zdelta, dword keyflags)
140 {
141 LLOG("MouseEvent " << UPP::Name(this) << " " << FormatIntHex(event));
142 switch(event) {
143 case MOUSEENTER:
144 MouseEnter(p, keyflags);
145 break;
146 case MOUSEMOVE:
147 MouseMove(p, keyflags);
148 break;
149 case LEFTDOWN:
150 LeftDown(p, keyflags);
151 break;
152 case LEFTDOUBLE:
153 LeftDouble(p, keyflags);
154 break;
155 case LEFTDRAG:
156 LeftDrag(p, keyflags);
157 break;
158 case LEFTHOLD:
159 LeftHold(p, keyflags);
160 break;
161 case LEFTTRIPLE:
162 LeftTriple(p, keyflags);
163 break;
164 case LEFTREPEAT:
165 LeftRepeat(p, keyflags);
166 break;
167 case LEFTUP:
168 LeftUp(p, keyflags);
169 break;
170 case RIGHTDRAG:
171 RightDrag(p, keyflags);
172 break;
173 case RIGHTHOLD:
174 RightHold(p, keyflags);
175 break;
176 case RIGHTTRIPLE:
177 RightTriple(p, keyflags);
178 break;
179 case RIGHTDOWN:
180 RightDown(p, keyflags);
181 break;
182 case RIGHTDOUBLE:
183 RightDouble(p, keyflags);
184 break;
185 case RIGHTREPEAT:
186 RightRepeat(p, keyflags);
187 break;
188 case RIGHTUP:
189 RightUp(p, keyflags);
190 break;
191 case MIDDLEDRAG:
192 MiddleDrag(p, keyflags);
193 break;
194 case MIDDLEHOLD:
195 MiddleHold(p, keyflags);
196 break;
197 case MIDDLETRIPLE:
198 MiddleTriple(p, keyflags);
199 break;
200 case MIDDLEDOWN:
201 MiddleDown(p, keyflags);
202 break;
203 case MIDDLEDOUBLE:
204 MiddleDouble(p, keyflags);
205 break;
206 case MIDDLEREPEAT:
207 MiddleRepeat(p, keyflags);
208 break;
209 case MIDDLEUP:
210 MiddleUp(p, keyflags);
211 break;
212 case MOUSELEAVE:
213 MouseLeave();
214 break;
215 case MOUSEWHEEL:
216 MouseWheel(p, zdelta, keyflags);
217 break;
218 case CURSORIMAGE:
219 return CursorImage(p, keyflags);
220 }
221 return Image::Arrow();
222 }
223
CursorImage(Point p,dword keyflags)224 Image Ctrl::CursorImage(Point p, dword keyflags)
225 {
226 return Image::Arrow();
227 }
228
IgnoreMouseClick()229 void Ctrl::IgnoreMouseClick()
230 {
231 GuiLock __;
232 LLOG("IgnoreMouseClick");
233 ignoreclick = true;
234 KillRepeat();
235 }
236
IgnoreMouseUp()237 void Ctrl::IgnoreMouseUp()
238 {
239 GuiLock __;
240 LLOG("Ctrl::IgnoreMouseUp");
241 if(GetMouseLeft() || GetMouseRight() || GetMouseMiddle()) {
242 IgnoreMouseClick();
243 ignoremouseup = true;
244 }
245 }
246
UnIgnoreMouse()247 void Ctrl::UnIgnoreMouse()
248 {
249 GuiLock __;
250 LLOG("Ctrl::EndIgnore");
251 KillRepeat();
252 ignoreclick = false;
253 ignoremouseup = false;
254 }
255
EndIgnore()256 void Ctrl::EndIgnore()
257 {
258 GuiLock __;
259 LLOG("Ctrl::EndIgnore");
260 if(GetMouseLeft() || GetMouseRight() || GetMouseMiddle()) return;
261 KillRepeat();
262 ignoreclick = false;
263 ignoremouseup = false;
264 }
265
IsMouseActive() const266 bool Ctrl::IsMouseActive() const
267 {
268 GuiLock __;
269 return IsVisible() && IsEnabled() && IsOpen() && !ignoremouse;
270 }
271
ChildFromPoint(Point & pt) const272 Ctrl *Ctrl::ChildFromPoint(Point& pt) const
273 {
274 GuiLock __;
275 Ctrl *q;
276 Point p = pt;
277 Rect view = GetView();
278 if(view.Contains(p)) {
279 Point vp = p - view.TopLeft();
280 for(q = GetLastChild(); q; q = q->prev) {
281 if(q->InView() && q->IsMouseActive()) {
282 Rect r = q->GetRect();
283 if(r.Contains(vp)) {
284 pt = vp - r.TopLeft();
285 return q;
286 }
287 }
288 }
289 return NULL;
290 }
291 for(q = GetLastChild(); q; q = q->prev) {
292 if(q->InFrame() && q->IsMouseActive()) {
293 Rect r = q->GetRect();
294 if(r.Contains(p)) {
295 pt = p - r.TopLeft();
296 return q;
297 }
298 }
299 }
300 return NULL;
301 }
302
MEvent0(int e,Point p,int zd)303 Image Ctrl::MEvent0(int e, Point p, int zd)
304 {
305 GuiLock __;
306 LLOG("MEvent0 " << Name() << " event: " << FormatIntHex(e, 0) << " point:" << p);
307 Ptr<Ctrl> _this = this;
308 mousepos = p;
309 dword mm = 0;
310 if((e & ACTION) == DOUBLE)
311 mm |= K_MOUSEDOUBLE;
312 if((e & ACTION) == TRIPLE)
313 mm |= K_MOUSETRIPLE;
314 Rect view = GetView();
315 if(mouseCtrl != this) {
316 if(mouseCtrl) {
317 Ptr<Ctrl> mousectrl = mouseCtrl;
318 mousectrl->MouseEventH(MOUSELEAVE, Point(0, 0), zd, GetMouseFlags() | mm);
319 if(mousectrl)
320 mousectrl->FrameMouseEventH(MOUSELEAVE, Point(0, 0), zd, GetMouseFlags() | mm);
321 }
322 mouseinframe = mouseinview = false;
323 if(_this) {
324 mouseCtrl = _this;
325 mouseinframe = true;
326 FrameMouseEventH(MOUSEENTER, p, zd, GetMouseFlags() | mm);
327 }
328 }
329 bool inview = view.Contains(p);
330 if(inview != mouseinview && _this) {
331 mouseinview = inview;
332 MouseEventH(inview ? MOUSEENTER : MOUSELEAVE, p, zd, GetMouseFlags() | mm);
333 }
334 if(_this) {
335 if(view.Contains(p) || HasCapture()) {
336 p -= view.TopLeft();
337 return MouseEventH(e, p, zd, GetMouseFlags() | mm);
338 }
339 else
340 return FrameMouseEventH(e, p, zd, GetMouseFlags() | mm);
341 }
342 return Image::Arrow();
343 }
344
LRepeat()345 void Ctrl::LRepeat() {
346 GuiLock __;
347 if(repeatTopCtrl && GetMouseLeft()) {
348 if(repeatTopCtrl->HasFocusDeep())
349 repeatTopCtrl->DispatchMouseEvent(LEFTREPEAT, repeatMousePos, 0);
350 }
351 else
352 KillRepeat();
353 LLOG("LRepeat " << UPP::Name(mouseCtrl));
354 }
355
sDistMax(Point a,Point b)356 static int sDistMax(Point a, Point b)
357 {
358 return IsNull(a) ? INT_MAX : max(abs(a.x - b.x), abs(a.y - b.y));
359 }
360
sDistMin(Point a,Point b)361 static int sDistMin(Point a, Point b)
362 {
363 return IsNull(a) ? -1 : max(abs(a.x - b.x), abs(a.y - b.y));
364 }
365
LRep()366 void Ctrl::LRep() {
367 LLOG("LRep");
368 UPP::SetTimeCallback(-GetKbdSpeed(), callback(&Ctrl::LRepeat), &mousepos);
369 }
370
LHold()371 void Ctrl::LHold() {
372 GuiLock __;
373 if(sDistMax(leftmousepos, mousepos) < GUI_DragDistance() && repeatTopCtrl && GetMouseLeft())
374 repeatTopCtrl->DispatchMouseEvent(LEFTHOLD, repeatMousePos, 0);
375 }
376
RRepeat()377 void Ctrl::RRepeat() {
378 GuiLock __;
379 if(repeatTopCtrl && GetMouseRight()) {
380 if(repeatTopCtrl->HasFocusDeep())
381 repeatTopCtrl->DispatchMouseEvent(RIGHTREPEAT, repeatMousePos, 0);
382 }
383 else
384 KillRepeat();
385 }
386
RRep()387 void Ctrl::RRep() {
388 UPP::SetTimeCallback(-GetKbdSpeed(), callback(&Ctrl::RRepeat), &mousepos);
389 }
390
RHold()391 void Ctrl::RHold() {
392 GuiLock __;
393 if(sDistMax(rightmousepos, mousepos) < GUI_DragDistance() && repeatTopCtrl && GetMouseRight())
394 repeatTopCtrl->DispatchMouseEvent(RIGHTHOLD, repeatMousePos, 0);
395 }
396
MRepeat()397 void Ctrl::MRepeat() {
398 GuiLock __;
399 if(repeatTopCtrl && GetMouseMiddle()) {
400 if(repeatTopCtrl->HasFocusDeep())
401 repeatTopCtrl->DispatchMouseEvent(MIDDLEREPEAT, repeatMousePos, 0);
402 }
403 else
404 KillRepeat();
405 }
406
MRep()407 void Ctrl::MRep() {
408 GuiLock __;
409 UPP::SetTimeCallback(-GetKbdSpeed(), callback(&Ctrl::MRepeat), &mousepos);
410 }
411
MHold()412 void Ctrl::MHold() {
413 GuiLock __;
414 if(sDistMax(middlemousepos, mousepos) < GUI_DragDistance() && repeatTopCtrl && GetMouseMiddle())
415 repeatTopCtrl->DispatchMouseEvent(MIDDLEHOLD, repeatMousePos, 0);
416 }
417
KillRepeat()418 void Ctrl::KillRepeat() {
419 GuiLock __;
420 LLOG("Ctrl::KillRepeat");
421 UPP::KillTimeCallback(&mousepos);
422 repeatTopCtrl = NULL;
423 leftmousepos = Null;
424 rightmousepos = Null;
425 middlemousepos = Null;
426 }
427
HasMouse() const428 bool Ctrl::HasMouse() const
429 {
430 GuiLock __;
431 return mouseCtrl == this;
432 }
433
HasMouseDeep() const434 bool Ctrl::HasMouseDeep() const
435 {
436 GuiLock __;
437 return mouseCtrl == this || HasChildDeep(mouseCtrl);
438 }
439
GetMouseCtrl()440 Ctrl *Ctrl::GetMouseCtrl()
441 {
442 GuiLock __;
443 return mouseCtrl;
444 }
445
HasMouseInFrame(const Rect & r) const446 bool Ctrl::HasMouseInFrame(const Rect& r) const
447 {
448 GuiLock __;
449 if(!HasMouse())
450 return false;
451 Rect q = GetVisibleScreenRect();
452 q = r.Offseted(q.TopLeft()) & q;
453 return q.Contains(GetMousePos());
454 }
455
HasMouseIn(const Rect & r) const456 bool Ctrl::HasMouseIn(const Rect& r) const
457 {
458 GuiLock __;
459 if(!HasMouse())
460 return false;
461 return (r.Offseted(GetScreenView().TopLeft()) & GetVisibleScreenView()).Contains(GetMousePos());
462 }
463
GetMouseViewPos() const464 Point Ctrl::GetMouseViewPos() const
465 {
466 GuiLock __;
467 return GetMousePos() - GetVisibleScreenView().TopLeft();
468 }
469
DoCursorShape()470 void Ctrl::DoCursorShape() {
471 GuiLock __;
472 Image m = CursorOverride();
473 if(IsNull(m))
474 if(mouseCtrl)
475 SetMouseCursor(mouseCtrl->MEvent0(CURSORIMAGE, mousepos, 0));
476 else
477 SetMouseCursor(Image::Arrow());
478 else
479 SetMouseCursor(m);
480 }
481
CheckMouseCtrl()482 void Ctrl::CheckMouseCtrl() {
483 LLOG("CheckMouseCtrl " << mouseCtrl);
484 GuiLock __;
485 Point p = GetMousePos();
486 if(mouseCtrl) {
487 Rect r = mouseCtrl->GetScreenRect();
488 LLOG("CheckMouseCtrl mouseCtrl " << UPP::Name(mouseCtrl) << " " << r);
489 if(!mouseCtrl->HasCapture() && !r.Contains(p)) {
490 Ptr<Ctrl> mousectrl = mouseCtrl;
491 if(mouseinview)
492 mousectrl->MouseEventH(MOUSELEAVE, p - mousectrl->GetScreenView().TopLeft(),
493 0, GetMouseFlags());
494 if(mouseinframe && mousectrl)
495 mousectrl->FrameMouseEventH(MOUSELEAVE, p - r.TopLeft(),
496 0, GetMouseFlags());
497 mouseinview = mouseinframe = false;
498 mouseCtrl = NULL;
499 leftmousepos = rightmousepos = middlemousepos = Null;
500 KillRepeat();
501 }
502 }
503 DoCursorShape();
504 }
505
506 Point leftdblpos = Null, rightdblpos = Null, middledblpos = Null;
507 int leftdbltime = Null, rightdbltime = Null, middledbltime = Null;
508
sDblTime(int time)509 bool sDblTime(int time)
510 {
511 return !IsNull(time) && (int)msecs() - time < GUI_DblClickTime();
512 }
513
DispatchMouse(int e,Point p,int zd)514 Image Ctrl::DispatchMouse(int e, Point p, int zd) {
515 GuiLock __;
516 if(e == MOUSEWHEEL && !zd) // ignore non-scroll wheel events
517 return Null;
518 if(e == MOUSEMOVE && repeatTopCtrl == this) {
519 if(sDistMin(leftmousepos, p) > GUI_DragDistance() && GetMouseLeft()) {
520 DispatchMouseEvent(LEFTDRAG, leftmousepos, 0);
521 leftmousepos = Null;
522 }
523 if(sDistMin(rightmousepos, p) > GUI_DragDistance() && GetMouseRight()) {
524 DispatchMouseEvent(RIGHTDRAG, rightmousepos, 0);
525 rightmousepos = Null;
526 }
527 if(sDistMin(middlemousepos, p) > GUI_DragDistance() && GetMouseMiddle()) {
528 DispatchMouseEvent(MIDDLEDRAG, middlemousepos, 0);
529 middlemousepos = Null;
530 }
531 }
532 repeatMousePos = p;
533 if(e == LEFTDOUBLE) {
534 leftdbltime = msecs();
535 leftdblpos = p;
536 UPP::SetTimeCallback(GetKbdDelay(), callback(&Ctrl::LRep), &mousepos);
537 repeatTopCtrl = this;
538 }
539 if(e == RIGHTDOUBLE) {
540 rightdbltime = msecs();
541 rightdblpos = p;
542 UPP::SetTimeCallback(GetKbdDelay(), callback(&Ctrl::RRep), &mousepos);
543 repeatTopCtrl = this;
544 }
545 if(e == MIDDLEDOUBLE) {
546 middledbltime = msecs();
547 middledblpos = p;
548 UPP::SetTimeCallback(GetKbdDelay(), callback(&Ctrl::MRep), &mousepos);
549 repeatTopCtrl = this;
550 }
551 if(e == LEFTDOWN) {
552 LLOG("Ctrl::DispatchMouse: init left repeat for " << UPP::Name(this) << " at " << p);
553 UPP::SetTimeCallback(GetKbdDelay(), callback(&Ctrl::LRep), &mousepos);
554 UPP::SetTimeCallback(2 * GetKbdDelay(), callback(&Ctrl::LHold), &mousepos);
555 leftmousepos = p;
556 if(sDistMax(leftdblpos, p) < GUI_DragDistance() && sDblTime(leftdbltime))
557 e = LEFTTRIPLE;
558 repeatTopCtrl = this;
559 }
560 if(e == RIGHTDOWN) {
561 LLOG("Ctrl::DispatchMouse: init right repeat for " << UPP::Name(this) << " at " << p);
562 UPP::SetTimeCallback(GetKbdDelay(), callback(&Ctrl::RRep), &mousepos);
563 UPP::SetTimeCallback(2 * GetKbdDelay(), callback(&Ctrl::RHold), &mousepos);
564 rightmousepos = p;
565 if(sDistMax(rightdblpos, p) < GUI_DragDistance() && sDblTime(rightdbltime))
566 e = RIGHTTRIPLE;
567 repeatTopCtrl = this;
568 }
569 if(e == MIDDLEDOWN) {
570 LLOG("Ctrl::DispatchMouse: init middle repeat for " << UPP::Name(this) << " at " << p);
571 UPP::SetTimeCallback(GetKbdDelay(), callback(&Ctrl::MRep), &mousepos);
572 UPP::SetTimeCallback(2 * GetKbdDelay(), callback(&Ctrl::MHold), &mousepos);
573 middlemousepos = p;
574 if(sDistMax(middledblpos, p) < GUI_DragDistance() && sDblTime(middledbltime))
575 e = MIDDLETRIPLE;
576 repeatTopCtrl = this;
577 }
578 if(repeatTopCtrl != this)
579 repeatTopCtrl = NULL;
580 if(e == LEFTUP)
581 leftmousepos = Null;
582 if(e == RIGHTUP)
583 rightmousepos = Null;
584 if(e == MIDDLEUP)
585 rightmousepos = Null;
586 if(findarg(e, LEFTUP, RIGHTUP, MIDDLEUP) >= 0)
587 KillRepeat();
588 Image result = DispatchMouseEvent(e, p, zd);
589 if(!GetMouseRight() && !GetMouseMiddle() && !GetMouseLeft())
590 ReleaseCtrlCapture();
591 return result;
592 }
593
DispatchMouseEvent(int e,Point p,int zd)594 Image Ctrl::DispatchMouseEvent(int e, Point p, int zd) {
595 GuiLock __;
596 if(captureCtrl && captureCtrl != this && captureCtrl->IsMouseActive()) {
597 if(captureCtrl->IsEnabled())
598 return captureCtrl->MEvent0(e, p + GetScreenRect().TopLeft() -
599 captureCtrl->GetScreenRect().TopLeft(), zd);
600 else
601 return Image::Arrow();
602 }
603 if(!IsEnabled())
604 return Image::Arrow();
605 Ctrl *top = this;
606 if(e == MOUSEWHEEL && !GetParent()) {
607 Ctrl *w = GetFocusCtrl();
608 if(w) {
609 top = w->GetTopCtrl();
610 p = GetMousePos() - top->GetScreenRect().TopLeft();
611 }
612 }
613 Ctrl *q = top->ChildFromPoint(p);
614 return q ? q->DispatchMouseEvent(e, p, zd) : top->MEvent0(e, p, zd);
615 }
616
SetCapture()617 bool Ctrl::SetCapture() {
618 GuiLock __;
619 ReleaseCtrlCapture();
620 if(!GetTopCtrl()->SetWndCapture()) return false;
621 captureCtrl = mouseCtrl = this;
622 return true;
623 }
624
ReleaseCapture()625 bool Ctrl::ReleaseCapture() {
626 GuiLock __;
627 return this == captureCtrl && ReleaseCtrlCapture();
628 }
629
ReleaseCtrlCapture()630 bool Ctrl::ReleaseCtrlCapture() {
631 GuiLock __;
632 LLOG("ReleaseCtrlCapture");
633 if(captureCtrl) {
634 captureCtrl->CancelMode();
635 Ctrl *w = captureCtrl->GetTopCtrl();
636 captureCtrl = NULL;
637 CheckMouseCtrl();
638 if(w->HasWndCapture()) {
639 w->ReleaseWndCapture();
640 return true;
641 }
642 }
643 return false;
644 }
645
HasCapture() const646 bool Ctrl::HasCapture() const {
647 GuiLock __;
648 if(captureCtrl != this)
649 return false;
650 return captureCtrl == this && GetTopCtrl()->HasWndCapture();
651 }
652
GetCaptureCtrl()653 Ctrl * Ctrl::GetCaptureCtrl()
654 {
655 GuiLock __;
656 return captureCtrl && captureCtrl->GetTopCtrl()->HasWndCapture() ? captureCtrl : NULL;
657 }
658
GetVisibleChild(Ctrl * ctrl,Point p,bool pointinframe)659 Ctrl *Ctrl::GetVisibleChild(Ctrl *ctrl, Point p, bool pointinframe)
660 {
661 GuiLock __;
662 if(!pointinframe)
663 p += ctrl->GetView().TopLeft();
664 Ctrl *q;
665 Rect view = ctrl->GetView();
666 if(view.Contains(p)) {
667 p -= view.TopLeft();
668 for(q = ctrl->GetLastChild(); q; q = q->GetPrev()) {
669 if(q->InView() && q->IsVisible()) {
670 Rect r = q->GetRect();
671 if(r.Contains(p))
672 return GetVisibleChild(q, p - r.TopLeft(), true);
673 }
674 }
675 }
676 else
677 for(q = ctrl->GetLastChild(); q; q = q->GetPrev()) {
678 if(q->InFrame() && q->IsVisible()) {
679 Rect r = q->GetRect();
680 if(r.Contains(p))
681 return GetVisibleChild(q, p - r.TopLeft(), true);
682 }
683 }
684 return ctrl;
685 }
686
AutoWaitCursor(int & avg)687 AutoWaitCursor::AutoWaitCursor(int& avg) : WaitCursor(avg >= 0), avg(avg) {
688 time0 = msecs();
689 }
690
~AutoWaitCursor()691 AutoWaitCursor::~AutoWaitCursor() {
692 if(time0) avg = msecs() - time0 - 500;
693 if(avg < -10000) avg = -10000;
694 if(avg > 10000) avg = 10000;
695 }
696
CursorOverride()697 Image& Ctrl::CursorOverride()
698 {
699 GuiLock __;
700 static Image m;
701 return m;
702 }
703
OverrideCursor(const Image & m)704 Image Ctrl::OverrideCursor(const Image& m)
705 {
706 GuiLock __;
707 Image om = CursorOverride();
708 CursorOverride() = m;
709 DoCursorShape();
710 if(!mouseCtrl)
711 SetMouseCursor(IsNull(m) ? Image::Arrow() : m);
712 return om;
713 }
714
Show()715 void WaitCursor::Show() {
716 if(flag)
717 prev = Ctrl::OverrideCursor(Image::Wait());
718 flag = false;
719 }
720
WaitCursor(bool show)721 WaitCursor::WaitCursor(bool show) {
722 LLOG("WaitCursor");
723 flag = true;
724 if(show) Show();
725 }
726
~WaitCursor()727 WaitCursor::~WaitCursor() {
728 if(!flag)
729 Ctrl::OverrideCursor(prev);
730 }
731
732 }
733