Logo ROOT  
Reference Guide
QuartzWindow.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 DEBUG_ROOT_COCOA
13 
14 //#define NDEBUG
15 
16 #ifdef DEBUG_ROOT_COCOA
17 #include <iostream>
18 #include <fstream>
19 
20 #include "TClass.h"
21 #endif
22 
23 #include <algorithm>
24 #include <stdexcept>
25 #include <cassert>
26 #include <vector>
27 
28 #include <Availability.h>
29 
30 #include "ROOTOpenGLView.h"
31 #include "CocoaConstants.h"
32 #include "QuartzWindow.h"
33 #include "QuartzPixmap.h"
34 #include "QuartzUtils.h"
35 #include "CocoaUtils.h"
36 #include "RConfigure.h"
37 #include "X11Colors.h"
38 #include "X11Buffer.h"
39 #include "TGWindow.h"
40 #include "TGClient.h"
41 #include "TSystem.h"
42 #include "TGCocoa.h"
43 #include "TROOT.h"
44 #include "TGTextView.h"
45 #include "TGView.h"
46 #include "TGCanvas.h"
47 
48 
49 namespace ROOT {
50 namespace MacOSX {
51 namespace X11 {
52 
53 #pragma mark - Create a window or a view.
54 
55 //______________________________________________________________________________
57  UInt_t clss, void */*visual*/, SetWindowAttributes_t *attr, UInt_t)
58 {
59  using namespace Details;
60 
61  NSRect winRect = {};
62  winRect.origin.x = GlobalXROOTToCocoa(x);
63  winRect.origin.y = GlobalYROOTToCocoa(y + h);
64  winRect.size.width = w;
65  winRect.size.height = h;
66 
67  const NSUInteger styleMask = kTitledWindowMask | kClosableWindowMask |
69 
70  QuartzWindow * const newWindow = [[QuartzWindow alloc] initWithContentRect : winRect
71  styleMask : styleMask
72  backing : NSBackingStoreBuffered
73  defer : YES
74  windowAttributes : attr];
75  if (!newWindow)
76  throw std::runtime_error("CreateTopLevelWindow failed");
77 
78  newWindow.fDepth = depth;
79  newWindow.fClass = clss;
80 
81  return newWindow;
82 }
83 
84 //______________________________________________________________________________
85 QuartzView *CreateChildView(QuartzView * /*parent*/, Int_t x, Int_t y, UInt_t w, UInt_t h, UInt_t /*border*/, Int_t /*depth*/,
86  UInt_t /*clss*/, void * /*visual*/, SetWindowAttributes_t *attr, UInt_t /*wtype*/)
87 {
88  NSRect viewRect = {};
89  viewRect.origin.x = x;
90  viewRect.origin.y = y;
91  viewRect.size.width = w;
92  viewRect.size.height = h;
93 
94  QuartzView * const view = [[QuartzView alloc] initWithFrame : viewRect windowAttributes : attr];
95  if (!view)
96  throw std::runtime_error("CreateChildView failed");
97 
98  return view;
99 }
100 
101 #pragma mark - root window (does not really exist, it's our desktop built of all screens).
102 
103 //______________________________________________________________________________
105 {
106  //'root' window does not exist, but we can request its attributes.
107  assert(attr != 0 && "GetRootWindowAttributes, parameter 'attr' is null");
108 
109 
110  NSArray * const screens = [NSScreen screens];
111  assert(screens != nil && "screens array is nil");
112  NSScreen * const mainScreen = [screens objectAtIndex : 0];
113  assert(mainScreen != nil && "screen with index 0 is nil");
114 
115  *attr = WindowAttributes_t();
116 
117  assert(dynamic_cast<TGCocoa *>(gVirtualX) &&
118  "GetRootWindowAttributes, gVirtualX is either null or has a wrong type");
119 
120  TGCocoa * const gCocoa = static_cast<TGCocoa *>(gVirtualX);
121 
122  const Rectangle &frame = gCocoa->GetDisplayGeometry();
123 
124  attr->fX = 0;
125  attr->fY = 0;
126  attr->fWidth = frame.fWidth;
127  attr->fHeight = frame.fHeight;
128  attr->fBorderWidth = 0;
129  attr->fYourEventMask = 0;
130  attr->fAllEventMasks = 0;//???
131 
132  attr->fDepth = NSBitsPerPixelFromDepth([mainScreen depth]);
133  attr->fVisual = 0;
134  attr->fRoot = 0;
135 }
136 
137 
138 #pragma mark - Coordinate conversions.
139 
140 //______________________________________________________________________________
141 NSPoint ConvertPointFromBaseToScreen(NSWindow *window, NSPoint windowPoint)
142 {
143  assert(window != nil && "ConvertPointFromBaseToScreen, parameter 'window' is nil");
144 
145  //I have no idea why apple deprecated function for a point conversion and requires rect conversion,
146  //point conversion seems to produce wrong results with HiDPI.
147 
148  NSRect tmpRect = {};
149  tmpRect.origin = windowPoint;
150  tmpRect.size = NSMakeSize(1., 1.);//This is strange size :) But if they require rect, 0,0 - will not work?
151  tmpRect = [window convertRectToScreen : tmpRect];
152 
153  return tmpRect.origin;
154 }
155 
156 //______________________________________________________________________________
157 NSPoint ConvertPointFromScreenToBase(NSPoint screenPoint, NSWindow *window)
158 {
159  assert(window != nil && "ConvertPointFromScreenToBase, parameter 'window' is nil");
160 
161  //I have no idea why apple deprecated function for a point conversion and requires rect conversion,
162  //point conversion seems to produce wrong results with HiDPI.
163 
164  NSRect tmpRect = {};
165  tmpRect.origin = screenPoint;
166  tmpRect.size = NSMakeSize(1., 1.);
167  tmpRect = [window convertRectFromScreen : tmpRect];
168 
169  return tmpRect.origin;
170 }
171 
172 //______________________________________________________________________________
173 int GlobalYCocoaToROOT(CGFloat yCocoa)
174 {
175  //We can have several physical displays and thus several NSScreens in some arbitrary order.
176  //With Cocoa, some screens can have negative coordinates - to the left ro down to the primary
177  //screen (whatever it means). With X11 (XQuartz) though it's always 0,0.
178 
179  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
180  "GlobalYCocoaToROOT, gVirtualX is either nul or has a wrong type");
181 
182  const Rectangle frame = ((TGCocoa *)gVirtualX)->GetDisplayGeometry();
183 
184  return int(frame.fHeight - (yCocoa - frame.fY));
185 }
186 
187 //______________________________________________________________________________
188 int GlobalXCocoaToROOT(CGFloat xCocoa)
189 {
190  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
191  "GlobalXCocoaToROOT, gVirtualX is either nul or has a wrong type");
192  const Rectangle frame = ((TGCocoa *)gVirtualX)->GetDisplayGeometry();
193  //With X11 coordinate space always starts from 0, 0
194  return int(xCocoa - frame.fX);
195 }
196 
197 //______________________________________________________________________________
198 int GlobalYROOTToCocoa(CGFloat yROOT)
199 {
200  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
201  "GlobalYROOTToCocoa, gVirtualX is either nul or has a wrong type");
202  const Rectangle frame = ((TGCocoa *)gVirtualX)->GetDisplayGeometry();
203 
204  return int(frame.fY + (frame.fHeight - yROOT));
205 }
206 
207 //______________________________________________________________________________
208 int GlobalXROOTToCocoa(CGFloat xROOT)
209 {
210  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
211  "GlobalXROOTToCocoa, gVirtualX is either nul or has a wrong type");
212  const Rectangle frame = ((TGCocoa *)gVirtualX)->GetDisplayGeometry();
213  //With X11 coordinate space always starts from 0, 0
214  return int(frame.fX + xROOT);
215 }
216 
217 //______________________________________________________________________________
218 int LocalYCocoaToROOT(NSView<X11Window> *parentView, CGFloat yCocoa)
219 {
220  assert(parentView != nil && "LocalYCocoaToROOT, parent view is nil");
221 
222  return int(parentView.frame.size.height - yCocoa);
223 }
224 
225 //______________________________________________________________________________
226 int LocalYROOTToCocoa(NSView<X11Window> *parentView, CGFloat yROOT)
227 {
228  //:)
229  assert(parentView != nil && "LocalYROOTToCocoa, parent view is nil");
230 
231  return int(parentView.frame.size.height - yROOT);
232 }
233 
234 
235 //______________________________________________________________________________
236 int LocalYROOTToCocoa(NSObject<X11Drawable> *drawable, CGFloat yROOT)
237 {
238  //:)
239  assert(drawable != nil && "LocalYROOTToCocoa, drawable is nil");
240 
241  return int(drawable.fHeight - yROOT);
242 }
243 
244 //______________________________________________________________________________
245 NSPoint TranslateToScreen(NSView<X11Window> *from, NSPoint point)
246 {
247  assert(from != nil && "TranslateToScreen, parameter 'from' is nil");
248 
249  const NSPoint winPoint = [from convertPoint : point toView : nil];
250 
251  NSPoint screenPoint = ConvertPointFromBaseToScreen([from window], winPoint);
252  screenPoint.x = GlobalXCocoaToROOT(screenPoint.x);
253  screenPoint.y = GlobalYCocoaToROOT(screenPoint.y);
254 
255  return screenPoint;
256 }
257 
258 //______________________________________________________________________________
259 NSPoint TranslateFromScreen(NSPoint point, NSView<X11Window> *to)
260 {
261  assert(to != nil && "TranslateFromScreen, parameter 'to' is nil");
262 
263  point.x = GlobalXROOTToCocoa(point.x);
264  point.y = GlobalYROOTToCocoa(point.y);
265  point = ConvertPointFromScreenToBase(point, [to window]);
266 
267  return [to convertPoint : point fromView : nil];
268 }
269 
270 //______________________________________________________________________________
271 NSPoint TranslateCoordinates(NSView<X11Window> *from, NSView<X11Window> *to, NSPoint sourcePoint)
272 {
273  //Both views are valid.
274  assert(from != nil && "TranslateCoordinates, parameter 'from' is nil");
275  assert(to != nil && "TranslateCoordinates, parameter 'to' is nil");
276 
277  if ([from window] == [to window]) {
278  //Both views are in the same window.
279  return [to convertPoint : sourcePoint fromView : from];
280  } else {
281  //May be, I can do it in one call, but it's not obvious for me
282  //what is 'pixel aligned backing store coordinates' and
283  //if they are the same as screen coordinates.
284 
285  //Many thanks to Apple for deprecated functions!!!
286 
287  const NSPoint win1Point = [from convertPoint : sourcePoint toView : nil];
288  const NSPoint screenPoint = ConvertPointFromBaseToScreen([from window], win1Point);
289  const NSPoint win2Point = ConvertPointFromScreenToBase(screenPoint, [to window]);
290 
291  return [to convertPoint : win2Point fromView : nil];
292  }
293 }
294 
295 //______________________________________________________________________________
297 {
298  assert(view != nil && "ScreenPointIsInView, parameter 'view' is nil");
299 
300  NSPoint point = {};
301  point.x = x, point.y = y;
302  point = TranslateFromScreen(point, view);
303  const NSRect viewFrame = view.frame;
304 
305  if (point.x < 0 || point.x > viewFrame.size.width)
306  return false;
307  if (point.y < 0 || point.y > viewFrame.size.height)
308  return false;
309 
310  return true;
311 }
312 
313 #pragma mark - Different FindView/Window functions iterating on the ROOT's windows/views.
314 
315 //______________________________________________________________________________
317 {
318  //array's counter is increased, all object in array are also retained.
319  const Util::AutoreleasePool pool;
320 
321  NSArray * const orderedWindows = [NSApp orderedWindows];
322  for (NSWindow *window in orderedWindows) {
323  if (![window isKindOfClass : [QuartzWindow class]])
324  continue;
325  QuartzWindow * const qw = (QuartzWindow *)window;
326  if (qw.fIsDeleted)//Because of reference counting this can happen.
327  continue;
328  //Check if point is inside.
330  return qw;
331  }
332 
333  return nil;
334 }
335 
336 //______________________________________________________________________________
337 NSView<X11Window> *FindDNDAwareViewInPoint(NSArray *children, Window_t dragWinID,
338  Window_t inputWinID, Int_t x, Int_t y, Int_t maxDepth)
339 {
340  assert(children != nil && "FindDNDAwareViewInPoint, parameter 'children' is nil");
341 
342  if (maxDepth <= 0)
343  return nil;
344 
345  NSEnumerator * const reverseEnumerator = [children reverseObjectEnumerator];
346  for (NSView<X11Window> *child in reverseEnumerator) {
347  if (!ScreenPointIsInView(child, x, y))
348  continue;
349  if (child.fIsDNDAware && child.fID != dragWinID && child.fID != inputWinID)
350  return child;//got it!
351 
352  NSView<X11Window> * const testView = FindDNDAwareViewInPoint([child subviews], dragWinID,
353  inputWinID, x, y, maxDepth - 1);
354  if (testView)
355  return testView;
356  }
357 
358  return nil;
359 }
360 
361 //______________________________________________________________________________
363  Int_t x, Int_t y, Int_t maxDepth)
364 {
365  //X and Y are ROOT's screen coordinates (Y is inverted).
366  if (maxDepth <= 0)
367  return nil;
368 
369  const Util::AutoreleasePool pool;
370 
371  if (!parentView) {//Start from the screen as a 'root' window.
372  NSArray * const orderedWindows = [NSApp orderedWindows];
373  for (NSWindow *window in orderedWindows) {
374  if (![window isKindOfClass : [QuartzWindow class]])
375  continue;
376  QuartzWindow * const qw = (QuartzWindow *)window;
377 
378  if (qw.fIsDeleted)//Because of reference counting this can happen.
379  continue;
380 
381  if (qw.fMapState != kIsViewable)
382  continue;
383 
384  //First, check this view itself, my be we found what we need already.
385  NSView<X11Window> *testView = qw.fContentView;
386  if (!ScreenPointIsInView(testView, x, y))
387  continue;
388 
389  if (testView.fIsDNDAware && testView.fID != dragWinID && testView.fID != inputWinID)
390  return testView;
391 
392  //Recursive part, check children.
393  NSArray * const children = [testView subviews];
394  testView = FindDNDAwareViewInPoint(children, dragWinID, inputWinID, x, y, maxDepth - 1);
395  if (testView)
396  return testView;
397  }
398 
399  //We did not find anything for 'root' window as parent.
400  return nil;
401  } else {
402  //Parent view is tested already (or should not be tested at all, check children.
403  return FindDNDAwareViewInPoint([parentView subviews], dragWinID, inputWinID, x, y, maxDepth);
404  }
405 }
406 
407 //______________________________________________________________________________
409 {
410  const Util::AutoreleasePool pool;
411 
412  NSArray * const orderedWindows = [NSApp orderedWindows];
413  for (NSWindow *nsWindow in orderedWindows) {
414  if (![nsWindow isKindOfClass : [QuartzWindow class]])
415  continue;
416 
417  QuartzWindow * const qWindow = (QuartzWindow *)nsWindow;
418 
419  if (qWindow.fIsDeleted)//Because of reference counting this can happen.
420  continue;
421 
422  if (qWindow.fMapState != kIsViewable)//Can it be false and still in this array???
423  continue;
424 
425  const NSPoint mousePosition = [qWindow mouseLocationOutsideOfEventStream];
426  const NSSize windowSize = qWindow.frame.size;
427  if (mousePosition.x >= 0 && mousePosition.x <= windowSize.width &&
428  mousePosition.y >= 0 && mousePosition.y <= windowSize.height)
429  return qWindow;
430  }
431 
432  return nil;
433 }
434 
435 //______________________________________________________________________________
437 {
438  const Util::AutoreleasePool pool;
439 
440  if (QuartzWindow *topLevel = FindWindowUnderPointer()) {
441  const NSPoint mousePosition = [topLevel mouseLocationOutsideOfEventStream];
442  return (NSView<X11Window> *)[[topLevel contentView] hitTest : mousePosition];
443  }
444 
445  return nil;
446 }
447 
448 //______________________________________________________________________________
450 {
451  //FindWindowForPointerEvent is required because due to grabs
452  //the receiver of the event can be different from the actual
453  //window under cursor.
454 
455  assert(pointerEvent != nil &&
456  "FindWindowForPointerEvent, parameter 'pointerEvent' is nil");
457 
458  const Util::AutoreleasePool pool;
459 
460  NSArray * const orderedWindows = [NSApp orderedWindows];
461  for (NSWindow *nsWindow in orderedWindows) {
462  if (![nsWindow isKindOfClass : [QuartzWindow class]])
463  continue;
464 
465  QuartzWindow * const qWindow = (QuartzWindow *)nsWindow;
466 
467  if (qWindow.fIsDeleted)//Because of reference counting this can happen.
468  continue;
469 
470  //Can it be false and still in this array???
471  if (qWindow.fMapState != kIsViewable)
472  continue;
473 
474  NSPoint mousePosition = [pointerEvent locationInWindow];
475  //The event has a window, so position is in this window's coordinate system,
476  //convert it into screen point first.
477  if ([pointerEvent window]) {
478  //convertBaseToScreen is deprecated.
479  //mousePosition = [[pointerEvent window] convertBaseToScreen : mousePosition];
480  mousePosition = ConvertPointFromBaseToScreen([pointerEvent window], mousePosition);
481  }
482 
483  //convertScreenToBase is deprecated.
484  //mousePosition = [qWindow convertScreenToBase : mousePosition];
485  mousePosition = ConvertPointFromScreenToBase(mousePosition, qWindow);
486 
487  const NSSize windowSize = qWindow.frame.size;
488  if (mousePosition.x >= 0 && mousePosition.x <= windowSize.width &&
489  mousePosition.y >= 0 && mousePosition.y <= windowSize.height)
490  return qWindow;
491  }
492 
493  return nil;
494 }
495 
496 //______________________________________________________________________________
498 {
499  //FindViewForPointerEvent is required because of grabs - the receiver of the
500  //event can be different from the actual window under cursor.
501 
502  assert(pointerEvent != nil &&
503  "FindViewForPointerEvent, parameter 'pointerEvent' is nil");
504 
505  const Util::AutoreleasePool pool;
506 
507  if (QuartzWindow *topLevel = FindWindowForPointerEvent(pointerEvent)) {
508  NSPoint mousePosition = [pointerEvent locationInWindow];
509  if ([pointerEvent window])
510  mousePosition = ConvertPointFromBaseToScreen([pointerEvent window], mousePosition);
511 
512  //convertScreenToBase is deprecated.
513  //mousePosition = [topLevel convertScreenToBase : mousePosition];
514  mousePosition = ConvertPointFromScreenToBase(mousePosition, topLevel);
515 
516  return (NSView<X11Window> *)[[topLevel contentView] hitTest : mousePosition];
517  }
518 
519  return nil;
520 }
521 
522 #pragma mark - Downscale image ("reading color bits" on retina macs).
523 
524 //Hoho, we support C++11?? Let's return by value then!!!
525 std::vector<unsigned char> DownscaledImageData(unsigned w, unsigned h, CGImageRef image)
526 {
527  assert(w != 0 && h != 0 && "DownscaledImageData, invalid geometry");
528  assert(image != nullptr && "DonwscaledImageData, invalid parameter 'image'");
529 
530  std::vector<unsigned char> result;
531  try {
532  result.resize(w * h * 4);
533  } catch (const std::bad_alloc &) {
534  NSLog(@"DownscaledImageData, memory allocation failed");
535  return result;
536  }
537 
538  const Util::CFScopeGuard<CGColorSpaceRef> colorSpace(CGColorSpaceCreateDeviceRGB());//[1]
539  if (!colorSpace.Get()) {
540  NSLog(@"DownscaledImageData, CGColorSpaceCreateDeviceRGB failed");
541  return result;
542  }
543 
544  Util::CFScopeGuard<CGContextRef> ctx(CGBitmapContextCreateWithData(&result[0], w, h, 8,
545  w * 4, colorSpace.Get(),
546  kCGImageAlphaPremultipliedLast, NULL, 0));
547  if (!ctx.Get()) {
548  NSLog(@"DownscaledImageData, CGBitmapContextCreateWithData failed");
549  return result;
550  }
551 
552  CGContextDrawImage(ctx.Get(), CGRectMake(0, 0, w, h), image);
553 
554  return result;
555 }
556 
557 #pragma mark - "Focus management" - just make another window key window.
558 
559 //______________________________________________________________________________
561 {
562  //XQuartz (and other X11
563  if (![NSApp isActive])
564  return;
565 
566  const Util::AutoreleasePool pool;
567 
568  NSArray * const orderedWindows = [NSApp orderedWindows];
569  for (NSWindow *nsWindow in orderedWindows) {
570  if (![nsWindow isKindOfClass : [QuartzWindow class]])
571  continue;
572 
573  QuartzWindow * const qWindow = (QuartzWindow *)nsWindow;
574 
575  if (qWindow.fIsDeleted || qWindow.fMapState != kIsViewable || qWindow.fID == winID)
576  continue;
577 
578  if (qWindow.fContentView.fOverrideRedirect)
579  continue;
580 
581  [qWindow makeKeyAndOrderFront : qWindow];
582  break;
583  }
584 }
585 
586 #pragma mark - 'shape mask' - to create a window with arbitrary (probably non-rectangle) shape.
587 
588 //______________________________________________________________________________
589 void ClipToShapeMask(NSView<X11Window> *view, CGContextRef ctx)
590 {
591  assert(view != nil && "ClipToShapeMask, parameter 'view' is nil");
592  assert(ctx != 0 && "ClipToShapeMask, parameter 'ctx' is null");
593 
594  QuartzWindow * const topLevelParent = view.fQuartzWindow;
595  assert(topLevelParent.fShapeCombineMask != nil &&
596  "ClipToShapeMask, fShapeCombineMask is nil on a top-level window");
597  assert(topLevelParent.fShapeCombineMask.fImage != 0 &&
598  "ClipToShapeMask, shape mask is null");
599 
600  //Important: shape mask should have the same width and height as
601  //a top-level window. In ROOT it does not :( Say hello to visual artifacts.
602 
603  //Attach clip mask to the context.
604  if (!view.fParentView) {
605  //'view' is a top-level view.
606  const CGRect clipRect = CGRectMake(0, 0, topLevelParent.fShapeCombineMask.fWidth,
607  topLevelParent.fShapeCombineMask.fHeight);
608  CGContextClipToMask(ctx, clipRect, topLevelParent.fShapeCombineMask.fImage);
609  } else {
610  NSRect clipRect = view.frame;
611  //More complex case: 'self' is a child view, we have to create a subimage from shape mask.
612  clipRect.origin = [view.fParentView convertPoint : clipRect.origin
613  toView : [view window].contentView];
614  clipRect.origin.y = X11::LocalYROOTToCocoa((NSView<X11Window> *)[view window].contentView,
615  clipRect.origin.y + clipRect.size.height);
616 
617  if (AdjustCropArea(topLevelParent.fShapeCombineMask, clipRect)) {
619  clipImageGuard(CGImageCreateWithImageInRect(topLevelParent.fShapeCombineMask.fImage,
620  NSRectToCGRect(clipRect)));
621  clipRect.origin = NSPoint();
622  CGContextClipToMask(ctx, NSRectToCGRect(clipRect), clipImageGuard.Get());
623  } else {
624  //View is invisible.
625  CGRect rect = {};
626  CGContextClipToRect(ctx, rect);
627  }
628  }
629 }
630 
631 #pragma mark - Window's geometry and attributes.
632 
633 //______________________________________________________________________________
635 {
636  assert(attr != 0 && "SetWindowAttributes, parameter 'attr' is null");
637  assert(window != nil && "SetWindowAttributes, parameter 'window' is nil");
638 
639  const Mask_t mask = attr->fMask;
640 
641  if (mask & kWABackPixel)
642  window.fBackgroundPixel = attr->fBackgroundPixel;
643 
644  if (mask & kWAEventMask)
645  window.fEventMask = attr->fEventMask;
646 
647  if (mask & kWABitGravity)
648  window.fBitGravity = attr->fBitGravity;
649 
650  if (mask & kWAWinGravity)
651  window.fWinGravity = attr->fWinGravity;
652 
653  if (mask & kWAOverrideRedirect) {
654  if ([(NSObject *)window isKindOfClass : [QuartzWindow class]]) {
655  QuartzWindow * const qw = (QuartzWindow *)window;
656  [qw setStyleMask : Details::kBorderlessWindowMask];
657  [qw setAlphaValue : 0.95];
658  }
659 
660  window.fOverrideRedirect = YES;
661  }
662 }
663 
664 //______________________________________________________________________________
666 {
667  assert(win != nil && "GetWindowGeometry, parameter 'win' is nil");
668  assert(dst != 0 && "GetWindowGeometry, parameter 'dst' is null");
669 
670  dst->fX = win.fX;
671  dst->fY = win.fY;
672 
673  dst->fWidth = win.fWidth;
674  dst->fHeight = win.fHeight;
675 }
676 
677 //______________________________________________________________________________
679 {
680  assert(window != nil && "GetWindowAttributes, parameter 'window' is nil");
681  assert(dst != 0 && "GetWindowAttributes, parameter 'attr' is null");
682 
683  *dst = WindowAttributes_t();
684 
685  //fX, fY, fWidth, fHeight.
686  GetWindowGeometry(window, dst);
687 
688  //Actually, most of them are not used by GUI.
689  dst->fBorderWidth = 0;
690  dst->fDepth = window.fDepth;
691  //Dummy value.
692  dst->fVisual = 0;
693  //Dummy value.
694  dst->fRoot = 0;
695  dst->fClass = window.fClass;
696  dst->fBitGravity = window.fBitGravity;
697  dst->fWinGravity = window.fWinGravity;
698  //Dummy value.
699  dst->fBackingStore = kAlways;//??? CHECK
700  dst->fBackingPlanes = 0;
701 
702  //Dummy value.
703  dst->fBackingPixel = 0;
704 
705  dst->fSaveUnder = 0;
706 
707  //Dummy value.
708  dst->fColormap = 0;
709  //Dummy value.
710  dst->fMapInstalled = kTRUE;
711 
712  dst->fMapState = window.fMapState;
713 
714  dst->fAllEventMasks = window.fEventMask;
715  dst->fYourEventMask = window.fEventMask;
716 
717  //Not used by GUI.
718  //dst->fDoNotPropagateMask
719 
720  dst->fOverrideRedirect = window.fOverrideRedirect;
721  //Dummy value.
722  dst->fScreen = 0;
723 }
724 
725 //With Apple's poor man's objective C/C++ + "brilliant" Cocoa you never know, what should be
726 //the linkage of callback functions, API + language dialects == MESS. I declare/define this comparators here
727 //as having "C++" linkage. If one good day clang will start to complane, I'll have to change this.
728 
729 #pragma mark - Comparators (I need them when changing a window's z-order).
730 
731 //______________________________________________________________________________
732 // SDK 10.11 and above ...
733 #ifdef MAC_OS_X_VERSION_10_11
734 NSComparisonResult CompareViewsToLower(__kindof NSView *view1, __kindof NSView *view2, void *context)
735 #else
736 NSComparisonResult CompareViewsToLower(id view1, id view2, void *context)
737 #endif
738 {
739  id topView = (id)context;
740  if (view1 == topView)
741  return NSOrderedAscending;
742  if (view2 == topView)
743  return NSOrderedDescending;
744 
745  return NSOrderedSame;
746 }
747 
748 //______________________________________________________________________________
749 // SDK 10.11 and above ...
750 #ifdef MAC_OS_X_VERSION_10_11
751 NSComparisonResult CompareViewsToRaise(__kindof NSView *view1, __kindof NSView *view2, void *context)
752 #else
753 NSComparisonResult CompareViewsToRaise(id view1, id view2, void *context)
754 #endif
755 {
756  id topView = (id)context;
757  if (view1 == topView)
758  return NSOrderedDescending;
759  if (view2 == topView)
760  return NSOrderedAscending;
761 
762  return NSOrderedSame;
763 }
764 
765 #pragma mark - Cursor's area.
766 
767 //______________________________________________________________________________
768 NSPoint GetCursorHotStop(NSImage *image, ECursor cursor)
769 {
770  assert(image != nil && "CursroHotSpot, parameter 'image' is nil");
771 
772  const NSSize imageSize = image.size;
773 
774  if (cursor == kArrowRight)
775  return NSMakePoint(imageSize.width, imageSize.height / 2);
776 
777  return NSMakePoint(imageSize.width / 2, imageSize.height / 2);
778 }
779 
780 //______________________________________________________________________________
781 NSCursor *CreateCustomCursor(ECursor currentCursor)
782 {
783  // Returns auto-released cursor object.
784  const char *pngFileName = 0;
785 
786  switch (currentCursor) {
787  case kMove:
788  pngFileName = "move_cursor.png";
789  break;
790  case kArrowHor:
791  pngFileName = "hor_arrow_cursor.png";
792  break;
793  case kArrowVer:
794  pngFileName = "ver_arrow_cursor.png";
795  break;
796  case kArrowRight:
797  pngFileName = "right_arrow_cursor.png";
798  break;
799  case kRotate:
800  pngFileName = "rotate.png";
801  break;
802  case kBottomLeft:
803  case kTopRight:
804  pngFileName = "top_right_cursor.png";
805  break;
806  case kTopLeft:
807  case kBottomRight:
808  pngFileName = "top_left_cursor.png";
809  break;
810  default:;
811  }
812 
813  if (pngFileName) {
814  const char * const path = gSystem->Which(TROOT::GetIconPath(), pngFileName, kReadPermission);
815  const Util::ScopedArray<const char> arrayGuard(path);
816 
817  if (!path || path[0] == 0) {
818  //File was not found.
819  return nil;
820  }
821 
822  NSString *nsPath = [NSString stringWithFormat : @"%s", path];//in autorelease pool.
823  NSImage * const cursorImage = [[NSImage alloc] initWithContentsOfFile : nsPath];
824 
825  if (!cursorImage)
826  return nil;
827 
828  const NSPoint hotSpot(X11::GetCursorHotStop(cursorImage, currentCursor));
829  NSCursor * const customCursor = [[[NSCursor alloc] initWithImage : cursorImage
830  hotSpot : hotSpot] autorelease];
831 
832  [cursorImage release];
833 
834  return customCursor;
835  }
836 
837  return nil;
838 }
839 
840 //______________________________________________________________________________
841 NSCursor *CreateCursor(ECursor currentCursor)
842 {
843  // Returns auto-released cursor object.
844 
845  //Cursors from TVirtaulX:
846  // kBottomLeft, kBottomRight, kTopLeft, kTopRight,
847  // kBottomSide, kLeftSide, kTopSide, kRightSide,
848  // kMove, kCross, kArrowHor, kArrowVer,
849  // kHand, kRotate, kPointer, kArrowRight,
850  // kCaret, kWatch
851 
852  NSCursor *cursor = nil;
853  switch (currentCursor) {
854  case kCross:
855  cursor = [NSCursor crosshairCursor];
856  break;
857  case kPointer:
858  cursor = [NSCursor arrowCursor];
859  break;
860  case kHand:
861  cursor = [NSCursor openHandCursor];
862  break;
863  case kLeftSide:
864  cursor = [NSCursor resizeLeftCursor];
865  break;
866  case kRightSide:
867  cursor = [NSCursor resizeRightCursor];
868  break;
869  case kTopSide:
870  cursor = [NSCursor resizeUpCursor];
871  break;
872  case kBottomSide:
873  cursor = [NSCursor resizeDownCursor];
874  break;
875  case kCaret:
876  cursor = [NSCursor IBeamCursor];
877  break;
878  case kRotate:
879  case kWatch:
880  default:
881  cursor = CreateCustomCursor(currentCursor);
882  }
883 
884  return cursor;
885 }
886 
887 //TGTextView/TGHtml is a very special window: it's a TGCompositeFrame,
888 //which has TGCompositeFrame inside (TGViewFrame). This TGViewFrame
889 //delegates Expose events to its parent, and parent tries to draw
890 //inside a TGViewFrame. This does not work with default
891 //QuartzView -drawRect/TGCocoa. So I need a trick to identify
892 //this special window.
893 
894 #pragma mark - Workarounds for a text view and its descendants.
895 
896 //______________________________________________________________________________
897 bool ViewIsTextView(unsigned viewID)
898 {
899  const TGWindow * const window = gClient->GetWindowById(viewID);
900  if (!window)
901  return false;
902  // This code used to use TObject::InheritsFrom, however since this is
903  // run under the AppKit, we can not call core/meta functions, otherwise
904  // we will run into deadlocks.
905  return dynamic_cast<const TGTextView*>(window);
906 }
907 
908 //______________________________________________________________________________
910 {
911  assert(view != nil && "ViewIsTextView, parameter 'view' is nil");
912 
913  return ViewIsTextView(view.fID);
914 }
915 
916 //______________________________________________________________________________
917 bool ViewIsTextViewFrame(NSView<X11Window> *view, bool checkParent)
918 {
919  assert(view != nil && "ViewIsTextViewFrame, parameter 'view' is nil");
920 
921  const TGWindow * const window = gClient->GetWindowById(view.fID);
922  if (!window)
923  return false;
924 
925  // This code used to use TObject::InheritsFrom, however since this is
926  // run under the AppKit, we can not call core/meta functions, otherwise
927  // we will run into deadlocks.
928  if (!dynamic_cast<const TGViewFrame*>(window))
929  return false;
930 
931  if (!checkParent)
932  return true;
933 
934  if (!view.fParentView)
935  return false;
936 
937  return ViewIsTextView(view.fParentView);
938 }
939 
940 //______________________________________________________________________________
941 bool ViewIsHtmlView(unsigned viewID)
942 {
943  const TGWindow * const window = gClient->GetWindowById(viewID);
944  if (!window)
945  return false;
946  // This code used to use TObject::InheritsFrom, however since this is
947  // run under the AppKit, we can not call core/meta functions, otherwise
948  // we will run into deadlocks.
949  return window->TestBit(TGWindow::kIsHtmlView);
950 }
951 
952 //______________________________________________________________________________
954 {
955  assert(view != nil && "ViewIsHtmlView, parameter 'view' is nil");
956 
957  return ViewIsHtmlView(view.fID);
958 }
959 
960 //______________________________________________________________________________
961 bool ViewIsHtmlViewFrame(NSView<X11Window> *view, bool checkParent)
962 {
963  //
964  assert(view != nil && "ViewIsHtmlViewFrame, parameter 'view' is nil");
965 
966  const TGWindow * const window = gClient->GetWindowById(view.fID);
967  if (!window)
968  return false;
969 
970  // This code used to use TObject::InheritsFrom, however since this is
971  // run under the AppKit, we can not call core/meta functions, otherwise
972  // we will run into deadlocks.
973  if (!dynamic_cast<const TGViewFrame*>(window))
974  return false;
975 
976  if (!checkParent)
977  return true;
978 
979  if (!view.fParentView)
980  return false;
981 
982  return ViewIsHtmlView(view.fParentView);
983 }
984 
985 //______________________________________________________________________________
987 {
988  assert(textView != nil && "FrameForTextView, parameter 'textView' is nil");
989 
990  for (NSView<X11Window> *child in [textView subviews]) {
991  if (ViewIsTextViewFrame(child, false))
992  return child;
993  }
994 
995  return nil;
996 }
997 
998 //______________________________________________________________________________
1000 {
1001  assert(htmlView != nil && "FrameForHtmlView, parameter 'htmlView' is nil");
1002 
1003  for (NSView<X11Window> *child in [htmlView subviews]) {
1004  if (ViewIsHtmlViewFrame(child, false))
1005  return child;
1006  }
1007 
1008  return nil;
1009 }
1010 
1011 #pragma mark - Workarounds for 'paint out of paint events'.
1012 
1013 //______________________________________________________________________________
1015 {
1016  assert(view != nil && "LockFocus, parameter 'view' is nil");
1017  assert([view isKindOfClass : [QuartzView class]] &&
1018  "LockFocus, QuartzView is expected");
1019 
1020  if ([view lockFocusIfCanDraw]) {
1021  NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
1022  assert(nsContext != nil && "LockFocus, currentContext is nil");
1023  CGContextRef currContext = (CGContextRef)[nsContext graphicsPort];
1024  assert(currContext != 0 && "LockFocus, graphicsPort is null");//remove this assert?
1025 
1026  ((QuartzView *)view).fContext = currContext;
1027 
1028  return true;
1029  }
1030 
1031  return false;
1032 }
1033 
1034 //______________________________________________________________________________
1036 {
1037  assert(view != nil && "UnlockFocus, parameter 'view' is nil");
1038  assert([view isKindOfClass : [QuartzView class]] &&
1039  "UnlockFocus, QuartzView is expected");
1040 
1041  [view unlockFocus];
1042  ((QuartzView *)view).fContext = 0;
1043 }
1044 
1045 }//X11
1046 }//MacOSX
1047 }//ROOT
1048 
1049 namespace Quartz = ROOT::Quartz;
1050 namespace Util = ROOT::MacOSX::Util;
1051 namespace X11 = ROOT::MacOSX::X11;
1052 namespace Details = ROOT::MacOSX::Details;
1053 
1054 #ifdef DEBUG_ROOT_COCOA
1055 
1056 #pragma mark - 'loggers'.
1057 
1058 namespace {
1059 
1060 //______________________________________________________________________________
1061 void log_attributes(const SetWindowAttributes_t *attr, unsigned winID)
1062 {
1063  //This function is loggin requests, at the moment I can not set all
1064  //of these attributes, so I first have to check, what is actually
1065  //requested by ROOT.
1066  static std::ofstream logfile("win_attr.txt");
1067 
1068  const Mask_t mask = attr->fMask;
1069  if (mask & kWABackPixmap)
1070  logfile<<"win "<<winID<<": BackPixmap\n";
1071  if (mask & kWABackPixel)
1072  logfile<<"win "<<winID<<": BackPixel\n";
1073  if (mask & kWABorderPixmap)
1074  logfile<<"win "<<winID<<": BorderPixmap\n";
1075  if (mask & kWABorderPixel)
1076  logfile<<"win "<<winID<<": BorderPixel\n";
1077  if (mask & kWABorderWidth)
1078  logfile<<"win "<<winID<<": BorderWidth\n";
1079  if (mask & kWABitGravity)
1080  logfile<<"win "<<winID<<": BitGravity\n";
1081  if (mask & kWAWinGravity)
1082  logfile<<"win "<<winID<<": WinGravity\n";
1083  if (mask & kWABackingStore)
1084  logfile<<"win "<<winID<<": BackingStore\n";
1085  if (mask & kWABackingPlanes)
1086  logfile<<"win "<<winID<<": BackingPlanes\n";
1087  if (mask & kWABackingPixel)
1088  logfile<<"win "<<winID<<": BackingPixel\n";
1089  if (mask & kWAOverrideRedirect)
1090  logfile<<"win "<<winID<<": OverrideRedirect\n";
1091  if (mask & kWASaveUnder)
1092  logfile<<"win "<<winID<<": SaveUnder\n";
1093  if (mask & kWAEventMask)
1094  logfile<<"win "<<winID<<": EventMask\n";
1095  if (mask & kWADontPropagate)
1096  logfile<<"win "<<winID<<": DontPropagate\n";
1097  if (mask & kWAColormap)
1098  logfile<<"win "<<winID<<": Colormap\n";
1099  if (mask & kWACursor)
1100  logfile<<"win "<<winID<<": Cursor\n";
1101 }
1102 
1103 //______________________________________________________________________________
1104 void print_mask_info(ULong_t mask)
1105 {
1106  if (mask & kButtonPressMask)
1107  NSLog(@"button press mask");
1108  if (mask & kButtonReleaseMask)
1109  NSLog(@"button release mask");
1110  if (mask & kExposureMask)
1111  NSLog(@"exposure mask");
1112  if (mask & kPointerMotionMask)
1113  NSLog(@"pointer motion mask");
1114  if (mask & kButtonMotionMask)
1115  NSLog(@"button motion mask");
1116  if (mask & kEnterWindowMask)
1117  NSLog(@"enter notify mask");
1118  if (mask & kLeaveWindowMask)
1119  NSLog(@"leave notify mask");
1120 }
1121 
1122 }
1123 #endif
1124 
1125 @implementation XorDrawingView
1126 {
1127  std::vector<ROOT::MacOSX::X11::Command *> xorOps;
1128 }
1129 
1130 - (void) setXorOperations : (const std::vector<ROOT::MacOSX::X11::Command *> &) primitives
1131 {
1132  xorOps = primitives;
1133 }
1134 
1135 - (void) drawRect : (NSRect) dirtyRect
1136 {
1137  [super drawRect:dirtyRect];
1138  NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
1139  if (!nsContext)
1140  return;
1141 
1142  CGContextRef cgContext = nsContext.CGContext;
1143  if (!cgContext)
1144  return;
1145 
1146  const Quartz::CGStateGuard ctxGuard(cgContext);
1147 
1148  CGContextSetRGBStrokeColor(cgContext, 0., 0., 0., 1.);
1149  CGContextSetLineWidth(cgContext, 1.);
1150 
1151  for (auto *command : xorOps) {
1152  command->Execute(cgContext);
1153  delete command;
1154  }
1155 
1156  xorOps.clear();
1157 }
1158 
1159 @end
1160 
1161 @implementation XorDrawingWindow
1162 
1163 - (instancetype) init
1164 {
1165  if (self = [super init])
1166  {
1167  self.styleMask = NSWindowStyleMaskBorderless; // No titlebar, buttons, etc.
1168  self.opaque = NO;
1169  self.hasShadow = NO;
1170  self.backgroundColor = NSColor.clearColor; // No background.
1171  self.ignoresMouseEvents = YES; // Lets mouse events pass through.
1172  self.contentView = [[XorDrawingView alloc] init];
1173  }
1174  return self;
1175 }
1176 
1177 #pragma mark - suppress the normal window behavior.
1178 - (BOOL)canBecomeKeyWindow
1179 {
1180  return NO;
1181 }
1182 - (BOOL)canBecomeMainWindow
1183 {
1184  return NO;
1185 }
1186 
1187 @end
1188 
1189 
1190 @implementation QuartzWindow
1191 
1192 @synthesize fMainWindow;
1193 @synthesize fHasFocus;
1194 
1195 #pragma mark - QuartzWindow's life cycle.
1196 
1197 //______________________________________________________________________________
1198 - (id) initWithContentRect : (NSRect) contentRect styleMask : (NSUInteger) windowStyle
1199  backing : (NSBackingStoreType) bufferingType defer : (BOOL) deferCreation
1200  windowAttributes : (const SetWindowAttributes_t *) attr
1201 {
1202  self = [super initWithContentRect : contentRect styleMask : windowStyle
1203  backing : bufferingType defer : deferCreation];
1204 
1205  if (self) {
1206  //ROOT's not able to draw GUI concurrently, thanks to global variables and gVirtualX itself.
1207  [self setAllowsConcurrentViewDrawing : NO];
1208 
1209  self.delegate = self;
1210  //create content view here.
1211  NSRect contentViewRect = contentRect;
1212  contentViewRect.origin.x = 0.f;
1213  contentViewRect.origin.y = 0.f;
1214 
1215  fContentView = [[QuartzView alloc] initWithFrame : contentViewRect windowAttributes : 0];
1216 
1217  [self setContentView : fContentView];
1218 
1219  [fContentView release];
1220  fDelayedTransient = NO;
1221 
1222  if (attr)
1223  X11::SetWindowAttributes(attr, self);
1224 
1225  fIsDeleted = NO;
1226  fHasFocus = NO;
1227  }
1228 
1229  return self;
1230 }
1231 
1232 //______________________________________________________________________________
1233 - (id) initWithGLView : (ROOTOpenGLView *) glView
1234 {
1235  using namespace Details;
1236 
1237  assert(glView != nil && "-initWithGLView, parameter 'glView' is nil");
1238 
1239  const NSUInteger styleMask = kTitledWindowMask | kClosableWindowMask |
1241 
1242  NSRect contentRect = glView.frame;
1243  contentRect.origin = NSPoint();
1244 
1245  self = [super initWithContentRect : contentRect styleMask : styleMask
1246  backing : NSBackingStoreBuffered defer : NO];
1247 
1248  if (self) {
1249  //ROOT's not able to draw GUI concurrently, thanks to global variables and gVirtualX itself.
1250  [self setAllowsConcurrentViewDrawing : NO];
1251  self.delegate = self;
1252  fContentView = glView;
1253  [self setContentView : fContentView];
1254  fDelayedTransient = NO;
1255  fIsDeleted = NO;
1256  fHasFocus = NO;
1257  }
1258 
1259  return self;
1260 }
1261 
1262 //______________________________________________________________________________
1263 - (void) dealloc
1264 {
1265  [fShapeCombineMask release];
1266  [super dealloc];
1267 }
1268 
1269 //______________________________________________________________________________
1270 - (BOOL) fIsDeleted
1271 {
1272  return fIsDeleted;
1273 }
1274 
1275 //______________________________________________________________________________
1276 - (void) setContentView:(NSView *)cv
1277 {
1278  [super setContentView:cv];
1279  if ([cv isKindOfClass:[QuartzView class]])
1280  fContentView = (QuartzView *)cv;
1281  else
1282  fContentView = nil;
1283 }
1284 
1285 //______________________________________________________________________________
1286 - (void) setFIsDeleted : (BOOL) deleted
1287 {
1288  fIsDeleted = deleted;
1289 }
1290 
1291 #pragma mark - Forwaring: I want to forward a lot of property setters/getters to the content view.
1292 
1293 //______________________________________________________________________________
1294 - (void) forwardInvocation : (NSInvocation *) anInvocation
1295 {
1296  if (!fContentView)
1297  return;
1298 
1299  if ([fContentView respondsToSelector : [anInvocation selector]]) {
1300  [anInvocation invokeWithTarget : fContentView];
1301  } else {
1302  [super forwardInvocation : anInvocation];
1303  }
1304 }
1305 
1306 //______________________________________________________________________________
1307 - (NSMethodSignature*) methodSignatureForSelector : (SEL) selector
1308 {
1309  NSMethodSignature *signature = [super methodSignatureForSelector : selector];
1310 
1311  if (!signature) {
1312  if (fContentView)
1313  signature = [fContentView methodSignatureForSelector : selector];
1314  }
1315 
1316  return signature;
1317 }
1318 
1319 //______________________________________________________________________________
1320 - (void) addTransientWindow : (QuartzWindow *) window
1321 {
1322  //Transient window: all the popups (menus, dialogs, popups, comboboxes, etc.)
1323  //always should be on the top of its 'parent' window.
1324  //To enforce this ordering, I have to connect such windows with parent/child
1325  //relation (it's not the same as a view hierarchy - both child and parent
1326  //windows are top-level windows).
1327 
1328  assert(window != nil && "-addTransientWindow:, parameter 'window' is nil");
1329 
1330  window.fMainWindow = self;
1331 
1332  if (window.fMapState != kIsViewable) {
1333  //If I add it as child, it'll immediately make a window visible
1334  //and this thing sucks.
1335  window.fDelayedTransient = YES;
1336  } else {
1337  [self addChildWindow : window ordered : NSWindowAbove];
1338  window.fDelayedTransient = NO;
1339  }
1340 }
1341 
1342 //______________________________________________________________________________
1343 - (void) makeKeyAndOrderFront : (id) sender
1344 {
1345 #pragma unused(sender)
1346 
1347  //The more I know Cocoa, the less I like it.
1348  //Window behavior between spaces is a total mess.
1349  //Set the window to join all spaces.
1350 #ifdef MAC_OS_X_VERSION_10_9
1351  [self setCollectionBehavior : NSWindowCollectionBehaviorMoveToActiveSpace];
1352 #else
1353  [self setCollectionBehavior : NSWindowCollectionBehaviorCanJoinAllSpaces];
1354 #endif
1355  //now bring it to the front, it will appear on the active space.
1356  [super makeKeyAndOrderFront : self];
1357  //then reset the collection behavior to default, so the window
1358  [self setCollectionBehavior : NSWindowCollectionBehaviorDefault];
1359 }
1360 
1361 //______________________________________________________________________________
1362 - (void) setFDelayedTransient : (BOOL) d
1363 {
1364  fDelayedTransient = d;
1365 }
1366 
1367 //______________________________________________________________________________
1369 {
1370  return fShapeCombineMask;
1371 }
1372 
1373 //______________________________________________________________________________
1374 - (void) setFShapeCombineMask : (QuartzImage *) mask
1375 {
1376  if (mask != fShapeCombineMask) {
1377  [fShapeCombineMask release];
1378  if (mask) {
1379  fShapeCombineMask = [mask retain];
1380  //TODO: Check window's shadow???
1381  }
1382  }
1383 }
1384 
1385 #pragma mark - X11Drawable's protocol.
1386 
1387 //______________________________________________________________________________
1388 - (BOOL) fIsPixmap
1389 {
1390  //Never.
1391  return NO;
1392 }
1393 
1394 //______________________________________________________________________________
1396 {
1397  //Never.
1398  return NO;
1399 }
1400 
1401 //______________________________________________________________________________
1402 - (CGFloat) fScaleFactor
1403 {
1404  if (!self.screen)
1405  return 1.;
1406  return self.screen.backingScaleFactor;
1407 }
1408 
1409 //______________________________________________________________________________
1410 - (int) fX
1411 {
1412  return X11::GlobalXCocoaToROOT(self.frame.origin.x);
1413 }
1414 
1415 //______________________________________________________________________________
1416 - (int) fY
1417 {
1418  return X11::GlobalYCocoaToROOT(self.frame.origin.y + self.frame.size.height);
1419 }
1420 
1421 //______________________________________________________________________________
1422 - (unsigned) fWidth
1423 {
1424  return self.frame.size.width;
1425 }
1426 
1427 //______________________________________________________________________________
1428 - (unsigned) fHeight
1429 {
1430  //NSWindow's frame (height component) also includes title-bar.
1431  //So I have to use content view's height.
1432  //Obviously, there is a "hole" == 22 pixels.
1433  assert(fContentView != nil && "-fHeight:, content view is nil");
1434 
1435  return fContentView.frame.size.height;
1436 }
1437 
1438 //______________________________________________________________________________
1439 - (void) setDrawableSize : (NSSize) newSize
1440 {
1441  //Can not simply do self.frame.size = newSize.
1442  assert(!(newSize.width < 0) && "-setDrawableSize:, width is negative");
1443  assert(!(newSize.height < 0) && "-setDrawableSize:, height is negative");
1444 
1445  NSRect frame = self.frame;
1446  //dY is potentially a titlebar height.
1447  const CGFloat dY = fContentView ? frame.size.height - fContentView.frame.size.height : 0.;
1448  //Adjust the frame.
1449  frame.origin.y = frame.origin.y + frame.size.height - newSize.height - dY;
1450  frame.size = newSize;
1451  frame.size.height += dY;
1452  [self setFrame : frame display : YES];
1453 }
1454 
1455 //______________________________________________________________________________
1456 - (void) setX : (int) x Y : (int) y width : (unsigned) w height : (unsigned) h
1457 {
1458  NSSize newSize = {};
1459  newSize.width = w;
1460  newSize.height = h;
1461  [self setContentSize : newSize];
1462 
1463  //Check how this is affected by title bar's height.
1464  NSPoint topLeft = {};
1465  topLeft.x = X11::GlobalXROOTToCocoa(x);
1466  topLeft.y = X11::GlobalYROOTToCocoa(y);
1467 
1468  [self setFrameTopLeftPoint : topLeft];
1469 }
1470 
1471 //______________________________________________________________________________
1472 - (void) setX : (int) x Y : (int) y
1473 {
1474  NSPoint topLeft = {};
1475  topLeft.x = X11::GlobalXROOTToCocoa(x);
1476  topLeft.y = X11::GlobalYROOTToCocoa(y);
1477 
1478  [self setFrameTopLeftPoint : topLeft];
1479 }
1480 
1481 //______________________________________________________________________________
1482 - (void) copy : (NSObject<X11Drawable> *) src area : (X11::Rectangle) area withMask : (QuartzImage *) mask
1483  clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
1484 {
1485  if (!fContentView)
1486  return;
1487 
1488  [fContentView copy : src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
1489 }
1490 
1491 //______________________________________________________________________________
1492 - (unsigned char *) readColorBits : (X11::Rectangle) area
1493 {
1494  if (!fContentView)
1495  return nullptr;
1496 
1497  return [fContentView readColorBits : area];
1498 }
1499 
1500 #pragma mark - XorDrawinWindow/View
1501 
1502 //______________________________________________________________________________
1503 - (void) addXorWindow
1504 {
1505  if ([self findXorWindow])
1506  return;
1507 
1508  XorDrawingWindow *special = [[XorDrawingWindow alloc] init];
1509  [self adjustXorWindowGeometry:special];
1510  [self addChildWindow : special ordered : NSWindowAbove];
1511  [special release];
1512 }
1513 
1514 //______________________________________________________________________________
1516 {
1517  if (auto win = [self findXorWindow])
1518  [self adjustXorWindowGeometry:win];
1519 }
1520 
1521 //______________________________________________________________________________
1523 {
1524  assert(win && "invalid (nil) parameter 'win'");
1525  auto frame = self.contentView.frame;
1526  frame = [self convertRectToScreen:frame];
1527  [win setFrame:frame display:NO];
1528 }
1529 
1530 //______________________________________________________________________________
1532 {
1533  if (auto win = [self findXorWindow]) {
1534  // For some reason, without ordeing out, the crosshair window's content stays
1535  // in the parent's window. Thus we first have to order out the crosshair window.
1536  [win orderOut:nil];
1537  [self removeChildWindow : win];
1538  }
1539 }
1540 
1541 //______________________________________________________________________________
1543 {
1544  auto children = [self childWindows];
1545  for (NSWindow *child in children) {
1546  if ([child isKindOfClass : XorDrawingWindow.class])
1547  return (XorDrawingWindow *)child;
1548  }
1549  return nil;
1550 }
1551 
1552 
1553 #pragma mark - X11Window protocol's implementation.
1554 
1555 //______________________________________________________________________________
1556 - (QuartzView *) fParentView
1557 {
1558  return nil;
1559 }
1560 
1561 //______________________________________________________________________________
1562 - (void) setFParentView : (QuartzView *) parent
1563 {
1564 #pragma unused(parent)
1565 }
1566 
1567 //______________________________________________________________________________
1569 {
1570  return fContentView;
1571 }
1572 
1573 //______________________________________________________________________________
1575 {
1576  return self;
1577 }
1578 
1579 //... many forwards to fContentView.
1580 
1581 //______________________________________________________________________________
1582 - (void) setFBackgroundPixel : (unsigned long) backgroundColor
1583 {
1584  if (!fContentView)
1585  return;
1586 
1587  if (!fShapeCombineMask) {
1588  CGFloat rgba[] = {0., 0., 0., 1.};
1589  X11::PixelToRGB(backgroundColor, rgba);
1590 
1591  [self setBackgroundColor : [NSColor colorWithColorSpace : [NSColorSpace deviceRGBColorSpace] components : rgba count : 4]];
1592  }
1593 
1594  fContentView.fBackgroundPixel = backgroundColor;
1595 }
1596 
1597 //______________________________________________________________________________
1598 - (unsigned long) fBackgroundPixel
1599 {
1600  if (!fContentView)
1601  return 0;
1602 
1604 }
1605 
1606 //______________________________________________________________________________
1607 - (int) fMapState
1608 {
1609  //Top-level window can be only kIsViewable or kIsUnmapped (not unviewable).
1610  if (!fContentView)
1611  return kIsUnmapped;
1612 
1613  if ([fContentView isHidden])
1614  return kIsUnmapped;
1615 
1616  return kIsViewable;
1617 }
1618 
1619 //______________________________________________________________________________
1620 - (void) addChild : (NSView<X11Window> *) child
1621 {
1622  assert(child != nil && "-addChild:, parameter 'child' is nil");
1623 
1624  if (!fContentView) {
1625  //This can happen only in case of re-parent operation.
1626  assert([child isKindOfClass : [QuartzView class]] &&
1627  "-addChild: gl view in a top-level window as content view is not supported");
1628 
1629  fContentView = (QuartzView *)child;
1630  [self setContentView : child];
1631  fContentView.fParentView = nil;
1632  } else
1633  [fContentView addChild : child];
1634 }
1635 
1636 //______________________________________________________________________________
1637 - (void) getAttributes : (WindowAttributes_t *) attr
1638 {
1639  if (!fContentView)
1640  return;
1641 
1642  assert(attr && "-getAttributes:, parameter 'attr' is nil");
1643 
1644  X11::GetWindowAttributes(self, attr);
1645 }
1646 
1647 //______________________________________________________________________________
1648 - (void) setAttributes : (const SetWindowAttributes_t *) attr
1649 {
1650  assert(attr != 0 && "-setAttributes:, parameter 'attr' is null");
1651 
1652 #ifdef DEBUG_ROOT_COCOA
1653  log_attributes(attr, self.fID);
1654 #endif
1655 
1656  X11::SetWindowAttributes(attr, self);
1657 }
1658 
1659 //______________________________________________________________________________
1660 - (void) mapRaised
1661 {
1662  if (!fContentView)
1663  return;
1664 
1665  const Util::AutoreleasePool pool;
1666 
1667  [fContentView setHidden : NO];
1668  [self makeKeyAndOrderFront : self];
1669  [fContentView configureNotifyTree];
1670 
1671  if (fDelayedTransient) {
1672  fDelayedTransient = NO;
1673  [fMainWindow addChildWindow : self ordered : NSWindowAbove];
1674  }
1675 }
1676 
1677 //______________________________________________________________________________
1678 - (void) mapWindow
1679 {
1680  if (!fContentView)
1681  return;
1682 
1683  const Util::AutoreleasePool pool;
1684 
1685  [fContentView setHidden : NO];
1686  [self makeKeyAndOrderFront : self];
1687  [fContentView configureNotifyTree];
1688 
1689  if (fDelayedTransient) {
1690  fDelayedTransient = NO;
1691  [fMainWindow addChildWindow : self ordered : NSWindowAbove];
1692  }
1693 }
1694 
1695 //______________________________________________________________________________
1696 - (void) mapSubwindows
1697 {
1698  if (!fContentView)
1699  return;
1700 
1701  const Util::AutoreleasePool pool;
1702 
1703  [fContentView mapSubwindows];
1704  [fContentView configureNotifyTree];
1705 }
1706 
1707 //______________________________________________________________________________
1708 - (void) unmapWindow
1709 {
1710  if (!fContentView)
1711  return;
1712 
1713  [fContentView setHidden : YES];
1714  [self orderOut : self];
1715 
1716  if (fMainWindow && !fDelayedTransient) {
1717  [fMainWindow removeChildWindow : self];
1718  fMainWindow = nil;
1719  }
1720 }
1721 
1722 #pragma mark - Events.
1723 
1724 //______________________________________________________________________________
1725 - (void) sendEvent : (NSEvent *) theEvent
1726 {
1727  //With XQuartz, if you open a menu and try to move a window without closing this menu,
1728  //window does not move, menu closes, and after that you can start draggin a window again.
1729  //With Cocoa I can not do such a thing (window WILL move), but still can report button release event
1730  //to close a menu.
1731  if (!fContentView)
1732  return;
1733 
1734  if (theEvent.type == Details::kLeftMouseDown || theEvent.type == Details::kRightMouseDown) {
1735  bool generateFakeRelease = false;
1736 
1737  const NSPoint windowPoint = [theEvent locationInWindow];
1738 
1739  if (windowPoint.x <= 4 || windowPoint.x >= self.fWidth - 4)
1740  generateFakeRelease = true;
1741 
1742  if (windowPoint.y <= 4 || windowPoint.y >= self.fHeight - 4)
1743  generateFakeRelease = true;
1744 
1745  const NSPoint viewPoint = [fContentView convertPoint : windowPoint fromView : nil];
1746 
1747  if (viewPoint.y <= 0 && windowPoint.y >= 0)
1748  generateFakeRelease = true;
1749 
1750  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1751  "-sendEvent:, gVirtualX is either null or not of TGCocoa type");
1752 
1753  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
1754  if (vx->GetEventTranslator()->HasPointerGrab() && generateFakeRelease) {
1756  theEvent.type == Details::kLeftMouseDown ?
1757  kButton1 : kButton3);
1758  //Yes, ignore this event completely (this means, you are not able to immediately start
1759  //resizing a window, if some popup is open. Actually, this is more or less
1760  //the same as with XQuartz and X11 version.
1761  return;
1762  }
1763  }
1764 
1765  [super sendEvent : theEvent];
1766 }
1767 
1768 #pragma mark - NSWindowDelegate's methods.
1769 
1770 //______________________________________________________________________________
1771 - (BOOL) windowShouldClose : (id) sender
1772 {
1773 #pragma unused(sender)
1774  if (!fContentView)
1775  return NO;
1776 
1777  if ([[self childWindows] count])
1778  return NO;
1779 
1780  //Prepare client message for a window.
1781  Event_t closeEvent = {};
1782  closeEvent.fWindow = fContentView.fID;
1783  closeEvent.fType = kClientMessage;
1784  closeEvent.fFormat = 32;//Taken from GUI classes.
1785  closeEvent.fHandle = TGCocoa::fgDeleteWindowAtom;
1786  closeEvent.fUser[0] = TGCocoa::fgDeleteWindowAtom;
1787  //Place it into the queue.
1788  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1789  "-windowShouldClose:, gVirtualX is either null or has a type different from TGCocoa");
1790  ((TGCocoa *)gVirtualX)->SendEvent(fContentView.fID, &closeEvent);
1791 
1792  //Do not let AppKit to close a window,
1793  //ROOT will do.
1794  return NO;
1795 }
1796 
1797 //______________________________________________________________________________
1798 - (void) windowDidBecomeKey : (NSNotification *) aNotification
1799 {
1800 #pragma unused(aNotification)
1801 
1802  if (!fContentView)
1803  return;
1804 
1806  fHasFocus = YES;
1807  //
1808  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1809  "-windowDidBecomeKey:, gVirtualX is null or not of TGCocoa type");
1810  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
1812  }
1813 }
1814 
1815 
1816 //______________________________________________________________________________
1817 - (void) windowDidResignKey : (NSNotification *) aNotification
1818 {
1819 #pragma unused(aNotification)
1820  fHasFocus = NO;
1821 }
1822 
1823 @end
1824 
1825 #pragma mark - Passive key grab info.
1826 
1827 @implementation PassiveKeyGrab
1828 
1829 //______________________________________________________________________________
1830 - (id) initWithKey : (unichar) keyCode modifiers : (NSUInteger) modifiers
1831 {
1832  if (self = [super init]) {
1833  fKeyCode = keyCode;
1834  fModifiers = modifiers;
1835  }
1836 
1837  return self;
1838 }
1839 
1840 //______________________________________________________________________________
1841 - (BOOL) matchKey : (unichar) keyCode modifiers : (NSUInteger) modifiers
1842 {
1843  return keyCode == fKeyCode && modifiers == fModifiers;
1844 }
1845 
1846 //______________________________________________________________________________
1847 - (BOOL) matchKey : (unichar) keyCode
1848 {
1849  return keyCode == fKeyCode;
1850 }
1851 
1852 //______________________________________________________________________________
1853 - (unichar) fKeyCode
1854 {
1855  return fKeyCode;
1856 }
1857 
1858 //______________________________________________________________________________
1859 - (NSUInteger) fModifiers
1860 {
1861  return fModifiers;
1862 }
1863 
1864 @end
1865 
1866 #pragma mark - X11 property emulation.
1867 
1869  NSData *fPropertyData;
1871  unsigned fFormat;
1872 }
1873 
1874 @property (nonatomic, readonly) Atom_t fType;
1875 
1876 @end
1877 
1878 @implementation QuartzWindowProperty
1879 
1880 @synthesize fType;
1881 
1882 //______________________________________________________________________________
1883 - (id) initWithData : (unsigned char *) data size : (unsigned) dataSize type : (Atom_t) type format : (unsigned) format
1884 {
1885  if (self = [super init]) {
1886  //Memory is zero-initialized, but just to make it explicit:
1887  fPropertyData = nil;
1888  fType = 0;
1889  fFormat = 0;
1890 
1891  [self resetPropertyData : data size : dataSize type : type format : format];
1892  }
1893 
1894  return self;
1895 }
1896 
1897 //______________________________________________________________________________
1898 - (void) dealloc
1899 {
1900  [fPropertyData release];
1901 
1902  [super dealloc];
1903 }
1904 
1905 //______________________________________________________________________________
1906 - (void) resetPropertyData : (unsigned char *) data size : (unsigned) dataSize
1907  type : (Atom_t) type format : (unsigned) format
1908 {
1909  [fPropertyData release];
1910 
1911  fFormat = format;
1912  if (format == 16)
1913  dataSize *= 2;
1914  else if (format == 32)
1915  dataSize *= 4;
1916 
1917  fPropertyData = [[NSData dataWithBytes : data length : dataSize] retain];
1918 
1919  fType = type;
1920 }
1921 
1922 //______________________________________________________________________________
1923 - (NSData *) fPropertyData
1924 {
1925  return fPropertyData;
1926 }
1927 
1928 //______________________________________________________________________________
1929 - (unsigned) fFormat
1930 {
1931  return fFormat;
1932 }
1933 
1934 @end
1935 
1936 #pragma mark - QuartzView.
1937 
1938 //
1939 //QuartzView is a children view (also is a content view for a top-level QuartzWindow).
1940 //
1941 
1942 @implementation QuartzView
1943 
1944 @synthesize fID;
1945 @synthesize fContext;
1946 /////////////////////
1947 //SetWindowAttributes_t/WindowAttributes_t
1948 @synthesize fEventMask;
1949 @synthesize fClass;
1950 @synthesize fDepth;
1951 @synthesize fBitGravity;
1952 @synthesize fWinGravity;
1953 @synthesize fBackgroundPixel;
1954 @synthesize fOverrideRedirect;
1955 //SetWindowAttributes_t/WindowAttributes_t
1956 /////////////////////
1957 @synthesize fHasFocus;
1958 @synthesize fParentView;
1959 
1960 @synthesize fPassiveGrabButton;
1961 @synthesize fPassiveGrabEventMask;
1962 @synthesize fPassiveGrabKeyModifiers;
1963 @synthesize fActiveGrabEventMask;
1964 @synthesize fPassiveGrabOwnerEvents;
1965 @synthesize fSnapshotDraw;
1966 @synthesize fCurrentCursor;
1967 @synthesize fIsDNDAware;
1968 
1969 #pragma mark - Lifetime.
1970 
1971 //______________________________________________________________________________
1972 - (id) initWithFrame : (NSRect) frame windowAttributes : (const SetWindowAttributes_t *)attr
1973 {
1974  if (self = [super initWithFrame : frame]) {
1975  //Make this explicit (though memory is zero initialized).
1976  fBackBuffer = nil;
1977  fID = 0;
1978 
1979  //Passive grab parameters.
1980  fPassiveGrabButton = -1;//0 is kAnyButton.
1983 
1984  fPassiveKeyGrabs = [[NSMutableArray alloc] init];
1985 
1986  [self setCanDrawConcurrently : NO];
1987 
1988  [self setHidden : YES];
1989  //Actually, check if view need this.
1990  //
1991  if (attr)
1992  X11::SetWindowAttributes(attr, self);
1993 
1995  fX11Properties = [[NSMutableDictionary alloc] init];
1996 
1999  fActiveGrabOwnerEvents = YES;
2000  }
2001 
2002  return self;
2003 }
2004 
2005 //______________________________________________________________________________
2006 - (void) dealloc
2007 {
2008  [fBackBuffer release];
2009  [fPassiveKeyGrabs release];
2010  [fX11Properties release];
2011  [fBackgroundPixmap release];
2012  [super dealloc];
2013 }
2014 
2015 #pragma mark - Tracking area.
2016 
2017 //Tracking area is required to ... track mouse motion events inside a view.
2018 
2019 //______________________________________________________________________________
2020 - (void) updateTrackingAreas
2021 {
2022  [super updateTrackingAreas];
2023 
2024  if (!fID)
2025  return;
2026 
2027  const Util::AutoreleasePool pool;
2028 
2029  if (NSArray *trackingArray = [self trackingAreas]) {
2030  const NSUInteger size = [trackingArray count];
2031  for (NSUInteger i = 0; i < size; ++i) {
2032  NSTrackingArea * const t = [trackingArray objectAtIndex : i];
2033  [self removeTrackingArea : t];
2034  }
2035  }
2036 
2037  const NSUInteger trackerOptions = NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited |
2038  NSTrackingActiveInActiveApp | NSTrackingInVisibleRect |
2039  NSTrackingEnabledDuringMouseDrag | NSTrackingCursorUpdate;
2040 
2041  NSRect frame = {};
2042  frame.size.width = self.fWidth;
2043  frame.size.height = self.fHeight;
2044 
2045  NSTrackingArea * const tracker = [[NSTrackingArea alloc] initWithRect : frame
2046  options : trackerOptions owner : self userInfo : nil];
2047  [self addTrackingArea : tracker];
2048  [tracker release];
2049 }
2050 
2051 //______________________________________________________________________________
2052 - (void) updateTrackingAreasAfterRaise
2053 {
2054  [self updateTrackingAreas];
2055 
2056  for (QuartzView *childView in [self subviews])
2057  [childView updateTrackingAreasAfterRaise];
2058 }
2059 
2060 #pragma mark - X11Drawable protocol.
2061 
2062 //______________________________________________________________________________
2063 - (BOOL) fIsPixmap
2064 {
2065  return NO;
2066 }
2067 
2068 //______________________________________________________________________________
2070 {
2071  return NO;
2072 }
2073 
2074 //______________________________________________________________________________
2075 - (CGFloat) fScaleFactor
2076 {
2077  return self.fQuartzWindow.fScaleFactor;
2078 }
2079 
2080 //______________________________________________________________________________
2081 - (int) fX
2082 {
2083  return self.frame.origin.x;
2084 }
2085 
2086 //______________________________________________________________________________
2087 - (int) fY
2088 {
2089  return self.frame.origin.y;
2090 }
2091 
2092 //______________________________________________________________________________
2093 - (unsigned) fWidth
2094 {
2095  return self.frame.size.width;
2096 }
2097 
2098 //______________________________________________________________________________
2099 - (unsigned) fHeight
2100 {
2101  return self.frame.size.height;
2102 }
2103 
2104 //______________________________________________________________________________
2105 - (void) setDrawableSize : (NSSize) newSize
2106 {
2107  assert(!(newSize.width < 0) && "-setDrawableSize, width is negative");
2108  assert(!(newSize.height < 0) && "-setDrawableSize, height is negative");
2109 
2110  //This will cause redraw(?)
2111 
2112  //In X11, resize changes the size, but upper-left corner is not changed.
2113  //In Cocoa, bottom-left is fixed.
2114  NSRect frame = self.frame;
2115  frame.size = newSize;
2116 
2117  self.frame = frame;
2118 }
2119 
2120 //______________________________________________________________________________
2121 - (void) setX : (int) x Y : (int) y width : (unsigned) w height : (unsigned) h
2122 {
2123  NSRect newFrame = {};
2124  newFrame.origin.x = x;
2125  newFrame.origin.y = y;
2126  newFrame.size.width = w;
2127  newFrame.size.height = h;
2128 
2129  self.frame = newFrame;
2130 }
2131 
2132 //______________________________________________________________________________
2133 - (void) setX : (int) x Y : (int) y
2134 {
2135  NSRect newFrame = self.frame;
2136  newFrame.origin.x = x;
2137  newFrame.origin.y = y;
2138 
2139  self.frame = newFrame;
2140 }
2141 
2142 //______________________________________________________________________________
2143 - (void) copyImage : (QuartzImage *) srcImage area : (X11::Rectangle) area
2144  withMask : (QuartzImage *) mask clipOrigin : (X11::Point) clipXY
2145  toPoint : (X11::Point) dstPoint
2146 {
2147  //Check parameters.
2148  assert(srcImage != nil &&
2149  "-copyImage:area:withMask:clipOrigin:toPoint:, parameter 'srcImage' is nil");
2150  assert(srcImage.fImage != nil &&
2151  "-copyImage:area:withMask:clipOrigin:toPoint:, srcImage.fImage is nil");
2152 
2153  //Check self.
2154  assert(self.fContext != 0 &&
2155  "-copyImage:area:withMask:clipOrigin:toPoint:, self.fContext is null");
2156 
2157  if (!X11::AdjustCropArea(srcImage, area)) {
2158  NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2159  " srcRect and copyRect do not intersect");
2160  return;
2161  }
2162 
2163  //No RAII for subImage, since it can be really subimage or image itself and
2164  //in these cases there is no need to release image.
2165  CGImageRef subImage = 0;
2166  bool needSubImage = false;
2167  if (area.fX || area.fY || area.fWidth != srcImage.fWidth || area.fHeight != srcImage.fHeight) {
2168  needSubImage = true;
2169  subImage = X11::CreateSubImage(srcImage, area);
2170  if (!subImage) {
2171  NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2172  " subimage creation failed");
2173  return;
2174  }
2175  } else
2176  subImage = srcImage.fImage;
2177 
2178  //Save context state.
2179  const Quartz::CGStateGuard ctxGuard(self.fContext);
2180 
2181  //Scale and translate to undo isFlipped.
2182  CGContextTranslateCTM(self.fContext, 0., self.fHeight);
2183  CGContextScaleCTM(self.fContext, 1., -1.);
2184  //Set clip mask on a context.
2185 
2186  if (mask) {
2187  assert(mask.fImage != nil &&
2188  "-copyImage:area:withMask:clipOrigin:toPoint:, mask.fImage is nil");
2189  assert(CGImageIsMask(mask.fImage) == true &&
2190  "-copyImage:area:withMask:clipOrigin:toPoint:, mask.fImage is not a mask");
2191  //clipXY.fY = X11::LocalYROOTToCocoa(self, clipXY.fY + mask.fHeight);
2192  const CGFloat clipY = X11::LocalYROOTToCocoa(self, CGFloat(clipXY.fY) + mask.fHeight);
2193  //const CGRect clipRect = CGRectMake(clipXY.fX, clipXY.fY, mask.fWidth, mask.fHeight);
2194  const CGRect clipRect = CGRectMake(clipXY.fX, clipY, mask.fWidth, mask.fHeight);
2195  CGContextClipToMask(self.fContext, clipRect, mask.fImage);
2196  }
2197 
2198  //Convert from X11 to Cocoa (as soon as we scaled y * -1).
2199  //dstPoint.fY = X11::LocalYROOTToCocoa(self, dstPoint.fY + area.fHeight);
2200  const CGFloat dstY = X11::LocalYROOTToCocoa(self, CGFloat(dstPoint.fY) + area.fHeight);
2201  //const CGRect imageRect = CGRectMake(dstPoint.fX, dstPoint.fY, area.fWidth, area.fHeight);
2202  const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2203  CGContextDrawImage(self.fContext, imageRect, subImage);
2204 
2205  if (needSubImage)
2206  CGImageRelease(subImage);
2207 }
2208 
2209 //______________________________________________________________________________
2210 - (void) copyView : (QuartzView *) srcView area : (X11::Rectangle) area toPoint : (X11::Point) dstPoint
2211 {
2212  //To copy one "window" to another "window", I have to ask source QuartzView to draw intself into
2213  //bitmap, and copy this bitmap into the destination view.
2214 
2215  assert(srcView != nil && "-copyView:area:toPoint:, parameter 'srcView' is nil");
2216 
2217  const NSRect frame = [srcView frame];
2218  //imageRep is in autorelease pool now.
2219  NSBitmapImageRep * const imageRep = [srcView bitmapImageRepForCachingDisplayInRect : frame];
2220  if (!imageRep) {
2221  NSLog(@"QuartzView: -copyView:area:toPoint failed");
2222  return;
2223  }
2224 
2225  assert(srcView != nil && "-copyView:area:toPoint:, parameter 'srcView' is nil");
2226  assert(self.fContext != 0 && "-copyView:area:toPoint, self.fContext is null");
2227 
2228  //It can happen, that src and self are the same.
2229  //cacheDisplayInRect calls drawRect with bitmap context
2230  //(and this will reset self.fContext: I have to save/restore it.
2231  CGContextRef ctx = srcView.fContext;
2232  srcView.fSnapshotDraw = YES;
2233  [srcView cacheDisplayInRect : frame toBitmapImageRep : imageRep];
2234  srcView.fSnapshotDraw = NO;
2235  srcView.fContext = ctx;
2236 
2237  const CGRect subImageRect = CGRectMake(area.fX, area.fY, area.fWidth, area.fHeight);
2238  const Util::CFScopeGuard<CGImageRef> subImage(CGImageCreateWithImageInRect(imageRep.CGImage, subImageRect));
2239 
2240  if (!subImage.Get()) {
2241  NSLog(@"QuartzView: -copyView:area:toPoint, CGImageCreateWithImageInRect failed");
2242  return;
2243  }
2244 
2245  const Quartz::CGStateGuard ctxGuard(self.fContext);
2246  const CGRect imageRect = CGRectMake(dstPoint.fX,
2247  [self visibleRect].size.height - (CGFloat(dstPoint.fY) + area.fHeight),
2248  area.fWidth, area.fHeight);
2249 
2250  CGContextTranslateCTM(self.fContext, 0., [self visibleRect].size.height);
2251  CGContextScaleCTM(self.fContext, 1., -1.);
2252 
2253  CGContextDrawImage(self.fContext, imageRect, subImage.Get());
2254 }
2255 
2256 //______________________________________________________________________________
2257 - (void) copyPixmap : (QuartzPixmap *) srcPixmap area : (X11::Rectangle) area
2258  withMask : (QuartzImage *) mask clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
2259 {
2260  //Check parameters.
2261  assert(srcPixmap != nil && "-copyPixmap:area:withMask:clipOrigin:toPoint:, parameter 'srcPixmap' is nil");
2262 
2263  if (!X11::AdjustCropArea(srcPixmap, area)) {
2264  NSLog(@"QuartzView: -copyPixmap:area:withMask:clipOrigin:toPoint,"
2265  " no intersection between pixmap rectangle and cropArea");
2266  return;
2267  }
2268 
2269  //Check self.
2270  assert(self.fContext != 0 &&
2271  "-copyPixmap:area:withMask:clipOrigin:toPoint:, self.fContext is null");
2272 
2273  //Save context state.
2274  const Quartz::CGStateGuard ctxGuard(self.fContext);
2275 
2276  CGContextTranslateCTM(self.fContext, 0., self.frame.size.height);//???
2277  CGContextScaleCTM(self.fContext, 1., -1.);
2278 
2279  const Util::CFScopeGuard<CGImageRef> imageFromPixmap([srcPixmap createImageFromPixmap]);
2280  assert(imageFromPixmap.Get() != 0 &&
2281  "-copyPixmap:area:withMask:clipOrigin:toPoint:, createImageFromPixmap failed");
2282 
2283  CGImageRef subImage = 0;
2284  bool needSubImage = false;
2285  if (area.fX || area.fY || area.fWidth != srcPixmap.fWidth || area.fHeight != srcPixmap.fHeight) {
2286  needSubImage = true;
2287  const CGRect subImageRect = CGRectMake(area.fX, area.fY, area.fHeight, area.fWidth);
2288  subImage = CGImageCreateWithImageInRect(imageFromPixmap.Get(), subImageRect);
2289  if (!subImage) {
2290  NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2291  " subimage creation failed");
2292  return;
2293  }
2294  } else
2295  subImage = imageFromPixmap.Get();
2296 
2297  if (mask) {
2298  assert(mask.fImage != nil &&
2299  "-copyPixmap:area:withMask:clipOrigin:toPoint:, mask.fImage is nil");
2300  assert(CGImageIsMask(mask.fImage) == true &&
2301  "-copyPixmap:area:withMask:clipOrigin:toPoint:, mask.fImage is not a mask");
2302 
2303  //clipXY.fY = X11::LocalYROOTToCocoa(self, clipXY.fY + mask.fHeight);
2304  const CGFloat clipY = X11::LocalYROOTToCocoa(self, CGFloat(clipXY.fY) + mask.fHeight);
2305  //const CGRect clipRect = CGRectMake(clipXY.fX, clipXY.fY, mask.fWidth, mask.fHeight);
2306  const CGRect clipRect = CGRectMake(clipXY.fX, clipY, mask.fWidth, mask.fHeight);
2307  CGContextClipToMask(self.fContext, clipRect, mask.fImage);
2308  }
2309 
2310  //dstPoint.fY = X11::LocalYCocoaToROOT(self, dstPoint.fY + area.fHeight);
2311  const CGFloat dstY = X11::LocalYCocoaToROOT(self, CGFloat(dstPoint.fY) + area.fHeight);
2312  const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2313  CGContextDrawImage(self.fContext, imageRect, imageFromPixmap.Get());
2314 
2315  if (needSubImage)
2316  CGImageRelease(subImage);
2317 }
2318 
2319 
2320 //______________________________________________________________________________
2321 - (void) copyImage : (QuartzImage *) srcImage area : (X11::Rectangle) area
2322  toPoint : (X11::Point) dstPoint
2323 {
2324  assert(srcImage != nil && "-copyImage:area:toPoint:, parameter 'srcImage' is nil");
2325  assert(srcImage.fImage != nil && "-copyImage:area:toPoint:, srcImage.fImage is nil");
2326  assert(self.fContext != 0 && "-copyImage:area:toPoint:, fContext is null");
2327 
2328  if (!X11::AdjustCropArea(srcImage, area)) {
2329  NSLog(@"QuartzView: -copyImage:area:toPoint, image and copy area do not intersect");
2330  return;
2331  }
2332 
2333  CGImageRef subImage = 0;
2334  bool needSubImage = false;
2335  if (area.fX || area.fY || area.fWidth != srcImage.fWidth || area.fHeight != srcImage.fHeight) {
2336  needSubImage = true;
2337  subImage = X11::CreateSubImage(srcImage, area);
2338  if (!subImage) {
2339  NSLog(@"QuartzView: -copyImage:area:toPoint:, subimage creation failed");
2340  return;
2341  }
2342  } else
2343  subImage = srcImage.fImage;
2344 
2345  const Quartz::CGStateGuard ctxGuard(self.fContext);
2346 
2347  CGContextTranslateCTM(self.fContext, 0., self.fHeight);
2348  CGContextScaleCTM(self.fContext, 1., -1.);
2349 
2350  //dstPoint.fY = X11::LocalYCocoaToROOT(self, dstPoint.fY + area.fHeight);
2351  const CGFloat dstY = X11::LocalYCocoaToROOT(self, CGFloat(dstPoint.fY) + area.fHeight);
2352  //const CGRect imageRect = CGRectMake(dstPoint.fX, dstPoint.fY, area.fWidth, area.fHeight);
2353  const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2354  CGContextDrawImage(self.fContext, imageRect, subImage);
2355 
2356  if (needSubImage)
2357  CGImageRelease(subImage);
2358 }
2359 
2360 //______________________________________________________________________________
2361 - (void) copy : (NSObject<X11Drawable> *) src area : (X11::Rectangle) area
2362  withMask : (QuartzImage *)mask clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
2363 {
2364  assert(src != nil && "-copy:area:withMask:clipOrigin:toPoint:, parameter 'src' is nil");
2365  assert(area.fWidth && area.fHeight && "-copy:area:withMask:clipOrigin:toPoint:, area to copy is empty");
2366 
2367  if ([src isKindOfClass : [QuartzWindow class]]) {
2368  //Forget about mask (can I have it???)
2369  QuartzWindow * const qw = (QuartzWindow *)src;
2370  //Will not work with OpenGL.
2371  [self copyView : (QuartzView *)qw.fContentView area : area toPoint : dstPoint];
2372  } else if ([src isKindOfClass : [QuartzView class]]) {
2373  //Forget about mask (can I have it???)
2374  [self copyView : (QuartzView *)src area : area toPoint : dstPoint];
2375  } else if ([src isKindOfClass : [QuartzPixmap class]]) {
2376  [self copyPixmap : (QuartzPixmap *)src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
2377  } else if ([src isKindOfClass : [QuartzImage class]]) {
2378  [self copyImage : (QuartzImage *)src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
2379  } else {
2380  assert(0 && "-copy:area:withMask:clipOrigin:toPoint:, src is of unknown type");
2381  }
2382 }
2383 
2384 //______________________________________________________________________________
2385 - (unsigned char *) readColorBits : (X11::Rectangle) area
2386 {
2387  //This is quite a bad idea - to read pixels back from a view,
2388  //but our GUI does exactly this. In case of Cocoa it's expensive
2389  //and not guaranteed to work.
2390 
2391  assert(area.fWidth && area.fHeight && "-readColorBits:, area to copy is empty");
2392 
2393  //int, not unsigned or something - to keep it simple.
2394  const NSRect visRect = [self visibleRect];
2395  const X11::Rectangle srcRect(int(visRect.origin.x), int(visRect.origin.y),
2396  unsigned(visRect.size.width), unsigned(visRect.size.height));
2397 
2398  if (!X11::AdjustCropArea(srcRect, area)) {
2399  NSLog(@"QuartzView: -readColorBits:, visible rect of view and copy area do not intersect");
2400  return nullptr;
2401  }
2402 
2403  //imageRep is autoreleased.
2404  NSBitmapImageRep * const imageRep = [self bitmapImageRepForCachingDisplayInRect : visRect];
2405  if (!imageRep) {
2406  NSLog(@"QuartzView: -readColorBits:, bitmapImageRepForCachingDisplayInRect failed");
2407  return nullptr;
2408  }
2409 
2410  CGContextRef ctx = self.fContext; //Save old context if any.
2411  [self cacheDisplayInRect : visRect toBitmapImageRep : imageRep];
2412  self.fContext = ctx; //Restore old context.
2413  //
2414  const NSInteger bitsPerPixel = [imageRep bitsPerPixel];
2415 
2416  assert(bitsPerPixel == 32 && "-readColorBits:, no alpha channel???");
2417  const NSInteger bytesPerRow = [imageRep bytesPerRow];
2418  unsigned dataWidth = bytesPerRow / (bitsPerPixel / 8);//assume an octet :(
2419 
2420  unsigned char *srcData = nullptr;
2421  std::vector<unsigned char> downscaled;
2422  if ([self.window.screen backingScaleFactor] > 1 && imageRep.CGImage) {
2423  downscaled = X11::DownscaledImageData(area.fWidth, area.fHeight, imageRep.CGImage);
2424  if (downscaled.size())
2425  srcData = &downscaled[0];
2426  dataWidth = area.fWidth;
2427  } else
2428  srcData = [imageRep bitmapData];
2429 
2430  if (!srcData) {
2431  NSLog(@"QuartzView: -readColorBits:, failed to obtain backing store contents");
2432  return nullptr;
2433  }
2434 
2435  //We have a source data now. Let's allocate buffer for ROOT's GUI and convert source data.
2436  unsigned char *data = nullptr;
2437 
2438  try {
2439  data = new unsigned char[area.fWidth * area.fHeight * 4];//bgra?
2440  } catch (const std::bad_alloc &) {
2441  NSLog(@"QuartzView: -readColorBits:, memory allocation failed");
2442  return nullptr;
2443  }
2444 
2445  unsigned char *dstPixel = data;
2446  const unsigned char *line = srcData + area.fY * dataWidth * 4;
2447  const unsigned char *srcPixel = line + area.fX * 4;
2448 
2449  for (unsigned i = 0; i < area.fHeight; ++i) {
2450  for (unsigned j = 0; j < area.fWidth; ++j, srcPixel += 4, dstPixel += 4) {
2451  dstPixel[0] = srcPixel[2];
2452  dstPixel[1] = srcPixel[1];
2453  dstPixel[2] = srcPixel[0];
2454  dstPixel[3] = srcPixel[3];
2455  }
2456 
2457  line += dataWidth * 4;
2458  srcPixel = line + area.fX * 4;
2459  }
2460 
2461  return data;
2462 }
2463 
2464 //______________________________________________________________________________
2465 - (void) setFBackgroundPixmap : (QuartzImage *) pixmap
2466 {
2467  if (fBackgroundPixmap != pixmap) {
2468  [fBackgroundPixmap release];
2469  if (pixmap)
2470  fBackgroundPixmap = [pixmap retain];
2471  else
2472  fBackgroundPixmap = nil;
2473  }
2474 }
2475 
2476 //______________________________________________________________________________
2478 {
2479  //I do not autorelease, screw this idiom!
2480 
2481  return fBackgroundPixmap;
2482 }
2483 
2484 //______________________________________________________________________________
2485 - (int) fMapState
2486 {
2487  if ([self isHidden])
2488  return kIsUnmapped;
2489 
2490  for (QuartzView *parent = fParentView; parent; parent = parent.fParentView) {
2491  if ([parent isHidden])
2492  return kIsUnviewable;
2493  }
2494 
2495  return kIsViewable;
2496 }
2497 
2498 //______________________________________________________________________________
2499 - (BOOL) fHasFocus
2500 {
2501  //With the latest update clang became a bit more stupid.
2502  //Let's write a stupid useless cargo cult code
2503  //to make IT SHUT THE F... UP.
2504  (void)fHasFocus;
2505  return NO;
2506 }
2507 
2508 //______________________________________________________________________________
2509 - (void) setFHasFocus : (BOOL) focus
2510 {
2511 #pragma unused(focus)
2512  //With the latest update clang became a bit more stupid.
2513  //Let's write a stupid useless cargo cult code
2514  //to make IT SHUT THE F... UP.
2515  (void)fHasFocus;
2516 }
2517 
2518 //______________________________________________________________________________
2520 {
2521  return fBackBuffer;//No autorelease, I know the object's lifetime myself.
2522 }
2523 
2524 //______________________________________________________________________________
2525 - (void) setFBackBuffer : (QuartzPixmap *) backBuffer
2526 {
2527  if (fBackBuffer != backBuffer) {
2528  [fBackBuffer release];
2529 
2530  if (backBuffer)
2531  fBackBuffer = [backBuffer retain];
2532  else
2533  fBackBuffer = nil;
2534  }
2535 }
2536 
2537 //______________________________________________________________________________
2539 {
2540  return self;
2541 }
2542 
2543 //______________________________________________________________________________
2545 {
2546  return (QuartzWindow *)[self window];
2547 }
2548 
2549 //______________________________________________________________________________
2551 {
2553 }
2554 
2555 //______________________________________________________________________________
2557 {
2559 }
2560 
2561 //______________________________________________________________________________
2562 - (void) activateGrab : (unsigned) eventMask ownerEvents : (BOOL) ownerEvents
2563 {
2565  fActiveGrabEventMask = eventMask;
2566  fActiveGrabOwnerEvents = ownerEvents;
2567 }
2568 
2569 //______________________________________________________________________________
2570 - (void) cancelGrab
2571 {
2574  fActiveGrabOwnerEvents = YES;
2575 }
2576 
2577 //______________________________________________________________________________
2578 - (BOOL) acceptsCrossingEvents : (unsigned) eventMask
2579 {
2580  bool accepts = fEventMask & eventMask;
2581 
2582  //In ROOT passive grabs are always with owner_events == true.
2584  accepts = accepts || (fPassiveGrabEventMask & eventMask);
2585 
2588  accepts = accepts || (fActiveGrabOwnerEvents & eventMask);
2589  else
2590  accepts = fActiveGrabOwnerEvents & eventMask;
2591  }
2592 
2593  return accepts;
2594 }
2595 
2596 //______________________________________________________________________________
2597 - (void) addChild : (NSView<X11Window> *) child
2598 {
2599  assert(child != nil && "-addChild:, parameter 'child' is nil");
2600 
2601  [self addSubview : child];
2602  child.fParentView = self;
2603 }
2604 
2605 //______________________________________________________________________________
2606 - (void) getAttributes : (WindowAttributes_t *) attr
2607 {
2608  assert(attr != 0 && "-getAttributes:, parameter 'attr' is null");
2609 
2610  X11::GetWindowAttributes(self, attr);
2611 }
2612 
2613 //______________________________________________________________________________
2614 - (void) setAttributes : (const SetWindowAttributes_t *)attr
2615 {
2616  assert(attr != 0 && "-setAttributes:, parameter 'attr' is null");
2617 
2618 #ifdef DEBUG_ROOT_COCOA
2619  log_attributes(attr, fID);
2620 #endif
2621 
2622  X11::SetWindowAttributes(attr, self);
2623 }
2624 
2625 //______________________________________________________________________________
2626 - (void) mapRaised
2627 {
2628  //Move view to the top of subviews.
2629  QuartzView * const parent = fParentView;
2630  [self removeFromSuperview];
2631  [parent addSubview : self];
2632  [self setHidden : NO];
2633 }
2634 
2635 //______________________________________________________________________________
2636 - (void) mapWindow
2637 {
2638  [self setHidden : NO];
2639 }
2640 
2641 //______________________________________________________________________________
2642 - (void) mapSubwindows
2643 {
2644  for (QuartzView * v in [self subviews])
2645  [v setHidden : NO];
2646 }
2647 
2648 //______________________________________________________________________________
2649 - (void) unmapWindow
2650 {
2651  [self setHidden : YES];
2652 }
2653 
2654 //______________________________________________________________________________
2655 - (BOOL) fIsOverlapped
2656 {
2657  return fIsOverlapped;
2658 }
2659 
2660 //______________________________________________________________________________
2661 - (void) setOverlapped : (BOOL) overlap
2662 {
2663  fIsOverlapped = overlap;
2664  for (NSView<X11Window> *child in [self subviews])
2665  [child setOverlapped : overlap];
2666 }
2667 
2668 //______________________________________________________________________________
2669 - (void) raiseWindow
2670 {
2671  //Now, I can not remove window and add it ...
2672  //For example, if you click on a tab, this:
2673  //1. Creates (potentially) a passive button grab
2674  //2. Raises this tab - changes the window order.
2675  //3. On a button release - grab is release.
2676  //The tough problem is, if I remove a view from subviews
2677  //and add it ... it will never receve the
2678  //release event thus a grab will 'hang' on
2679  //view leading to bugs and artifacts.
2680  //So instead I have to ... SORT!!!!!
2681 
2682  using namespace X11;//Comparators.
2683 
2684  for (QuartzView *sibling in [fParentView subviews]) {
2685  if (self == sibling)
2686  continue;
2687  if ([sibling isHidden])
2688  continue;
2689 
2690  if (NSEqualRects(sibling.frame, self.frame)) {
2691  [sibling setOverlapped : YES];
2692  [sibling setHidden : YES];
2693  }
2694  }
2695 
2696  [self setOverlapped : NO];
2697  //
2698  [self setHidden : NO];
2699  //
2700  [fParentView sortSubviewsUsingFunction : CompareViewsToRaise context : (void *)self];
2701  //
2702  [self updateTrackingAreasAfterRaise];
2703  //
2704  [self setNeedsDisplay : YES];
2705 }
2706 
2707 //______________________________________________________________________________
2708 - (void) lowerWindow
2709 {
2710  //See comment about sorting in -raiseWindow.
2711 
2712  using namespace X11;
2713 
2714  NSEnumerator * const reverseEnumerator = [[fParentView subviews] reverseObjectEnumerator];
2715  for (QuartzView *sibling in reverseEnumerator) {
2716  if (sibling == self)
2717  continue;
2718 
2719  if (NSEqualRects(sibling.frame, self.frame)) {
2720  [sibling setOverlapped : NO];
2721  //
2722  [sibling setHidden : NO];
2723  //
2724  [sibling setNeedsDisplay : YES];
2725  [self setOverlapped : YES];
2726  //
2727  [self setHidden : YES];
2728  //
2729  break;
2730  }
2731  }
2732 
2733  [fParentView sortSubviewsUsingFunction : CompareViewsToLower context : (void*)self];
2734 }
2735 
2736 //______________________________________________________________________________
2737 - (BOOL) isFlipped
2738 {
2739  //Now view's placement, geometry, moving and resizing can be
2740  //done with ROOT's (X11) coordinates without conversion - we're are 'flipped'.
2741  return YES;
2742 }
2743 
2744 //______________________________________________________________________________
2746 {
2747  if (self.fMapState == kIsViewable || fIsOverlapped == YES) {
2749  assert(dynamic_cast<TGCocoa *>(gVirtualX) &&
2750  "-configureNotifyTree, gVirtualX is either null or has type different from TGCocoa");
2751  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
2752  vx->GetEventTranslator()->GenerateConfigureNotifyEvent(self, self.frame);
2753  }
2754 
2755  for (NSView<X11Window> *v in [self subviews])
2756  [v configureNotifyTree];
2757  }
2758 }
2759 
2760 #pragma mark - Key grabs.
2761 
2762 //______________________________________________________________________________
2763 - (void) addPassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2764 {
2765  [self removePassiveKeyGrab : keyCode modifiers : modifiers];
2766  PassiveKeyGrab * const newGrab = [[PassiveKeyGrab alloc] initWithKey : keyCode
2767  modifiers : modifiers];
2768  [fPassiveKeyGrabs addObject : newGrab];
2769  [newGrab release];
2770 }
2771 
2772 //______________________________________________________________________________
2773 - (void) removePassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2774 {
2775  const NSUInteger count = [fPassiveKeyGrabs count];
2776  for (NSUInteger i = 0; i < count; ++i) {
2777  PassiveKeyGrab *grab = [fPassiveKeyGrabs objectAtIndex : i];
2778  if ([grab matchKey : keyCode modifiers : modifiers]) {
2779  [fPassiveKeyGrabs removeObjectAtIndex : i];
2780  break;
2781  }
2782  }
2783 }
2784 
2785 //______________________________________________________________________________
2786 - (PassiveKeyGrab *) findPassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2787 {
2788  NSEnumerator * const enumerator = [fPassiveKeyGrabs objectEnumerator];
2789  while (PassiveKeyGrab *grab = (PassiveKeyGrab *)[enumerator nextObject]) {
2790  if ([grab matchKey : keyCode modifiers : modifiers])
2791  return grab;
2792  }
2793 
2794  return nil;
2795 }
2796 
2797 //______________________________________________________________________________
2798 - (PassiveKeyGrab *) findPassiveKeyGrab : (unichar) keyCode
2799 {
2800  //Do not check modifiers.
2801  NSEnumerator * const enumerator = [fPassiveKeyGrabs objectEnumerator];
2802  while (PassiveKeyGrab *grab = (PassiveKeyGrab *)[enumerator nextObject]) {
2803  if ([grab matchKey : keyCode])
2804  return grab;
2805  }
2806 
2807  return nil;
2808 }
2809 
2810 #pragma mark - Painting mechanics.
2811 
2812 //______________________________________________________________________________
2813 - (void) drawRect : (NSRect) dirtyRect
2814 {
2815 #pragma unused(dirtyRect)
2816 
2817  using namespace X11;
2818 
2819  if (fID) {
2820  if (TGWindow * const window = gClient->GetWindowById(fID)) {
2821  //It's never painted, parent renders child. true == check the parent also.
2822  if (ViewIsTextViewFrame(self, true) ||ViewIsHtmlViewFrame(self, true))
2823  return;
2824 
2825  NSGraphicsContext * const nsContext = [NSGraphicsContext currentContext];
2826  assert(nsContext != nil && "-drawRect:, currentContext returned nil");
2827 
2828  TGCocoa * const vx = (TGCocoa *)gVirtualX;
2829  vx->CocoaDrawON();
2830 
2831  fContext = (CGContextRef)[nsContext graphicsPort];
2832  assert(fContext != 0 && "-drawRect:, graphicsPort returned null");
2833 
2834  const Quartz::CGStateGuard ctxGuard(fContext);
2835 
2836  //Non-rectangular windows.
2839 
2840  // This code used to use TObject::InheritsFrom, however since this is
2841  // run under the AppKit, we can not call core/meta functions, otherwise
2842  // we will run into deadlocks.
2843  if (dynamic_cast<const TGContainer*>(window))//It always has an ExposureMask.
2844  vx->GetEventTranslator()->GenerateExposeEvent(self, [self visibleRect]);
2845 
2846  if (fEventMask & kExposureMask) {
2847  if (ViewIsTextView(self)) {
2848  //Send Expose event, using child view (this is how it's done in GUI :( ).
2849  [NSColor.whiteColor setFill];
2850  NSRectFill(dirtyRect);
2851  NSView<X11Window> * const viewFrame = FrameForTextView(self);
2852  if (viewFrame)//Now we set fExposedRegion for TGView.
2853  vx->GetEventTranslator()->GenerateExposeEvent(viewFrame, viewFrame.visibleRect);
2854  }
2855 
2856  if (ViewIsHtmlView(self)) {
2857  NSView<X11Window> *const viewFrame = FrameForHtmlView(self);
2858  if (viewFrame)
2859  vx->GetEventTranslator()->GenerateExposeEvent(viewFrame, viewFrame.visibleRect);
2860  }
2861 
2862  //Ask ROOT's widget/window to draw itself.
2863  gClient->NeedRedraw(window, kTRUE);
2864 
2865  if (!fSnapshotDraw) {
2866  //If Cocoa repaints widget, cancel all ROOT's "outside of paint event"
2867  //rendering into this widget.
2868  gClient->CancelRedraw(window);
2870  }
2871  }
2872 
2873  if (fBackBuffer) {
2874  //Very "special" window.
2875  const X11::Rectangle copyArea(0, 0, fBackBuffer.fWidth, fBackBuffer.fHeight);
2876  [self copy : fBackBuffer area : copyArea withMask : nil
2877  clipOrigin : X11::Point() toPoint : X11::Point()];
2878  }
2879 
2880  vx->CocoaDrawOFF();
2881 #ifdef DEBUG_ROOT_COCOA
2882  CGContextSetRGBStrokeColor(fContext, 1., 0., 0., 1.);
2883  CGContextStrokeRect(fContext, dirtyRect);
2884 #endif
2885 
2886  fContext = 0;
2887  } else {
2888 #ifdef DEBUG_ROOT_COCOA
2889  NSLog(@"QuartzView: -drawRect: method, no window for id %u was found", fID);
2890 #endif
2891  }
2892  }
2893 }
2894 
2895 #pragma mark - Geometry.
2896 
2897 //______________________________________________________________________________
2898 - (void) setFrame : (NSRect) newFrame
2899 {
2900  //In case of TBrowser, setFrame started infinite recursion:
2901  //HandleConfigure for embedded main frame emits signal, slot
2902  //calls layout, layout calls setFrame -> HandleConfigure and etc. etc.
2903  if (NSEqualRects(newFrame, self.frame))
2904  return;
2905 
2906  [super setFrame : newFrame];
2907 }
2908 
2909 //______________________________________________________________________________
2910 - (void) setFrameSize : (NSSize) newSize
2911 {
2912  //Check, if setFrameSize calls setFrame.
2913 
2914  [super setFrameSize : newSize];
2915 
2916  if ((fEventMask & kStructureNotifyMask) && (self.fMapState == kIsViewable || fIsOverlapped == YES)) {
2917  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
2918  "setFrameSize:, gVirtualX is either null or has a type, different from TGCocoa");
2919  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
2920  vx->GetEventTranslator()->GenerateConfigureNotifyEvent(self, self.frame);
2921  }
2922 
2923  [self setNeedsDisplay : YES];//?
2924 }
2925 
2926 #pragma mark - Event handling.
2927 
2928 //______________________________________________________________________________
2929 - (void) mouseDown : (NSEvent *) theEvent
2930 {
2931  assert(fID != 0 && "-mouseDown:, fID is 0");
2932 
2933  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
2934  "-mouseDown:, gVirtualX is either null or has a type, different from TGCocoa");
2935  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
2936  vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton1);
2937 }
2938 
2939 //______________________________________________________________________________
2940 - (void) scrollWheel : (NSEvent*) theEvent
2941 {
2942  assert(fID != 0 && "-scrollWheel:, fID is 0");
2943 
2944 
2945  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
2946  "-scrollWheel:, gVirtualX is either null or has a type, different from TGCocoa");
2947 
2948  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
2949  const CGFloat deltaY = [theEvent deltaY];
2950  if (deltaY < 0) {
2951  vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton5);
2952  vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton5);
2953  } else if (deltaY > 0) {
2954  vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton4);
2955  vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton4);
2956  }
2957 }
2958 
2959 #ifdef DEBUG_ROOT_COCOA
2960 //______________________________________________________________________________
2961 - (void) printViewInformation
2962 {
2963  assert(fID != 0 && "-printWindowInformation, fID is 0");
2964  const TGWindow * const window = gClient->GetWindowById(fID);
2965  assert(window != 0 && "printWindowInformation, window not found");
2966 
2967  NSLog(@"-----------------View %u info:---------------------", fID);
2968  NSLog(@"ROOT's window class is %s", window->IsA()->GetName());
2969  NSLog(@"event mask is:");
2970  print_mask_info(fEventMask);
2971  NSLog(@"grab mask is:");
2972  print_mask_info(fPassiveGrabEventMask);
2973  NSLog(@"view's geometry: x == %g, y == %g, w == %g, h == %g", self.frame.origin.x,
2974  self.frame.origin.y, self.frame.size.width, self.frame.size.height);
2975  NSLog(@"----------------End of view info------------------");
2976 }
2977 #endif
2978 
2979 //______________________________________________________________________________
2980 - (void) rightMouseDown : (NSEvent *) theEvent
2981 {
2982  assert(fID != 0 && "-rightMouseDown:, fID is 0");
2983 
2984 #ifdef DEBUG_ROOT_COCOA
2985  [self printViewInformation];
2986 #endif
2987 
2988  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
2989  "-rightMouseDown:, gVirtualX is either null or has type different from TGCocoa");
2990  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
2991  vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton3);
2992 }
2993 
2994 //______________________________________________________________________________
2995 - (void) otherMouseDown : (NSEvent *) theEvent
2996 {
2997  assert(fID != 0 && "-otherMouseDown:, fID is 0");
2998 
2999  //Funny enough, [theEvent buttonNumber] is not the same thing as button masked in [NSEvent pressedMouseButtons],
3000  //button number actually is a kind of right operand for bitshift for pressedMouseButtons.
3001  if ([theEvent buttonNumber] == 2) {//this '2' will correspond to '4' in pressedMouseButtons.
3002  //I do not care about mouse buttons after left/right/wheel - ROOT does not have
3003  //any code for this.
3004  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3005  "-otherMouseDown:, gVirtualX is either null or has type different from TGCocoa");
3006  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3007  vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton2);
3008  }
3009 }
3010 
3011 //______________________________________________________________________________
3012 - (void) mouseUp : (NSEvent *) theEvent
3013 {
3014  assert(fID != 0 && "-mouseUp:, fID is 0");
3015 
3016  assert(dynamic_cast<TGCocoa *>(gVirtualX) &&
3017  "-mouseUp:, gVirtualX is either null or has type different from TGCocoa");
3018  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3019  vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton1);
3020 }
3021 
3022 //______________________________________________________________________________
3023 - (void) rightMouseUp : (NSEvent *) theEvent
3024 {
3025 
3026  assert(fID != 0 && "-rightMouseUp:, fID is 0");
3027 
3028  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3029  "-rightMouseUp:, gVirtualX is either null or has type different from TGCocoa");
3030 
3031  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3032  vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton3);
3033 }
3034 
3035 //______________________________________________________________________________
3036 - (void) otherMouseUp : (NSEvent *) theEvent
3037 {
3038  assert(fID != 0 && "-otherMouseUp:, fID is 0");
3039 
3040  //Here I assume it's always kButton2.
3041  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3042  "-otherMouseUp:, gVirtualX is either null or has type different from TGCocoa");
3043  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3044  vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton2);
3045 }
3046 
3047 //______________________________________________________________________________
3048 - (void) mouseEntered : (NSEvent *) theEvent
3049 {
3050  assert(fID != 0 && "-mouseEntered:, fID is 0");
3051  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3052  "-mouseEntered:, gVirtualX is null or not of TGCocoa type");
3053 
3054  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3055  vx->GetEventTranslator()->GenerateCrossingEvent(theEvent);
3056 }
3057 
3058 //______________________________________________________________________________
3059 - (void) mouseExited : (NSEvent *) theEvent
3060 {
3061  assert(fID != 0 && "-mouseExited:, fID is 0");
3062 
3063  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3064  "-mouseExited:, gVirtualX is null or not of TGCocoa type");
3065 
3066  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3067  vx->GetEventTranslator()->GenerateCrossingEvent(theEvent);
3068 }
3069 
3070 //______________________________________________________________________________
3071 - (void) mouseMoved : (NSEvent *) theEvent
3072 {
3073  assert(fID != 0 && "-mouseMoved:, fID is 0");
3074 
3075  if (fParentView)//Suppress events in all views, except the top-level one.
3076  return;
3077 
3078  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3079  "-mouseMoved:, gVirtualX is null or not of TGCocoa type");
3080 
3081  TGCocoa *vx = static_cast<TGCocoa *>(gVirtualX);
3083 }
3084 
3085 //______________________________________________________________________________
3086 - (void) mouseDragged : (NSEvent *) theEvent
3087 {
3088  assert(fID != 0 && "-mouseDragged:, fID is 0");
3089 
3090  TGCocoa * const vx = dynamic_cast<TGCocoa *>(gVirtualX);
3091  assert(vx != 0 && "-mouseDragged:, gVirtualX is null or not of TGCocoa type");
3092 
3094 }
3095 
3096 //______________________________________________________________________________
3097 - (void) rightMouseDragged : (NSEvent *) theEvent
3098 {
3099  assert(fID != 0 && "-rightMouseDragged:, fID is 0");
3100 
3101  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3102  "-rightMouseDragged:, gVirtualX is null or not of TGCocoa type");
3103 
3104  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3106 }
3107 
3108 //______________________________________________________________________________
3109 - (void) otherMouseDragged : (NSEvent *) theEvent
3110 {
3111  assert(fID != 0 && "-otherMouseDragged:, fID is 0");
3112 
3113  if ([theEvent buttonNumber] == 2) {
3114  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3115  "-otherMouseDragged:, gVirtualX is null or not of TGCocoa type");
3116  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3118  }
3119 }
3120 
3121 //______________________________________________________________________________
3122 - (void) keyDown : (NSEvent *) theEvent
3123 {
3124  assert(fID != 0 && "-keyDown:, fID is 0");
3125 
3126  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3127  "-keyDown:, gVirtualX is null or not of TGCocoa type");
3128 
3129  NSView<X11Window> *eventView = self;
3130  if (NSView<X11Window> *pointerView = X11::FindViewUnderPointer())
3131  eventView = pointerView;
3132 
3133  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3134  vx->GetEventTranslator()->GenerateKeyPressEvent(eventView, theEvent);
3135 }
3136 
3137 //______________________________________________________________________________
3138 - (void) keyUp : (NSEvent *) theEvent
3139 {
3140  assert(fID != 0 && "-keyUp:, fID is 0");
3141 
3142  assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3143  "-keyUp:, gVirtualX is null or not of TGCocoa type");
3144 
3145  TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3146  NSView<X11Window> *eventView = self;
3147  if (NSView<X11Window> *pointerView = X11::FindViewUnderPointer())
3148  eventView = pointerView;
3149 
3150  vx->GetEventTranslator()->GenerateKeyReleaseEvent(eventView, theEvent);
3151 }
3152 
3153 #pragma mark - First responder stuff.
3154 
3155 //______________________________________________________________________________
3156 - (BOOL) acceptsFirstMouse : (NSEvent *) theEvent
3157 {
3158 #pragma unused(theEvent)
3159  return YES;
3160 }
3161 
3162 //______________________________________________________________________________
3163 - (BOOL) acceptsFirstResponder
3164 {
3165  return YES;
3166 }
3167 
3168 #pragma mark - Cursors.
3169 
3170 //______________________________________________________________________________
3171 - (void) setFCurrentCursor : (ECursor) cursor
3172 {
3173  if (cursor != fCurrentCursor) {
3174  fCurrentCursor = cursor;
3175  [self.fQuartzWindow invalidateCursorRectsForView : self];
3176  }
3177 }
3178 
3179 //______________________________________________________________________________
3180 - (NSCursor *) createCustomCursor
3181 {
3182  const char *pngFileName = 0;
3183 
3184  switch (fCurrentCursor) {
3185  case kMove:
3186  pngFileName = "move_cursor.png";
3187  break;
3188  case kArrowHor:
3189  pngFileName = "hor_arrow_cursor.png";
3190  break;
3191  case kArrowVer:
3192  pngFileName = "ver_arrow_cursor.png";
3193  break;
3194  case kArrowRight:
3195  pngFileName = "right_arrow_cursor.png";
3196  break;
3197  case kRotate:
3198  pngFileName = "rotate.png";
3199  break;
3200  case kBottomLeft:
3201  case kTopRight:
3202  pngFileName = "top_right_cursor.png";
3203  break;
3204  case kTopLeft:
3205  case kBottomRight:
3206  pngFileName = "top_left_cursor.png";
3207  break;
3208  default:;
3209  }
3210 
3211  if (pngFileName) {
3212  const char * const path = gSystem->Which(TROOT::GetIconPath(), pngFileName, kReadPermission);
3213  const Util::ScopedArray<const char> arrayGuard(path);
3214 
3215  if (!path || path[0] == 0) {
3216  //File was not found.
3217  return nil;
3218  }
3219 
3220  NSString *nsPath = [NSString stringWithFormat : @"%s", path];//in autorelease pool.
3221  NSImage * const cursorImage = [[NSImage alloc] initWithContentsOfFile : nsPath];
3222 
3223  if (!cursorImage)
3224  return nil;
3225 
3226  NSPoint hotSpot = X11::GetCursorHotStop(cursorImage, fCurrentCursor);
3227  NSCursor * const customCursor = [[[NSCursor alloc] initWithImage : cursorImage
3228  hotSpot : hotSpot] autorelease];
3229 
3230  [cursorImage release];
3231 
3232  return customCursor;
3233  }
3234 
3235  return nil;
3236 }
3237 
3238 //______________________________________________________________________________
3239 - (void) resetCursorRects
3240 {
3241  if (NSCursor * const cursor = X11::CreateCursor(fCurrentCursor))
3242  [self addCursorRect : self.visibleRect cursor : cursor];
3243 }
3244 
3245 //______________________________________________________________________________
3246 - (void) cursorUpdate
3247 {
3248  if (NSCursor * const cursor = X11::CreateCursor(fCurrentCursor)) {
3249  // NB: [window invalidateCursorRectsForView] called here has the
3250  // same problem as commented below in -cursorUpdate:.
3251  [cursor set];
3252  }
3253 }
3254 
3255 //______________________________________________________________________________
3256 - (void) cursorUpdate : (NSEvent *) event
3257 {
3258 #pragma unused(event)
3259  // It looks like [NSCursor set] method does not work properly when called from
3260  // cursorUpdate:, having, say, a parent frame with 'arrow' cursor and a child (completely
3261  // filling its parent's area) with 'cross', it happens the 'cross' cursor is not always
3262  // set correctly, for example:
3263  // if we have a TCanvas and resize it, cursor is 'arrow' inside this canvas,
3264  // though it must be 'cross'. This all, as it always happesn with "thinking different"
3265  // Apple is somehow related to run loop or something. As always, it's not documented,
3266  // so Apple can continue to think different. The idea with performSelector comes from:
3267  // http://stackoverflow.com/questions/8430236/nscursor-set-method-has-no-effect
3268  // Or may be it's just a bug:
3269  // http://stackoverflow.com/questions/13901232/nscursor-set-not-working-on-unfocused-window
3270  [self performSelector : @selector(cursorUpdate) withObject : nil afterDelay : 0.05f];
3271 }
3272 
3273 #pragma mark - Emulated X11 properties.
3274 
3275 //______________________________________________________________________________
3276 - (void) setProperty : (const char *) propName data : (unsigned char *) propData
3277  size : (unsigned) dataSize forType : (Atom_t) dataType format : (unsigned) format
3278 {
3279  assert(propName != 0 && "-setProperty:data:size:forType:, parameter 'propName' is null");
3280  assert(propData != 0 && "-setProperty:data:size:forType:, parameter 'propData' is null");
3281  assert(dataSize != 0 && "-setProperty:data:size:forType:, parameter 'dataSize' is 0");
3282 
3283  NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3284  QuartzWindowProperty * property = (QuartzWindowProperty *)[fX11Properties valueForKey : key];
3285 
3286  //At the moment (and I think this will never change) TGX11 always calls XChangeProperty with PropModeReplace.
3287  if (property)
3288  [property resetPropertyData : propData size : dataSize type : dataType format : format];
3289  else {
3290  //No property found, add a new one.
3291  property = [[QuartzWindowProperty alloc] initWithData : propData size : dataSize
3292  type : dataType format : format];
3293  [fX11Properties setObject : property forKey : key];
3294  [property release];
3295  }
3296 }
3297 
3298 //______________________________________________________________________________
3299 - (BOOL) hasProperty : (const char *) propName
3300 {
3301  assert(propName != 0 && "-hasProperty:, propName parameter is null");
3302 
3303  NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3304  QuartzWindowProperty * const property = (QuartzWindowProperty *)[fX11Properties valueForKey : key];
3305 
3306  return property != nil;
3307 }
3308 
3309 //______________________________________________________________________________
3310 - (unsigned char *) getProperty : (const char *) propName returnType : (Atom_t *) type
3311  returnFormat : (unsigned *) format nElements : (unsigned *) nElements
3312 {
3313  assert(propName != 0 &&
3314  "-getProperty:returnType:returnFormat:nElements:, parameter 'propName' is null");
3315  assert(type != 0 &&
3316  "-getProperty:returnType:returnFormat:nElements:, parameter 'type' is null");
3317  assert(format != 0 &&
3318  "-getProperty:returnType:returnFormat:nElements:, parameter 'format' is null");
3319  assert(nElements != 0 &&
3320  "-getProperty:returnType:returnFormat:nElements:, parameter 'nElements' is null");
3321 
3322  NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3323  QuartzWindowProperty * const property = (QuartzWindowProperty *)[fX11Properties valueForKey : key];
3324  assert(property != 0 &&
3325  "-getProperty:returnType:returnFormat:nElements, property not found");
3326 
3327  NSData * const propData = property.fPropertyData;
3328 
3329  const NSUInteger dataSize = [propData length];
3330  unsigned char *buff = 0;
3331  try {
3332  buff = new unsigned char[dataSize]();
3333  } catch (const std::bad_alloc &) {
3334  //Hmm, can I log, if new failed? :)
3335  NSLog(@"QuartzWindow: -getProperty:returnType:returnFormat:nElements:,"
3336  " memory allocation failed");
3337  return 0;
3338  }
3339 
3340  [propData getBytes : buff length : dataSize];
3341  *format = property.fFormat;
3342 
3343  *nElements = dataSize;
3344 
3345  if (*format == 16)
3346  *nElements= dataSize / 2;
3347  else if (*format == 32)
3348  *nElements = dataSize / 4;
3349 
3350  *type = property.fType;
3351 
3352  return buff;
3353 }
3354 
3355 //______________________________________________________________________________
3356 - (void) removeProperty : (const char *) propName
3357 {
3358  assert(propName != 0 && "-removeProperty:, parameter 'propName' is null");
3359 
3360  NSString * const key = [NSString stringWithCString : propName
3361  encoding : NSASCIIStringEncoding];
3362  [fX11Properties removeObjectForKey : key];
3363 }
3364 
3365 //DND
3366 //______________________________________________________________________________
3367 - (NSDragOperation) draggingEntered : (id<NSDraggingInfo>) sender
3368 {
3369  NSPasteboard * const pasteBoard = [sender draggingPasteboard];
3370  const NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
3371 
3372  if ([[pasteBoard types] containsObject : NSFilenamesPboardType] && (sourceDragMask & NSDragOperationCopy))
3373  return NSDragOperationCopy;
3374 
3375  return NSDragOperationNone;
3376 }
3377 
3378 //______________________________________________________________________________
3379 - (BOOL) performDragOperation : (id<NSDraggingInfo>) sender
3380 {
3381  //We can drag some files (images, pdfs, source code files) from
3382  //finder to ROOT's window (mainly TCanvas or text editor).
3383  //The logic is totally screwed here :((( - ROOT will try to
3384  //read a property of some window (not 'self', unfortunately) -
3385  //this works since on Window all data is in a global clipboard
3386  //(on X11 it simply does not work at all).
3387  //I'm attaching the file name as a property for the top level window,
3388  //there is no other way to make this data accessible for ROOT.
3389 
3390  NSPasteboard * const pasteBoard = [sender draggingPasteboard];
3391  const NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
3392 
3393  if ([[pasteBoard types] containsObject : NSFilenamesPboardType] && (sourceDragMask & NSDragOperationCopy)) {
3394 
3395  //Here I try to put string ("file://....") into window's property to make
3396  //it accesible from ROOT's GUI.
3397  const Atom_t textUriAtom = gVirtualX->InternAtom("text/uri-list", kFALSE);
3398 
3399  NSArray * const files = [pasteBoard propertyListForType : NSFilenamesPboardType];
3400  for (NSString *path in files) {
3401  //ROOT can not process several files, use the first one.
3402  NSString * const item = [@"file://" stringByAppendingString : path];
3403  //Yes, only ASCII encoding, but after all, ROOT's not able to work with NON-ASCII strings.
3404  const NSUInteger len = [item lengthOfBytesUsingEncoding : NSASCIIStringEncoding] + 1;
3405  try {
3406  std::vector<unsigned char> propertyData(len);
3407  [item getCString : (char *)&propertyData[0] maxLength : propertyData.size()
3408  encoding : NSASCIIStringEncoding];
3409  //There is no any guarantee, that this will ever work, logic in TGDNDManager is totally crazy.
3410  NSView<X11Window> * const targetView = self.fQuartzWindow.fContentView;
3411  [targetView setProperty : "_XC_DND_DATA" data : &propertyData[0]
3412  size : propertyData.size() forType : textUriAtom format : 8];
3413  } catch (const std::bad_alloc &) {
3414  //Hehe, can I log something in case of bad_alloc??? ;)
3415  NSLog(@"QuartzView: -performDragOperation:, memory allocation failed");
3416  return NO;
3417  }
3418 
3419  break;
3420  }
3421 
3422  //Property is attached now.
3423 
3424  //Gdk on windows creates three events on file drop (WM_DROPFILES): XdndEnter, XdndPosition, XdndDrop.
3425  //1. Dnd enter.
3426  Event_t event1 = {};
3427  event1.fType = kClientMessage;
3428  event1.fWindow = fID;
3429  event1.fHandle = gVirtualX->InternAtom("XdndEnter", kFALSE);
3430  event1.fUser[0] = long(fID);
3431  event1.fUser[2] = textUriAtom;//gVirtualX->InternAtom("text/uri-list", kFALSE);
3432  //
3433  gVirtualX->SendEvent(fID, &event1);
3434 
3435  //2. Dnd position.
3436  Event_t event2 = {};
3437  event2.fType = kClientMessage;
3438  event2.fWindow = fID;
3439  event2.fHandle = gVirtualX->InternAtom("XdndPosition", kFALSE);
3440  event2.fUser[0] = long(fID);
3441  event2.fUser[2] = 0;//Here I have to pack x and y for drop coordinates, shifting by 16 bits.
3442  NSPoint dropPoint = [sender draggingLocation];
3443  //convertPointFromBase is deprecated.
3444  //dropPoint = [self convertPointFromBase : dropPoint];
3445  dropPoint = [self convertPoint : dropPoint fromView : nil];
3446  //
3447  dropPoint = X11::TranslateToScreen(self, dropPoint);
3448  event2.fUser[2] = UShort_t(dropPoint.y) | (UShort_t(dropPoint.x) << 16);
3449 
3450  gVirtualX->SendEvent(fID, &event2);
3451 
3452  Event_t event3 = {};
3453  event3.fType = kClientMessage;
3454  event3.fWindow = fID;
3455  event3.fHandle = gVirtualX->InternAtom("XdndDrop", kFALSE);
3456 
3457  gVirtualX->SendEvent(fID, &event3);
3458  }
3459 
3460  return YES;//Always ok, even if file type is not supported - no need in "animation".
3461 }
3462 
3463 @end
NSEvent
ROOT::MacOSX::X11::GlobalXROOTToCocoa
int GlobalXROOTToCocoa(CGFloat xROOT)
Definition: QuartzWindow.mm:208
Event_t::fType
EGEventType fType
of event (see EGEventType)
Definition: GuiTypes.h:175
kWABorderPixel
const Mask_t kWABorderPixel
Definition: GuiTypes.h:142
-[QuartzView configureNotifyTree]
void configureNotifyTree()
Definition: QuartzWindow.mm:2745
-[QuartzWindow fIsOpenGLWidget]
BOOL fIsOpenGLWidget()
Definition: QuartzWindow.mm:1395
X11Window-p
Definition: X11Drawable.h:65
kWABackingStore
const Mask_t kWABackingStore
Definition: GuiTypes.h:146
WindowAttributes_t::fBackingPixel
ULong_t fBackingPixel
value to be used when restoring planes
Definition: GuiTypes.h:126
kButton2
@ kButton2
Definition: GuiTypes.h:214
-[QuartzView fY]
int fY()
Definition: QuartzWindow.mm:2087
CocoaConstants.h
ROOT::MacOSX::X11::EventTranslator::HasPointerGrab
bool HasPointerGrab() const
Definition: X11Events.mm:1238
kLeftSide
@ kLeftSide
Definition: GuiTypes.h:373
SetWindowAttributes_t::fBitGravity
Int_t fBitGravity
one of bit gravity values
Definition: GuiTypes.h:99
kWABorderWidth
const Mask_t kWABorderWidth
Definition: GuiTypes.h:143
QuartzWindow::fHasFocus
BOOL fHasFocus
Definition: QuartzWindow.h:70
ROOT::MacOSX::X11::ViewIsHtmlView
bool ViewIsHtmlView(unsigned viewID)
Definition: QuartzWindow.mm:941
TGWindow
ROOT GUI Window base class.
Definition: TGWindow.h:23
ROOT::MacOSX::X11::FindWindowInPoint
QuartzWindow * FindWindowInPoint(Int_t x, Int_t y)
Definition: QuartzWindow.mm:316
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:100
NSView
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
-[QuartzView cancelGrab]
void cancelGrab()
Definition: QuartzWindow.mm:2570
SetWindowAttributes_t::fEventMask
Long_t fEventMask
set of events that should be saved
Definition: GuiTypes.h:105
kWADontPropagate
const Mask_t kWADontPropagate
Definition: GuiTypes.h:152
TGCocoa::CocoaDrawON
void CocoaDrawON()
Definition: TGCocoa.mm:4411
QuartzImage::fWidth
unsigned fWidth
Definition: QuartzPixmap.h:93
kTopSide
@ kTopSide
Definition: GuiTypes.h:373
QuartzWindow::fQuartzWindow
QuartzWindow * fQuartzWindow
Definition: QuartzWindow.h:151
QuartzView::fPassiveGrabKeyModifiers
unsigned fPassiveGrabKeyModifiers
Definition: QuartzWindow.h:211
CocoaUtils.h
kRightSide
@ kRightSide
Definition: GuiTypes.h:373
kAlways
@ kAlways
Definition: GuiTypes.h:45
QuartzView::fBackBuffer
QuartzPixmap * fBackBuffer
Definition: QuartzWindow.h:218
ROOT::MacOSX::X11::TranslateCoordinates
NSPoint TranslateCoordinates(NSView< X11Window > *fromView, NSView< X11Window > *toView, NSPoint sourcePoint)
Definition: QuartzWindow.mm:271
X11Drawable-p
Definition: X11Drawable.h:34
kPointerMotionMask
const Mask_t kPointerMotionMask
Definition: GuiTypes.h:163
TGCocoa::GetCommandBuffer
ROOT::MacOSX::X11::CommandBuffer * GetCommandBuffer() const
Definition: TGCocoa.mm:4405
QuartzWindow.h
ECursor
ECursor
Definition: GuiTypes.h:372
UShort_t
unsigned short UShort_t
Definition: RtypesCore.h:40
kArrowVer
@ kArrowVer
Definition: GuiTypes.h:374
kIsUnmapped
@ kIsUnmapped
Definition: GuiTypes.h:46
gVirtualX
#define gVirtualX
Definition: TVirtualX.h:338
ROOT::MacOSX::X11::TranslateToScreen
NSPoint TranslateToScreen(NSView< X11Window > *from, NSPoint point)
Definition: QuartzWindow.mm:245
ROOT::MacOSX::X11::ViewIsHtmlView
bool ViewIsHtmlView(NSView< X11Window > *view)
Definition: QuartzWindow.mm:953
kIsViewable
@ kIsViewable
Definition: GuiTypes.h:46
QuartzView::fBackgroundPixmap
QuartzImage * fBackgroundPixmap
Definition: QuartzWindow.h:223
TSystem::Which
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1545
X11Buffer.h
kBottomLeft
@ kBottomLeft
Definition: GuiTypes.h:372
QuartzPixmap::fHeight
unsigned fHeight
Definition: QuartzPixmap.h:38
ROOT::MacOSX::X11::ScreenPointIsInView
bool ScreenPointIsInView(NSView< X11Window > *view, Int_t x, Int_t y)
Definition: QuartzWindow.mm:296
ROOT::MacOSX::Details::kRightMouseDown
const NSEventType kRightMouseDown
Definition: CocoaConstants.mm:45
ROOT::MacOSX::X11::FrameForHtmlView
NSView< X11Window > * FrameForHtmlView(NSView< X11Window > *htmlView)
Definition: QuartzWindow.mm:999
TROOT::GetIconPath
static const TString & GetIconPath()
Get the icon path in the installation. Static utility function.
Definition: TROOT.cxx:3080
ROOT::MacOSX::X11::EventTranslator::GenerateExposeEvent
void GenerateExposeEvent(NSView< X11Window > *view, const NSRect &exposedRect)
Definition: X11Events.mm:1174
ROOT::MacOSX::X11::FindWindowForPointerEvent
QuartzWindow * FindWindowForPointerEvent(NSEvent *pointerEvent)
Definition: QuartzWindow.mm:449
WindowAttributes_t::fAllEventMasks
Long_t fAllEventMasks
set of events all people have interest in
Definition: GuiTypes.h:131
kWAColormap
const Mask_t kWAColormap
Definition: GuiTypes.h:153
-[QuartzWindow fScaleFactor]
CGFloat fScaleFactor()
Definition: QuartzWindow.mm:1402
QuartzPixmap::fWidth
unsigned fWidth
Definition: QuartzPixmap.h:37
-[QuartzView fX]
int fX()
Definition: QuartzWindow.mm:2081
kButton4
@ kButton4
Definition: GuiTypes.h:215
QuartzUtils.h
fModifiers
unsigned int fModifiers
Definition: cppyy.h:12
WindowAttributes_t
Window attributes that can be inquired.
Definition: GuiTypes.h:114
Int_t
int Int_t
Definition: RtypesCore.h:45
QuartzImage
Definition: QuartzPixmap.h:87
ROOT::MacOSX::X11::SetWindowAttributes
void SetWindowAttributes(const SetWindowAttributes_t *attr, NSObject< X11Window > *window)
Definition: QuartzWindow.mm:634
Event_t::fFormat
Int_t fFormat
Next fields only used by kClientMessageEvent.
Definition: GuiTypes.h:186
ROOT::MacOSX::X11::TranslateFromScreen
NSPoint TranslateFromScreen(NSPoint point, NSView< X11Window > *to)
Definition: QuartzWindow.mm:259
-[QuartzView lowerWindow]
void lowerWindow()
Definition: QuartzWindow.mm:2708
kClientMessage
@ kClientMessage
Definition: GuiTypes.h:63
ROOTOpenGLView.h
kArrowHor
@ kArrowHor
Definition: GuiTypes.h:374
QuartzView::fCurrentGrabType
ROOT::MacOSX::X11::PointerGrab fCurrentGrabType
Definition: QuartzWindow.h:225
x
Double_t x[n]
Definition: legend1.C:17
ROOT::MacOSX::X11::FindWindowUnderPointer
QuartzWindow * FindWindowUnderPointer()
Definition: QuartzWindow.mm:408
TGView.h
TClass.h
kButton1
@ kButton1
Definition: GuiTypes.h:214
-[QuartzView mapRaised]
void mapRaised()
Definition: QuartzWindow.mm:2626
long
long
Definition: Converters.cxx:876
SetWindowAttributes_t::fBackgroundPixel
ULong_t fBackgroundPixel
background pixel
Definition: GuiTypes.h:95
ROOT::MacOSX::X11::CreateTopLevelWindow
QuartzWindow * CreateTopLevelWindow(Int_t x, Int_t y, UInt_t w, UInt_t h, UInt_t border, Int_t depth, UInt_t clss, void *visual, SetWindowAttributes_t *attr, UInt_t)
Definition: QuartzWindow.mm:56
kBottomSide
@ kBottomSide
Definition: GuiTypes.h:373
kMove
@ kMove
Definition: GuiTypes.h:374
Event_t::fUser
Longptr_t fUser[5]
5 longs can be used by client message events NOTE: only [0], [1] and [2] may be used.
Definition: GuiTypes.h:187
-[QuartzWindow mapRaised]
void mapRaised()
Definition: QuartzWindow.mm:1660
WindowAttributes_t::fMapInstalled
Bool_t fMapInstalled
boolean, is color map currently installed
Definition: GuiTypes.h:129
WindowAttributes_t::fWinGravity
Int_t fWinGravity
one of the window gravity values
Definition: GuiTypes.h:123
QuartzWindow::fShapeCombineMask
QuartzImage * fShapeCombineMask
Definition: QuartzWindow.h:74
QuartzView::fMapState
int fMapState
Definition: QuartzWindow.h:268
kButtonPressMask
const Mask_t kButtonPressMask
Definition: GuiTypes.h:161
SetWindowAttributes_t::fMask
Mask_t fMask
bit mask specifying which fields are valid
Definition: GuiTypes.h:110
ROOT::MacOSX::X11::Rectangle::fHeight
unsigned fHeight
Definition: CocoaGuiTypes.h:25
kWACursor
const Mask_t kWACursor
Definition: GuiTypes.h:154
WindowAttributes_t::fBackingStore
Int_t fBackingStore
kNotUseful, kWhenMapped, kAlways
Definition: GuiTypes.h:124
ROOT::MacOSX::X11::EventTranslator::GenerateButtonReleaseEvent
void GenerateButtonReleaseEvent(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1270
v
@ v
Definition: rootcling_impl.cxx:3664
kBottomRight
@ kBottomRight
Definition: GuiTypes.h:372
kIsUnviewable
@ kIsUnviewable
Definition: GuiTypes.h:46
TGWindow.h
ROOT::MacOSX::Details::kBorderlessWindowMask
const NSUInteger kBorderlessWindowMask
Definition: CocoaConstants.mm:53
NSWindow
WindowAttributes_t::fDepth
Int_t fDepth
depth of window
Definition: GuiTypes.h:118
QuartzWindow::fMapState
int fMapState
Definition: QuartzWindow.h:141
kLeaveWindowMask
const Mask_t kLeaveWindowMask
Definition: GuiTypes.h:168
-[QuartzView raiseWindow]
void raiseWindow()
Definition: QuartzWindow.mm:2669
ROOT::MacOSX::Util
Definition: CocoaUtils.h:22
TGCocoa::CocoaDrawOFF
void CocoaDrawOFF()
Definition: TGCocoa.mm:4417
ROOT::MacOSX::X11::EventTranslator::GenerateCrossingEvent
void GenerateCrossingEvent(NSEvent *theEvent)
Definition: X11Events.mm:1192
WindowAttributes_t::fBorderWidth
Int_t fBorderWidth
border width of window
Definition: GuiTypes.h:117
id
XFontStruct * id
Definition: TGX11.cxx:109
WindowAttributes_t::fWidth
Int_t fWidth
Definition: GuiTypes.h:116
kWASaveUnder
const Mask_t kWASaveUnder
Definition: GuiTypes.h:150
WindowAttributes_t::fHeight
Int_t fHeight
width and height of window
Definition: GuiTypes.h:116
kArrowRight
@ kArrowRight
Definition: GuiTypes.h:375
QuartzView::fEventMask
long fEventMask
Definition: QuartzWindow.h:198
kWatch
@ kWatch
Definition: GuiTypes.h:375
kWABitGravity
const Mask_t kWABitGravity
Definition: GuiTypes.h:144
TROOT.h
-[QuartzView fIsOpenGLWidget]
BOOL fIsOpenGLWidget()
Definition: QuartzWindow.mm:2069
ROOT::MacOSX::X11::CreateChildView
QuartzView * CreateChildView(QuartzView *parent, Int_t x, Int_t y, UInt_t w, UInt_t h, UInt_t border, Int_t depth, UInt_t clss, void *visual, SetWindowAttributes_t *attr, UInt_t wtype)
Definition: QuartzWindow.mm:85
ROOT::MacOSX::X11::kPGPassiveGrab
@ kPGPassiveGrab
Definition: X11Events.h:46
ROOT::MacOSX::X11::ViewIsHtmlViewFrame
bool ViewIsHtmlViewFrame(NSView< X11Window > *view, bool checkParent)
Definition: QuartzWindow.mm:961
ROOT::MacOSX::X11::FindDNDAwareViewInPoint
NSView< X11Window > * FindDNDAwareViewInPoint(NSView *parentView, Window_t dragWinID, Window_t inputWinID, Int_t x, Int_t y, Int_t maxDepth)
Definition: QuartzWindow.mm:362
ROOT::MacOSX::X11::EventTranslator::GenerateKeyPressEvent
void GenerateKeyPressEvent(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1285
QuartzWindow::fBackgroundPixel
unsigned long fBackgroundPixel
Definition: QuartzWindow.h:140
gClient
#define gClient
Definition: TGClient.h:157
-[QuartzView isFlipped]
BOOL isFlipped()
Definition: QuartzWindow.mm:2737
WindowAttributes_t::fVisual
void * fVisual
the associated visual structure
Definition: GuiTypes.h:119
ROOT::MacOSX::X11::FindViewUnderPointer
NSView< X11Window > * FindViewUnderPointer()
Definition: QuartzWindow.mm:436
TGCocoa.h
-[QuartzWindow findXorWindow]
XorDrawingWindow * findXorWindow()
Definition: QuartzWindow.mm:1542
-[QuartzWindow mapWindow]
void mapWindow()
Definition: QuartzWindow.mm:1678
ROOT::Quartz::CGStateGuard
Definition: QuartzUtils.h:23
QuartzView::fContext
CGContextRef fContext
Definition: QuartzWindow.h:197
kWABorderPixmap
const Mask_t kWABorderPixmap
Definition: GuiTypes.h:141
ROOT::MacOSX::X11::CreateSubImage
CGImageRef CreateSubImage(QuartzImage *image, const Rectangle &area)
Definition: QuartzPixmap.mm:774
ROOT::MacOSX::X11::DownscaledImageData
std::vector< unsigned char > DownscaledImageData(unsigned w, unsigned h, CGImageRef image)
Definition: QuartzWindow.mm:525
TMVA::Experimental::SOFIE::ETensorType::BOOL
@ BOOL
kRotate
@ kRotate
Definition: GuiTypes.h:374
ROOT::MacOSX::X11::EventTranslator::GenerateKeyReleaseEvent
void GenerateKeyReleaseEvent(NSView< X11Window > *eventView, NSEvent *theEvent)
Definition: X11Events.mm:1301
X11Drawable-p::fID
unsigned fID
Definition: X11Drawable.h:37
Event_t::fHandle
Handle_t fHandle
general resource handle (used for atoms or windows)
Definition: GuiTypes.h:185
-[QuartzView activatePassiveGrab]
void activatePassiveGrab()
Definition: QuartzWindow.mm:2550
kTopLeft
@ kTopLeft
Definition: GuiTypes.h:372
TSystem.h
QuartzView::fIsDNDAware
BOOL fIsDNDAware
Definition: QuartzWindow.h:216
X11Window-p::fClass
int fClass
Definition: X11Drawable.h:82
QuartzView::fDepth
int fDepth
Definition: QuartzWindow.h:200
-[QuartzWindow fX]
int fX()
Definition: QuartzWindow.mm:1410
-[QuartzWindow mapSubwindows]
void mapSubwindows()
Definition: QuartzWindow.mm:1696
SetWindowAttributes_t::fWinGravity
Int_t fWinGravity
one of the window gravity values
Definition: GuiTypes.h:100
h
#define h(i)
Definition: RSha256.hxx:106
QuartzView::fCurrentCursor
ECursor fCurrentCursor
Definition: QuartzWindow.h:215
TGCocoa
This class implements TVirtualX interface for MacOS X, using Cocoa and Quartz 2D.
Definition: TGCocoa.h:58
TGCocoa::GetDisplayGeometry
ROOT::MacOSX::X11::Rectangle GetDisplayGeometry() const
Definition: TGCocoa.mm:606
QuartzView::fPassiveGrabOwnerEvents
BOOL fPassiveGrabOwnerEvents
Definition: QuartzWindow.h:213
size
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
QuartzPixmap
Definition: QuartzPixmap.h:31
kButton3
@ kButton3
Definition: GuiTypes.h:214
-[XorDrawingWindow init]
instancetype init()
Definition: QuartzWindow.mm:1163
TGWindow::GetName
virtual const char * GetName() const
Return unique name, used in SavePrimitive methods.
Definition: TGWindow.cxx:336
QuartzView::fHasFocus
BOOL fHasFocus
Definition: QuartzWindow.h:206
ROOT::MacOSX::X11::Rectangle::fX
int fX
Definition: CocoaGuiTypes.h:21
QuartzView::fContentView
NSView< X11Window > * fContentView
Definition: QuartzWindow.h:279
QuartzWindow::fDelayedTransient
BOOL fDelayedTransient
Definition: QuartzWindow.h:73
ROOT::MacOSX::Util::CFScopeGuard
Definition: CocoaUtils.h:268
Atom_t
Handle_t Atom_t
WM token.
Definition: GuiTypes.h:37
QuartzWindowProperty
Definition: QuartzWindow.mm:1868
-[QuartzWindow fHeight]
unsigned fHeight()
Definition: QuartzWindow.mm:1428
kWAWinGravity
const Mask_t kWAWinGravity
Definition: GuiTypes.h:145
WindowAttributes_t::fBitGravity
Int_t fBitGravity
one of bit gravity values
Definition: GuiTypes.h:122
QuartzView
Definition: QuartzWindow.h:194
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:101
kCross
@ kCross
Definition: GuiTypes.h:374
ROOT::MacOSX::X11::WindowLostFocus
void WindowLostFocus(Window_t winID)
Definition: QuartzWindow.mm:560
QuartzView::fBitGravity
int fBitGravity
Definition: QuartzWindow.h:201
ROOT::MacOSX::X11::FrameForTextView
NSView< X11Window > * FrameForTextView(NSView< X11Window > *textView)
Definition: QuartzWindow.mm:986
-[QuartzWindow removeXorWindow]
void removeXorWindow()
Definition: QuartzWindow.mm:1531
kButtonReleaseMask
const Mask_t kButtonReleaseMask
Definition: GuiTypes.h:162
-[QuartzView fWidth]
unsigned fWidth()
Definition: QuartzWindow.mm:2093
ROOT::MacOSX::X11::GlobalYROOTToCocoa
int GlobalYROOTToCocoa(CGFloat yROOT)
Definition: QuartzWindow.mm:198
ROOT::MacOSX::X11::LocalYROOTToCocoa
int LocalYROOTToCocoa(NSView< X11Window > *parentView, CGFloat yROOT)
Definition: QuartzWindow.mm:226
QuartzView::fPassiveGrabButton
int fPassiveGrabButton
Definition: QuartzWindow.h:209
ROOT::MacOSX::X11::GetRootWindowAttributes
void GetRootWindowAttributes(WindowAttributes_t *attr)
Definition: QuartzWindow.mm:104
QuartzWindow::fMainWindow
QuartzWindow * fMainWindow
Definition: QuartzWindow.h:69
ROOT::MacOSX::X11::Rectangle
Definition: CocoaGuiTypes.h:20
-[QuartzWindow fY]
int fY()
Definition: QuartzWindow.mm:1416
QuartzView::fQuartzWindow
QuartzWindow * fQuartzWindow
Definition: QuartzWindow.h:280
QuartzView::fPassiveGrabEventMask
unsigned fPassiveGrabEventMask
Definition: QuartzWindow.h:210
-[QuartzWindow adjustXorWindowGeometry]
void adjustXorWindowGeometry()
Definition: QuartzWindow.mm:1515
Window_t
Handle_t Window_t
Window handle.
Definition: GuiTypes.h:29
UInt_t
unsigned int UInt_t
Definition: RtypesCore.h:46
ROOT::MacOSX::X11::EventTranslator::GenerateFocusChangeEvent
void GenerateFocusChangeEvent(NSView< X11Window > *eventView)
Definition: X11Events.mm:1321
TGCocoa::fgDeleteWindowAtom
static Atom_t fgDeleteWindowAtom
Definition: TGCocoa.h:469
y
Double_t y[n]
Definition: legend1.C:17
TGCocoa::GetEventTranslator
ROOT::MacOSX::X11::EventTranslator * GetEventTranslator() const
Definition: TGCocoa.mm:4399
ULong_t
unsigned long ULong_t
Definition: RtypesCore.h:55
QuartzImage::fHeight
unsigned fHeight
Definition: QuartzPixmap.h:94
ROOT::MacOSX::X11::CreateCustomCursor
NSCursor * CreateCustomCursor(ECursor currentCursor)
Definition: QuartzWindow.mm:781
TGWindow::kIsHtmlView
@ kIsHtmlView
Definition: TGWindow.h:62
TGClient.h
ROOT::MacOSX::X11::kPGImplicitGrab
@ kPGImplicitGrab
Definition: X11Events.h:44
WindowAttributes_t::fY
Int_t fY
location of window
Definition: GuiTypes.h:115
QuartzView::fID
unsigned fID
Definition: QuartzWindow.h:196
line
TLine * line
Definition: entrylistblock_figure1.C:235
-[QuartzView fHeight]
unsigned fHeight()
Definition: QuartzWindow.mm:2099
kWABackingPlanes
const Mask_t kWABackingPlanes
Definition: GuiTypes.h:147
Event_t::fWindow
Window_t fWindow
window reported event is relative to
Definition: GuiTypes.h:176
kPointer
@ kPointer
Definition: GuiTypes.h:375
void
typedef void((*Func_t)())
fClass
Cppyy::TCppType_t fClass
Definition: DeclareConverters.h:260
-[QuartzView mapSubwindows]
void mapSubwindows()
Definition: QuartzWindow.mm:2642
ROOT::MacOSX::X11::ViewIsTextView
bool ViewIsTextView(unsigned viewID)
Definition: QuartzWindow.mm:897
kHand
@ kHand
Definition: GuiTypes.h:374
QuartzWindowProperty::fFormat
unsigned fFormat
Definition: QuartzWindow.mm:1871
unsigned int
ROOT::MacOSX::X11::GlobalXCocoaToROOT
int GlobalXCocoaToROOT(CGFloat xCocoa)
Definition: QuartzWindow.mm:188
ROOTOpenGLView
Definition: ROOTOpenGLView.h:23
XorDrawingWindow
Definition: QuartzWindow.h:55
-[QuartzWindow fIsPixmap]
BOOL fIsPixmap()
Definition: QuartzWindow.mm:1388
X11Window-p::fDepth
int fDepth
Definition: X11Drawable.h:83
ROOT::MacOSX::X11::Rectangle::fWidth
unsigned fWidth
Definition: CocoaGuiTypes.h:24
QuartzView::fOverrideRedirect
BOOL fOverrideRedirect
Definition: QuartzWindow.h:204
kTopRight
@ kTopRight
Definition: GuiTypes.h:372
ROOT::MacOSX::X11::EventTranslator::GenerateConfigureNotifyEvent
void GenerateConfigureNotifyEvent(NSView< X11Window > *view, const NSRect &newFrame)
Definition: X11Events.mm:1149
ROOT::MacOSX::Details
Definition: TMacOSXSystem.h:30
TGTextView.h
gSystem
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
kWAEventMask
const Mask_t kWAEventMask
Definition: GuiTypes.h:151
ROOT::MacOSX::X11::EventTranslator::GeneratePointerMotionEvent
void GeneratePointerMotionEvent(NSEvent *theEvent)
Definition: X11Events.mm:1244
-[QuartzWindow fWidth]
unsigned fWidth()
Definition: QuartzWindow.mm:1422
WindowAttributes_t::fSaveUnder
Bool_t fSaveUnder
boolean, should bits under be saved?
Definition: GuiTypes.h:127
QuartzView::fBackgroundPixel
unsigned long fBackgroundPixel
Definition: QuartzWindow.h:203
ROOT::MacOSX::X11::GetCursorHotStop
NSPoint GetCursorHotStop(NSImage *image, ECursor cursor)
Definition: QuartzWindow.mm:768
kExposureMask
const Mask_t kExposureMask
Definition: GuiTypes.h:165
kWABackPixel
const Mask_t kWABackPixel
Definition: GuiTypes.h:140
kWABackingPixel
const Mask_t kWABackingPixel
Definition: GuiTypes.h:148
TGContainer
Manages a content area.
Definition: TGCanvas.h:31
WindowAttributes_t::fRoot
Window_t fRoot
root of screen containing window
Definition: GuiTypes.h:120
ROOT::MacOSX::Details::kClosableWindowMask
const NSUInteger kClosableWindowMask
Definition: CocoaConstants.mm:51
ROOT::MacOSX::Util::ScopedArray
Definition: CocoaUtils.h:327
ROOT::Quartz
Definition: QuartzFillArea.h:33
kCaret
@ kCaret
Definition: GuiTypes.h:375
ROOT::MacOSX::X11::AdjustCropArea
bool AdjustCropArea(const Rectangle &srcRect, Rectangle &cropArea)
Definition: QuartzPixmap.mm:862
ROOT::MacOSX::X11::GetWindowGeometry
void GetWindowGeometry(NSObject< X11Window > *win, WindowAttributes_t *dst)
Definition: QuartzWindow.mm:665
ROOT::MacOSX::Util::CFScopeGuard::Get
RefType Get() const
Definition: CocoaUtils.h:286
WindowAttributes_t::fScreen
void * fScreen
back pointer to correct screen
Definition: GuiTypes.h:135
QuartzImage::fImage
ROOT::MacOSX::Util::CFScopeGuard< CGImageRef > fImage
Definition: QuartzPixmap.h:96
-[QuartzView fIsPixmap]
BOOL fIsPixmap()
Definition: QuartzWindow.mm:2063
-[QuartzView unmapWindow]
void unmapWindow()
Definition: QuartzWindow.mm:2649
QuartzView::fX11Properties
NSMutableDictionary * fX11Properties
Definition: QuartzWindow.h:222
ROOT::MacOSX::X11::CompareViewsToRaise
NSComparisonResult CompareViewsToRaise(id view1, id view2, void *context)
Definition: QuartzWindow.mm:753
TGTextView
A TGTextView is a text viewer widget.
Definition: TGTextView.h:22
ROOT::MacOSX::X11::LockFocus
bool LockFocus(NSView< X11Window > *view)
Definition: QuartzWindow.mm:1014
WindowAttributes_t::fYourEventMask
Long_t fYourEventMask
my event mask
Definition: GuiTypes.h:132
Event_t
Event structure.
Definition: GuiTypes.h:174
QuartzView::fWinGravity
int fWinGravity
Definition: QuartzWindow.h:202
NSObject
kButton5
@ kButton5
Definition: GuiTypes.h:215
TGCanvas.h
ROOT::MacOSX::X11::ViewIsTextView
bool ViewIsTextView(NSView< X11Window > *view)
Definition: QuartzWindow.mm:909
QuartzView::fActiveGrabEventMask
unsigned fActiveGrabEventMask
Definition: QuartzWindow.h:212
QuartzView::fParentView
QuartzView * fParentView
Definition: QuartzWindow.h:207
d
#define d(i)
Definition: RSha256.hxx:102
ROOT::MacOSX::X11::LocalYCocoaToROOT
int LocalYCocoaToROOT(NSView< X11Window > *parentView, CGFloat yCocoa)
Definition: QuartzWindow.mm:218
WindowAttributes_t::fColormap
Colormap_t fColormap
color map to be associated with window
Definition: GuiTypes.h:128
PassiveKeyGrab
Definition: QuartzWindow.h:174
ROOT::MacOSX::X11::ConvertPointFromBaseToScreen
NSPoint ConvertPointFromBaseToScreen(NSWindow *window, NSPoint windowPoint)
Definition: QuartzWindow.mm:141
ROOT::MacOSX::X11::PixelToRGB
void PixelToRGB(Pixel_t pixelColor, CGFloat *rgb)
Definition: X11Colors.mm:920
QuartzView::fActiveGrabOwnerEvents
BOOL fActiveGrabOwnerEvents
Definition: QuartzWindow.h:227
ROOT::MacOSX::X11::ViewIsTextViewFrame
bool ViewIsTextViewFrame(NSView< X11Window > *view, bool checkParent)
Definition: QuartzWindow.mm:917
QuartzView::fSnapshotDraw
BOOL fSnapshotDraw
Definition: QuartzWindow.h:214
ROOT::MacOSX::X11::EventTranslator::GenerateButtonPressEvent
void GenerateButtonPressEvent(NSView< X11Window > *eventView, NSEvent *theEvent, EMouseButton btn)
Definition: X11Events.mm:1257
X11Window-p::fParentView
QuartzView * fParentView
Definition: X11Drawable.h:100
QuartzWindow::fParentView
QuartzView * fParentView
Definition: QuartzWindow.h:149
TGViewFrame
Definition: TGView.h:109
-[QuartzView activateImplicitGrab]
void activateImplicitGrab()
Definition: QuartzWindow.mm:2556
WindowAttributes_t::fX
Int_t fX
Definition: GuiTypes.h:115
ROOT::MacOSX::X11::FindViewForPointerEvent
NSView< X11Window > * FindViewForPointerEvent(NSEvent *pointerEvent)
Definition: QuartzWindow.mm:497
ROOT::MacOSX::Details::kMiniaturizableWindowMask
const NSUInteger kMiniaturizableWindowMask
Definition: CocoaConstants.mm:49
-[QuartzView mapWindow]
void mapWindow()
Definition: QuartzWindow.mm:2636
kStructureNotifyMask
const Mask_t kStructureNotifyMask
Definition: GuiTypes.h:166
-[QuartzWindow dealloc]
void dealloc()
Definition: QuartzWindow.mm:1263
-[QuartzView fScaleFactor]
CGFloat fScaleFactor()
Definition: QuartzWindow.mm:2075
ROOT::MacOSX::Details::kResizableWindowMask
const NSUInteger kResizableWindowMask
Definition: CocoaConstants.mm:50
ROOT::MacOSX::Details::kTitledWindowMask
const NSUInteger kTitledWindowMask
Definition: CocoaConstants.mm:52
kEnterWindowMask
const Mask_t kEnterWindowMask
Definition: GuiTypes.h:167
type
int type
Definition: TGX11.cxx:121
XorDrawingView
Definition: QuartzWindow.h:45
ROOT::MacOSX::X11::GetWindowAttributes
void GetWindowAttributes(NSObject< X11Window > *window, WindowAttributes_t *dst)
Definition: QuartzWindow.mm:678
WindowAttributes_t::fClass
Int_t fClass
kInputOutput, kInputOnly
Definition: GuiTypes.h:121
kWAOverrideRedirect
const Mask_t kWAOverrideRedirect
Definition: GuiTypes.h:149
X11Colors.h
-[QuartzWindow addXorWindow]
void addXorWindow()
Definition: QuartzWindow.mm:1503
QuartzWindow::fIsDeleted
BOOL fIsDeleted
Definition: QuartzWindow.h:75
QuartzWindowProperty::fType
Atom_t fType
Definition: QuartzWindow.mm:1870
QuartzView::fIsOverlapped
BOOL fIsOverlapped
Definition: QuartzWindow.h:220
kReadPermission
@ kReadPermission
Definition: TSystem.h:47
ROOT::MacOSX::X11::UnlockFocus
void UnlockFocus(NSView< X11Window > *view)
Definition: QuartzWindow.mm:1035
WindowAttributes_t::fMapState
Int_t fMapState
kIsUnmapped, kIsUnviewable, kIsViewable
Definition: GuiTypes.h:130
ROOT::MacOSX::X11::CompareViewsToLower
NSComparisonResult CompareViewsToLower(id view1, id view2, void *context)
Definition: QuartzWindow.mm:736
ROOT::MacOSX::X11::Rectangle::fY
int fY
Definition: CocoaGuiTypes.h:22
WindowAttributes_t::fBackingPlanes
ULong_t fBackingPlanes
planes to be preserved if possible
Definition: GuiTypes.h:125
ROOT::MacOSX::X11::kPGActiveGrab
@ kPGActiveGrab
Definition: X11Events.h:45
QuartzPixmap.h
ROOT::MacOSX::Details::kLeftMouseDown
const NSEventType kLeftMouseDown
Definition: CocoaConstants.mm:44
-[QuartzWindow unmapWindow]
void unmapWindow()
Definition: QuartzWindow.mm:1708
ROOT::MacOSX::X11::kPGNoGrab
@ kPGNoGrab
Definition: X11Events.h:43
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4
WindowAttributes_t::fOverrideRedirect
Bool_t fOverrideRedirect
boolean value for override-redirect
Definition: GuiTypes.h:134
QuartzWindow::fContentView
QuartzView * fContentView
Definition: QuartzWindow.h:72
ROOT::MacOSX::X11::GlobalYCocoaToROOT
int GlobalYCocoaToROOT(CGFloat yCocoa)
Definition: QuartzWindow.mm:173
kWABackPixmap
const Mask_t kWABackPixmap
Definition: GuiTypes.h:139
ROOT::MacOSX::X11::ConvertPointFromScreenToBase
NSPoint ConvertPointFromScreenToBase(NSPoint screenPoint, NSWindow *window)
Definition: QuartzWindow.mm:157
ROOT::MacOSX::X11::ClipToShapeMask
void ClipToShapeMask(NSView< X11Window > *view, CGContextRef ctx)
Definition: QuartzWindow.mm:589
QuartzView::fPassiveKeyGrabs
NSMutableArray * fPassiveKeyGrabs
Definition: QuartzWindow.h:219
ROOT::MacOSX::Util::AutoreleasePool
Definition: CocoaUtils.h:168
QuartzWindowProperty::fPropertyData
NSData * fPropertyData
Definition: QuartzWindow.mm:1869
kButtonMotionMask
const Mask_t kButtonMotionMask
Definition: GuiTypes.h:164
PassiveKeyGrab::fKeyCode
unichar fKeyCode
Definition: QuartzWindow.h:176
ROOT::MacOSX::X11::CreateCursor
NSCursor * CreateCursor(ECursor currentCursor)
Definition: QuartzWindow.mm:841
int
ROOT::MacOSX::X11
Definition: CocoaGuiTypes.h:10
SetWindowAttributes_t
Attributes that can be used when creating or changing a window.
Definition: GuiTypes.h:93
ROOT::MacOSX::X11::CommandBuffer::RemoveGraphicsOperationsForWindow
void RemoveGraphicsOperationsForWindow(Window_t wid)
Definition: X11Buffer.mm:662
QuartzWindow
Definition: QuartzWindow.h:67