Logo ROOT   6.10/09
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 
76 namespace ROOT {
77 namespace MacOSX {
78 namespace X11 {
79 
80 namespace {
81 
82 //Convert unichar (from [NSEvent characters]) into
83 //ROOT's key symbol (from KeySymbols.h).
84 template<typename T1, typename T2>
85 struct KeySymPair {
88 
89  bool operator < (const KeySymPair &rhs)const
90  {
91  return fFirst < rhs.fFirst;
92  }
93 };
94 
95 }
96 
97 //______________________________________________________________________________
98 void 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 
314 namespace Detail {
315 
316 #pragma mark - Several aux. functions to extract parameters from Cocoa events.
317 
318 //______________________________________________________________________________
319 Time_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 //______________________________________________________________________________
328 Event_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 //______________________________________________________________________________
341 void 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 //______________________________________________________________________________
369 unsigned 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 //______________________________________________________________________________
390 unsigned 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 //______________________________________________________________________________
409 bool 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 //______________________________________________________________________________
427 bool 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.
444 enum Ancestry {
449 };
450 
451 //______________________________________________________________________________
452 Ancestry 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;
473  return kAHaveNonRootAncestor;
474  }
475 
476  return kAAncestorIsRoot;
477 }
478 
479 //______________________________________________________________________________
480 Ancestry 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 //______________________________________________________________________________
496 NSView<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 //______________________________________________________________________________
513 NSView<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 //______________________________________________________________________________
540 void 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 //______________________________________________________________________________
575 void 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 //______________________________________________________________________________
607 void 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 //______________________________________________________________________________
636 void 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 //______________________________________________________________________________
686 void 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 //______________________________________________________________________________
717 void 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 //______________________________________________________________________________
761 void 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 //______________________________________________________________________________
805 void 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 //______________________________________________________________________________
826 void 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 //______________________________________________________________________________
849 void 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 //______________________________________________________________________________
865 void 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 //______________________________________________________________________________
879 void 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 //______________________________________________________________________________
895 void 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 //______________________________________________________________________________
914 void 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 //______________________________________________________________________________
944 void 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 //______________________________________________________________________________
975 void 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 //______________________________________________________________________________
1015 void 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 //______________________________________________________________________________
1086 void 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 //______________________________________________________________________________
1135 EventTranslator::EventTranslator()
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 //______________________________________________________________________________
1149 void 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  //fXRoot?
1160  //fYRoot?
1161  newEvent.fWidth = newFrame.size.width;
1162  newEvent.fHeight = newFrame.size.height;
1163 
1164  TGWindow * const window = gClient->GetWindowById(view.fID);
1165  assert(window != 0 && "GenerateConfigureNotifyEvent, window was not found");
1166  window->HandleEvent(&newEvent);
1167 }
1168 
1169 //______________________________________________________________________________
1170 void EventTranslator::GenerateDestroyNotify(unsigned /*winID*/)
1171 {
1172  //Noop.
1173 }
1174 
1175 //______________________________________________________________________________
1176 void EventTranslator::GenerateExposeEvent(NSView<X11Window> *view, const NSRect &exposedRect)
1177 {
1178  assert(view != nil && "GenerateExposeEvent, parameter 'view' is nil");
1179 
1180  Event_t exposeEvent = {};
1181  exposeEvent.fWindow = view.fID;
1182  exposeEvent.fType = kExpose;
1183  exposeEvent.fX = exposedRect.origin.x;
1184  exposeEvent.fY = exposedRect.origin.y;
1185  exposeEvent.fWidth = exposedRect.size.width;
1186  exposeEvent.fHeight = exposedRect.size.height;
1187 
1188  TGWindow * const window = gClient->GetWindowById(view.fID);
1189  assert(window != 0 && "GenerateExposeEvent, window was not found");
1190  window->HandleEvent(&exposeEvent);
1191 }
1192 
1193 //______________________________________________________________________________
1195 {
1196  //View parameter can be nil.
1197  assert(theEvent != nil && "GenerateCrossingEvent, parameter 'event' is nil");
1198 
1201 }
1202 
1203 //______________________________________________________________________________
1205 {
1206  assert(theEvent && "GenerateCrossingEventNoGrab, parameter 'theEvent' is nil");
1207 
1208  NSView<X11Window> * const candidateView = FindViewForPointerEvent(theEvent);
1209  //We moved from fViewUnderPointer (leave event) to candidateView (enter event).
1211  fViewUnderPointer = candidateView;
1212 }
1213 
1214 //______________________________________________________________________________
1216 {
1217  assert(theEvent != nil && "GenerateCrossingEventActiveGrab, parameter 'theEvent' is nil");
1218 
1219  NSView<X11Window> * const candidateView = FindViewForPointerEvent(theEvent);
1220 
1221  if (fOwnerEvents) {
1222  //Either passive grab (which was activated) or active grab set by TGCocoa::GrabPointer with
1223  //owner_events == true. This works the same way as nograb case, except not only fEventMask
1224  //is checked, but for grab view (if it's boundary was crossed) either it's passive grab mask
1225  //or active is also checked.
1227  theEvent, kNotifyNormal);
1228  } else if (fButtonGrabView && (fViewUnderPointer || candidateView)) {
1229  //Either implicit grab or GrabPointer with owner_events == false,
1230  //only grab view can receive enter/leave notify events. Only
1231  //grab event mask is checked, not view's own event mask.
1233  fButtonGrabView, fGrabEventMask, theEvent);
1234  }
1235 
1236  fViewUnderPointer = candidateView;
1237 }
1238 
1239 //______________________________________________________________________________
1241 {
1242  return fPointerGrabType != kPGNoGrab;
1243 }
1244 
1245 //______________________________________________________________________________
1247 {
1248  assert(theEvent != nil && "GeneratePointerMotionEvent, parameter 'theEvent' is nil");
1249 
1250 
1251 
1252  if (fPointerGrabType == kPGNoGrab)
1253  return GeneratePointerMotionEventNoGrab(theEvent);
1254  else
1255  return GeneratePointerMotionEventActiveGrab(theEvent);
1256 }
1257 
1258 //______________________________________________________________________________
1259 void EventTranslator::GenerateButtonPressEvent(NSView<X11Window> *eventView, NSEvent *theEvent,
1260  EMouseButton btn)
1261 {
1262  assert(eventView != nil && "GenerateButtonPressEvent, parameter 'eventView' is nil");
1263  assert(theEvent != nil && "GenerateButtonpressEvent, parameter 'theEvent' is nil");
1264 
1265  if (fPointerGrabType == kPGNoGrab)
1266  return GenerateButtonPressEventNoGrab(eventView, theEvent, btn);
1267  else
1268  return GenerateButtonPressEventActiveGrab(eventView, theEvent, btn);
1269 }
1270 
1271 //______________________________________________________________________________
1272 void EventTranslator::GenerateButtonReleaseEvent(NSView<X11Window> *eventView, NSEvent *theEvent,
1273  EMouseButton btn)
1274 {
1275  assert(eventView != nil && "GenerateButtonReleaseEvent, parameter 'eventView' is nil");
1276  assert(theEvent != nil && "GenerateButtonReleaseEvent, parameter 'theEvent' is nil");
1277 
1278  if (fPointerGrabType == kPGNoGrab)
1279  return GenerateButtonReleaseEventNoGrab(eventView, theEvent, btn);
1280  else
1281  return GenerateButtonReleaseEventActiveGrab(eventView, theEvent, btn);
1282 
1283 
1284 }
1285 
1286 //______________________________________________________________________________
1287 void EventTranslator::GenerateKeyPressEvent(NSView<X11Window> *eventView, NSEvent *theEvent)
1288 {
1289  assert(eventView != nil && "GenerateKeyPressEvent, parameter 'eventView' is nil");
1290  assert(theEvent != nil && "GenerateKeyPressEvent, parameter 'theEvent' is nil");
1291 
1292  if (![[theEvent charactersIgnoringModifiers] length])
1293  return;
1294 
1295  if (!fFocusView)
1296  return;
1297 
1298  !fKeyGrabView ? GenerateKeyPressEventNoGrab(eventView, theEvent) :
1299  GenerateKeyEventActiveGrab(eventView, theEvent);
1300 }
1301 
1302 //______________________________________________________________________________
1303 void EventTranslator::GenerateKeyReleaseEvent(NSView<X11Window> *eventView, NSEvent *theEvent)
1304 {
1305  assert(eventView != nil && "GenerateKeyReleaseEvent, parameter 'eventView' is nil");
1306  assert(theEvent != nil && "GenerateKeyReleaseEvent, parameter 'theEvent' is nil");
1307 
1308  if (![[theEvent charactersIgnoringModifiers] length])
1309  return;
1310 
1311  if (!fFocusView)
1312  return;
1313 
1314  !fKeyGrabView ? GenerateKeyReleaseEventNoGrab(eventView, theEvent) :
1315  //GenerateKeyEventActiveGrab(eventView, theEvent);
1317 
1318  //Oh, only God forgives.
1319  fKeyGrabView = nil;
1320 }
1321 
1322 //______________________________________________________________________________
1323 void EventTranslator::GenerateFocusChangeEvent(NSView<X11Window> *eventView)
1324 {
1325  if (eventView == fFocusView)
1326  return;
1327 
1328  if (fFocusView && (fFocusView.fEventMask & kFocusChangeMask))
1330 
1331  if (eventView) {
1332  if (eventView.fEventMask & kFocusChangeMask)
1334 
1335  fFocusView = eventView;
1336  } else
1337  fFocusView = nil;
1338 }
1339 
1340 //______________________________________________________________________________
1341 void EventTranslator::SetPointerGrab(NSView<X11Window> *grabView, unsigned eventMask, bool ownerEvents)
1342 {
1343  assert(grabView != nil && "SetPointerGrab, parameter 'grabView' is nil");
1344 
1345  if (fButtonGrabView) {
1346  //This can happen with X11, does this happen with ROOT's GUI?
1347  //Hm, should I send leave notify to the previous grab???
1348  [fButtonGrabView cancelGrab];
1349  }
1350 
1351  //There is no kNoButton, unfortunately (but there is additional check on
1352  //grab type).
1354 
1355  //
1356  fButtonGrabView = grabView;
1358  fGrabEventMask = eventMask;
1359  fOwnerEvents = ownerEvents;
1360 
1361  //Generate sequence of crossing events - as if pointer
1362  //"jumps" to the grab view.
1363 
1364  if (grabView != fViewUnderPointer) {
1365  const NSPoint location = [[grabView window] mouseLocationOutsideOfEventStream];
1366  const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc] initWithWindow : [grabView window]
1367  location : location]);
1368  if (!event.Get()) {
1369  //Hehe, if this happend, is it still possible to log????
1370  NSLog(@"EventTranslator::SetPointerGrab, crossing event initialization failed");
1371  return;
1372  }
1373 
1374  Detail::GenerateCrossingEvents(fEventQueue, fViewUnderPointer, grabView, event.Get(), kNotifyGrab);//Uffffff, done!
1375  }
1376 
1377  //Activate the current grab now.
1378  [fButtonGrabView activateGrab : eventMask ownerEvents : fOwnerEvents];
1379 }
1380 
1381 //______________________________________________________________________________
1383 {
1384  if (fButtonGrabView)
1385  //Cancel grab (active, passive, implicit).
1386  [fButtonGrabView cancelGrab];
1387 
1388  //We generate sequence of leave/enter notify events (if any) as if we jumped from the grab view to the pointer view.
1389 
1390  if (NSView<X11Window> * const candidateView = FindViewUnderPointer()) {
1391  const NSPoint location = [[candidateView window] mouseLocationOutsideOfEventStream];
1392  const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc] initWithWindow : [candidateView window]
1393  location : location ]);
1394 
1395  if (!event.Get()) {
1396  //Hehe, if this happend, is it still possible to log????
1397  NSLog(@"EventTranslator::CancelPointerGrab, crossing event initialization failed");
1398  return;
1399  }
1400 
1402  //
1403  fViewUnderPointer = candidateView;
1404  } else if (fButtonGrabView) {
1405  //convertScreenToBase is deprecated.
1406  //const NSPoint location = [[fButtonGrabView window] convertScreenToBase : [NSEvent mouseLocation]];
1407  const NSPoint location = ConvertPointFromScreenToBase([NSEvent mouseLocation], [fButtonGrabView window]);
1408 
1409  const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc] initWithWindow : [fButtonGrabView window]
1410  location : location ]);
1411 
1412  if (!event.Get()) {
1413  //Hehe, if this happend, is it still possible to log????
1414  NSLog(@"EventTranslator::CancelPointerGrab, crossing event initialization failed");
1415  fViewUnderPointer = nil;
1416  return;
1417  }
1418 
1420  //
1421  fViewUnderPointer = nil;
1422  }
1423 
1424 
1426  fButtonGrabView = nil;
1428  fGrabEventMask = 0;
1429  fOwnerEvents = true;
1430 }
1431 
1432 //______________________________________________________________________________
1433 void EventTranslator::SetInputFocus(NSView<X11Window> *newFocusView)
1434 {
1435  if (fFocusView && (fFocusView.fEventMask & kFocusChangeMask))
1437 
1438  if (newFocusView) {
1439  if (newFocusView.fEventMask & kFocusChangeMask)
1441 
1442  fFocusView = newFocusView;
1443  } else
1444  fFocusView = nil;
1445 
1446 }
1447 
1448 //______________________________________________________________________________
1450 {
1451  if (fFocusView)
1452  return fFocusView.fID;
1453 
1454  return 0;
1455 }
1456 
1457 namespace {
1458 
1459 //______________________________________________________________________________
1460 void ClearPointerIfViewIsRelated(NSView<X11Window> *&view, Window_t winID)
1461 {
1462  NSView<X11Window> *v = view;
1463  if (v) {
1464  for (; v; v = v.fParentView) {
1465  if (v.fID == winID) {
1466  view = nil;
1467  break;
1468  }
1469  }
1470  }
1471 }
1472 
1473 }//unnamed namespace.
1474 
1475 //______________________________________________________________________________
1477 {
1478  //Window was unmapped, check, if it's the same window as the current grab,
1479  //or focus window, or key grabbing window and if so - do cleanup.
1480 
1481  if (fButtonGrabView) {
1482  for (NSView<X11Window> *view = fButtonGrabView; view; view = view.fParentView) {
1483  if (view.fID == winID) {
1485  break;
1486  }
1487  }
1488  }
1489 
1490  if (fViewUnderPointer) {
1491  for (NSView<X11Window> *view = fViewUnderPointer; view; view = view.fParentView) {
1492  if (view.fID == winID) {
1493  NSPoint location = {};
1494  location.x = fViewUnderPointer.fWidth / 2;
1495  location.y = fViewUnderPointer.fHeight / 2;
1496  location = [fViewUnderPointer convertPoint : location toView : nil];
1497 
1498  const Util::NSScopeGuard<FakeCrossingEvent> event([[FakeCrossingEvent alloc]
1499  initWithWindow : [fViewUnderPointer window]
1500  location : location]);
1501  if (!event.Get()) {
1502  //Hehe, if this happend, is it still possible to log????
1503  NSLog(@"EventTranslator::CheckUnmappedView, crossing event initialization failed");
1504  return;
1505  }
1506 
1508  fViewUnderPointer = nil;
1509 
1510  break;
1511  }
1512  }
1513  }
1514 
1515  ClearPointerIfViewIsRelated(fFocusView, winID);
1516  ClearPointerIfViewIsRelated(fKeyGrabView, winID);
1517 }
1518 
1519 //______________________________________________________________________________
1521 {
1522  //Without grab, things are simple: find a view which accepts pointer motion event.
1523  assert(theEvent != nil && "GeneratePointerMotionEventNoGrab, parameter 'theEvent' is nil");
1524 
1525  const Mask_t maskToTest = [NSEvent pressedMouseButtons] ?
1528 
1529  //Event without any emulated grab, receiver view can be "wrong" (result of Cocoa's "dragging").
1530  if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1531  //Do propagation.
1532  candidateView = Detail::FindViewToPropagateEvent(candidateView, maskToTest);
1533  if (candidateView)//We have such a view, send event to a corresponding ROOT's window.
1534  Detail::SendPointerMotionEvent(fEventQueue, candidateView, theEvent);
1535  }
1536 }
1537 
1538 //______________________________________________________________________________
1540 {
1541  //More complex case. Grab can be result of button press and set by SetPointerGrab.
1542  //In case of button press (this is either passive->active or implicit grab),
1543  //Cocoa has it's own grab, so view (and window) can be not under cursor (but still
1544  //it receives events). So I can not simple use eventView here.
1545 
1546  if (!fButtonGrabView)//Implicit grab when nobody has PressButtonMask
1547  return;
1548 
1549  //assert(eventView != nil && "GeneratePointerMotionEventActiveGrab, view parameter is nil");
1550  assert(theEvent != nil && "GeneratePointerMotionEventActiveGrab, parameter 'theEvent' is nil");
1551 
1552  const Mask_t maskToTest = [NSEvent pressedMouseButtons] ?
1555 
1556  if (fOwnerEvents) {
1557  //Complex case, we have to correctly report event.
1558  if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1559  candidateView = Detail::FindViewToPropagateEvent(candidateView, maskToTest,
1561  if (candidateView)//We have such a view, send event to a corresponding ROOT's window.
1562  Detail::SendPointerMotionEvent(fEventQueue, candidateView, theEvent);
1563  } else {
1564  //No such window - dispatch to the grab view.
1565  //Else: either implicit grab, or user requested grab with owner_grab == False.
1566  if (fGrabEventMask & maskToTest)
1568  }
1569  } else {
1570  //Else: either implicit grab, or user requested grab with owner_grab == False.
1571  if (fGrabEventMask & maskToTest)
1573  }
1574 }
1575 
1576 //______________________________________________________________________________
1577 void EventTranslator::GenerateButtonPressEventNoGrab(NSView<X11Window> *view, NSEvent *theEvent,
1578  EMouseButton btn)
1579 {
1580  //Generate button press event when no pointer grab is active:
1581  //either find a window with a passive grab, or create an implicit
1582  //grab (to emulate X11's behavior).
1583 
1584  assert(view != nil && "GenerateButtonPressEventNoGrab, parameter 'view' is nil");
1585  assert(theEvent != nil && "GenerateButtonPressEventNoGrab, parameter 'theEvent' is nil");
1586 
1587  FindButtonGrab(view, theEvent, btn);
1588 
1589  fImplicitGrabButton = btn;//This info is useless for any grab type except the implicit one.
1590 
1591  //Now we have to generate a sequence of enter/leave notify events,
1592  //like we "jump" from the previous view under the pointer to a grab view.
1593 
1595 
1596  //"Activate" a grab now, depending on type.
1597  if (fButtonGrabView) {
1599  [fButtonGrabView activatePassiveGrab];
1600  else if (fPointerGrabType == kPGImplicitGrab)
1601  [fButtonGrabView activateImplicitGrab];
1602  }
1603 
1604  //Send press event to a grab view (either passive grab or implicit,
1605  //but it has the required event bitmask).
1606  if (fButtonGrabView)
1608 }
1609 
1610 //______________________________________________________________________________
1611 void EventTranslator::GenerateButtonPressEventActiveGrab(NSView<X11Window> * /*view*/, NSEvent *theEvent,
1612  EMouseButton btn)
1613 {
1614  //Generate button press event in the presence of activated pointer grab.
1615 
1616  //assert(view != nil && "GenerateButtonPressEventActiveGrab, view parameter is nil");
1617  assert(theEvent != nil && "GenerateButtonPressEventActiveGrab, parameter 'theEvent' is nil");
1618 
1619  //I did not find in X11 spec. the case when I have two passive grabs on window A and window B,
1620  //say left button on A and right button on B. What should happen if I press left button in A, move to
1621  //B and press the right button? In my test programm on X11 (Ubuntu) I can see, that now they BOTH
1622  //are active grabs. I'm not going to implement this mess, unless I have a correct formal description.
1623  if (!fButtonGrabView)
1624  return;
1625 
1626  if (fOwnerEvents) {
1627  if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1628  //Do propagation.
1629  candidateView = Detail::FindViewToPropagateEvent(candidateView, kButtonPressMask,
1631  //We have such a view, send an event to a corresponding ROOT's window.
1632  if (candidateView)
1633  Detail::SendButtonPressEvent(fEventQueue, candidateView, theEvent, btn);
1634  } else {
1637  }
1638  } else {
1641  }
1642 }
1643 
1644 //______________________________________________________________________________
1645 void EventTranslator::GenerateButtonReleaseEventNoGrab(NSView<X11Window> *eventView, NSEvent *theEvent,
1646  EMouseButton btn)
1647 {
1648  //Generate button release event when there is no active pointer grab. Can this even happen??
1649  assert(eventView != nil && "GenerateButtonReleaseEventNoGrab, parameter 'eventView' is nil");
1650  assert(theEvent != nil && "GenerateButtonReleaseEventNoGrabm parameter 'theEvent' is nil");
1651 
1652  if (NSView<X11Window> *candidateView = Detail::FindViewToPropagateEvent(eventView, kButtonReleaseMask))
1653  Detail::SendButtonReleaseEvent(fEventQueue, candidateView, theEvent, btn);
1654 }
1655 
1656 //______________________________________________________________________________
1657 void EventTranslator::GenerateButtonReleaseEventActiveGrab(NSView<X11Window> *eventView, NSEvent *theEvent,
1658  EMouseButton btn)
1659 {
1660  //Generate button release event in the presence of active grab (explicit pointer grab, activated passive grab or implicit grab).
1661 
1662  assert(eventView != nil && "GenerateButtonReleaseEventActiveGrab, parameter 'eventView' is nil");
1663  assert(theEvent != nil && "GenerateButtonReleaseEventActiveGrab, parameter 'theEvent' is nil");
1664 
1665  if (!fButtonGrabView) {
1666  //Still we have to cancel this grab (it's implicit grab on a root window).
1668  return;
1669  }
1670 
1671  //What if view is deleted in the middle of this function?
1672  const Util::NSStrongReference<NSView<X11Window> *> eventViewGuard(eventView);
1673 
1674  if (fButtonGrabView) {
1675  if (fOwnerEvents) {//X11: Either XGrabPointer with owner_events == True or passive grab (owner_events is always true)
1676  if (NSView<X11Window> *candidateView = FindViewForPointerEvent(theEvent)) {
1677  candidateView = Detail::FindViewToPropagateEvent(candidateView, kButtonReleaseMask,
1679  //candidateView is either some view, or grab view, if its mask is ok.
1680  if (candidateView)
1681  Detail::SendButtonReleaseEvent(fEventQueue, candidateView, theEvent, btn);
1682  } else if (fGrabEventMask & kButtonReleaseMask)
1684  } else {//Either implicit grab or GrabPointer with owner_events == False.
1687  }
1688  } else {
1689  CancelPointerGrab();//root window had a grab, cancel it now.
1690  }
1691 
1693  (btn == fButtonGrabView.fPassiveGrabButton || fButtonGrabView.fPassiveGrabButton == kAnyButton))
1695 
1698 }
1699 
1700 //______________________________________________________________________________
1701 void EventTranslator::GenerateKeyPressEventNoGrab(NSView<X11Window> *eventView, NSEvent *theEvent)
1702 {
1703  assert(eventView != nil && "GenerateKeyPressEventNoGrab, parameter 'eventView' is nil");
1704  assert(theEvent != nil && "GenerateKeyPressEventNoGrab, parameter 'theEvent' is nil");
1705  assert(fFocusView != nil && "GenerateKeyPressEventNoGrab, fFocusView is nil");
1706 
1707  FindKeyGrabView(eventView, theEvent);
1708 
1709  if (!fKeyGrabView) {
1710  NSView<X11Window> *candidateView = fFocusView;
1711  if (Detail::IsParent(fFocusView, eventView)) {
1712  NSView<X11Window> * const testView = Detail::FindViewToPropagateEvent(eventView, kKeyPressMask);
1713 
1714  if (testView && (testView == fFocusView || Detail::IsParent(fFocusView, testView)))
1715  candidateView = testView;
1716  }
1717 
1718  GenerateKeyEventForView(candidateView, theEvent);
1719  } else
1721 }
1722 
1723 //______________________________________________________________________________
1724 void EventTranslator::GenerateKeyEventActiveGrab(NSView<X11Window> *eventView, NSEvent *theEvent)
1725 {
1726  assert(eventView != nil && "GenerateKeyEventActiveGrab, parameter 'eventView' is nil");
1727  assert(theEvent != nil && "GenerateKeyEventActiveGrab, parameter 'theEvent' is nil");
1728  assert(fFocusView != nil && "GenerateKeyEventActiveGrab, fFocusView is nil");
1729 
1730  const Mask_t eventMask = theEvent.type == Details::kKeyDown ? kKeyPressMask : kKeyReleaseMask;
1731 
1732  if (Detail::IsParent(fFocusView, eventView) || fFocusView == eventView) {
1733  NSView<X11Window> * const testView = Detail::FindViewToPropagateEvent(eventView, eventMask);
1734  if (testView && (testView == fFocusView || Detail::IsParent(fFocusView, testView)))
1735  GenerateKeyEventForView(testView, theEvent);
1736  } else
1737  GenerateKeyEventForView(fFocusView, theEvent);//Should I check the mask???
1738 
1739  if (theEvent.type == Details::kKeyUp && fKeyGrabView) {
1740  //Cancel grab?
1741 
1742  //NSString *characters = [theEvent charactersIgnoringModifiers];
1743  //assert(characters != nil && "GenerateKeyEventActiveGrab, [theEvent characters] returned nil");
1744  //assert([characters length] > 0 && "GenerateKeyEventActiveGrab, characters is an empty string");
1745 
1746  //Here I have a real trouble: on a key press GUI removes ... passive key grabs ...
1747  //this "does not affect any active grab", but later on a key release ... I'm not
1748  //able to find a grab to remove and can not ... cancel the grab.
1749  //I do it the same way it's done on Windows after all.
1750  //So, the condition was commented :(
1751  //if ([fKeyGrabView findPassiveKeyGrab : [characters characterAtIndex : 0]])
1752  fKeyGrabView = nil;//Cancel grab.
1753  }
1754 }
1755 
1756 //______________________________________________________________________________
1757 void EventTranslator::GenerateKeyReleaseEventNoGrab(NSView<X11Window> *eventView, NSEvent *theEvent)
1758 {
1759  assert(eventView != nil && "GenerateKeyReleaseEventNoGrab, parameter 'eventView' is nil");
1760  assert(theEvent != nil && "GenerateKeyReleaseEventNoGrab, parameter 'theEvent' is nil");
1761 
1762  NSView<X11Window> *candidateView = fFocusView;
1763 
1764  if (eventView == fFocusView || Detail::IsParent(fFocusView, eventView)) {
1765  NSView<X11Window> * const testView = Detail::FindViewToPropagateEvent(eventView, kKeyReleaseMask);
1766  if (testView && (testView == fFocusView || Detail::IsParent(fFocusView, testView)))
1767  candidateView = testView;
1768  }
1769 
1770  GenerateKeyEventForView(candidateView, theEvent);
1771 }
1772 
1773 //______________________________________________________________________________
1774 void EventTranslator::GenerateKeyEventForView(NSView<X11Window> *view, NSEvent *theEvent)
1775 {
1776  //Generate key press event for a view without grab.
1777  assert(view != nil && "GenerateKeyEventForView, parameter 'view' is nil");
1778  assert(theEvent != nil && "GenerateKeyEventForView, parameter 'theEvent' is nil");
1779  assert((theEvent.type == Details::kKeyDown || theEvent.type == Details::kKeyUp) &&
1780  "GenerateKeyEvenForView, event's type must be keydown or keyup");
1781 
1782  const Mask_t eventType = theEvent.type == Details::kKeyDown ? kKeyPressMask : kKeyReleaseMask;
1783 
1784  NSView<X11Window> *childView = nil;
1785 
1786  NSPoint mousePosition = {};
1787  if (QuartzWindow * const topLevel = FindWindowUnderPointer())
1788  mousePosition = [topLevel mouseLocationOutsideOfEventStream];
1789 
1790  if (eventType == kKeyPressMask)
1791  Detail::SendKeyPressEvent(fEventQueue, view, childView, theEvent, mousePosition);
1792  else
1793  Detail::SendKeyReleaseEvent(fEventQueue, view, childView, theEvent, mousePosition);
1794 }
1795 
1796 //______________________________________________________________________________
1797 void EventTranslator::FindButtonGrab(NSView<X11Window> *fromView, NSEvent *theEvent, EMouseButton btn)
1798 {
1799  //Find a view to become a grab view - either passive or implicit.
1800 
1801  assert(fromView != nil && "FindButtonGrabView, parameter 'fromView' is nil");
1802  assert(theEvent != nil && "FindButtonGrabView, parameter 'theEvent' is nil");
1803 
1804  assert(fPointerGrabType == kPGNoGrab && "FindButtonGrabView, grab is already activated");
1805 
1806  const unsigned keyModifiers = Detail::GetKeyboardModifiersFromCocoaEvent(theEvent);
1807 
1808  NSView<X11Window> *grabView = 0;
1809  NSView<X11Window> *buttonPressView = 0;
1810 
1811  for (NSView<X11Window> *view = fromView; view != nil; view = view.fParentView) {
1812  //Top-first view to receive button press event.
1813  if (!buttonPressView && (view.fEventMask & kButtonPressMask))
1814  buttonPressView = view;
1815 
1816  //Bottom-first view with passive grab.
1817  if (view.fPassiveGrabButton == kAnyButton || view.fPassiveGrabButton == btn) {
1818  //Check modifiers.
1819  if (view.fPassiveGrabKeyModifiers == kAnyModifier || (view.fPassiveGrabKeyModifiers & keyModifiers))
1820  grabView = view;
1821  }
1822  }
1823 
1824  if (grabView) {
1825  fButtonGrabView = grabView;
1827  fGrabEventMask = grabView.fPassiveGrabEventMask;
1828  fOwnerEvents = grabView.fPassiveGrabOwnerEvents;
1829  } else if (buttonPressView) {
1830  //This is an implicit grab.
1831  fButtonGrabView = buttonPressView;
1833  fGrabEventMask = buttonPressView.fEventMask;
1834  fOwnerEvents = false;
1835  } else {
1836  //Implicit grab with 'root' window?
1837  fButtonGrabView = nil;
1839  fGrabEventMask = 0;
1840  fOwnerEvents = false;
1841  }
1842 }
1843 
1844 //______________________________________________________________________________
1845 void EventTranslator::FindKeyGrabView(NSView<X11Window> *eventView, NSEvent *theEvent)
1846 {
1847  assert(eventView != nil && "FindKeyGrabView, parameter 'eventView' is nil");
1848  assert(theEvent != nil && "FindKeyGrabView, parameter 'theEvent' is nil");
1849 
1850  NSString * const characters = [theEvent charactersIgnoringModifiers];
1851  assert(characters != nil && "FindKeyGrabView, [theEvent characters] returned nil");
1852  assert([characters length] > 0 && "FindKeyGrabView, characters is an empty string");
1853 
1854  const unichar keyCode = [characters characterAtIndex : 0];
1855  const NSUInteger modifiers = [theEvent modifierFlags] & Details::kDeviceIndependentModifierFlagsMask;
1856 
1857  NSView<X11Window> *currentView = fFocusView;
1858  if (eventView != fFocusView && Detail::IsParent(fFocusView, eventView))
1859  currentView = eventView;
1860 
1861  for (; currentView; currentView = currentView.fParentView) {
1862  if ([currentView findPassiveKeyGrab : keyCode modifiers : modifiers])
1863  fKeyGrabView = currentView;
1864  }
1865 }
1866 
1867 }//X11
1868 }//MacOSX
1869 }//ROOT
NSUInteger GetCocoaKeyModifiersFromROOTKeyModifiers(UInt_t rootKeyModifiers)
Definition: X11Events.mm:261
void GenerateCrossingEventForGrabView(EventQueue_t &queue, NSView< X11Window > *fromView, NSView< X11Window > *toView, NSView< X11Window > *grabView, Mask_t grabEventMask, NSEvent *theEvent)
Definition: X11Events.mm:1086
const Mask_t kKeyReleaseMask
Definition: GuiTypes.h:159
int GlobalXCocoaToROOT(CGFloat xCocoa)
EXMagic
Definition: GuiTypes.h:218
void SendLeaveEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:575
void GenerateCrossingEventParentToChild(EventQueue_t &queue, NSView< X11Window > *parent, NSView< X11Window > *child, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:944
void GenerateConfigureNotifyEvent(NSView< X11Window > *view, const NSRect &newFrame)
Definition: X11Events.mm:1149
void GeneratePointerMotionEventActiveGrab(NSEvent *theEvent)
Definition: X11Events.mm:1539
Bool_t operator<(const TDatime &d1, const TDatime &d2)
Definition: TDatime.h:106
NSView< X11Window > * FindViewForPointerEvent(NSEvent *pointerEvent)
void SendFocusOutEvent(EventQueue_t &queue, NSView< X11Window > *view, EXMagic mode)
Definition: X11Events.mm:826
UInt_t GetModifiers()
Definition: X11Events.mm:300
void GeneratePointerMotionEvent(NSEvent *theEvent)
Definition: X11Events.mm:1246
const Mask_t kButton2Mask
Definition: GuiTypes.h:203
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
Int_t MapKeySymToKeyCode(Int_t keySym)
Definition: X11Events.mm:178
const Mask_t kKeyMod2Mask
Definition: GuiTypes.h:198
UInt_t Mask_t
Definition: GuiTypes.h:40
const Mask_t kKeyShiftMask
Definition: GuiTypes.h:194
Ancestry FindRelation(NSView< X11Window > *view1, NSView< X11Window > *view2, NSView< X11Window > **lca)
Definition: X11Events.mm:480
const NSUInteger kDeviceIndependentModifierFlagsMask
const Mask_t kKeyMod1Mask
Definition: GuiTypes.h:197
void GenerateKeyReleaseEvent(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1303
const Mask_t kButtonMotionMask
Definition: GuiTypes.h:163
ULong_t Time_t
Definition: GuiTypes.h:41
const Mask_t kLeaveWindowMask
Definition: GuiTypes.h:167
void SendLeaveEventClosedRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:895
void MapUnicharToKeySym(unichar key, char *buf, Int_t len, UInt_t &rootKeySym)
Definition: X11Events.mm:98
NSView< X11Window > * FindViewToPropagateEvent(NSView< X11Window > *viewFrom, Mask_t checkMask)
Definition: X11Events.mm:496
Int_t fY
Definition: GuiTypes.h:177
unsigned GetKeyboardModifiersFromCocoaEvent(NSEvent *theEvent)
Definition: X11Events.mm:369
#define gClient
Definition: TGClient.h:166
void GenerateButtonReleaseEventActiveGrab(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1657
std::deque< Event_t > EventQueue_t
Definition: X11Events.h:49
const NSUInteger kAlternateKeyMask
int Int_t
Definition: RtypesCore.h:41
void GenerateKeyPressEventNoGrab(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1701
void FindKeyGrabView(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1845
DerivedType * Get() const
Definition: CocoaUtils.h:136
Window_t fWindow
Definition: GuiTypes.h:175
NSView< X11Window > * fButtonGrabView
Definition: X11Events.h:116
void GenerateButtonPressEvent(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1259
void SendButtonPressEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:636
void GenerateCrossingEventFromChild1ToChild2(EventQueue_t &queue, NSView< X11Window > *child1, NSView< X11Window > *child2, NSView< X11Window > *ancestor, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:975
const NSEventType kKeyDown
const Mask_t kPointerMotionMask
Definition: GuiTypes.h:162
NSView< X11Window > * fFocusView
Definition: X11Events.h:118
NSView< X11Window > * FindViewToPropagateEvent(NSView< X11Window > *viewFrom, Mask_t checkMask, NSView< X11Window > *grabView, Mask_t grabMask)
Definition: X11Events.mm:513
void GenerateButtonReleaseEventNoGrab(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1645
void GenerateCrossingEventChildToParent(EventQueue_t &queue, NSView< X11Window > *parent, NSView< X11Window > *child, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:914
void SendPointerMotionEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent)
Definition: X11Events.mm:607
NSPoint ConvertPointFromBaseToScreen(NSWindow *window, NSPoint windowPoint)
Int_t fXRoot
Definition: GuiTypes.h:178
void SendKeyPressEvent(EventQueue_t &queue, NSView< X11Window > *view, NSView< X11Window > *childView, NSEvent *theEvent, NSPoint windowPoint)
Definition: X11Events.mm:717
const Mask_t kKeyLockMask
Definition: GuiTypes.h:195
void SetInputFocus(NSView< X11Window > *focusView)
Definition: X11Events.mm:1433
NSPoint ConvertPointFromScreenToBase(NSPoint screenPoint, NSWindow *window)
Time_t TimeForCocoaEvent(NSEvent *theEvent)
Definition: X11Events.mm:319
void GenerateCrossingEvents(EventQueue_t &queue, NSView< X11Window > *fromView, NSView< X11Window > *toView, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:1015
const NSEventType kKeyUp
void FindButtonGrab(NSView< X11Window > *fromView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1797
const Mask_t kButtonPressMask
Definition: GuiTypes.h:160
NSView< X11Window > * FindViewUnderPointer()
NSPoint TranslateToScreen(NSView< X11Window > *from, NSPoint point)
const Mask_t kKeyPressMask
Definition: GuiTypes.h:158
const Mask_t kButton3Mask
Definition: GuiTypes.h:204
int GlobalYCocoaToROOT(CGFloat yCocoa)
EMouseButton
Definition: GuiTypes.h:213
void GenerateExposeEvent(NSView< X11Window > *view, const NSRect &exposedRect)
Definition: X11Events.mm:1176
Time_t fTime
Definition: GuiTypes.h:176
unsigned GetModifiersFromCocoaEvent(NSEvent *theEvent)
Definition: X11Events.mm:390
SVector< double, 2 > v
Definition: Dict.h:5
EGEventType fType
Definition: GuiTypes.h:174
UInt_t fHeight
Definition: GuiTypes.h:181
QuartzWindow * FindWindowUnderPointer()
void GenerateButtonPressEventActiveGrab(NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1611
const NSUInteger kCommandKeyMask
void SendEnterEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EXMagic detail)
Definition: X11Events.mm:540
unsigned int UInt_t
Definition: RtypesCore.h:42
void GenerateDestroyNotify(unsigned winID)
Int_t fYRoot
Definition: GuiTypes.h:178
Ancestry FindLowestCommonAncestor(NSView< X11Window > *view1, NSView< X11Window > *view2, NSView< X11Window > **lca)
Definition: X11Events.mm:452
const NSUInteger kShiftKeyMask
void SendLeaveEventRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:879
void SendEnterEventRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:849
void GenerateKeyEventActiveGrab(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1724
NSView< X11Window > * fKeyGrabView
Definition: X11Events.h:117
EKeySym
Definition: KeySymbols.h:25
bool IsInBranch(NSView< X11Window > *parent, NSView< X11Window > *child, NSView< X11Window > *testView)
Definition: X11Events.mm:427
const Mask_t kEnterWindowMask
Definition: GuiTypes.h:166
void GenerateButtonPressEventNoGrab(NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1577
T2 fSecond
Definition: X11Events.mm:87
void ConvertEventLocationToROOTXY(NSEvent *cocoaEvent, NSView< X11Window > *eventView, Event_t *rootEvent)
Definition: X11Events.mm:341
void SendFocusInEvent(EventQueue_t &queue, NSView< X11Window > *view, EXMagic mode)
Definition: X11Events.mm:805
static Int_t init()
void GenerateCrossingEventActiveGrab(NSEvent *theEvent)
Definition: X11Events.mm:1215
virtual Bool_t HandleEvent(Event_t *)
Definition: TGWindow.h:103
const Mask_t kButtonReleaseMask
Definition: GuiTypes.h:161
UInt_t fCode
Definition: GuiTypes.h:179
NSView< X11Window > * fViewUnderPointer
Definition: X11Events.h:109
#define T2
Definition: md5.inl:146
void GenerateCrossingEvent(NSEvent *theEvent)
Definition: X11Events.mm:1194
const NSUInteger kControlKeyMask
Long_t fUser[5]
Definition: GuiTypes.h:186
UInt_t GetKeyboardModifiers()
Definition: X11Events.mm:280
void SendEnterEventClosedRange(EventQueue_t &queue, NSView< X11Window > *from, NSView< X11Window > *to, NSEvent *theEvent, EXMagic mode)
Definition: X11Events.mm:865
UInt_t fWidth
Definition: GuiTypes.h:181
#define T1
Definition: md5.inl:145
Handle_t Window_t
Definition: GuiTypes.h:28
void GenerateKeyReleaseEventNoGrab(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1757
void GeneratePointerMotionEventNoGrab(NSEvent *theEvent)
Definition: X11Events.mm:1520
const Mask_t kFocusChangeMask
Definition: GuiTypes.h:168
void CheckUnmappedView(Window_t winID)
Definition: X11Events.mm:1476
void GenerateCrossingEventNoGrab(NSEvent *theEvent)
Definition: X11Events.mm:1204
void GenerateKeyPressEvent(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1287
Event_t NewX11EventFromCocoaEvent(unsigned windowID, NSEvent *theEvent)
Definition: X11Events.mm:328
void SendButtonReleaseEvent(EventQueue_t &queue, NSView< X11Window > *view, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:686
UInt_t fState
Definition: GuiTypes.h:180
const Mask_t kKeyControlMask
Definition: GuiTypes.h:196
void GenerateKeyEventForView(NSView< X11Window > *view, NSEvent *theEvent)
Definition: X11Events.mm:1774
bool IsParent(NSView< X11Window > *testParent, NSView< X11Window > *testChild)
Definition: X11Events.mm:409
const Mask_t kAnyModifier
Definition: GuiTypes.h:209
const NSUInteger kAlphaShiftKeyMask
const Mask_t kButton1Mask
Definition: GuiTypes.h:202
void SetPointerGrab(NSView< X11Window > *grabView, unsigned eventMask, bool ownerEvents)
Definition: X11Events.mm:1341
Int_t fX
Definition: GuiTypes.h:177
void GenerateFocusChangeEvent(NSView< X11Window > *eventView)
Definition: X11Events.mm:1323
void SendKeyReleaseEvent(EventQueue_t &queue, NSView< X11Window > *view, NSView< X11Window > *childView, NSEvent *theEvent, NSPoint windowPoint)
Definition: X11Events.mm:761
T1 fFirst
Definition: X11Events.mm:86
void GenerateButtonReleaseEvent(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1272