Logo ROOT   6.18/05
Reference Guide
X11Events.mm
Go to the documentation of this file.
1// @(#)root/graf2d:$Id$
2// Author: Timur Pocheptsov 16/02/2012
3
4/*************************************************************************
5 * Copyright (C) 1995-2012, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//#define NDEBUG
13
14#include <algorithm>
15#include <cassert>
16
17#include <Cocoa/Cocoa.h>
18
19#include "CocoaConstants.h"
20#include "ROOTOpenGLView.h"
21#include "QuartzWindow.h"
22#include "CocoaUtils.h"
23#include "KeySymbols.h"
24#include "X11Events.h"
25#include "TGClient.h"
26#include "TGWindow.h"
27#include "TList.h"
28
29@interface FakeCrossingEvent : NSEvent {
30 NSWindow *fQuartzWindow;
31 NSPoint fLocationInWindow;
32}
33
34@end
35
36@implementation FakeCrossingEvent
37
38//______________________________________________________________________________
39- (id) initWithWindow : (NSWindow *) window location : (NSPoint) location
40{
41 //Window should be always non-nil: we either enter some window, or exit some window.
42 assert(window && "initWithWindow:location:, parameter 'window' is nil");
43
44 if (self = [super init]) {
45 fQuartzWindow = window;
46 fLocationInWindow = location;
47 }
48
49 return self;
50}
51
52//______________________________________________________________________________
53- (NSWindow *) window
54{
55 assert(fQuartzWindow && "window, fQuartzWindow is nil");
56 return fQuartzWindow;
57}
58
59//______________________________________________________________________________
60- (NSPoint) locationInWindow
61{
62 assert(fQuartzWindow != nil && "locationInWindow, fQuartzWindow is nil");
63 return fLocationInWindow;
64}
65
66//______________________________________________________________________________
67- (NSTimeInterval) timestamp
68{
69 //Hehe.
70 return 0.;
71}
72
73@end
74
75
76namespace ROOT {
77namespace MacOSX {
78namespace X11 {
79
80namespace {
81
82//Convert unichar (from [NSEvent characters]) into
83//ROOT's key symbol (from KeySymbols.h).
84template<typename T1, typename T2>
85struct KeySymPair {
88
89 bool operator < (const KeySymPair &rhs)const
90 {
91 return fFirst < rhs.fFirst;
92 }
93};
94
95}
96
97//______________________________________________________________________________
98void MapUnicharToKeySym(unichar key, char *buf, Int_t /*len*/, UInt_t &rootKeySym)
99{
100 assert(buf != 0 && "MapUnicharToKeySym, parameter 'buf' is null");
101
102 static const KeySymPair<unichar, EKeySym> keyMap[] = {
103 {NSEnterCharacter, kKey_Enter},
104 {NSTabCharacter, kKey_Tab},
105 {NSCarriageReturnCharacter, kKey_Return},
106 {NSBackTabCharacter, kKey_Backtab},
107 //WHYWHYWHY apple does not have a constant for escape????
108 {27, kKey_Escape},
109 {NSDeleteCharacter, kKey_Backspace},
110 {NSUpArrowFunctionKey, kKey_Up},
111 {NSDownArrowFunctionKey, kKey_Down},
112 {NSLeftArrowFunctionKey, kKey_Left},
113 {NSRightArrowFunctionKey, kKey_Right},
114 {NSF1FunctionKey, kKey_F1},
115 {NSF2FunctionKey, kKey_F2},
116 {NSF3FunctionKey, kKey_F3},
117 {NSF4FunctionKey, kKey_F4},
118 {NSF5FunctionKey, kKey_F5},
119 {NSF6FunctionKey, kKey_F6},
120 {NSF7FunctionKey, kKey_F7},
121 {NSF8FunctionKey, kKey_F8},
122 {NSF9FunctionKey, kKey_F8},
123 {NSF10FunctionKey, kKey_F10},
124 {NSF11FunctionKey, kKey_F11},
125 {NSF12FunctionKey, kKey_F12},
126 {NSF13FunctionKey, kKey_F13},
127 {NSF14FunctionKey, kKey_F14},
128 {NSF15FunctionKey, kKey_F15},
129 {NSF16FunctionKey, kKey_F16},
130 {NSF17FunctionKey, kKey_F17},
131 {NSF18FunctionKey, kKey_F18},
132 {NSF19FunctionKey, kKey_F19},
133 {NSF20FunctionKey, kKey_F20},
134 {NSF21FunctionKey, kKey_F21},
135 {NSF22FunctionKey, kKey_F22},
136 {NSF23FunctionKey, kKey_F23},
137 {NSF24FunctionKey, kKey_F24},
138 {NSF25FunctionKey, kKey_F25},
139 {NSF26FunctionKey, kKey_F26},
140 {NSF27FunctionKey, kKey_F27},
141 {NSF28FunctionKey, kKey_F28},
142 {NSF29FunctionKey, kKey_F29},
143 {NSF30FunctionKey, kKey_F30},
144 {NSF31FunctionKey, kKey_F31},
145 {NSF32FunctionKey, kKey_F32},
146 {NSF33FunctionKey, kKey_F33},
147 {NSF34FunctionKey, kKey_F34},
148 {NSF35FunctionKey, kKey_F35},
149 {NSInsertFunctionKey, kKey_Insert},
150 {NSDeleteFunctionKey, kKey_Delete},
151 {NSHomeFunctionKey, kKey_Home},
152 {NSEndFunctionKey, kKey_End},
153 {NSPageUpFunctionKey, kKey_PageUp},
154 {NSPageDownFunctionKey, kKey_PageDown},
155 {NSPrintScreenFunctionKey, kKey_Print},
156 {NSScrollLockFunctionKey, kKey_ScrollLock},
157 {NSPauseFunctionKey, kKey_Pause},
158 {NSSysReqFunctionKey, kKey_SysReq}};
159
160 const unsigned nEntries = sizeof keyMap / sizeof keyMap[0];
161
162 buf[1] = 0;
163
164 KeySymPair<unichar, EKeySym> valueToFind = {};
165 valueToFind.fFirst = key;
166 const KeySymPair<unichar, EKeySym> *iter = std::lower_bound(keyMap, keyMap + nEntries, valueToFind);
167
168 if (iter != keyMap + nEntries && iter->fFirst == key) {
169 buf[0] = key <= 0x7e ? key : 0;
170 rootKeySym = iter->fSecond;
171 } else {
172 buf[0] = key;//????
173 rootKeySym = key;
174 }
175}
176
177//______________________________________________________________________________
179{
180 //Apart from special keys, ROOT has also ASCII symbols, they map directly to themselves.
181 if (keySym >= 0x20 && keySym <= 0x7e)
182 return keySym;
183
184 static const KeySymPair<EKeySym, unichar> keyMap[] = {
185 {kKey_Escape, 27},
186 {kKey_Tab, NSTabCharacter},
187 {kKey_Backtab, NSBackTabCharacter},
188 {kKey_Backspace, NSDeleteCharacter},
189 {kKey_Return, NSCarriageReturnCharacter},
190 {kKey_Enter, NSEnterCharacter},
191 {kKey_Insert, NSInsertFunctionKey},
192 {kKey_Delete, NSDeleteFunctionKey},
193 {kKey_Pause, NSPauseFunctionKey},
194 {kKey_Print, NSPrintScreenFunctionKey},
195 {kKey_SysReq, NSSysReqFunctionKey},
196 {kKey_Home, NSHomeFunctionKey},
197 {kKey_End, NSEndFunctionKey},
198 {kKey_Left, NSLeftArrowFunctionKey},
199 {kKey_Up, NSUpArrowFunctionKey},
200 {kKey_Right, NSRightArrowFunctionKey},
201 {kKey_Down, NSDownArrowFunctionKey},
202 {kKey_PageUp, NSPageUpFunctionKey},
203 {kKey_PageDown, NSPageDownFunctionKey},
204 //This part is bad.
205 {kKey_Shift, 0},
206 {kKey_Control, 0},
207 {kKey_Alt, 0},
208 {kKey_CapsLock, 0},
209 {kKey_NumLock, 0},
210 //
211 {kKey_ScrollLock, NSScrollLockFunctionKey},
212 {kKey_F1, NSF1FunctionKey},
213 {kKey_F2, NSF2FunctionKey},
214 {kKey_F3, NSF3FunctionKey},
215 {kKey_F4, NSF4FunctionKey},
216 {kKey_F5, NSF5FunctionKey},
217 {kKey_F6, NSF6FunctionKey},
218 {kKey_F7, NSF7FunctionKey},
219 {kKey_F8, NSF8FunctionKey},
220 {kKey_F8, NSF9FunctionKey},
221 {kKey_F10, NSF10FunctionKey},
222 {kKey_F11, NSF11FunctionKey},
223 {kKey_F12, NSF12FunctionKey},
224 {kKey_F13, NSF13FunctionKey},
225 {kKey_F14, NSF14FunctionKey},
226 {kKey_F15, NSF15FunctionKey},
227 {kKey_F16, NSF16FunctionKey},
228 {kKey_F17, NSF17FunctionKey},
229 {kKey_F18, NSF18FunctionKey},
230 {kKey_F19, NSF19FunctionKey},
231 {kKey_F20, NSF20FunctionKey},
232 {kKey_F21, NSF21FunctionKey},
233 {kKey_F22, NSF22FunctionKey},
234 {kKey_F23, NSF23FunctionKey},
235 {kKey_F24, NSF24FunctionKey},
236 {kKey_F25, NSF25FunctionKey},
237 {kKey_F26, NSF26FunctionKey},
238 {kKey_F27, NSF27FunctionKey},
239 {kKey_F28, NSF28FunctionKey},
240 {kKey_F29, NSF29FunctionKey},
241 {kKey_F30, NSF30FunctionKey},
242 {kKey_F31, NSF31FunctionKey},
243 {kKey_F32, NSF32FunctionKey},
244 {kKey_F33, NSF33FunctionKey},
245 {kKey_F34, NSF34FunctionKey},
246 {kKey_F35, NSF35FunctionKey}
247 };
248
249 const unsigned nEntries = sizeof keyMap / sizeof keyMap[0];
250
251 KeySymPair<EKeySym, unichar> valueToFind = {};
252 valueToFind.fFirst = static_cast<EKeySym>(keySym);
253 const KeySymPair<EKeySym, unichar> *iter = std::lower_bound(keyMap, keyMap + nEntries, valueToFind);
254 if (iter != keyMap + nEntries && iter->fFirst == keySym)
255 return iter->fSecond;
256
257 return 0;
258}
259
260//______________________________________________________________________________
262{
263 NSUInteger cocoaModifiers = 0;
264
265 if (rootModifiers & kKeyLockMask)
266 cocoaModifiers |= Details::kAlphaShiftKeyMask;
267 if (rootModifiers & kKeyShiftMask)
268 cocoaModifiers |= Details::kShiftKeyMask;
269 if (rootModifiers & kKeyControlMask)
270 cocoaModifiers |= Details::kControlKeyMask;
271 if (rootModifiers & kKeyMod1Mask)
272 cocoaModifiers |= Details::kAlternateKeyMask;
273 if (rootModifiers & kKeyMod2Mask)
274 cocoaModifiers |= Details::kCommandKeyMask;
275
276 return cocoaModifiers;
277}
278
279//______________________________________________________________________________
281{
282 const NSUInteger modifiers = [NSEvent modifierFlags];
283
284 UInt_t rootModifiers = 0;
285 if (modifiers & Details::kAlphaShiftKeyMask)
286 rootModifiers |= kKeyLockMask;
287 if (modifiers & Details::kShiftKeyMask)
288 rootModifiers |= kKeyShiftMask;
289 if (modifiers & Details::kControlKeyMask)
290 rootModifiers |= kKeyControlMask;
291 if (modifiers & Details::kAlternateKeyMask)
292 rootModifiers |= kKeyMod1Mask;
293 if (modifiers & Details::kCommandKeyMask)
294 rootModifiers |= kKeyMod2Mask;
295
296 return rootModifiers;
297}
298
299//______________________________________________________________________________
301{
302 UInt_t rootModifiers = GetKeyboardModifiers();
303 const NSUInteger buttons = [NSEvent pressedMouseButtons];
304 if (buttons & 1)
305 rootModifiers |= kButton1Mask;
306 if (buttons & 2)
307 rootModifiers |= kButton3Mask;
308 if (buttons & (1 << 2))
309 rootModifiers |= kButton2Mask;
310
311 return rootModifiers;
312}
313
314namespace Detail {
315
316#pragma mark - Several aux. functions to extract parameters from Cocoa events.
317
318//______________________________________________________________________________
319Time_t TimeForCocoaEvent(NSEvent *theEvent)
320{
321 //1. Event is not nil.
322 assert(theEvent != nil && "TimeForCocoaEvent, parameter 'theEvent' is nil");
323
324 return [theEvent timestamp] * 1000;
325}
326
327//______________________________________________________________________________
328Event_t NewX11EventFromCocoaEvent(unsigned windowID, NSEvent *theEvent)
329{
330 //1. Event is not nil.
331
332 assert(theEvent != nil && "NewX11EventFromCocoaEvent, parameter 'theEvent' is nil");
333
334 Event_t newEvent = {};
335 newEvent.fWindow = windowID;
336 newEvent.fTime = TimeForCocoaEvent(theEvent);
337 return newEvent;
338}
339
340//______________________________________________________________________________
341void ConvertEventLocationToROOTXY(NSEvent *cocoaEvent, NSView<X11Window> *eventView, Event_t *rootEvent)
342{
343 //1. All parameters are valid.
344 //Both event and view must be in the same window, I do not check this here.
345
346 assert(cocoaEvent != nil && "ConvertEventLocationToROOTXY, parameter 'cocoaEvent' is nil");
347 assert(eventView != nil && "ConvertEventLocationToROOTXY, parameter 'eventView' is nil");
348 assert(rootEvent != 0 && "ConvertEventLocationToROOTXY, parameter 'rootEvent' is null");
349
350 if (![cocoaEvent window])
351 NSLog(@"Error in ConvertEventLocationToROOTXY, window property"
352 " of event is nil, can not convert coordinates correctly");
353
354 //Due to some reason, Apple has deprectated point conversion and requires to convert ... a rect.
355 //Even more, on HiDPI point conversion produces wrong results and rect conversion works.
356
357 const NSPoint screenPoint = ConvertPointFromBaseToScreen([cocoaEvent window], [cocoaEvent locationInWindow]);
358 const NSPoint winPoint = ConvertPointFromScreenToBase(screenPoint, [eventView window]);
359 const NSPoint viewPoint = [eventView convertPoint : winPoint fromView : nil];
360
361 rootEvent->fX = viewPoint.x;
362 rootEvent->fY = viewPoint.y;
363
364 rootEvent->fXRoot = GlobalXCocoaToROOT(screenPoint.x);
365 rootEvent->fYRoot = GlobalYCocoaToROOT(screenPoint.y);
366}
367
368//______________________________________________________________________________
369unsigned GetKeyboardModifiersFromCocoaEvent(NSEvent *theEvent)
370{
371 assert(theEvent != nil && "GetKeyboardModifiersFromCocoaEvent, parameter 'event' is nil");
372
373 const NSUInteger modifiers = [theEvent modifierFlags];
374 unsigned rootModifiers = 0;
375 if (modifiers & Details::kAlphaShiftKeyMask)
376 rootModifiers |= kKeyLockMask;
377 if (modifiers & Details::kShiftKeyMask)
378 rootModifiers |= kKeyShiftMask;
379 if (modifiers & Details::kControlKeyMask)
380 rootModifiers |= kKeyControlMask;
381 if (modifiers & Details::kAlternateKeyMask)
382 rootModifiers |= kKeyMod1Mask;
383 if (modifiers & Details::kCommandKeyMask)
384 rootModifiers |= kKeyMod2Mask;
385
386 return rootModifiers;
387}
388
389//______________________________________________________________________________
390unsigned GetModifiersFromCocoaEvent(NSEvent *theEvent)
391{
392 assert(theEvent != nil && "GetModifiersFromCocoaEvent, parameter 'event' is nil");
393
394 unsigned rootModifiers = GetKeyboardModifiersFromCocoaEvent(theEvent);
395 const NSUInteger buttons = [NSEvent pressedMouseButtons];
396 if (buttons & 1)
397 rootModifiers |= kButton1Mask;
398 if (buttons & 2)
399 rootModifiers |= kButton3Mask;
400 if (buttons & (1 << 2))
401 rootModifiers |= kButton2Mask;
402
403 return rootModifiers;
404}
405
406#pragma mark - Misc. aux. functions.
407
408//______________________________________________________________________________
409bool IsParent(NSView<X11Window> *testParent, NSView<X11Window> *testChild)
410{
411 assert(testParent != nil && "IsParent, parameter 'testParent' is nil");
412 assert(testChild != nil && "IsParent, parameter 'testChild' is nil");
413
414 if (testChild.fParentView) {
415 NSView<X11Window> *parent = testChild.fParentView;
416 while (parent) {
417 if(parent == testParent)
418 return true;
419 parent = parent.fParentView;
420 }
421 }
422
423 return false;
424}
425
426//______________________________________________________________________________
427bool IsInBranch(NSView<X11Window> *parent, NSView<X11Window> *child, NSView<X11Window> *testView)
428{
429 assert(child != nil && "IsInBranch, parameter 'child' is nil");
430 assert(testView != nil && "IsInBranch, parameter 'testView' is nil");
431
432 if (testView == child || testView == parent)
433 return true;
434
435 for (NSView<X11Window> *current = child.fParentView; current != parent; current = current.fParentView) {
436 if (current == testView)
437 return true;
438 }
439
440 return false;
441}
442
443//Relation between two views.
450
451//______________________________________________________________________________
452Ancestry FindLowestCommonAncestor(NSView<X11Window> *view1, NSView<X11Window> *view2,
453 NSView<X11Window> **lca)
454{
455 //Search for the lowest common ancestor.
456 //View1 can not be parent of view2, view2 can not be parent of view1,
457 //I do not check this condition here.
458
459 assert(view1 != nil && "FindLowestCommonAncestor, parameter 'view1' is nil");
460 assert(view2 != nil && "findLowestCommonAncestor, parameter 'view2' is nil");
461 assert(lca != 0 && "FindLowestCommonAncestor, parameter 'lca' is null");
462
463 if (!view1.fParentView)
464 return kAAncestorIsRoot;
465
466 if (!view2.fParentView)
467 return kAAncestorIsRoot;
468
469 NSView<X11Window> * const ancestor = (NSView<X11Window> *)[view1 ancestorSharedWithView : view2];
470
471 if (ancestor) {
472 *lca = ancestor;
474 }
475
476 return kAAncestorIsRoot;
477}
478
479//______________________________________________________________________________
480Ancestry FindRelation(NSView<X11Window> *view1, NSView<X11Window> *view2, NSView<X11Window> **lca)
481{
482 assert(view1 != nil && "FindRelation, view1 parameter is nil");
483 assert(view2 != nil && "FindRelation, view2 parameter is nil");
484 assert(lca != 0 && "FindRelation, lca parameter is nil");
485
486 if (IsParent(view1, view2))
487 return kAView1IsParent;
488
489 if (IsParent(view2, view1))
490 return kAView2IsParent;
491
492 return FindLowestCommonAncestor(view1, view2, lca);
493}
494
495//______________________________________________________________________________
496NSView<X11Window> *FindViewToPropagateEvent(NSView<X11Window> *viewFrom, Mask_t checkMask)
497{
498 //This function does not check passive grabs.
499 assert(viewFrom != nil && "FindViewToPropagateEvent, parameter 'view' is nil");
500
501 if (viewFrom.fEventMask & checkMask)
502 return viewFrom;
503
504 for (viewFrom = viewFrom.fParentView; viewFrom; viewFrom = viewFrom.fParentView) {
505 if (viewFrom.fEventMask & checkMask)
506 return viewFrom;
507 }
508
509 return nil;
510}
511
512//______________________________________________________________________________
513NSView<X11Window> *FindViewToPropagateEvent(NSView<X11Window> *viewFrom, Mask_t checkMask,
514 NSView<X11Window> *grabView, Mask_t grabMask)
515{
516 //This function is called when we have a grab and owner_events == true,
517 //in this case the grab view itself (and its grab mask) is checked
518 //at the end (if no view was found before). Grab view can be in a hierarchy
519 //for a 'viewFrom' view and can have matching fEventMask.
520
521 assert(viewFrom != nil && "FindViewToPropagateEvent, parameter 'view' is nil");
522
523 if (viewFrom.fEventMask & checkMask)
524 return viewFrom;
525
526 for (viewFrom = viewFrom.fParentView; viewFrom; viewFrom = viewFrom.fParentView) {
527 if (viewFrom.fEventMask & checkMask)
528 return viewFrom;
529 }
530
531 if (grabView && (grabMask & checkMask))
532 return grabView;
533
534 return nil;
535}
536
537#pragma mark - Aux. 'low-level' functions to generate events and call HandleEvent for a root window.
538
539//______________________________________________________________________________
540void SendEnterEvent(EventQueue_t &queue, NSView<X11Window> *view, NSEvent *theEvent,
541 EXMagic detail)
542{
543 //1. Parameters are valid.
544 //2. view.fID is valid.
545 //3. A window for view.fID exists.
546 //This view must receive enter notify, I do not check it here.
547
548 assert(view != nil && "SendEnterEvent, parameter 'view' is nil");
549 assert(theEvent != nil && "SendEnterEvent, parameter 'event' is nil");
550 assert(view.fID != 0 && "SendEnterEvent, view.fID is 0");
551
552 TGWindow * const window = gClient->GetWindowById(view.fID);
553 if (!window) {
554#ifdef DEBUG_ROOT_COCOA
555 NSLog(@"SendEnterEvent, ROOT's widget %u was not found", view.fID);
556#endif
557 return;
558 }
559
560 Event_t enterEvent = NewX11EventFromCocoaEvent(view.fID, theEvent);
561 enterEvent.fType = kEnterNotify;
562 enterEvent.fCode = detail;
563 enterEvent.fState = GetModifiersFromCocoaEvent(theEvent);
564 //Coordinates. Event possible happend not in a view,
565 //but window should be the same. Also, coordinates are always
566 //inside a view.
567
568 ConvertEventLocationToROOTXY(theEvent, view, &enterEvent);
569
570 //Enqueue event again.
571 queue.push_back(enterEvent);
572}
573
574//______________________________________________________________________________
575void SendLeaveEvent(EventQueue_t &queue, NSView<X11Window> *view, NSEvent *theEvent,
576 EXMagic detail)
577{
578 //1. Parameters are valid.
579 //2. view.fID is valid.
580 //3. A window for view.fID exists.
581 //This window should receive leave event, I do not check it here.
582
583 assert(view != nil && "SendLeaveEvent, parameter 'view' is nil");
584 assert(theEvent != nil && "SendLeaveEvent, parameter 'event' is nil");
585 assert(view.fID != 0 && "SendLeaveEvent, view.fID is 0");
586
587 TGWindow * const window = gClient->GetWindowById(view.fID);
588 if (!window) {
589#ifdef DEBUG_ROOT_COCOA
590 NSLog(@"SendLeaveEvent, ROOT's widget %u was not found", view.fID);
591#endif
592 return;
593 }
594
595 Event_t leaveEvent = NewX11EventFromCocoaEvent(view.fID, theEvent);
596 leaveEvent.fType = kLeaveNotify;
597 leaveEvent.fCode = detail;
598 leaveEvent.fState = GetModifiersFromCocoaEvent(theEvent);
599 //Coordinates. Event possibly happend not in a view, also, coordinates are out of
600 //the view.
601 ConvertEventLocationToROOTXY(theEvent, view, &leaveEvent);
602 //Enqueue event for ROOT.
603 queue.push_back(leaveEvent);
604}
605
606//______________________________________________________________________________
607void SendPointerMotionEvent(EventQueue_t &queue, NSView<X11Window> *view, NSEvent *theEvent)
608{
609 //1. Parameters are valid.
610 //2. view.fID is valid.
611 //3. A window for view.fID exists.
612 //View receives pointer motion events, I do not check this condition here.
613
614 assert(view != nil && "SendPointerMotionEvent, parameter 'view' is nil");
615 assert(theEvent != nil && "SendPointerMotionEvent, parameter 'event' is nil");
616 assert(view.fID != 0 && "SendPointerMotionEvent, view.fID is 0");
617
618 TGWindow * const window = gClient->GetWindowById(view.fID);
619 if (!window) {
620#ifdef DEBUG_ROOT_COCOA
621 NSLog(@"SendPointerMotionEvent, ROOT's widget %u was not found", view.fID);
622#endif
623 return;
624 }
625
626 Event_t motionEvent = NewX11EventFromCocoaEvent(view.fID, theEvent);
627 motionEvent.fType = kMotionNotify;
628 motionEvent.fState = GetModifiersFromCocoaEvent(theEvent);
629
630 ConvertEventLocationToROOTXY(theEvent, view, &motionEvent);
631 //Enqueue event for ROOT.
632 queue.push_back(motionEvent);
633}
634
635//______________________________________________________________________________
636void SendButtonPressEvent(EventQueue_t &queue, NSView<X11Window> *view, NSEvent *theEvent,
637 EMouseButton btn)
638{
639 //1. Parameters are valid.
640 //2. view.fID is valid.
641 //3. A window for view.fID exists.
642 //View receives this event (either grab or select input)
643 // - I do not check this condition here.
644
645 assert(view != nil && "SendButtonPressEvent, parameter 'view' is nil");
646 assert(theEvent != nil && "SendButtonPressEvent, parameter 'event' is nil");
647 assert(view.fID != 0 && "SendButtonPressEvent, view.fID is 0");
648
649 TGWindow * const window = gClient->GetWindowById(view.fID);
650 if (!window) {
651#ifdef DEBUG_ROOT_COCOA
652 NSLog(@"SendButtonpressEvent, ROOT's widget %u was not found", view.fID);
653#endif
654 return;
655 }
656
657 Event_t pressEvent = NewX11EventFromCocoaEvent(view.fID, theEvent);
658 pressEvent.fType = kButtonPress;
659 pressEvent.fCode = btn;
660 pressEvent.fState = GetKeyboardModifiersFromCocoaEvent(theEvent);
661 //
662 ConvertEventLocationToROOTXY(theEvent, view, &pressEvent);
663 //
664 //
665 //ROOT uses "subwindow" parameter for button press event also, for example,
666 //scroll bar has several children windows - "buttons", they are not selecting
667 //button press events (and not grabbing pointer).
668 //This will work wrong, if we have overlapping views - we'll find a wrong subwindow.
669 //
670
671 NSPoint viewPoint = {};
672 viewPoint.x = pressEvent.fX;
673 viewPoint.y = pressEvent.fY;
674 for (NSView<X11Window> *child in [view subviews]) {
675 if (!child.fIsOverlapped && [child hitTest : viewPoint]) {//Hit test goes down along the tree.
676 pressEvent.fUser[0] = child.fID;
677 break;
678 }
679 }
680
681 //Enqueue event for ROOT.
682 queue.push_back(pressEvent);
683}
684
685//______________________________________________________________________________
686void SendButtonReleaseEvent(EventQueue_t &queue, NSView<X11Window> *view, NSEvent *theEvent,
687 EMouseButton btn)
688{
689 //1. Parameters are valid.
690 //2. view.fID is valid.
691 //3. A window for view.fID exists.
692 //View must button release events, I do not check this here.
693
694 assert(view != nil && "SendButtonReleaseEvent, parameter 'view' is nil");
695 assert(theEvent != nil && "SendButtonReleaseEvent, parameter 'event' is nil");
696 assert(view.fID != 0 && "SendButtonReleaseEvent, view.fID is 0");
697
698 TGWindow * const window = gClient->GetWindowById(view.fID);
699 if (!window) {
700#ifdef DEBUG_ROOT_COCOA
701 NSLog(@"SendButtonReleaseEvent, ROOT's widget %u was not found", view.fID);
702#endif
703 return;
704 }
705
706 Event_t releaseEvent = NewX11EventFromCocoaEvent(view.fID, theEvent);
707 releaseEvent.fType = kButtonRelease;
708 releaseEvent.fCode = btn;
709 releaseEvent.fState = GetKeyboardModifiersFromCocoaEvent(theEvent);
710 //
711 ConvertEventLocationToROOTXY(theEvent, view, &releaseEvent);
712 //Enqueue for ROOT.
713 queue.push_back(releaseEvent);
714}
715
716//______________________________________________________________________________
717void SendKeyPressEvent(EventQueue_t &queue, NSView<X11Window> *view, NSView<X11Window> *childView,
718 NSEvent *theEvent, NSPoint windowPoint)
719{
720 assert(view != nil && "SendKeyPressEvent, parameter 'view' is nil");
721 assert(theEvent != nil && "SendKeyPressEvent, parameter 'event' is nil");
722 assert(view.fID != 0 && "SendKeyPressEvent, view.fID is 0");
723
724 TGWindow * const window = gClient->GetWindowById(view.fID);
725 if (!window) {
726#ifdef DEBUG_ROOT_COCOA
727 NSLog(@"SendKeyPressEvent, ROOT's widget %u was not found", view.fID);
728#endif
729 return;
730 }
731
732 Event_t keyPressEvent = NewX11EventFromCocoaEvent(view.fID, theEvent);
733 keyPressEvent.fType = kGKeyPress;
734 keyPressEvent.fState = GetKeyboardModifiersFromCocoaEvent(theEvent);
735
736 NSString * const characters = [theEvent charactersIgnoringModifiers];
737 assert(characters != nil && "SendKeyPressEvent, [theEvent characters] returned nil");
738 assert([characters length] > 0 && "SendKeyPressEvent, characters is an empty string");
739
740 keyPressEvent.fCode = [characters characterAtIndex : 0];
741
742 //convertPointFromBase is deprecated.
743 //const NSPoint viewPoint = [view convertPointFromBase : windowPoint];
744 const NSPoint viewPoint = [view convertPoint : windowPoint fromView : nil];
745
746 //Coords.
747 keyPressEvent.fX = viewPoint.x;
748 keyPressEvent.fY = viewPoint.y;
749 const NSPoint screenPoint = TranslateToScreen(view, viewPoint);
750 keyPressEvent.fXRoot = screenPoint.x;
751 keyPressEvent.fYRoot = screenPoint.y;
752 //Subwindow.
753 if (childView)
754 keyPressEvent.fUser[0] = childView.fID;
755
756 //Enqueue for ROOT.
757 queue.push_back(keyPressEvent);
758}
759
760//______________________________________________________________________________
761void SendKeyReleaseEvent(EventQueue_t &queue, NSView<X11Window> *view, NSView<X11Window> *childView,
762 NSEvent *theEvent, NSPoint windowPoint)
763{
764 assert(view != nil && "SendKeyReleaseEvent, parameter 'view' is nil");
765 assert(theEvent != nil && "SendKeyReleaseEvent, parameter 'event' is nil");
766 assert(view.fID != 0 && "SendKeyReleaseEvent, view.fID is 0");
767
768 TGWindow * const window = gClient->GetWindowById(view.fID);
769 if (!window) {
770#ifdef DEBUG_ROOT_COCOA
771 NSLog(@"SendKeyPressEvent, ROOT's widget %u was not found", view.fID);
772#endif
773 return;
774 }
775
776 Event_t keyReleaseEvent = NewX11EventFromCocoaEvent(view.fID, theEvent);
777 keyReleaseEvent.fType = kKeyRelease;
778
779 keyReleaseEvent.fState = GetKeyboardModifiersFromCocoaEvent(theEvent);
780
781 NSString * const characters = [theEvent charactersIgnoringModifiers];
782 assert(characters != nil && "SendKeyReleaseEvent, [theEvent characters] returned nil");
783 assert([characters length] > 0 && "SendKeyReleaseEvent, characters is an empty string");
784 keyReleaseEvent.fCode = [characters characterAtIndex : 0];
785
786 //Coords.
787 const NSPoint viewPoint = [view convertPoint : windowPoint fromView : nil];
788 keyReleaseEvent.fX = viewPoint.x;
789 keyReleaseEvent.fY = viewPoint.y;
790 const NSPoint screenPoint = TranslateToScreen(view, viewPoint);
791
792 keyReleaseEvent.fXRoot = screenPoint.x;
793 keyReleaseEvent.fYRoot = screenPoint.y;
794
795 //Subwindow.
796 if (childView)
797 keyReleaseEvent.fUser[0] = childView.fID;
798
799 //Enqueue for ROOT.
800 queue.push_back(keyReleaseEvent);
801}
802
803
804//______________________________________________________________________________
805void SendFocusInEvent(EventQueue_t &queue, NSView<X11Window> *view, EXMagic mode)
806{
807 assert(view != nil && "SendFocusInEvent, parameter 'view' is nil");
808 //
809 TGWindow * const window = gClient->GetWindowById(view.fID);
810 if (!window) {
811#ifdef DEBUG_ROOT_COCOA
812 NSLog(@"SendFocusInEvent, ROOT's widget %u was not found", view.fID);
813#endif
814 return;
815 }
816
817 Event_t focusInEvent = {};
818 focusInEvent.fWindow = view.fID;
819 focusInEvent.fType = kFocusIn;
820 focusInEvent.fCode = mode;
821
822 queue.push_back(focusInEvent);
823}
824
825//______________________________________________________________________________
826void SendFocusOutEvent(EventQueue_t &queue, NSView<X11Window> *view, EXMagic mode)
827{
828 assert(view != nil && "SendFocusOutEvent, parameter 'view' is nil");
829 //
830 TGWindow * const window = gClient->GetWindowById(view.fID);
831 if (!window) {
832#ifdef DEBUG_ROOT_COCOA
833 NSLog(@"SendFocusOutEvent, ROOT's widget %u was not found", view.fID);
834#endif
835 return;
836 }
837
838 Event_t focusOutEvent = {};
839 focusOutEvent.fWindow = view.fID;
840 focusOutEvent.fType = kFocusOut;
841 focusOutEvent.fCode = mode;//code mode :)
842
843 queue.push_back(focusOutEvent);
844}
845
846#pragma mark - Aux. functions to send events to view's branch.
847
848//______________________________________________________________________________
849void SendEnterEventRange(EventQueue_t &queue, NSView<X11Window> *from, NSView<X11Window> *to,
850 NSEvent *theEvent, EXMagic mode)
851{
852 //[from, to) - legal range, 'to' must be ancestor for 'from'.
853 assert(from != nil && "SendEnterEventRange, 'from' parameter is nil");
854 assert(to != nil && "SendEnterEventRange, 'to' parameter is nil");
855 assert(theEvent != nil && "SendEnterEventRange, event parameter is nil");
856
857 while (from != to) {
858 if ([from acceptsCrossingEvents : kEnterWindowMask])
859 SendEnterEvent(queue, from, theEvent, mode);
860 from = from.fParentView;
861 }
862}
863
864//______________________________________________________________________________
865void SendEnterEventClosedRange(EventQueue_t &queue, NSView<X11Window> *from, NSView<X11Window> *to,
866 NSEvent *theEvent, EXMagic mode)
867{
868 //[from, to] - inclusive, legal range, 'to' must be ancestor for 'from'.
869 assert(from != nil && "SendEnterEventClosedRange, 'from' parameter is nil");
870 assert(to != nil && "SendEnterEventClosedRange, 'to' parameter is nil");
871 assert(theEvent != nil && "SendEnterEventClosedRange, event parameter is nil");
872
873 SendEnterEventRange(queue, from, to, theEvent, mode);
874 if ([to acceptsCrossingEvents : kEnterWindowMask])
875 SendEnterEvent(queue, to, theEvent, mode);
876}
877
878//______________________________________________________________________________
879void SendLeaveEventRange(EventQueue_t &queue, NSView<X11Window> *from, NSView<X11Window> *to,
880 NSEvent *theEvent, EXMagic mode)
881{
882 //[from, to) - legal range, 'to' must be ancestor for 'from'.
883 assert(from != nil && "SendLeaveEventRange, 'from' parameter is nil");
884 assert(to != nil && "SendLeaveEventRange, 'to' parameter is nil");
885 assert(theEvent != nil && "SendLeaveEventRange, event parameter is nil");
886
887 while (from != to) {
888 if ([from acceptsCrossingEvents : kLeaveWindowMask])
889 SendLeaveEvent(queue, from, theEvent, mode);
890 from = from.fParentView;
891 }
892}
893
894//______________________________________________________________________________
895void SendLeaveEventClosedRange(EventQueue_t &queue, NSView<X11Window> *from, NSView<X11Window> *to,
896 NSEvent *theEvent, EXMagic mode)
897{
898 //[from, to] - inclusive, legal range, 'to' must be ancestor for 'from'.
899 assert(from != nil && "SendLeaveEventClosedRange, 'from' parameter is nil");
900 assert(to != nil && "SendLeaveEventClosedRange, 'to' parameter is nil");
901 assert(theEvent != nil && "SendLeaveEventClosedRange, event parameter is nil");
902
903 SendLeaveEventRange(queue, from, to, theEvent, mode);
904 if ([to acceptsCrossingEvents : kLeaveWindowMask])
905 SendLeaveEvent(queue, to, theEvent, mode);
906}
907
908#pragma mark - Top-level crossing event generators.
909
910//When passing parent and child view, parent view always
911//precedes the child, even if function's name is GenerateCrossingEventChildToParent.
912
913//______________________________________________________________________________
914void GenerateCrossingEventChildToParent(EventQueue_t &queue, NSView<X11Window> *parent, NSView<X11Window> *child,
915 NSEvent *theEvent, EXMagic detail)
916{
917 //Pointer moves from window A to window B and A is an inferior of B.
918 //Generate LeaveNotify on A (with detail NotifyAncestor).
919 //Generate LeaveNotify for every window between A and B, exclusive (with detail NotifyVirtual)
920 //Generate EnterNotify for B with detail NotifyInferior.
921
922 //ROOT does not have NotifyAncestor/NotifyInferior.
923
924 assert(parent != nil && "GenerateCrossingEventChildToParent, parameter 'parent' is nil");
925 assert(child != nil && "GenerateCrossingEventChildToParent, parameter 'child' is nil");
926 assert(theEvent != nil && "GenerateCrossingEventChildToParent, parameter 'event' is nil");
927 assert(child.fParentView != nil &&
928 "GenerateCrossingEventChildToParent, parameter 'child' must have QuartzView* parent");
929
930 //acceptsCrossingEvents will check grab event mask also, if view is a grab and if
931 //owner_events == true.
932 if ([child acceptsCrossingEvents : kLeaveWindowMask])
933 SendLeaveEvent(queue, child, theEvent, detail);
934
935 //Leave event to a branch [child.fParentView, parent)
936 SendLeaveEventRange(queue, child.fParentView, parent, theEvent, detail);
937
938 //Enter event for the parent view.
939 if ([parent acceptsCrossingEvents : kEnterWindowMask])
940 SendEnterEvent(queue, parent, theEvent, detail);
941}
942
943//______________________________________________________________________________
944void GenerateCrossingEventParentToChild(EventQueue_t &queue, NSView<X11Window> *parent, NSView<X11Window> *child,
945 NSEvent *theEvent, EXMagic detail)
946{
947 //Pointer moves from window A to window B and B is an inferior of A.
948 //Generate LeaveNotify event for A, detail == NotifyInferior.
949 //Generate EnterNotify for each window between window A and window B, exclusive,
950 // detail == NotifyVirtual (no such entity in ROOT).
951 //Generate EnterNotify on window B, detail == NotifyAncestor.
952
953 //ROOT does not have NotifyInferior/NotifyAncestor.
954
955 assert(parent != nil && "GenerateCrossingEventParentToChild, parameter 'parent' is nil");
956 assert(child != nil && "GenerateCrossingEventParentToChild, parameter 'child' is nil");
957 assert(theEvent != nil && "GenerateCrossingEventParentToChild, parameter 'event' is nil");
958 assert(child.fParentView != nil &&
959 "GenerateCrossingEventParentToChild, parameter 'child' must have QuartzView* parent");
960
961 //If view is a grab and owner_events == true,
962 //acceptsCrossingEvents will check the grab event mask also.
963 if ([parent acceptsCrossingEvents : kLeaveWindowMask])
964 SendLeaveEvent(queue, parent, theEvent, detail);
965
966 //Enter event for [child.fParentView, parent) - order is reversed, but it does not really matter.
967 SendEnterEventRange(queue, child.fParentView, parent, theEvent, detail);
968
969 //Enter event for the child view.
970 if ([child acceptsCrossingEvents : kEnterWindowMask])
971 SendEnterEvent(queue, child, theEvent, detail);
972}
973
974//______________________________________________________________________________
975void GenerateCrossingEventFromChild1ToChild2(EventQueue_t &queue, NSView<X11Window> *child1, NSView<X11Window> *child2,
976 NSView<X11Window> *ancestor, NSEvent *theEvent, EXMagic detail)
977{
978 //Pointer moves from window A to window B and window C is their lowest common ancestor.
979 //Generate LeaveNotify for window A with detail == NotifyNonlinear.
980 //Generate LeaveNotify for each window between A and C, exclusive, with detail == NotifyNonlinearVirtual
981 //Generate EnterNotify (detail == NotifyNonlinearVirtual) for each window between C and B, exclusive
982 //Generate EnterNotify for window B, with detail == NotifyNonlinear.
983
984 assert(child1 != nil && "GenerateCrossingEventFromChild1ToChild2, parameter 'child1' is nil");
985 assert(child2 != nil && "GenerateCrossingEventFromChild1ToChild2, child2 parameter is nil");
986 assert(theEvent != nil && "GenerateCrossingEventFromChild1ToChild2, theEvent parameter is nil");
987
988 //ROOT does not have NotifyNonlinear/NotifyNonlinearVirtual.
989
990 //acceptsCrossingEvents also checks grab event mask, if this view has a grab
991 //and owner_events == true.
992 if ([child1 acceptsCrossingEvents : kLeaveWindowMask])
993 SendLeaveEvent(queue, child1, theEvent, detail);
994
995 if (!ancestor) {
996 if (child1.fParentView)//Leave [child1.fParentView contentView]
997 SendLeaveEventClosedRange(queue, child1.fParentView,
998 (NSView<X11Window> *)[[child1 window] contentView], theEvent, detail);
999 if (child2.fParentView)//Enter [child2.fParentView contentView] - order is reversed.
1000 SendEnterEventClosedRange(queue, child2.fParentView,
1001 (NSView<X11Window> *)[[child2 window] contentView], theEvent, detail);
1002 } else {
1003 if (child1.fParentView)//Leave [child1.fParentView ancestor)
1004 SendLeaveEventRange(queue, child1.fParentView, ancestor, theEvent, detail);
1005 if (child2.fParentView)//Enter [child2.fParentView, ancestor) - order reversed.
1006 SendEnterEventRange(queue, child2.fParentView, ancestor, theEvent, detail);
1007 }
1008
1009 if ([child2 acceptsCrossingEvents : kEnterWindowMask])
1010 SendEnterEvent(queue, child2, theEvent, detail);
1011}
1012
1013
1014//______________________________________________________________________________
1015void GenerateCrossingEvents(EventQueue_t &queue, NSView<X11Window> *fromView, NSView<X11Window> *toView,
1016 NSEvent *theEvent, EXMagic detail)
1017{
1018 //Pointer moved from 'fromView' to 'toView'.
1019 //Check their relationship and generate leave/enter notify events.
1020
1021 assert(theEvent != nil && "GenerateCrossingEvent, event parameter is nil");
1022
1023 if (fromView == toView) {
1024 //This can happen: tracking areas for stacked windows call
1025 //mouseExited even for overlapped views (so you have a bunch of mouseExited/mouseEntered
1026 //for one cursor move). In mouseEntered/mouseExited
1027 //I'm looking for the top level view under cursor and try to generate cross event
1028 //for this view only.
1029 return;
1030 }
1031
1032 if (!fromView) {
1033 //We enter window "from the screen" - do not leave any window.
1034 //Send EnterNotify event.
1035 //Send enter notify event to a branch [toView contentView], order of
1036 //views is reversed, but no GUI actually depends on this.
1037 if (toView)
1038 SendEnterEventClosedRange(queue, toView, (NSView<X11Window> *)[[toView window] contentView],
1039 theEvent, detail);
1040 } else if (!toView) {
1041 //We exit all views. Order is correct here.
1042 SendLeaveEventClosedRange(queue, fromView, (NSView<X11Window> *)[[fromView window] contentView],
1043 theEvent, detail);
1044 } else {
1045 NSView<X11Window> *ancestor = 0;
1046 const Ancestry rel = FindRelation(fromView, toView, &ancestor);
1047 if (rel == kAView1IsParent) {
1048 //Case 1.
1049 //From A to B.
1050 //_________________
1051 //| A |
1052 //| |---------| |
1053 //| | B | |
1054 //| | | |
1055 //| |---------| |
1056 //| |
1057 //|________________|
1058 GenerateCrossingEventParentToChild(queue, fromView, toView, theEvent, detail);
1059 } else if (rel == kAView2IsParent) {
1060 //Case 2.
1061 //From A to B.
1062 //_________________
1063 //| B |
1064 //| |---------| |
1065 //| | A | |
1066 //| | | |
1067 //| |---------| |
1068 //| |
1069 //|________________|
1070 GenerateCrossingEventChildToParent(queue, toView, fromView, theEvent, detail);
1071 } else {
1072 //Case 3.
1073 //|--------------------------------|
1074 //| C |------| |-------| |
1075 //| | A | | B | |
1076 //| |______| |_______| |
1077 //|________________________________|
1078 //Ancestor is either some view, or 'root' window.
1079 //The fourth case (different screens) is not implemented (and I do not know, if I want to implement it).
1080 GenerateCrossingEventFromChild1ToChild2(queue, fromView, toView, ancestor, theEvent, detail);
1081 }
1082 }
1083}
1084
1085//______________________________________________________________________________
1086void GenerateCrossingEventForGrabView(EventQueue_t &queue, NSView<X11Window> *fromView, NSView<X11Window> *toView,
1087 NSView<X11Window> *grabView, Mask_t grabEventMask, NSEvent *theEvent)
1088{
1089 //When owner events == false, only grab view receives enter/leave notify events.
1090
1091 //Send enter/leave event to a grab view.
1092 assert(theEvent != nil && "GenerateCrossingEventForGrabView, parameter 'event' is nil");
1093 assert(grabView != nil && "GenerateCrossingEventForGrabView, parameter 'grabView' is nil");
1094 assert((fromView != nil || toView != nil) &&
1095 "GenerateCrossingEventForGrabView, both 'toView' and 'fromView' parameters are nil");
1096
1097 if (fromView == toView)//No crossing at all?
1098 return;
1099
1100 const bool wantsEnter = grabEventMask & kEnterWindowMask;
1101 const bool wantsLeave = grabEventMask & kLeaveWindowMask;
1102
1103 if (fromView == grabView && wantsLeave)
1104 return SendLeaveEvent(queue, grabView, theEvent, kNotifyNormal);
1105
1106 if (toView == grabView && wantsEnter)
1107 return SendEnterEvent(queue, grabView, theEvent, kNotifyNormal);
1108
1109 if (!fromView) {
1110 //We enter window "from the screen" - do not leave any window.
1111 //Send EnterNotify event to the grab view, if it's "in the branch".
1112 if (wantsEnter && IsParent(grabView, toView))
1113 SendEnterEvent(queue, grabView, theEvent, kNotifyNormal);
1114 } else if (!toView) {
1115 //We exit all views..
1116 if (wantsLeave && IsParent(grabView, fromView))
1117 SendLeaveEvent(queue, grabView, theEvent, kNotifyNormal);
1118 } else {
1119 NSView<X11Window> *ancestor = 0;
1120 FindRelation(fromView, toView, &ancestor);
1121
1122 if (IsInBranch(nil, fromView, grabView)) {
1123 if (wantsLeave)
1124 SendLeaveEvent(queue, grabView, theEvent, kNotifyNormal);
1125 } else if (IsInBranch(nil, toView, grabView)) {
1126 if (wantsEnter)
1127 SendEnterEvent(queue, grabView, theEvent, kNotifyNormal);
1128 }
1129 }
1130}
1131
1132}//Detail
1133
1134//______________________________________________________________________________
1136 : fViewUnderPointer(nil),
1137 fPointerGrabType(kPGNoGrab),
1138 fGrabEventMask(0),
1139 fOwnerEvents(true),
1140 fButtonGrabView(nil),
1141 fKeyGrabView(nil),
1142 fFocusView(nil),
1143 fImplicitGrabButton(kAnyButton)
1144
1145{
1146}
1147
1148//______________________________________________________________________________
1149void EventTranslator::GenerateConfigureNotifyEvent(NSView<X11Window> *view, const NSRect &newFrame)
1150{
1151 assert(view != nil && "GenerateConfigureNotifyEvent, parameter 'view' is nil");
1152
1153 Event_t newEvent = {};
1154 newEvent.fWindow = view.fID;
1155 newEvent.fType = kConfigureNotify;
1156
1157 newEvent.fX = newFrame.origin.x;
1158 newEvent.fY = newFrame.origin.y;
1159
1160 newEvent.fWidth = newFrame.size.width;
1161 newEvent.fHeight = newFrame.size.height;
1162
1163 TGWindow * const window = gClient->GetWindowById(view.fID);
1164 if (window) window->HandleEvent(&newEvent);
1165}
1166
1167//______________________________________________________________________________
1168void EventTranslator::GenerateDestroyNotify(unsigned /*winID*/)
1169{
1170 //Noop.
1171}
1172
1173//______________________________________________________________________________
1174void EventTranslator::GenerateExposeEvent(NSView<X11Window> *view, const NSRect &exposedRect)
1175{
1176 assert(view != nil && "GenerateExposeEvent, parameter 'view' is nil");
1177
1178 Event_t exposeEvent = {};
1179 exposeEvent.fWindow = view.fID;
1180 exposeEvent.fType = kExpose;
1181 exposeEvent.fX = exposedRect.origin.x;
1182 exposeEvent.fY = exposedRect.origin.y;
1183 exposeEvent.fWidth = exposedRect.size.width;
1184 exposeEvent.fHeight = exposedRect.size.height;
1185
1186 TGWindow * const window = gClient->GetWindowById(view.fID);
1187 assert(window != 0 && "GenerateExposeEvent, window was not found");
1188 window->HandleEvent(&exposeEvent);
1189}
1190
1191//______________________________________________________________________________
1193{
1194 //View parameter can be nil.
1195 assert(theEvent != nil && "GenerateCrossingEvent, parameter 'event' is nil");
1196
1199}
1200
1201//______________________________________________________________________________
1203{
1204 assert(theEvent && "GenerateCrossingEventNoGrab, parameter 'theEvent' is nil");
1205
1206 NSView<X11Window> * const candidateView = FindViewForPointerEvent(theEvent);
1207 //We moved from fViewUnderPointer (leave event) to candidateView (enter event).
1209 fViewUnderPointer = candidateView;
1210}
1211
1212//______________________________________________________________________________
1214{
1215 assert(theEvent != nil && "GenerateCrossingEventActiveGrab, parameter 'theEvent' is nil");
1216
1217 NSView<X11Window> * const candidateView = FindViewForPointerEvent(theEvent);
1218
1219 if (fOwnerEvents) {
1220 //Either passive grab (which was activated) or active grab set by TGCocoa::GrabPointer with
1221 //owner_events == true. This works the same way as nograb case, except not only fEventMask
1222 //is checked, but for grab view (if it's boundary was crossed) either it's passive grab mask
1223 //or active is also checked.
1225 theEvent, kNotifyNormal);
1226 } else if (fButtonGrabView && (fViewUnderPointer || candidateView)) {
1227 //Either implicit grab or GrabPointer with owner_events == false,
1228 //only grab view can receive enter/leave notify events. Only
1229 //grab event mask is checked, not view's own event mask.
1231 fButtonGrabView, fGrabEventMask, theEvent);
1232 }
1233
1234 fViewUnderPointer = candidateView;
1235}
1236
1237//______________________________________________________________________________
1239{
1240 return fPointerGrabType != kPGNoGrab;
1241}
1242
1243//______________________________________________________________________________
1245{
1246 assert(theEvent != nil && "GeneratePointerMotionEvent, parameter 'theEvent' is nil");
1247
1248
1249
1251 return GeneratePointerMotionEventNoGrab(theEvent);
1252 else
1253 return GeneratePointerMotionEventActiveGrab(theEvent);
1254}
1255
1256//______________________________________________________________________________
1257void EventTranslator::GenerateButtonPressEvent(NSView<X11Window> *eventView, NSEvent *theEvent,
1258 EMouseButton btn)
1259{
1260 assert(eventView != nil && "GenerateButtonPressEvent, parameter 'eventView' is nil");
1261 assert(theEvent != nil && "GenerateButtonpressEvent, parameter 'theEvent' is nil");
1262
1264 return GenerateButtonPressEventNoGrab(eventView, theEvent, btn);
1265 else
1266 return GenerateButtonPressEventActiveGrab(eventView, theEvent, btn);
1267}
1268
1269//______________________________________________________________________________
1270void EventTranslator::GenerateButtonReleaseEvent(NSView<X11Window> *eventView, NSEvent *theEvent,
1271 EMouseButton btn)
1272{
1273 assert(eventView != nil && "GenerateButtonReleaseEvent, parameter 'eventView' is nil");
1274 assert(theEvent != nil && "GenerateButtonReleaseEvent, parameter 'theEvent' is nil");
1275
1277 return GenerateButtonReleaseEventNoGrab(eventView, theEvent, btn);
1278 else
1279 return GenerateButtonReleaseEventActiveGrab(eventView, theEvent, btn);
1280
1281
1282}
1283
1284//______________________________________________________________________________
1285void EventTranslator::GenerateKeyPressEvent(NSView<X11Window> *eventView, NSEvent *theEvent)
1286{
1287 assert(eventView != nil && "GenerateKeyPressEvent, parameter 'eventView' is nil");
1288 assert(theEvent != nil && "GenerateKeyPressEvent, parameter 'theEvent' is nil");
1289
1290 if (![[theEvent charactersIgnoringModifiers] length])
1291 return;
1292
1293 if (!fFocusView)
1294 return;
1295
1296 !fKeyGrabView ? GenerateKeyPressEventNoGrab(eventView, theEvent) :
1297 GenerateKeyEventActiveGrab(eventView, theEvent);
1298}
1299
1300//______________________________________________________________________________
1301void EventTranslator::GenerateKeyReleaseEvent(NSView<X11Window> *eventView, NSEvent *theEvent)
1302{
1303 assert(eventView != nil && "GenerateKeyReleaseEvent, parameter 'eventView' is nil");
1304 assert(theEvent != nil && "GenerateKeyReleaseEvent, parameter 'theEvent' is nil");
1305
1306 if (![[theEvent charactersIgnoringModifiers] length])
1307 return;
1308
1309 if (!fFocusView)
1310 return;
1311
1312 !fKeyGrabView ? GenerateKeyReleaseEventNoGrab(eventView, theEvent) :
1313 //GenerateKeyEventActiveGrab(eventView, theEvent);
1315
1316 //Oh, only God forgives.
1317 fKeyGrabView = nil;
1318}
1319
1320//______________________________________________________________________________
1321void EventTranslator::GenerateFocusChangeEvent(NSView<X11Window> *eventView)
1322{
1323 if (eventView == fFocusView)
1324 return;
1325
1326 if (fFocusView && (fFocusView.fEventMask & kFocusChangeMask))
1328
1329 if (eventView) {
1330 if (eventView.fEventMask & kFocusChangeMask)
1332
1333 fFocusView = eventView;
1334 } else
1335 fFocusView = nil;
1336}
1337
1338//______________________________________________________________________________
1339void EventTranslator::SetPointerGrab(NSView<X11Window> *grabView, unsigned eventMask, bool ownerEvents)
1340{
1341 assert(grabView != nil && "SetPointerGrab, parameter 'grabView' is nil");
1342
1343 if (fButtonGrabView) {
1344 //This can happen with X11, does this happen with ROOT's GUI?
1345 //Hm, should I send leave notify to the previous grab???
1346 [fButtonGrabView cancelGrab];
1347 }
1348
1349 //There is no kNoButton, unfortunately (but there is additional check on
1350 //grab type).
1352
1353 //
1354 fButtonGrabView = grabView;
1356 fGrabEventMask = eventMask;
1357 fOwnerEvents = ownerEvents;
1358
1359 //Generate sequence of crossing events - as if pointer
1360 //"jumps" to the grab view.
1361
1362 if (grabView != fViewUnderPointer) {
1363 const NSPoint location = [[grabView window] mouseLocationOutsideOfEventStream];
1364 const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc] initWithWindow : [grabView window]
1365 location : location]);
1366 if (!event.Get()) {
1367 //Hehe, if this happend, is it still possible to log????
1368 NSLog(@"EventTranslator::SetPointerGrab, crossing event initialization failed");
1369 return;
1370 }
1371
1372 Detail::GenerateCrossingEvents(fEventQueue, fViewUnderPointer, grabView, event.Get(), kNotifyGrab);//Uffffff, done!
1373 }
1374
1375 //Activate the current grab now.
1376 [fButtonGrabView activateGrab : eventMask ownerEvents : fOwnerEvents];
1377}
1378
1379//______________________________________________________________________________
1381{
1382 if (fButtonGrabView)
1383 //Cancel grab (active, passive, implicit).
1384 [fButtonGrabView cancelGrab];
1385
1386 //We generate sequence of leave/enter notify events (if any) as if we jumped from the grab view to the pointer view.
1387
1388 if (NSView<X11Window> * const candidateView = FindViewUnderPointer()) {
1389 const NSPoint location = [[candidateView window] mouseLocationOutsideOfEventStream];
1390 const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc] initWithWindow : [candidateView window]
1391 location : location ]);
1392
1393 if (!event.Get()) {
1394 //Hehe, if this happend, is it still possible to log????
1395 NSLog(@"EventTranslator::CancelPointerGrab, crossing event initialization failed");
1396 return;
1397 }
1398
1400 //
1401 fViewUnderPointer = candidateView;
1402 } else if (fButtonGrabView) {
1403 //convertScreenToBase is deprecated.
1404 //const NSPoint location = [[fButtonGrabView window] convertScreenToBase : [NSEvent mouseLocation]];
1405 const NSPoint location = ConvertPointFromScreenToBase([NSEvent mouseLocation], [fButtonGrabView window]);
1406
1407 const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc] initWithWindow : [fButtonGrabView window]
1408 location : location ]);
1409
1410 if (!event.Get()) {
1411 //Hehe, if this happend, is it still possible to log????
1412 NSLog(@"EventTranslator::CancelPointerGrab, crossing event initialization failed");
1413 fViewUnderPointer = nil;
1414 return;
1415 }
1416
1418 //
1419 fViewUnderPointer = nil;
1420 }
1421
1422
1424 fButtonGrabView = nil;
1426 fGrabEventMask = 0;
1427 fOwnerEvents = true;
1428}
1429
1430//______________________________________________________________________________
1431void EventTranslator::SetInputFocus(NSView<X11Window> *newFocusView)
1432{
1433 if (fFocusView && (fFocusView.fEventMask & kFocusChangeMask))
1435
1436 if (newFocusView) {
1437 if (newFocusView.fEventMask & kFocusChangeMask)
1439
1440 fFocusView = newFocusView;
1441 } else
1442 fFocusView = nil;
1443
1444}
1445
1446//______________________________________________________________________________
1448{
1449 if (fFocusView)
1450 return fFocusView.fID;
1451
1452 return 0;
1453}
1454
1455namespace {
1456
1457//______________________________________________________________________________
1458void ClearPointerIfViewIsRelated(NSView<X11Window> *&view, Window_t winID)
1459{
1460 NSView<X11Window> *v = view;
1461 if (v) {
1462 for (; v; v = v.fParentView) {
1463 if (v.fID == winID) {
1464 view = nil;
1465 break;
1466 }
1467 }
1468 }
1469}
1470
1471}//unnamed namespace.
1472
1473//______________________________________________________________________________
1475{
1476 //Window was unmapped, check, if it's the same window as the current grab,
1477 //or focus window, or key grabbing window and if so - do cleanup.
1478
1479 if (fButtonGrabView) {
1480 for (NSView<X11Window> *view = fButtonGrabView; view; view = view.fParentView) {
1481 if (view.fID == winID) {
1483 break;
1484 }
1485 }
1486 }
1487
1488 if (fViewUnderPointer) {
1489 for (NSView<X11Window> *view = fViewUnderPointer; view; view = view.fParentView) {
1490 if (view.fID == winID) {
1491 NSPoint location = {};
1492 location.x = fViewUnderPointer.fWidth / 2;
1493 location.y = fViewUnderPointer.fHeight / 2;
1494 location = [fViewUnderPointer convertPoint : location toView : nil];
1495
1496 const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc]
1497 initWithWindow : [fViewUnderPointer window]
1498 location : location]);
1499 if (!event.Get()) {
1500 //Hehe, if this happend, is it still possible to log????
1501 NSLog(@"EventTranslator::CheckUnmappedView, crossing event initialization failed");
1502 return;
1503 }
1504
1506 fViewUnderPointer = nil;
1507
1508 break;
1509 }
1510 }
1511 }
1512
1513 ClearPointerIfViewIsRelated(fFocusView, winID);
1514 ClearPointerIfViewIsRelated(fKeyGrabView, winID);
1515}
1516
1517//______________________________________________________________________________
1519{
1520 //Without grab, things are simple: find a view which accepts pointer motion event.
1521 assert(theEvent != nil && "GeneratePointerMotionEventNoGrab, parameter 'theEvent' is nil");
1522
1523 const Mask_t maskToTest = [NSEvent pressedMouseButtons] ?
1526
1527 //Event without any emulated grab, receiver view can be "wrong" (result of Cocoa's "dragging").
1528 if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1529 //Do propagation.
1530 candidateView = Detail::FindViewToPropagateEvent(candidateView, maskToTest);
1531 if (candidateView)//We have such a view, send event to a corresponding ROOT's window.
1532 Detail::SendPointerMotionEvent(fEventQueue, candidateView, theEvent);
1533 }
1534}
1535
1536//______________________________________________________________________________
1538{
1539 //More complex case. Grab can be result of button press and set by SetPointerGrab.
1540 //In case of button press (this is either passive->active or implicit grab),
1541 //Cocoa has it's own grab, so view (and window) can be not under cursor (but still
1542 //it receives events). So I can not simple use eventView here.
1543
1544 if (!fButtonGrabView)//Implicit grab when nobody has PressButtonMask
1545 return;
1546
1547 //assert(eventView != nil && "GeneratePointerMotionEventActiveGrab, view parameter is nil");
1548 assert(theEvent != nil && "GeneratePointerMotionEventActiveGrab, parameter 'theEvent' is nil");
1549
1550 const Mask_t maskToTest = [NSEvent pressedMouseButtons] ?
1553
1554 if (fOwnerEvents) {
1555 //Complex case, we have to correctly report event.
1556 if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1557 candidateView = Detail::FindViewToPropagateEvent(candidateView, maskToTest,
1559 if (candidateView)//We have such a view, send event to a corresponding ROOT's window.
1560 Detail::SendPointerMotionEvent(fEventQueue, candidateView, theEvent);
1561 } else {
1562 //No such window - dispatch to the grab view.
1563 //Else: either implicit grab, or user requested grab with owner_grab == False.
1564 if (fGrabEventMask & maskToTest)
1566 }
1567 } else {
1568 //Else: either implicit grab, or user requested grab with owner_grab == False.
1569 if (fGrabEventMask & maskToTest)
1571 }
1572}
1573
1574//______________________________________________________________________________
1575void EventTranslator::GenerateButtonPressEventNoGrab(NSView<X11Window> *view, NSEvent *theEvent,
1576 EMouseButton btn)
1577{
1578 //Generate button press event when no pointer grab is active:
1579 //either find a window with a passive grab, or create an implicit
1580 //grab (to emulate X11's behavior).
1581
1582 assert(view != nil && "GenerateButtonPressEventNoGrab, parameter 'view' is nil");
1583 assert(theEvent != nil && "GenerateButtonPressEventNoGrab, parameter 'theEvent' is nil");
1584
1585 FindButtonGrab(view, theEvent, btn);
1586
1587 fImplicitGrabButton = btn;//This info is useless for any grab type except the implicit one.
1588
1589 //Now we have to generate a sequence of enter/leave notify events,
1590 //like we "jump" from the previous view under the pointer to a grab view.
1591
1593
1594 //"Activate" a grab now, depending on type.
1595 if (fButtonGrabView) {
1597 [fButtonGrabView activatePassiveGrab];
1599 [fButtonGrabView activateImplicitGrab];
1600 }
1601
1602 //Send press event to a grab view (either passive grab or implicit,
1603 //but it has the required event bitmask).
1604 if (fButtonGrabView)
1606}
1607
1608//______________________________________________________________________________
1609void EventTranslator::GenerateButtonPressEventActiveGrab(NSView<X11Window> * /*view*/, NSEvent *theEvent,
1610 EMouseButton btn)
1611{
1612 //Generate button press event in the presence of activated pointer grab.
1613
1614 //assert(view != nil && "GenerateButtonPressEventActiveGrab, view parameter is nil");
1615 assert(theEvent != nil && "GenerateButtonPressEventActiveGrab, parameter 'theEvent' is nil");
1616
1617 //I did not find in X11 spec. the case when I have two passive grabs on window A and window B,
1618 //say left button on A and right button on B. What should happen if I press left button in A, move to
1619 //B and press the right button? In my test programm on X11 (Ubuntu) I can see, that now they BOTH
1620 //are active grabs. I'm not going to implement this mess, unless I have a correct formal description.
1621 if (!fButtonGrabView)
1622 return;
1623
1624 if (fOwnerEvents) {
1625 if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1626 //Do propagation.
1627 candidateView = Detail::FindViewToPropagateEvent(candidateView, kButtonPressMask,
1629 //We have such a view, send an event to a corresponding ROOT's window.
1630 if (candidateView)
1631 Detail::SendButtonPressEvent(fEventQueue, candidateView, theEvent, btn);
1632 } else {
1635 }
1636 } else {
1639 }
1640}
1641
1642//______________________________________________________________________________
1643void EventTranslator::GenerateButtonReleaseEventNoGrab(NSView<X11Window> *eventView, NSEvent *theEvent,
1644 EMouseButton btn)
1645{
1646 //Generate button release event when there is no active pointer grab. Can this even happen??
1647 assert(eventView != nil && "GenerateButtonReleaseEventNoGrab, parameter 'eventView' is nil");
1648 assert(theEvent != nil && "GenerateButtonReleaseEventNoGrabm parameter 'theEvent' is nil");
1649
1650 if (NSView<X11Window> *candidateView = Detail::FindViewToPropagateEvent(eventView, kButtonReleaseMask))
1651 Detail::SendButtonReleaseEvent(fEventQueue, candidateView, theEvent, btn);
1652}
1653
1654//______________________________________________________________________________
1655void EventTranslator::GenerateButtonReleaseEventActiveGrab(NSView<X11Window> *eventView, NSEvent *theEvent,
1656 EMouseButton btn)
1657{
1658 //Generate button release event in the presence of active grab (explicit pointer grab, activated passive grab or implicit grab).
1659
1660 assert(eventView != nil && "GenerateButtonReleaseEventActiveGrab, parameter 'eventView' is nil");
1661 assert(theEvent != nil && "GenerateButtonReleaseEventActiveGrab, parameter 'theEvent' is nil");
1662
1663 if (!fButtonGrabView) {
1664 //Still we have to cancel this grab (it's implicit grab on a root window).
1666 return;
1667 }
1668
1669 //What if view is deleted in the middle of this function?
1670 const Util::NSStrongReference<NSView<X11Window> *> eventViewGuard(eventView);
1671
1672 if (fButtonGrabView) {
1673 if (fOwnerEvents) {//X11: Either XGrabPointer with owner_events == True or passive grab (owner_events is always true)
1674 if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1675 candidateView = Detail::FindViewToPropagateEvent(candidateView, kButtonReleaseMask,
1677 //candidateView is either some view, or grab view, if its mask is ok.
1678 if (candidateView)
1679 Detail::SendButtonReleaseEvent(fEventQueue, candidateView, theEvent, btn);
1682 } else {//Either implicit grab or GrabPointer with owner_events == False.
1685 }
1686 } else {
1687 CancelPointerGrab();//root window had a grab, cancel it now.
1688 }
1689
1691 (btn == fButtonGrabView.fPassiveGrabButton || fButtonGrabView.fPassiveGrabButton == kAnyButton))
1693
1696}
1697
1698//______________________________________________________________________________
1699void EventTranslator::GenerateKeyPressEventNoGrab(NSView<X11Window> *eventView, NSEvent *theEvent)
1700{
1701 assert(eventView != nil && "GenerateKeyPressEventNoGrab, parameter 'eventView' is nil");
1702 assert(theEvent != nil && "GenerateKeyPressEventNoGrab, parameter 'theEvent' is nil");
1703 assert(fFocusView != nil && "GenerateKeyPressEventNoGrab, fFocusView is nil");
1704
1705 FindKeyGrabView(eventView, theEvent);
1706
1707 if (!fKeyGrabView) {
1708 NSView<X11Window> *candidateView = fFocusView;
1709 if (Detail::IsParent(fFocusView, eventView)) {
1710 NSView<X11Window> * const testView = Detail::FindViewToPropagateEvent(eventView, kKeyPressMask);
1711
1712 if (testView && (testView == fFocusView || Detail::IsParent(fFocusView, testView)))
1713 candidateView = testView;
1714 }
1715
1716 GenerateKeyEventForView(candidateView, theEvent);
1717 } else
1719}
1720
1721//______________________________________________________________________________
1722void EventTranslator::GenerateKeyEventActiveGrab(NSView<X11Window> *eventView, NSEvent *theEvent)
1723{
1724 assert(eventView != nil && "GenerateKeyEventActiveGrab, parameter 'eventView' is nil");
1725 assert(theEvent != nil && "GenerateKeyEventActiveGrab, parameter 'theEvent' is nil");
1726 assert(fFocusView != nil && "GenerateKeyEventActiveGrab, fFocusView is nil");
1727
1728 const Mask_t eventMask = theEvent.type == Details::kKeyDown ? kKeyPressMask : kKeyReleaseMask;
1729
1730 if (Detail::IsParent(fFocusView, eventView) || fFocusView == eventView) {
1731 NSView<X11Window> * const testView = Detail::FindViewToPropagateEvent(eventView, eventMask);
1732 if (testView && (testView == fFocusView || Detail::IsParent(fFocusView, testView)))
1733 GenerateKeyEventForView(testView, theEvent);
1734 } else
1735 GenerateKeyEventForView(fFocusView, theEvent);//Should I check the mask???
1736
1737 if (theEvent.type == Details::kKeyUp && fKeyGrabView) {
1738 //Cancel grab?
1739
1740 //NSString *characters = [theEvent charactersIgnoringModifiers];
1741 //assert(characters != nil && "GenerateKeyEventActiveGrab, [theEvent characters] returned nil");
1742 //assert([characters length] > 0 && "GenerateKeyEventActiveGrab, characters is an empty string");
1743
1744 //Here I have a real trouble: on a key press GUI removes ... passive key grabs ...
1745 //this "does not affect any active grab", but later on a key release ... I'm not
1746 //able to find a grab to remove and can not ... cancel the grab.
1747 //I do it the same way it's done on Windows after all.
1748 //So, the condition was commented :(
1749 //if ([fKeyGrabView findPassiveKeyGrab : [characters characterAtIndex : 0]])
1750 fKeyGrabView = nil;//Cancel grab.
1751 }
1752}
1753
1754//______________________________________________________________________________
1755void EventTranslator::GenerateKeyReleaseEventNoGrab(NSView<X11Window> *eventView, NSEvent *theEvent)
1756{
1757 assert(eventView != nil && "GenerateKeyReleaseEventNoGrab, parameter 'eventView' is nil");
1758 assert(theEvent != nil && "GenerateKeyReleaseEventNoGrab, parameter 'theEvent' is nil");
1759
1760 NSView<X11Window> *candidateView = fFocusView;
1761
1762 if (eventView == fFocusView || Detail::IsParent(fFocusView, eventView)) {
1763 NSView<X11Window> * const testView = Detail::FindViewToPropagateEvent(eventView, kKeyReleaseMask);
1764 if (testView && (testView == fFocusView || Detail::IsParent(fFocusView, testView)))
1765 candidateView = testView;
1766 }
1767
1768 GenerateKeyEventForView(candidateView, theEvent);
1769}
1770
1771//______________________________________________________________________________
1772void EventTranslator::GenerateKeyEventForView(NSView<X11Window> *view, NSEvent *theEvent)
1773{
1774 //Generate key press event for a view without grab.
1775 assert(view != nil && "GenerateKeyEventForView, parameter 'view' is nil");
1776 assert(theEvent != nil && "GenerateKeyEventForView, parameter 'theEvent' is nil");
1777 assert((theEvent.type == Details::kKeyDown || theEvent.type == Details::kKeyUp) &&
1778 "GenerateKeyEvenForView, event's type must be keydown or keyup");
1779
1780 const Mask_t eventType = theEvent.type == Details::kKeyDown ? kKeyPressMask : kKeyReleaseMask;
1781
1782 NSView<X11Window> *childView = nil;
1783
1784 NSPoint mousePosition = {};
1785 if (QuartzWindow * const topLevel = FindWindowUnderPointer())
1786 mousePosition = [topLevel mouseLocationOutsideOfEventStream];
1787
1788 if (eventType == kKeyPressMask)
1789 Detail::SendKeyPressEvent(fEventQueue, view, childView, theEvent, mousePosition);
1790 else
1791 Detail::SendKeyReleaseEvent(fEventQueue, view, childView, theEvent, mousePosition);
1792}
1793
1794//______________________________________________________________________________
1795void EventTranslator::FindButtonGrab(NSView<X11Window> *fromView, NSEvent *theEvent, EMouseButton btn)
1796{
1797 //Find a view to become a grab view - either passive or implicit.
1798
1799 assert(fromView != nil && "FindButtonGrabView, parameter 'fromView' is nil");
1800 assert(theEvent != nil && "FindButtonGrabView, parameter 'theEvent' is nil");
1801
1802 assert(fPointerGrabType == kPGNoGrab && "FindButtonGrabView, grab is already activated");
1803
1804 const unsigned keyModifiers = Detail::GetKeyboardModifiersFromCocoaEvent(theEvent);
1805
1806 NSView<X11Window> *grabView = 0;
1807 NSView<X11Window> *buttonPressView = 0;
1808
1809 for (NSView<X11Window> *view = fromView; view != nil; view = view.fParentView) {
1810 //Top-first view to receive button press event.
1811 if (!buttonPressView && (view.fEventMask & kButtonPressMask))
1812 buttonPressView = view;
1813
1814 //Bottom-first view with passive grab.
1815 if (view.fPassiveGrabButton == kAnyButton || view.fPassiveGrabButton == btn) {
1816 //Check modifiers.
1817 if (view.fPassiveGrabKeyModifiers == kAnyModifier || (view.fPassiveGrabKeyModifiers & keyModifiers))
1818 grabView = view;
1819 }
1820 }
1821
1822 if (grabView) {
1823 fButtonGrabView = grabView;
1825 fGrabEventMask = grabView.fPassiveGrabEventMask;
1826 fOwnerEvents = grabView.fPassiveGrabOwnerEvents;
1827 } else if (buttonPressView) {
1828 //This is an implicit grab.
1829 fButtonGrabView = buttonPressView;
1831 fGrabEventMask = buttonPressView.fEventMask;
1832 fOwnerEvents = false;
1833 } else {
1834 //Implicit grab with 'root' window?
1835 fButtonGrabView = nil;
1837 fGrabEventMask = 0;
1838 fOwnerEvents = false;
1839 }
1840}
1841
1842//______________________________________________________________________________
1843void EventTranslator::FindKeyGrabView(NSView<X11Window> *eventView, NSEvent *theEvent)
1844{
1845 assert(eventView != nil && "FindKeyGrabView, parameter 'eventView' is nil");
1846 assert(theEvent != nil && "FindKeyGrabView, parameter 'theEvent' is nil");
1847
1848 NSString * const characters = [theEvent charactersIgnoringModifiers];
1849 assert(characters != nil && "FindKeyGrabView, [theEvent characters] returned nil");
1850 assert([characters length] > 0 && "FindKeyGrabView, characters is an empty string");
1851
1852 const unichar keyCode = [characters characterAtIndex : 0];
1853 const NSUInteger modifiers = [theEvent modifierFlags] & Details::kDeviceIndependentModifierFlagsMask;
1854
1855 NSView<X11Window> *currentView = fFocusView;
1856 if (eventView != fFocusView && Detail::IsParent(fFocusView, eventView))
1857 currentView = eventView;
1858
1859 for (; currentView; currentView = currentView.fParentView) {
1860 if ([currentView findPassiveKeyGrab : keyCode modifiers : modifiers])
1861 fKeyGrabView = currentView;
1862 }
1863}
1864
1865}//X11
1866}//MacOSX
1867}//ROOT
SVector< double, 2 > v
Definition: Dict.h:5
@ kConfigureNotify
Definition: GuiTypes.h:61
@ kGKeyPress
Definition: GuiTypes.h:59
@ kExpose
Definition: GuiTypes.h:61
@ kButtonRelease
Definition: GuiTypes.h:59
@ kButtonPress
Definition: GuiTypes.h:59
@ kFocusOut
Definition: GuiTypes.h:60
@ kMotionNotify
Definition: GuiTypes.h:60
@ kFocusIn
Definition: GuiTypes.h:60
@ kEnterNotify
Definition: GuiTypes.h:60
@ kKeyRelease
Definition: GuiTypes.h:59
@ kLeaveNotify
Definition: GuiTypes.h:60
const Mask_t kButtonMotionMask
Definition: GuiTypes.h:163
const Mask_t kFocusChangeMask
Definition: GuiTypes.h:168
const Mask_t kKeyLockMask
Definition: GuiTypes.h:195
const Mask_t kButtonPressMask
Definition: GuiTypes.h:160
const Mask_t kKeyMod1Mask
Definition: GuiTypes.h:197
EXMagic
Definition: GuiTypes.h:218
@ kNotifyGrab
Definition: GuiTypes.h:218
@ kNotifyUngrab
Definition: GuiTypes.h:218
@ kNotifyNormal
Definition: GuiTypes.h:218
const Mask_t kKeyReleaseMask
Definition: GuiTypes.h:159
const Mask_t kAnyModifier
Definition: GuiTypes.h:209
const Mask_t kKeyPressMask
Definition: GuiTypes.h:158
ULong_t Time_t
Definition: GuiTypes.h:41
const Mask_t kButton1Mask
Definition: GuiTypes.h:202
const Mask_t kPointerMotionMask
Definition: GuiTypes.h:162
const Mask_t kKeyShiftMask
Definition: GuiTypes.h:194
const Mask_t kKeyControlMask
Definition: GuiTypes.h:196
const Mask_t kKeyMod2Mask
Definition: GuiTypes.h:198
const Mask_t kButton3Mask
Definition: GuiTypes.h:204
const Mask_t kLeaveWindowMask
Definition: GuiTypes.h:167
const Mask_t kButton2Mask
Definition: GuiTypes.h:203
UInt_t Mask_t
Definition: GuiTypes.h:40
const Mask_t kButtonReleaseMask
Definition: GuiTypes.h:161
const Mask_t kEnterWindowMask
Definition: GuiTypes.h:166
EMouseButton
Definition: GuiTypes.h:213
@ kAnyButton
Definition: GuiTypes.h:213
Handle_t Window_t
Definition: GuiTypes.h:28
EKeySym
Definition: KeySymbols.h:25
@ kKey_Right
Definition: KeySymbols.h:42
@ kKey_Down
Definition: KeySymbols.h:43
@ kKey_F30
Definition: KeySymbols.h:86
@ kKey_F15
Definition: KeySymbols.h:71
@ kKey_Print
Definition: KeySymbols.h:35
@ kKey_F1
Definition: KeySymbols.h:57
@ kKey_F24
Definition: KeySymbols.h:80
@ kKey_PageDown
Definition: KeySymbols.h:47
@ kKey_F28
Definition: KeySymbols.h:84
@ kKey_F4
Definition: KeySymbols.h:60
@ kKey_CapsLock
Definition: KeySymbols.h:53
@ kKey_F5
Definition: KeySymbols.h:61
@ kKey_F12
Definition: KeySymbols.h:68
@ kKey_F6
Definition: KeySymbols.h:62
@ kKey_F34
Definition: KeySymbols.h:90
@ kKey_F29
Definition: KeySymbols.h:85
@ kKey_F8
Definition: KeySymbols.h:64
@ kKey_Up
Definition: KeySymbols.h:41
@ kKey_Return
Definition: KeySymbols.h:30
@ kKey_Alt
Definition: KeySymbols.h:52
@ kKey_ScrollLock
Definition: KeySymbols.h:55
@ kKey_F23
Definition: KeySymbols.h:79
@ kKey_Delete
Definition: KeySymbols.h:33
@ kKey_F3
Definition: KeySymbols.h:59
@ kKey_Left
Definition: KeySymbols.h:40
@ kKey_Escape
Definition: KeySymbols.h:26
@ kKey_F16
Definition: KeySymbols.h:72
@ kKey_F26
Definition: KeySymbols.h:82
@ kKey_Shift
Definition: KeySymbols.h:49
@ kKey_Backspace
Definition: KeySymbols.h:29
@ kKey_F25
Definition: KeySymbols.h:81
@ kKey_Home
Definition: KeySymbols.h:38
@ kKey_F33
Definition: KeySymbols.h:89
@ kKey_F35
Definition: KeySymbols.h:91
@ kKey_Insert
Definition: KeySymbols.h:32
@ kKey_F20
Definition: KeySymbols.h:76
@ kKey_F22
Definition: KeySymbols.h:78
@ kKey_Enter
Definition: KeySymbols.h:31
@ kKey_Control
Definition: KeySymbols.h:50
@ kKey_Tab
Definition: KeySymbols.h:27
@ kKey_F14
Definition: KeySymbols.h:70
@ kKey_F32
Definition: KeySymbols.h:88
@ kKey_Backtab
Definition: KeySymbols.h:28
@ kKey_SysReq
Definition: KeySymbols.h:36
@ kKey_End
Definition: KeySymbols.h:39
@ kKey_F19
Definition: KeySymbols.h:75
@ kKey_F18
Definition: KeySymbols.h:74
@ kKey_NumLock
Definition: KeySymbols.h:54
@ kKey_F27
Definition: KeySymbols.h:83
@ kKey_F2
Definition: KeySymbols.h:58
@ kKey_F21
Definition: KeySymbols.h:77
@ kKey_F17
Definition: KeySymbols.h:73
@ kKey_F31
Definition: KeySymbols.h:87
@ kKey_F13
Definition: KeySymbols.h:69
@ kKey_PageUp
Definition: KeySymbols.h:45
@ kKey_Pause
Definition: KeySymbols.h:34
@ kKey_F11
Definition: KeySymbols.h:67
@ kKey_F7
Definition: KeySymbols.h:63
@ kKey_F10
Definition: KeySymbols.h:66
static Int_t init()
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t operator<(const TDatime &d1, const TDatime &d2)
Definition: TDatime.h:106
#define gClient
Definition: TGClient.h:166
XFontStruct * id
Definition: TGX11.cxx:108
T1 fFirst
Definition: X11Events.mm:86
T2 fSecond
Definition: X11Events.mm:87
DerivedType * Get() const
Definition: CocoaUtils.h:136
void CheckUnmappedView(Window_t winID)
Definition: X11Events.mm:1474
void FindKeyGrabView(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1843
NSView< X11Window > * fButtonGrabView
Definition: X11Events.h:116
void GenerateFocusChangeEvent(NSView< X11Window > *eventView)
Definition: X11Events.mm:1321
void FindButtonGrab(NSView< X11Window > *fromView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1795
void GenerateExposeEvent(NSView< X11Window > *view, const NSRect &exposedRect)
Definition: X11Events.mm:1174
NSView< X11Window > * fFocusView
Definition: X11Events.h:118
void GenerateKeyEventActiveGrab(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1722
void GenerateConfigureNotifyEvent(NSView< X11Window > *view, const NSRect &newFrame)
Definition: X11Events.mm:1149
void GenerateCrossingEvent(NSEvent *theEvent)
Definition: X11Events.mm:1192
void GenerateKeyEventForView(NSView< X11Window > *view, NSEvent *theEvent)
Definition: X11Events.mm:1772
void GenerateButtonPressEventActiveGrab(NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1609
void GeneratePointerMotionEventNoGrab(NSEvent *theEvent)
Definition: X11Events.mm:1518
void GenerateCrossingEventActiveGrab(NSEvent *theEvent)
Definition: X11Events.mm:1213
NSView< X11Window > * fKeyGrabView
Definition: X11Events.h:117
void GenerateButtonReleaseEventActiveGrab(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1655
void GenerateButtonReleaseEventNoGrab(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1643
void GenerateKeyReleaseEvent(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1301
void SetPointerGrab(NSView< X11Window > *grabView, unsigned eventMask, bool ownerEvents)
Definition: X11Events.mm:1339
void GenerateKeyPressEvent(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1285
void GenerateKeyPressEventNoGrab(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1699
void GenerateKeyReleaseEventNoGrab(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1755
void GenerateCrossingEventNoGrab(NSEvent *theEvent)
Definition: X11Events.mm:1202
void GeneratePointerMotionEventActiveGrab(NSEvent *theEvent)
Definition: X11Events.mm:1537
void GenerateButtonPressEvent(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1257
void GeneratePointerMotionEvent(NSEvent *theEvent)
Definition: X11Events.mm:1244
void GenerateDestroyNotify(unsigned winID)
NSView< X11Window > * fViewUnderPointer
Definition: X11Events.h:109
void SetInputFocus(NSView< X11Window > *focusView)
Definition: X11Events.mm:1431
void GenerateButtonPressEventNoGrab(NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1575
void GenerateButtonReleaseEvent(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1270
virtual Bool_t HandleEvent(Event_t *)
Definition: TGWindow.h:107
#define T2
Definition: md5.inl:146
#define T1
Definition: md5.inl:145
const NSUInteger kCommandKeyMask
const NSUInteger kDeviceIndependentModifierFlagsMask
const NSUInteger kAlternateKeyMask
const NSUInteger kControlKeyMask
const NSEventType kKeyUp
const NSUInteger kAlphaShiftKeyMask
const NSUInteger kShiftKeyMask
const NSEventType kKeyDown
Ancestry FindLowestCommonAncestor(NSView< X11Window > *view1, NSView< X11Window > *view2, NSView< X11Window > **lca)
Definition: X11Events.mm:452
void GenerateCrossingEventParentToChild(EventQueue_t &queue, NSView< X11Window > *parent, NSView< X11Window > *child, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:944
void ConvertEventLocationToROOTXY(NSEvent *cocoaEvent, NSView< X11Window > *eventView, Event_t *rootEvent)
Definition: X11Events.mm:341
void SendEnterEventClosedRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:865
bool IsParent(NSView< X11Window > *testParent, NSView< X11Window > *testChild)
Definition: X11Events.mm:409
void SendLeaveEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:575
void SendKeyReleaseEvent(EventQueue_t &queue, NSView< X11Window > *view, NSView< X11Window > *childView, NSEvent *theEvent, NSPoint windowPoint)
Definition: X11Events.mm:761
unsigned GetModifiersFromCocoaEvent(NSEvent *theEvent)
Definition: X11Events.mm:390
void GenerateCrossingEventForGrabView(EventQueue_t &queue, NSView< X11Window > *fromView, NSView< X11Window > *toView, NSView< X11Window > *grabView, Mask_t grabEventMask, NSEvent *theEvent)
Definition: X11Events.mm:1086
void SendFocusInEvent(EventQueue_t &queue, NSView< X11Window > *view, EXMagic mode)
Definition: X11Events.mm:805
Ancestry FindRelation(NSView< X11Window > *view1, NSView< X11Window > *view2, NSView< X11Window > **lca)
Definition: X11Events.mm:480
void GenerateCrossingEventChildToParent(EventQueue_t &queue, NSView< X11Window > *parent, NSView< X11Window > *child, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:914
Time_t TimeForCocoaEvent(NSEvent *theEvent)
Definition: X11Events.mm:319
void SendFocusOutEvent(EventQueue_t &queue, NSView< X11Window > *view, EXMagic mode)
Definition: X11Events.mm:826
NSView< X11Window > * FindViewToPropagateEvent(NSView< X11Window > *viewFrom, Mask_t checkMask)
Definition: X11Events.mm:496
void SendPointerMotionEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent)
Definition: X11Events.mm:607
void SendKeyPressEvent(EventQueue_t &queue, NSView< X11Window > *view, NSView< X11Window > *childView, NSEvent *theEvent, NSPoint windowPoint)
Definition: X11Events.mm:717
void SendEnterEventRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:849
void SendLeaveEventClosedRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:895
void SendButtonReleaseEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:686
void GenerateCrossingEventFromChild1ToChild2(EventQueue_t &queue, NSView< X11Window > *child1, NSView< X11Window > *child2, NSView< X11Window > *ancestor, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:975
void SendLeaveEventRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:879
void GenerateCrossingEvents(EventQueue_t &queue, NSView< X11Window > *fromView, NSView< X11Window > *toView, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:1015
void SendButtonPressEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:636
bool IsInBranch(NSView< X11Window > *parent, NSView< X11Window > *child, NSView< X11Window > *testView)
Definition: X11Events.mm:427
Event_t NewX11EventFromCocoaEvent(unsigned windowID, NSEvent *theEvent)
Definition: X11Events.mm:328
void SendEnterEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:540
unsigned GetKeyboardModifiersFromCocoaEvent(NSEvent *theEvent)
Definition: X11Events.mm:369
Int_t MapKeySymToKeyCode(Int_t keySym)
Definition: X11Events.mm:178
NSPoint ConvertPointFromScreenToBase(NSPoint screenPoint, NSWindow *window)
int GlobalYCocoaToROOT(CGFloat yCocoa)
std::deque< Event_t > EventQueue_t
Definition: X11Events.h:49
void MapUnicharToKeySym(unichar key, char *buf, Int_t len, UInt_t &rootKeySym)
Definition: X11Events.mm:98
NSPoint ConvertPointFromBaseToScreen(NSWindow *window, NSPoint windowPoint)
NSPoint TranslateToScreen(NSView< X11Window > *from, NSPoint point)
int GlobalXCocoaToROOT(CGFloat xCocoa)
UInt_t GetModifiers()
Definition: X11Events.mm:300
NSView< X11Window > * FindViewForPointerEvent(NSEvent *pointerEvent)
NSView< X11Window > * FindViewUnderPointer()
UInt_t GetKeyboardModifiers()
Definition: X11Events.mm:280
QuartzWindow * FindWindowUnderPointer()
NSUInteger GetCocoaKeyModifiersFromROOTKeyModifiers(UInt_t rootKeyModifiers)
Definition: X11Events.mm:261
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
EGEventType fType
Definition: GuiTypes.h:174
Int_t fY
Definition: GuiTypes.h:177
Int_t fXRoot
Definition: GuiTypes.h:178
UInt_t fWidth
Definition: GuiTypes.h:181
UInt_t fHeight
Definition: GuiTypes.h:181
Window_t fWindow
Definition: GuiTypes.h:175
UInt_t fState
Definition: GuiTypes.h:180
Int_t fYRoot
Definition: GuiTypes.h:178
Int_t fX
Definition: GuiTypes.h:177
Long_t fUser[5]
Definition: GuiTypes.h:186
Time_t fTime
Definition: GuiTypes.h:176
UInt_t fCode
Definition: GuiTypes.h:179