Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
49namespace ROOT {
50namespace MacOSX {
51namespace 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 |
68 kMiniaturizableWindowMask | kResizableWindowMask;
69
73 defer : YES
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//______________________________________________________________________________
85QuartzView *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
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");
113 assert(mainScreen != nil && "screen with index 0 is nil");
114
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
133 attr->fVisual = 0;
134 attr->fRoot = 0;
135}
136
137
138#pragma mark - Coordinate conversions.
139
140//______________________________________________________________________________
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?
152
153 return tmpRect.origin;
154}
155
156//______________________________________________________________________________
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.);
168
169 return tmpRect.origin;
170}
171
172//______________________________________________________________________________
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//______________________________________________________________________________
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//______________________________________________________________________________
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//______________________________________________________________________________
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//______________________________________________________________________________
219{
220 assert(parentView != nil && "LocalYCocoaToROOT, parent view is nil");
221
222 return int(parentView.frame.size.height - yCocoa);
223}
224
225//______________________________________________________________________________
227{
228 //:)
229 assert(parentView != nil && "LocalYROOTToCocoa, parent view is nil");
230
231 return int(parentView.frame.size.height - yROOT);
232}
233
234
235//______________________________________________________________________________
237{
238 //:)
239 assert(drawable != nil && "LocalYROOTToCocoa, drawable is nil");
240
241 return int(drawable.fHeight - yROOT);
242}
243
244//______________________________________________________________________________
245NSPoint 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);
254
255 return screenPoint;
256}
257
258//______________________________________________________________________________
259NSPoint 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//______________________________________________________________________________
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.
320
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.
329 if (ScreenPointIsInView(qw.fContentView, x, y))
330 return qw;
331 }
332
333 return nil;
334}
335
336//______________________________________________________________________________
339{
340 assert(children != nil && "FindDNDAwareViewInPoint, parameter 'children' is nil");
341
342 if (maxDepth <= 0)
343 return nil;
344
348 continue;
349 if (child.fIsDNDAware && child.fID != dragWinID && child.fID != inputWinID)
350 return child;//got it!
351
353 inputWinID, x, y, maxDepth - 1);
354 if (testView)
355 return testView;
356 }
357
358 return nil;
359}
360
361//______________________________________________________________________________
364{
365 //X and Y are ROOT's screen coordinates (Y is inverted).
366 if (maxDepth <= 0)
367 return nil;
368
370
371 if (!parentView) {//Start from the screen as a 'root' window.
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;
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];
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.
404 }
405}
406
407//______________________________________________________________________________
409{
411
414 if (![nsWindow isKindOfClass : [QuartzWindow class]])
415 continue;
416
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
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//______________________________________________________________________________
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
456 "FindWindowForPointerEvent, parameter 'pointerEvent' is nil");
457
459
462 if (![nsWindow isKindOfClass : [QuartzWindow class]])
463 continue;
464
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
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];
481 }
482
483 //convertScreenToBase is deprecated.
484 //mousePosition = [qWindow convertScreenToBase : mousePosition];
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
503 "FindViewForPointerEvent, parameter 'pointerEvent' is nil");
504
506
509 if ([pointerEvent window])
511
512 //convertScreenToBase is deprecated.
513 //mousePosition = [topLevel convertScreenToBase : mousePosition];
515
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!!!
525std::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
539 if (!colorSpace.Get()) {
540 NSLog(@"DownscaledImageData, CGColorSpaceCreateDeviceRGB failed");
541 return result;
542 }
543
545 w * 4, colorSpace.Get(),
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
567
570 if (![nsWindow isKindOfClass : [QuartzWindow class]])
571 continue;
572
574
575 if (qWindow.fIsDeleted || qWindow.fMapState != kIsViewable || qWindow.fID == winID)
576 continue;
577
578 if (qWindow.fContentView.fOverrideRedirect)
579 continue;
580
582 break;
583 }
584}
585
586#pragma mark - 'shape mask' - to create a window with arbitrary (probably non-rectangle) shape.
587
588//______________________________________________________________________________
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];
615 clipRect.origin.y + clipRect.size.height);
616
617 if (AdjustCropArea(topLevelParent.fShapeCombineMask, clipRect)) {
621 clipRect.origin = NSPoint();
623 } else {
624 //View is invisible.
625 CGRect 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
654 if ([(NSObject *)window isKindOfClass : [QuartzWindow class]]) {
655 QuartzWindow * const qw = (QuartzWindow *)window;
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
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
735#else
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
752#else
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//______________________________________________________________________________
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//______________________________________________________________________________
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);
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.
824
825 if (!cursorImage)
826 return nil;
827
831
832 [cursorImage release];
833
834 return customCursor;
835 }
836
837 return nil;
838}
839
840//______________________________________________________________________________
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
853 switch (currentCursor) {
854 case kCross:
856 break;
857 case kPointer:
859 break;
860 case kHand:
862 break;
863 case kLeftSide:
865 break;
866 case kRightSide:
868 break;
869 case kTopSide:
871 break;
872 case kBottomSide:
874 break;
875 case kCaret:
877 break;
878 case kRotate:
879 case kWatch:
880 default:
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//______________________________________________________________________________
897bool 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//______________________________________________________________________________
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//______________________________________________________________________________
941bool 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//______________________________________________________________________________
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
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
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]) {
1022 assert(nsContext != nil && "LockFocus, currentContext is nil");
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
1049namespace Quartz = ROOT::Quartz;
1050namespace Util = ROOT::MacOSX::Util;
1051namespace X11 = ROOT::MacOSX::X11;
1052namespace Details = ROOT::MacOSX::Details;
1053
1054#ifdef DEBUG_ROOT_COCOA
1055
1056#pragma mark - 'loggers'.
1057
1058namespace {
1059
1060//______________________________________________________________________________
1061void 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";
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//______________________________________________________________________________
1105{
1106 if (mask & kButtonPressMask)
1107 NSLog(@"button press mask");
1109 NSLog(@"button release mask");
1110 if (mask & kExposureMask)
1111 NSLog(@"exposure mask");
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) addXorCommand : (ROOT::MacOSX::X11::Command *) cmd
1131{
1132 xorOps.push_back(cmd);
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
1147
1148 CGContextSetRGBStrokeColor(cgContext, 0., 0., 0., 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
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.
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];
1221
1222 if (attr)
1224
1225 fIsDeleted = NO;
1226 fHasFocus = NO;
1228 }
1229
1230 return self;
1231}
1232
1233//______________________________________________________________________________
1234- (id) initWithGLView : (ROOTOpenGLView *) glView
1235{
1236 using namespace Details;
1237
1238 assert(glView != nil && "-initWithGLView, parameter 'glView' is nil");
1239
1240 const NSUInteger styleMask = kTitledWindowMask | kClosableWindowMask |
1242
1243 NSRect contentRect = glView.frame;
1244 contentRect.origin = NSPoint();
1245
1246 self = [super initWithContentRect : contentRect styleMask : styleMask
1247 backing : NSBackingStoreBuffered defer : NO];
1248
1249 if (self) {
1250 //ROOT's not able to draw GUI concurrently, thanks to global variables and gVirtualX itself.
1251 [self setAllowsConcurrentViewDrawing : NO];
1252 self.delegate = self;
1254 [self setContentView : fContentView];
1256 fIsDeleted = NO;
1257 fHasFocus = NO;
1259 }
1260
1261 return self;
1262}
1263
1264//______________________________________________________________________________
1265- (void) dealloc
1266{
1267 [fShapeCombineMask release];
1268 [super dealloc];
1269}
1270
1271//______________________________________________________________________________
1272- (BOOL) fIsDeleted
1273{
1274 return fIsDeleted;
1275}
1276
1277//______________________________________________________________________________
1278- (void) setContentView:(NSView *)cv
1279{
1280 [super setContentView:cv];
1283 else
1284 fContentView = nil;
1285}
1286
1287//______________________________________________________________________________
1288- (void) setFIsDeleted : (BOOL) deleted
1289{
1291}
1292
1293#pragma mark - Forwaring: I want to forward a lot of property setters/getters to the content view.
1294
1295//______________________________________________________________________________
1296- (void) forwardInvocation : (NSInvocation *) anInvocation
1297{
1298 if (!fContentView)
1299 return;
1300
1301 if ([fContentView respondsToSelector : [anInvocation selector]]) {
1302 [anInvocation invokeWithTarget : fContentView];
1303 } else {
1304 [super forwardInvocation : anInvocation];
1305 }
1306}
1307
1308//______________________________________________________________________________
1310{
1311 NSMethodSignature *signature = [super methodSignatureForSelector : selector];
1312
1313 if (!signature) {
1314 if (fContentView)
1315 signature = [fContentView methodSignatureForSelector : selector];
1316 }
1317
1318 return signature;
1319}
1320
1321//______________________________________________________________________________
1322- (void) addTransientWindow : (QuartzWindow *) window
1323{
1324 //Transient window: all the popups (menus, dialogs, popups, comboboxes, etc.)
1325 //always should be on the top of its 'parent' window.
1326 //To enforce this ordering, I have to connect such windows with parent/child
1327 //relation (it's not the same as a view hierarchy - both child and parent
1328 //windows are top-level windows).
1329
1330 assert(window != nil && "-addTransientWindow:, parameter 'window' is nil");
1331
1332 window.fMainWindow = self;
1333
1334 if (window.fMapState != kIsViewable) {
1335 //If I add it as child, it'll immediately make a window visible
1336 //and this thing sucks.
1337 window.fDelayedTransient = YES;
1338 } else {
1339 [self addChildWindow : window ordered : NSWindowAbove];
1340 window.fDelayedTransient = NO;
1341 }
1342}
1343
1344//______________________________________________________________________________
1345- (void) makeKeyAndOrderFront : (id) sender
1346{
1347#pragma unused(sender)
1348
1349 //The more I know Cocoa, the less I like it.
1350 //Window behavior between spaces is a total mess.
1351 //Set the window to join all spaces.
1352#ifdef MAC_OS_X_VERSION_10_9
1353 [self setCollectionBehavior : NSWindowCollectionBehaviorMoveToActiveSpace];
1354#else
1355 [self setCollectionBehavior : NSWindowCollectionBehaviorCanJoinAllSpaces];
1356#endif
1357 //now bring it to the front, it will appear on the active space.
1358 [super makeKeyAndOrderFront : self];
1359 //then reset the collection behavior to default, so the window
1360 [self setCollectionBehavior : NSWindowCollectionBehaviorDefault];
1361}
1362
1363//______________________________________________________________________________
1364- (void) setFDelayedTransient : (BOOL) d
1365{
1367}
1368
1369//______________________________________________________________________________
1371{
1372 return fShapeCombineMask;
1373}
1374
1375//______________________________________________________________________________
1376- (void) setFShapeCombineMask : (QuartzImage *) mask
1377{
1378 if (mask != fShapeCombineMask) {
1379 [fShapeCombineMask release];
1380 if (mask) {
1381 fShapeCombineMask = [mask retain];
1382 //TODO: Check window's shadow???
1383 }
1384 }
1385}
1386
1387#pragma mark - X11Drawable's protocol.
1388
1389//______________________________________________________________________________
1390- (BOOL) fIsPixmap
1391{
1392 //Never.
1393 return NO;
1394}
1395
1396//______________________________________________________________________________
1397- (BOOL) fIsOpenGLWidget
1398{
1399 //Never.
1400 return NO;
1401}
1402
1403//______________________________________________________________________________
1404- (CGFloat) fScaleFactor
1405{
1406 if (!self.screen)
1407 return 1.;
1408 return self.screen.backingScaleFactor;
1409}
1410
1411//______________________________________________________________________________
1412- (int) fX
1413{
1414 return X11::GlobalXCocoaToROOT(self.frame.origin.x);
1415}
1416
1417//______________________________________________________________________________
1418- (int) fY
1419{
1420 return X11::GlobalYCocoaToROOT(self.frame.origin.y + self.frame.size.height);
1421}
1422
1423//______________________________________________________________________________
1424- (unsigned) fWidth
1425{
1426 return self.frame.size.width;
1427}
1428
1429//______________________________________________________________________________
1430- (unsigned) fHeight
1431{
1432 //NSWindow's frame (height component) also includes title-bar.
1433 //So I have to use content view's height.
1434 //Obviously, there is a "hole" == 22 pixels.
1435 assert(fContentView != nil && "-fHeight:, content view is nil");
1436
1437 return fContentView.frame.size.height;
1438}
1439
1440//______________________________________________________________________________
1441- (void) setDrawableSize : (NSSize) newSize
1442{
1443 //Can not simply do self.frame.size = newSize.
1444 assert(!(newSize.width < 0) && "-setDrawableSize:, width is negative");
1445 assert(!(newSize.height < 0) && "-setDrawableSize:, height is negative");
1446
1447 NSRect frame = self.frame;
1448 // Some sanity check (rather random and inconsistent, based on the recent M1 crash/assert):
1449 if (frame.origin.x < -100000. || frame.origin.x > 100000.) {
1450 // Hope nobody has screens like this!
1451 NSLog(@"Attempting to set a frame with X: %g", frame.origin.x);
1452 frame.origin.x = 0.; // Otherwise, AppKit seems to use uint(-1) to initialise frames ... sometimes?
1453 }
1454 //dY is potentially a titlebar height.
1455 const CGFloat dY = fContentView ? frame.size.height - fContentView.frame.size.height : 0.;
1456 //Adjust the frame.
1457 frame.origin.y = frame.origin.y + frame.size.height - newSize.height - dY;
1458 frame.size = newSize;
1459 frame.size.height += dY;
1460 [self setFrame : frame display : YES];
1461}
1462
1463//______________________________________________________________________________
1464- (void) setX : (int) x Y : (int) y width : (unsigned) w height : (unsigned) h
1465{
1466 NSSize newSize = {};
1467 newSize.width = w;
1468 newSize.height = h;
1469 [self setContentSize : newSize];
1470
1471 //Check how this is affected by title bar's height.
1472 NSPoint topLeft = {};
1475
1476 [self setFrameTopLeftPoint : topLeft];
1477}
1478
1479//______________________________________________________________________________
1480- (void) setX : (int) x Y : (int) y
1481{
1482 NSPoint topLeft = {};
1485
1486 [self setFrameTopLeftPoint : topLeft];
1487}
1488
1489//______________________________________________________________________________
1490- (void) copy : (NSObject<X11Drawable> *) src area : (X11::Rectangle) area withMask : (QuartzImage *) mask
1491 clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
1492{
1493 if (!fContentView)
1494 return;
1495
1496 [fContentView copy : src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
1497}
1498
1499//______________________________________________________________________________
1500- (unsigned char *) readColorBits : (X11::Rectangle) area
1501{
1502 if (!fContentView)
1503 return nullptr;
1504
1505 return [fContentView readColorBits : area];
1506}
1507
1508#pragma mark - XorDrawinWindow/View
1509
1510//______________________________________________________________________________
1512{
1513 auto res = [self findXorWindow];
1514 if (res)
1515 return res;
1516
1517 XorDrawingWindow *special = [[XorDrawingWindow alloc] init];
1518 res = special;
1519 [self adjustXorWindowGeometry : special];
1520 [self addChildWindow : special ordered : NSWindowAbove];
1521 [special release];
1522 return res;
1523}
1524
1525//______________________________________________________________________________
1527{
1528 assert(win && "invalid (nil) parameter 'win'");
1529 auto frame = self.contentView.frame;
1530 frame = [self convertRectToScreen:frame];
1531 [win setFrame:frame display:NO];
1532}
1533
1534//______________________________________________________________________________
1535- (void) removeXorWindow
1536{
1537 if (auto win = [self findXorWindow]) {
1538 // For some reason, without ordeing out, the crosshair window's content stays
1539 // in the parent's window. Thus we first have to order out the crosshair window.
1540 [win orderOut:nil];
1541 [self removeChildWindow : win];
1542 }
1543}
1544
1545//______________________________________________________________________________
1547{
1548 auto children = [self childWindows];
1549 for (NSWindow *child in children) {
1552 }
1553 return nil;
1554}
1555
1556//______________________________________________________________________________
1557- (void) addXorLine : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2
1558{
1559 auto xorWindow = [self addXorWindow];
1560
1561 try {
1562 auto cmd = std::make_unique<ROOT::MacOSX::X11::DrawLineXor>(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2));
1563 cmd->setView(view);
1564
1565 auto cv = (XorDrawingView *)xorWindow.contentView;
1566 [cv addXorCommand : cmd.get()];
1567 cmd.release();
1568 [cv setNeedsDisplay : YES];
1569
1570 } catch (const std::exception &) {
1571 throw;
1572 }
1573}
1574
1575//______________________________________________________________________________
1576- (void) addXorBox : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2
1577{
1578 auto xorWindow = [self addXorWindow];
1579
1580 try {
1581 auto cmd = std::make_unique<ROOT::MacOSX::X11::DrawBoxXor>(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2));
1582 cmd->setView(view);
1583
1584 auto cv = (XorDrawingView *)xorWindow.contentView;
1585 [cv addXorCommand : cmd.get()];
1586 cmd.release();
1587 [cv setNeedsDisplay : YES];
1588 } catch (const std::exception &) {
1589 throw;
1590 }
1591}
1592
1593//______________________________________________________________________________
1594- (void) addXorPolyLine : (QuartzView *) view : (Int_t) n : (TPoint *) pnts : (const TAttLine &) att
1595{
1596 auto xorWindow = [self addXorWindow];
1597
1598 try {
1599 auto cmd = std::make_unique<ROOT::MacOSX::X11::DrawPolyLineXor>(-1, att);
1600 cmd->setView(view);
1601 cmd->setPoints(n, pnts);
1602
1603 auto cv = (XorDrawingView *)xorWindow.contentView;
1604 [cv addXorCommand : cmd.get()];
1605 cmd.release();
1606 [cv setNeedsDisplay : YES];
1607
1608 } catch (const std::exception &) {
1609 throw;
1610 }
1611}
1612
1613//______________________________________________________________________________
1614- (void) addXorMarker : (QuartzView *) view : (Int_t) n : (TPoint *) pnts : (const TAttMarker &) att
1615{
1616 auto xorWindow = [self addXorWindow];
1617
1618 try {
1619 auto cmd = std::make_unique<ROOT::MacOSX::X11::DrawMarkerXor>(-1, att);
1620 cmd->setView(view);
1621 cmd->setPoints(n, pnts);
1622
1623 auto cv = (XorDrawingView *)xorWindow.contentView;
1624 [cv addXorCommand : cmd.get()];
1625 cmd.release();
1626 [cv setNeedsDisplay : YES];
1627
1628 } catch (const std::exception &) {
1629 throw;
1630 }
1631}
1632
1633//______________________________________________________________________________
1634- (void) setDrawMode : (TVirtualX::EDrawMode) newMode
1635{
1637 [self removeXorWindow];
1638
1640}
1641
1642//______________________________________________________________________________
1643- (TVirtualX::EDrawMode) getDrawMode
1644{
1645 return fDrawMode;
1646}
1647
1648
1649#pragma mark - X11Window protocol's implementation.
1650
1651//______________________________________________________________________________
1653{
1654 return nil;
1655}
1656
1657//______________________________________________________________________________
1658- (void) setFParentView : (QuartzView *) parent
1659{
1660#pragma unused(parent)
1661}
1662
1663//______________________________________________________________________________
1665{
1666 return fContentView;
1667}
1668
1669//______________________________________________________________________________
1671{
1672 return self;
1673}
1674
1675//... many forwards to fContentView.
1676
1677//______________________________________________________________________________
1678- (void) setFBackgroundPixel : (unsigned long) backgroundColor
1679{
1680 if (!fContentView)
1681 return;
1682
1683 if (!fShapeCombineMask) {
1684 CGFloat rgba[] = {0., 0., 0., 1.};
1686
1687 [self setBackgroundColor : [NSColor colorWithColorSpace : [NSColorSpace deviceRGBColorSpace] components : rgba count : 4]];
1688 }
1689
1691}
1692
1693//______________________________________________________________________________
1694- (unsigned long) fBackgroundPixel
1695{
1696 if (!fContentView)
1697 return 0;
1698
1700}
1701
1702//______________________________________________________________________________
1703- (int) fMapState
1704{
1705 //Top-level window can be only kIsViewable or kIsUnmapped (not unviewable).
1706 if (!fContentView)
1707 return kIsUnmapped;
1708
1709 if ([fContentView isHidden])
1710 return kIsUnmapped;
1711
1712 return kIsViewable;
1713}
1714
1715//______________________________________________________________________________
1716- (void) addChild : (NSView<X11Window> *) child
1717{
1718 assert(child != nil && "-addChild:, parameter 'child' is nil");
1719
1720 if (!fContentView) {
1721 //This can happen only in case of re-parent operation.
1723 "-addChild: gl view in a top-level window as content view is not supported");
1724
1726 [self setContentView : child];
1728 } else
1729 [fContentView addChild : child];
1730}
1731
1732//______________________________________________________________________________
1733- (void) getAttributes : (WindowAttributes_t *) attr
1734{
1735 if (!fContentView)
1736 return;
1737
1738 assert(attr && "-getAttributes:, parameter 'attr' is nil");
1739
1741}
1742
1743//______________________________________________________________________________
1744- (void) setAttributes : (const SetWindowAttributes_t *) attr
1745{
1746 assert(attr != 0 && "-setAttributes:, parameter 'attr' is null");
1747
1748#ifdef DEBUG_ROOT_COCOA
1749 log_attributes(attr, self.fID);
1750#endif
1751
1753}
1754
1755//______________________________________________________________________________
1756- (void) mapRaised
1757{
1758 if (!fContentView)
1759 return;
1760
1762
1763 [fContentView setHidden : NO];
1764 [self makeKeyAndOrderFront : self];
1765 [fContentView configureNotifyTree];
1766
1767 if (fDelayedTransient) {
1769 [fMainWindow addChildWindow : self ordered : NSWindowAbove];
1770 }
1771}
1772
1773//______________________________________________________________________________
1774- (void) mapWindow
1775{
1776 if (!fContentView)
1777 return;
1778
1780
1781 [fContentView setHidden : NO];
1782 [self makeKeyAndOrderFront : self];
1783 [fContentView configureNotifyTree];
1784
1785 if (fDelayedTransient) {
1787 [fMainWindow addChildWindow : self ordered : NSWindowAbove];
1788 }
1789}
1790
1791//______________________________________________________________________________
1792- (void) mapSubwindows
1793{
1794 if (!fContentView)
1795 return;
1796
1798
1799 [fContentView mapSubwindows];
1800 [fContentView configureNotifyTree];
1801}
1802
1803//______________________________________________________________________________
1804- (void) unmapWindow
1805{
1806 if (!fContentView)
1807 return;
1808
1809 [fContentView setHidden : YES];
1810 [self orderOut : self];
1811
1813 [fMainWindow removeChildWindow : self];
1814 fMainWindow = nil;
1815 }
1816}
1817
1818#pragma mark - Events.
1819
1820//______________________________________________________________________________
1821- (void) sendEvent : (NSEvent *) theEvent
1822{
1823 //With XQuartz, if you open a menu and try to move a window without closing this menu,
1824 //window does not move, menu closes, and after that you can start draggin a window again.
1825 //With Cocoa I can not do such a thing (window WILL move), but still can report button release event
1826 //to close a menu.
1827 if (!fContentView)
1828 return;
1829
1831 bool generateFakeRelease = false;
1832
1833 const NSPoint windowPoint = [theEvent locationInWindow];
1834
1835 if (windowPoint.x <= 4 || windowPoint.x >= self.fWidth - 4)
1836 generateFakeRelease = true;
1837
1838 if (windowPoint.y <= 4 || windowPoint.y >= self.fHeight - 4)
1839 generateFakeRelease = true;
1840
1841 const NSPoint viewPoint = [fContentView convertPoint : windowPoint fromView : nil];
1842
1843 if (viewPoint.y <= 0 && windowPoint.y >= 0)
1844 generateFakeRelease = true;
1845
1846 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1847 "-sendEvent:, gVirtualX is either null or not of TGCocoa type");
1848
1849 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
1850 if (vx->GetEventTranslator()->HasPointerGrab() && generateFakeRelease) {
1851 vx->GetEventTranslator()->GenerateButtonReleaseEvent(fContentView, theEvent,
1853 kButton1 : kButton3);
1854 //Yes, ignore this event completely (this means, you are not able to immediately start
1855 //resizing a window, if some popup is open. Actually, this is more or less
1856 //the same as with XQuartz and X11 version.
1857 return;
1858 }
1859 }
1860
1861 [super sendEvent : theEvent];
1862}
1863
1864#pragma mark - NSWindowDelegate's methods.
1865
1866//______________________________________________________________________________
1867- (BOOL) windowShouldClose : (id) sender
1868{
1869#pragma unused(sender)
1870 if (!fContentView)
1871 return NO;
1872
1873 if ([[self childWindows] count])
1874 return NO;
1875
1876 //Prepare client message for a window.
1877 Event_t closeEvent = {};
1878 closeEvent.fWindow = fContentView.fID;
1879 closeEvent.fType = kClientMessage;
1880 closeEvent.fFormat = 32;//Taken from GUI classes.
1883 //Place it into the queue.
1884 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1885 "-windowShouldClose:, gVirtualX is either null or has a type different from TGCocoa");
1886 ((TGCocoa *)gVirtualX)->SendEvent(fContentView.fID, &closeEvent);
1887
1888 //Do not let AppKit to close a window,
1889 //ROOT will do.
1890 return NO;
1891}
1892
1893//______________________________________________________________________________
1894- (void) windowDidBecomeKey : (NSNotification *) aNotification
1895{
1896#pragma unused(aNotification)
1897
1898 if (!fContentView)
1899 return;
1900
1902 fHasFocus = YES;
1903 //
1904 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1905 "-windowDidBecomeKey:, gVirtualX is null or not of TGCocoa type");
1906 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
1907 vx->GetEventTranslator()->GenerateFocusChangeEvent(self.fContentView);
1908 }
1909}
1910
1911
1912//______________________________________________________________________________
1913- (void) windowDidResignKey : (NSNotification *) aNotification
1914{
1915#pragma unused(aNotification)
1916 fHasFocus = NO;
1917}
1918
1919@end
1920
1921#pragma mark - Passive key grab info.
1922
1923@implementation PassiveKeyGrab
1924
1925//______________________________________________________________________________
1926- (id) initWithKey : (unichar) keyCode modifiers : (NSUInteger) modifiers
1927{
1928 if (self = [super init]) {
1929 fKeyCode = keyCode;
1931 }
1932
1933 return self;
1934}
1935
1936//______________________________________________________________________________
1937- (BOOL) matchKey : (unichar) keyCode modifiers : (NSUInteger) modifiers
1938{
1939 return keyCode == fKeyCode && modifiers == fModifiers;
1940}
1941
1942//______________________________________________________________________________
1943- (BOOL) matchKey : (unichar) keyCode
1944{
1945 return keyCode == fKeyCode;
1946}
1947
1948//______________________________________________________________________________
1949- (unichar) fKeyCode
1950{
1951 return fKeyCode;
1952}
1953
1954//______________________________________________________________________________
1955- (NSUInteger) fModifiers
1956{
1957 return fModifiers;
1958}
1959
1960@end
1961
1962#pragma mark - X11 property emulation.
1963
1967 unsigned fFormat;
1968}
1969
1970@property (nonatomic, readonly) Atom_t fType;
1971
1972@end
1973
1974@implementation QuartzWindowProperty
1975
1976@synthesize fType;
1977
1978//______________________________________________________________________________
1979- (id) initWithData : (unsigned char *) data size : (unsigned) dataSize type : (Atom_t) type format : (unsigned) format
1980{
1981 if (self = [super init]) {
1982 //Memory is zero-initialized, but just to make it explicit:
1984 fType = 0;
1985 fFormat = 0;
1986
1987 [self resetPropertyData : data size : dataSize type : type format : format];
1988 }
1989
1990 return self;
1991}
1992
1993//______________________________________________________________________________
1994- (void) dealloc
1995{
1996 [fPropertyData release];
1997
1998 [super dealloc];
1999}
2000
2001//______________________________________________________________________________
2002- (void) resetPropertyData : (unsigned char *) data size : (unsigned) dataSize
2003 type : (Atom_t) type format : (unsigned) format
2004{
2005 [fPropertyData release];
2006
2007 fFormat = format;
2008 if (format == 16)
2009 dataSize *= 2;
2010 else if (format == 32)
2011 dataSize *= 4;
2012
2013 fPropertyData = [[NSData dataWithBytes : data length : dataSize] retain];
2014
2015 fType = type;
2016}
2017
2018//______________________________________________________________________________
2020{
2021 return fPropertyData;
2022}
2023
2024//______________________________________________________________________________
2025- (unsigned) fFormat
2026{
2027 return fFormat;
2028}
2029
2030@end
2031
2032#pragma mark - QuartzView.
2033
2034//
2035//QuartzView is a children view (also is a content view for a top-level QuartzWindow).
2036//
2037
2038@implementation QuartzView
2039
2040@synthesize fID;
2041@synthesize fContext;
2042/////////////////////
2043//SetWindowAttributes_t/WindowAttributes_t
2044@synthesize fEventMask;
2045@synthesize fClass;
2046@synthesize fDepth;
2047@synthesize fBitGravity;
2048@synthesize fWinGravity;
2049@synthesize fBackgroundPixel;
2050@synthesize fOverrideRedirect;
2051//SetWindowAttributes_t/WindowAttributes_t
2052/////////////////////
2053@synthesize fHasFocus;
2054@synthesize fParentView;
2055
2056@synthesize fPassiveGrabButton;
2057@synthesize fPassiveGrabEventMask;
2058@synthesize fPassiveGrabKeyModifiers;
2059@synthesize fActiveGrabEventMask;
2060@synthesize fPassiveGrabOwnerEvents;
2061@synthesize fSnapshotDraw;
2062@synthesize fCurrentCursor;
2063@synthesize fIsDNDAware;
2064
2065#pragma mark - Lifetime.
2066
2067//______________________________________________________________________________
2068- (id) initWithFrame : (NSRect) frame windowAttributes : (const SetWindowAttributes_t *)attr
2069{
2070 if (self = [super initWithFrame : frame]) {
2071 //Make this explicit (though memory is zero initialized).
2072 fBackBuffer = nil;
2073 fID = 0;
2074
2075 fDirectDraw = NO;
2076
2077 //Passive grab parameters.
2078 fPassiveGrabButton = -1;//0 is kAnyButton.
2081
2082 fPassiveKeyGrabs = [[NSMutableArray alloc] init];
2083
2084 [self setCanDrawConcurrently : NO];
2085
2086 [self setHidden : YES];
2087 //Actually, check if view need this.
2088 //
2089 if (attr)
2091
2093 fX11Properties = [[NSMutableDictionary alloc] init];
2094
2098 }
2099
2100 return self;
2101}
2102
2103//______________________________________________________________________________
2104- (void) dealloc
2105{
2106 [fBackBuffer release];
2107 [fPassiveKeyGrabs release];
2108 [fX11Properties release];
2109 [fBackgroundPixmap release];
2110 [super dealloc];
2111}
2112
2113#pragma mark - Tracking area.
2114
2115//Tracking area is required to ... track mouse motion events inside a view.
2116
2117//______________________________________________________________________________
2118- (void) updateTrackingAreas
2119{
2120 [super updateTrackingAreas];
2121
2122 if (!fID)
2123 return;
2124
2126
2128 const NSUInteger size = [trackingArray count];
2129 for (NSUInteger i = 0; i < size; ++i) {
2130 NSTrackingArea * const t = [trackingArray objectAtIndex : i];
2131 [self removeTrackingArea : t];
2132 }
2133 }
2134
2138
2139 NSRect frame = {};
2140 frame.size.width = self.fWidth;
2141 frame.size.height = self.fHeight;
2142
2143 NSTrackingArea * const tracker = [[NSTrackingArea alloc] initWithRect : frame
2144 options : trackerOptions owner : self userInfo : nil];
2145 [self addTrackingArea : tracker];
2146 [tracker release];
2147}
2148
2149//______________________________________________________________________________
2151{
2152 [self updateTrackingAreas];
2153
2156}
2157
2158#pragma mark - X11Drawable protocol.
2159
2160//______________________________________________________________________________
2161- (BOOL) fIsPixmap
2162{
2163 return NO;
2164}
2165
2166//______________________________________________________________________________
2167- (BOOL) fIsOpenGLWidget
2168{
2169 return NO;
2170}
2171
2172//______________________________________________________________________________
2173- (CGFloat) fScaleFactor
2174{
2175 return self.fQuartzWindow.fScaleFactor;
2176}
2177
2178//______________________________________________________________________________
2179- (int) fX
2180{
2181 return self.frame.origin.x;
2182}
2183
2184//______________________________________________________________________________
2185- (int) fY
2186{
2187 return self.frame.origin.y;
2188}
2189
2190//______________________________________________________________________________
2191- (unsigned) fWidth
2192{
2193 return self.frame.size.width;
2194}
2195
2196//______________________________________________________________________________
2197- (unsigned) fHeight
2198{
2199 return self.frame.size.height;
2200}
2201
2202//______________________________________________________________________________
2203- (void) setDrawableSize : (NSSize) newSize
2204{
2205 assert(!(newSize.width < 0) && "-setDrawableSize, width is negative");
2206 assert(!(newSize.height < 0) && "-setDrawableSize, height is negative");
2207
2208 //This will cause redraw(?)
2209
2210 //In X11, resize changes the size, but upper-left corner is not changed.
2211 //In Cocoa, bottom-left is fixed.
2212 NSRect frame = self.frame;
2213 frame.size = newSize;
2214
2215 self.frame = frame;
2216}
2217
2218//______________________________________________________________________________
2219- (TAttLine *) attLine
2220{
2221 return &fAttLine;
2222}
2223
2224//______________________________________________________________________________
2225- (TAttFill *) attFill
2226{
2227 return &fAttFill;
2228}
2229
2230//______________________________________________________________________________
2232{
2233 return &fAttMarker;
2234}
2235
2236//______________________________________________________________________________
2237- (TAttText *) attText
2238{
2239 return &fAttText;
2240}
2241
2242//______________________________________________________________________________
2243- (void) setDrawMode : (TVirtualX::EDrawMode) newMode
2244{
2245 [self.fQuartzWindow setDrawMode:newMode];
2246}
2247
2248//______________________________________________________________________________
2249- (TVirtualX::EDrawMode) getDrawMode
2250{
2251 return [self.fQuartzWindow getDrawMode];
2252}
2253
2254//______________________________________________________________________________
2255- (void) setDirectDraw : (BOOL) mode
2256{
2257 fDirectDraw = mode;
2258
2259 // while painting operates with the pixmap, set direct flag for it too
2260 if (fBackBuffer)
2261 [fBackBuffer setDirectDraw : mode];
2262}
2263
2264//______________________________________________________________________________
2265- (BOOL) isDirectDraw
2266{
2267 return fDirectDraw;
2268}
2269
2270//______________________________________________________________________________
2271- (void) setX : (int) x Y : (int) y width : (unsigned) w height : (unsigned) h
2272{
2273 NSRect newFrame = {};
2274 newFrame.origin.x = x;
2275 newFrame.origin.y = y;
2276 newFrame.size.width = w;
2277 newFrame.size.height = h;
2278
2279 self.frame = newFrame;
2280}
2281
2282//______________________________________________________________________________
2283- (void) setX : (int) x Y : (int) y
2284{
2285 NSRect newFrame = self.frame;
2286 newFrame.origin.x = x;
2287 newFrame.origin.y = y;
2288
2289 self.frame = newFrame;
2290}
2291
2292//______________________________________________________________________________
2293- (void) copyImage : (QuartzImage *) srcImage area : (X11::Rectangle) area
2294 withMask : (QuartzImage *) mask clipOrigin : (X11::Point) clipXY
2295 toPoint : (X11::Point) dstPoint
2296{
2297 //Check parameters.
2298 assert(srcImage != nil &&
2299 "-copyImage:area:withMask:clipOrigin:toPoint:, parameter 'srcImage' is nil");
2300 assert(srcImage.fImage != nil &&
2301 "-copyImage:area:withMask:clipOrigin:toPoint:, srcImage.fImage is nil");
2302
2303 //Check self.
2304 assert(self.fContext != 0 &&
2305 "-copyImage:area:withMask:clipOrigin:toPoint:, self.fContext is null");
2306
2308 NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2309 " srcRect and copyRect do not intersect");
2310 return;
2311 }
2312
2313 //No RAII for subImage, since it can be really subimage or image itself and
2314 //in these cases there is no need to release image.
2315 CGImageRef subImage = 0;
2316 bool needSubImage = false;
2317 if (area.fX || area.fY || area.fWidth != srcImage.fWidth || area.fHeight != srcImage.fHeight) {
2318 needSubImage = true;
2320 if (!subImage) {
2321 NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2322 " subimage creation failed");
2323 return;
2324 }
2325 } else
2326 subImage = srcImage.fImage;
2327
2328 //Save context state.
2329 const Quartz::CGStateGuard ctxGuard(self.fContext);
2330
2331 //Scale and translate to undo isFlipped.
2332 CGContextTranslateCTM(self.fContext, 0., self.fHeight);
2333 CGContextScaleCTM(self.fContext, 1., -1.);
2334 //Set clip mask on a context.
2335
2336 if (mask) {
2337 assert(mask.fImage != nil &&
2338 "-copyImage:area:withMask:clipOrigin:toPoint:, mask.fImage is nil");
2339 assert(CGImageIsMask(mask.fImage) == true &&
2340 "-copyImage:area:withMask:clipOrigin:toPoint:, mask.fImage is not a mask");
2341 //clipXY.fY = X11::LocalYROOTToCocoa(self, clipXY.fY + mask.fHeight);
2342 const CGFloat clipY = X11::LocalYROOTToCocoa(self, CGFloat(clipXY.fY) + mask.fHeight);
2343 //const CGRect clipRect = CGRectMake(clipXY.fX, clipXY.fY, mask.fWidth, mask.fHeight);
2344 const CGRect clipRect = CGRectMake(clipXY.fX, clipY, mask.fWidth, mask.fHeight);
2345 CGContextClipToMask(self.fContext, clipRect, mask.fImage);
2346 }
2347
2348 //Convert from X11 to Cocoa (as soon as we scaled y * -1).
2349 //dstPoint.fY = X11::LocalYROOTToCocoa(self, dstPoint.fY + area.fHeight);
2350 const CGFloat dstY = X11::LocalYROOTToCocoa(self, CGFloat(dstPoint.fY) + area.fHeight);
2351 //const CGRect imageRect = CGRectMake(dstPoint.fX, dstPoint.fY, area.fWidth, area.fHeight);
2352 const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2354
2355 if (needSubImage)
2357}
2358
2359//______________________________________________________________________________
2360- (void) copyView : (QuartzView *) srcView area : (X11::Rectangle) area toPoint : (X11::Point) dstPoint
2361{
2362 //To copy one "window" to another "window", I have to ask source QuartzView to draw intself into
2363 //bitmap, and copy this bitmap into the destination view.
2364
2365 assert(srcView != nil && "-copyView:area:toPoint:, parameter 'srcView' is nil");
2366
2367 const NSRect frame = [srcView frame];
2368 //imageRep is in autorelease pool now.
2369 NSBitmapImageRep * const imageRep = [srcView bitmapImageRepForCachingDisplayInRect : frame];
2370 if (!imageRep) {
2371 NSLog(@"QuartzView: -copyView:area:toPoint failed");
2372 return;
2373 }
2374
2375 assert(srcView != nil && "-copyView:area:toPoint:, parameter 'srcView' is nil");
2376 assert(self.fContext != 0 && "-copyView:area:toPoint, self.fContext is null");
2377
2378 //It can happen, that src and self are the same.
2379 //cacheDisplayInRect calls drawRect with bitmap context
2380 //(and this will reset self.fContext: I have to save/restore it.
2381 CGContextRef ctx = srcView.fContext;
2382 srcView.fSnapshotDraw = YES;
2383 [srcView cacheDisplayInRect : frame toBitmapImageRep : imageRep];
2384 srcView.fSnapshotDraw = NO;
2385 srcView.fContext = ctx;
2386
2387 const CGRect subImageRect = CGRectMake(area.fX, area.fY, area.fWidth, area.fHeight);
2389
2390 if (!subImage.Get()) {
2391 NSLog(@"QuartzView: -copyView:area:toPoint, CGImageCreateWithImageInRect failed");
2392 return;
2393 }
2394
2395 const Quartz::CGStateGuard ctxGuard(self.fContext);
2397 [self visibleRect].size.height - (CGFloat(dstPoint.fY) + area.fHeight),
2398 area.fWidth, area.fHeight);
2399
2400 CGContextTranslateCTM(self.fContext, 0., [self visibleRect].size.height);
2401 CGContextScaleCTM(self.fContext, 1., -1.);
2402
2403 CGContextDrawImage(self.fContext, imageRect, subImage.Get());
2404}
2405
2406//______________________________________________________________________________
2407- (void) copyPixmap : (QuartzPixmap *) srcPixmap area : (X11::Rectangle) area
2408 withMask : (QuartzImage *) mask clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
2409{
2410 //Check parameters.
2411 assert(srcPixmap != nil && "-copyPixmap:area:withMask:clipOrigin:toPoint:, parameter 'srcPixmap' is nil");
2412
2414 NSLog(@"QuartzView: -copyPixmap:area:withMask:clipOrigin:toPoint,"
2415 " no intersection between pixmap rectangle and cropArea");
2416 return;
2417 }
2418
2419 //Check self.
2420 assert(self.fContext != 0 &&
2421 "-copyPixmap:area:withMask:clipOrigin:toPoint:, self.fContext is null");
2422
2423 //Save context state.
2424 const Quartz::CGStateGuard ctxGuard(self.fContext);
2425
2426 CGContextTranslateCTM(self.fContext, 0., self.frame.size.height);//???
2427 CGContextScaleCTM(self.fContext, 1., -1.);
2428
2429 const Util::CFScopeGuard<CGImageRef> imageFromPixmap([srcPixmap createImageFromPixmap]);
2430 assert(imageFromPixmap.Get() != 0 &&
2431 "-copyPixmap:area:withMask:clipOrigin:toPoint:, createImageFromPixmap failed");
2432
2433 CGImageRef subImage = 0;
2434 bool needSubImage = false;
2435 if (area.fX || area.fY || area.fWidth != srcPixmap.fWidth || area.fHeight != srcPixmap.fHeight) {
2436 needSubImage = true;
2437 const CGRect subImageRect = CGRectMake(area.fX, area.fY, area.fHeight, area.fWidth);
2439 if (!subImage) {
2440 NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2441 " subimage creation failed");
2442 return;
2443 }
2444 } else
2445 subImage = imageFromPixmap.Get();
2446
2447 if (mask) {
2448 assert(mask.fImage != nil &&
2449 "-copyPixmap:area:withMask:clipOrigin:toPoint:, mask.fImage is nil");
2450 assert(CGImageIsMask(mask.fImage) == true &&
2451 "-copyPixmap:area:withMask:clipOrigin:toPoint:, mask.fImage is not a mask");
2452
2453 //clipXY.fY = X11::LocalYROOTToCocoa(self, clipXY.fY + mask.fHeight);
2454 const CGFloat clipY = X11::LocalYROOTToCocoa(self, CGFloat(clipXY.fY) + mask.fHeight);
2455 //const CGRect clipRect = CGRectMake(clipXY.fX, clipXY.fY, mask.fWidth, mask.fHeight);
2456 const CGRect clipRect = CGRectMake(clipXY.fX, clipY, mask.fWidth, mask.fHeight);
2457 CGContextClipToMask(self.fContext, clipRect, mask.fImage);
2458 }
2459
2460 //dstPoint.fY = X11::LocalYCocoaToROOT(self, dstPoint.fY + area.fHeight);
2461 const CGFloat dstY = X11::LocalYCocoaToROOT(self, CGFloat(dstPoint.fY) + area.fHeight);
2462 const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2464
2465 if (needSubImage)
2467}
2468
2469
2470//______________________________________________________________________________
2471- (void) copyImage : (QuartzImage *) srcImage area : (X11::Rectangle) area
2472 toPoint : (X11::Point) dstPoint
2473{
2474 assert(srcImage != nil && "-copyImage:area:toPoint:, parameter 'srcImage' is nil");
2475 assert(srcImage.fImage != nil && "-copyImage:area:toPoint:, srcImage.fImage is nil");
2476 assert(self.fContext != 0 && "-copyImage:area:toPoint:, fContext is null");
2477
2479 NSLog(@"QuartzView: -copyImage:area:toPoint, image and copy area do not intersect");
2480 return;
2481 }
2482
2483 CGImageRef subImage = 0;
2484 bool needSubImage = false;
2485 if (area.fX || area.fY || area.fWidth != srcImage.fWidth || area.fHeight != srcImage.fHeight) {
2486 needSubImage = true;
2488 if (!subImage) {
2489 NSLog(@"QuartzView: -copyImage:area:toPoint:, subimage creation failed");
2490 return;
2491 }
2492 } else
2493 subImage = srcImage.fImage;
2494
2495 const Quartz::CGStateGuard ctxGuard(self.fContext);
2496
2497 CGContextTranslateCTM(self.fContext, 0., self.fHeight);
2498 CGContextScaleCTM(self.fContext, 1., -1.);
2499
2500 //dstPoint.fY = X11::LocalYCocoaToROOT(self, dstPoint.fY + area.fHeight);
2501 const CGFloat dstY = X11::LocalYCocoaToROOT(self, CGFloat(dstPoint.fY) + area.fHeight);
2502 //const CGRect imageRect = CGRectMake(dstPoint.fX, dstPoint.fY, area.fWidth, area.fHeight);
2503 const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2505
2506 if (needSubImage)
2508}
2509
2510//______________________________________________________________________________
2511- (void) copy : (NSObject<X11Drawable> *) src area : (X11::Rectangle) area
2512 withMask : (QuartzImage *)mask clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
2513{
2514 assert(src != nil && "-copy:area:withMask:clipOrigin:toPoint:, parameter 'src' is nil");
2515 assert(area.fWidth && area.fHeight && "-copy:area:withMask:clipOrigin:toPoint:, area to copy is empty");
2516
2517 if ([src isKindOfClass : [QuartzWindow class]]) {
2518 //Forget about mask (can I have it???)
2519 QuartzWindow * const qw = (QuartzWindow *)src;
2520 //Will not work with OpenGL.
2521 [self copyView : (QuartzView *)qw.fContentView area : area toPoint : dstPoint];
2522 } else if ([src isKindOfClass : [QuartzView class]]) {
2523 //Forget about mask (can I have it???)
2524 [self copyView : (QuartzView *)src area : area toPoint : dstPoint];
2525 } else if ([src isKindOfClass : [QuartzPixmap class]]) {
2526 [self copyPixmap : (QuartzPixmap *)src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
2527 } else if ([src isKindOfClass : [QuartzImage class]]) {
2528 [self copyImage : (QuartzImage *)src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
2529 } else {
2530 assert(0 && "-copy:area:withMask:clipOrigin:toPoint:, src is of unknown type");
2531 }
2532}
2533
2534//______________________________________________________________________________
2535- (unsigned char *) readColorBits : (X11::Rectangle) area
2536{
2537 //This is quite a bad idea - to read pixels back from a view,
2538 //but our GUI does exactly this. In case of Cocoa it's expensive
2539 //and not guaranteed to work.
2540
2541 assert(area.fWidth && area.fHeight && "-readColorBits:, area to copy is empty");
2542
2543 //int, not unsigned or something - to keep it simple.
2544 NSRect visRect = [self visibleRect];
2545 // 'Sanitize' visible rect, which is different starting from macOS 14 -
2546 // in that it's considered to be visible even in a hidden part which has
2547 // no 'color bits' at all an result in reading arbitrary colored 'pixels',
2548 // probably black ones:
2549 if (visRect.origin.y < 0) {
2550 visRect.size.height += visRect.origin.y;
2551 visRect.origin.y = 0.;
2552 }
2553 if (visRect.origin.x < 0) {
2554 visRect.size.width += visRect.origin.x;
2555 visRect.origin.x = 0.;
2556 }
2557
2558 const X11::Rectangle srcRect(int(visRect.origin.x), int(visRect.origin.y),
2559 unsigned(visRect.size.width), unsigned(visRect.size.height));
2560
2562 NSLog(@"QuartzView: -readColorBits:, visible rect of view and copy area do not intersect");
2563 return nullptr;
2564 }
2565
2566 //imageRep is autoreleased.
2567 NSBitmapImageRep * const imageRep = [self bitmapImageRepForCachingDisplayInRect : visRect];
2568 if (!imageRep) {
2569 NSLog(@"QuartzView: -readColorBits:, bitmapImageRepForCachingDisplayInRect failed");
2570 return nullptr;
2571 }
2572
2573 CGContextRef ctx = self.fContext; //Save old context if any.
2574 [self cacheDisplayInRect : visRect toBitmapImageRep : imageRep];
2575 self.fContext = ctx; //Restore old context.
2576 //
2577 const NSInteger bitsPerPixel = [imageRep bitsPerPixel];
2578
2579 assert(bitsPerPixel == 32 && "-readColorBits:, no alpha channel???");
2580 const NSInteger bytesPerRow = [imageRep bytesPerRow];
2581 unsigned dataWidth = bytesPerRow / (bitsPerPixel / 8);//assume an octet :(
2582
2583 unsigned char *srcData = nullptr;
2584 std::vector<unsigned char> downscaled;
2585 if ([self.window.screen backingScaleFactor] > 1 && imageRep.CGImage) {
2586 downscaled = X11::DownscaledImageData(area.fWidth, area.fHeight, imageRep.CGImage);
2587 if (downscaled.size())
2588 srcData = &downscaled[0];
2589 dataWidth = area.fWidth;
2590 } else
2591 srcData = [imageRep bitmapData];
2592
2593 if (!srcData) {
2594 NSLog(@"QuartzView: -readColorBits:, failed to obtain backing store contents");
2595 return nullptr;
2596 }
2597
2598 //We have a source data now. Let's allocate buffer for ROOT's GUI and convert source data.
2599 unsigned char *data = nullptr;
2600
2601 try {
2602 data = new unsigned char[area.fWidth * area.fHeight * 4];//bgra?
2603 } catch (const std::bad_alloc &) {
2604 NSLog(@"QuartzView: -readColorBits:, memory allocation failed");
2605 return nullptr;
2606 }
2607
2608 unsigned char *dstPixel = data;
2609 const unsigned char *line = srcData + area.fY * dataWidth * 4;
2610 const unsigned char *srcPixel = line + area.fX * 4;
2611
2612 for (unsigned i = 0; i < area.fHeight; ++i) {
2613 for (unsigned j = 0; j < area.fWidth; ++j, srcPixel += 4, dstPixel += 4) {
2614 dstPixel[0] = srcPixel[2];
2615 dstPixel[1] = srcPixel[1];
2616 dstPixel[2] = srcPixel[0];
2617 dstPixel[3] = srcPixel[3];
2618 }
2619
2620 line += dataWidth * 4;
2621 srcPixel = line + area.fX * 4;
2622 }
2623
2624 return data;
2625}
2626
2627//______________________________________________________________________________
2628- (void) setFBackgroundPixmap : (QuartzImage *) pixmap
2629{
2630 if (fBackgroundPixmap != pixmap) {
2631 [fBackgroundPixmap release];
2632 if (pixmap)
2634 else
2636 }
2637}
2638
2639//______________________________________________________________________________
2641{
2642 //I do not autorelease, screw this idiom!
2643
2644 return fBackgroundPixmap;
2645}
2646
2647//______________________________________________________________________________
2648- (int) fMapState
2649{
2650 if ([self isHidden])
2651 return kIsUnmapped;
2652
2653 for (QuartzView *parent = fParentView; parent; parent = parent.fParentView) {
2654 if ([parent isHidden])
2655 return kIsUnviewable;
2656 }
2657
2658 return kIsViewable;
2659}
2660
2661//______________________________________________________________________________
2662- (BOOL) fHasFocus
2663{
2664 //With the latest update clang became a bit more stupid.
2665 //Let's write a stupid useless cargo cult code
2666 //to make IT SHUT THE F... UP.
2667 (void)fHasFocus;
2668 return NO;
2669}
2670
2671//______________________________________________________________________________
2672- (void) setFHasFocus : (BOOL) focus
2673{
2674#pragma unused(focus)
2675 //With the latest update clang became a bit more stupid.
2676 //Let's write a stupid useless cargo cult code
2677 //to make IT SHUT THE F... UP.
2678 (void)fHasFocus;
2679}
2680
2681//______________________________________________________________________________
2683{
2684 return fBackBuffer;//No autorelease, I know the object's lifetime myself.
2685}
2686
2687//______________________________________________________________________________
2688- (void) setFBackBuffer : (QuartzPixmap *) backBuffer
2689{
2690 if (fBackBuffer != backBuffer) {
2691 [fBackBuffer release];
2692
2693 if (backBuffer)
2694 fBackBuffer = [backBuffer retain];
2695 else
2696 fBackBuffer = nil;
2697 }
2698}
2699
2700//______________________________________________________________________________
2702{
2703 return self;
2704}
2705
2706//______________________________________________________________________________
2708{
2709 return (QuartzWindow *)[self window];
2710}
2711
2712//______________________________________________________________________________
2713- (void) activatePassiveGrab
2714{
2716}
2717
2718//______________________________________________________________________________
2719- (void) activateImplicitGrab
2720{
2722}
2723
2724//______________________________________________________________________________
2725- (void) activateGrab : (unsigned) eventMask ownerEvents : (BOOL) ownerEvents
2726{
2730}
2731
2732//______________________________________________________________________________
2733- (void) cancelGrab
2734{
2738}
2739
2740//______________________________________________________________________________
2741- (BOOL) acceptsCrossingEvents : (unsigned) eventMask
2742{
2743 bool accepts = fEventMask & eventMask;
2744
2745 //In ROOT passive grabs are always with owner_events == true.
2748
2752 else
2754 }
2755
2756 return accepts;
2757}
2758
2759//______________________________________________________________________________
2760- (void)didAddSubview:(NSView *)subview
2761{
2762 [super didAddSubview:subview];
2763 self.wantsLayer = YES;
2764 self.layer.masksToBounds = YES;
2765}
2766
2767//______________________________________________________________________________
2768- (void)willRemoveSubview:(NSView *)subview
2769{
2770 [super willRemoveSubview:subview];
2771 self.wantsLayer = YES;
2772 self.layer.masksToBounds = self.subviews.count > 1;
2773}
2774
2775//______________________________________________________________________________
2776- (void) addChild : (NSView<X11Window> *) child
2777{
2778 assert(child != nil && "-addChild:, parameter 'child' is nil");
2779
2780 [self addSubview : child];
2781 child.fParentView = self;
2782}
2783
2784//______________________________________________________________________________
2785- (void) getAttributes : (WindowAttributes_t *) attr
2786{
2787 assert(attr != 0 && "-getAttributes:, parameter 'attr' is null");
2788
2790}
2791
2792//______________________________________________________________________________
2793- (void) setAttributes : (const SetWindowAttributes_t *)attr
2794{
2795 assert(attr != 0 && "-setAttributes:, parameter 'attr' is null");
2796
2797#ifdef DEBUG_ROOT_COCOA
2799#endif
2800
2802}
2803
2804//______________________________________________________________________________
2805- (void) mapRaised
2806{
2807 //Move view to the top of subviews.
2808 QuartzView * const parent = fParentView;
2809 [self removeFromSuperview];
2810 [parent addSubview : self];
2811 [self setHidden : NO];
2812}
2813
2814//______________________________________________________________________________
2815- (void) mapWindow
2816{
2817 [self setHidden : NO];
2818}
2819
2820//______________________________________________________________________________
2821- (void) mapSubwindows
2822{
2823 for (QuartzView * v in [self subviews])
2824 [v setHidden : NO];
2825}
2826
2827//______________________________________________________________________________
2828- (void) unmapWindow
2829{
2830 [self setHidden : YES];
2831}
2832
2833//______________________________________________________________________________
2834- (BOOL) fIsOverlapped
2835{
2836 return fIsOverlapped;
2837}
2838
2839//______________________________________________________________________________
2840- (void) setOverlapped : (BOOL) overlap
2841{
2844 [child setOverlapped : overlap];
2845}
2846
2847//______________________________________________________________________________
2848- (void) raiseWindow
2849{
2850 //Now, I can not remove window and add it ...
2851 //For example, if you click on a tab, this:
2852 //1. Creates (potentially) a passive button grab
2853 //2. Raises this tab - changes the window order.
2854 //3. On a button release - grab is release.
2855 //The tough problem is, if I remove a view from subviews
2856 //and add it ... it will never receve the
2857 //release event thus a grab will 'hang' on
2858 //view leading to bugs and artifacts.
2859 //So instead I have to ... SORT!!!!!
2860
2861 using namespace X11;//Comparators.
2862
2864 if (self == sibling)
2865 continue;
2866 if ([sibling isHidden])
2867 continue;
2868
2869 if (NSEqualRects(sibling.frame, self.frame)) {
2870 [sibling setOverlapped : YES];
2871 [sibling setHidden : YES];
2872 }
2873 }
2874
2875 [self setOverlapped : NO];
2876 //
2877 [self setHidden : NO];
2878 //
2879 [fParentView sortSubviewsUsingFunction : CompareViewsToRaise context : (void *)self];
2880 //
2881 [self updateTrackingAreasAfterRaise];
2882 //
2883 [self setNeedsDisplay : YES];
2884}
2885
2886//______________________________________________________________________________
2887- (void) lowerWindow
2888{
2889 //See comment about sorting in -raiseWindow.
2890
2891 using namespace X11;
2892
2893 NSEnumerator * const reverseEnumerator = [[fParentView subviews] reverseObjectEnumerator];
2895 if (sibling == self)
2896 continue;
2897
2898 if (NSEqualRects(sibling.frame, self.frame)) {
2899 [sibling setOverlapped : NO];
2900 //
2901 [sibling setHidden : NO];
2902 //
2903 [sibling setNeedsDisplay : YES];
2904 [self setOverlapped : YES];
2905 //
2906 [self setHidden : YES];
2907 //
2908 break;
2909 }
2910 }
2911
2912 [fParentView sortSubviewsUsingFunction : CompareViewsToLower context : (void*)self];
2913}
2914
2915//______________________________________________________________________________
2916- (BOOL) isFlipped
2917{
2918 //Now view's placement, geometry, moving and resizing can be
2919 //done with ROOT's (X11) coordinates without conversion - we're are 'flipped'.
2920 return YES;
2921}
2922
2923//______________________________________________________________________________
2924- (void) configureNotifyTree
2925{
2926 if (self.fMapState == kIsViewable || fIsOverlapped == YES) {
2928 assert(dynamic_cast<TGCocoa *>(gVirtualX) &&
2929 "-configureNotifyTree, gVirtualX is either null or has type different from TGCocoa");
2930 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
2931 vx->GetEventTranslator()->GenerateConfigureNotifyEvent(self, self.frame);
2932 }
2933
2935 [v configureNotifyTree];
2936 }
2937}
2938
2939#pragma mark - Key grabs.
2940
2941//______________________________________________________________________________
2942- (void) addPassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2943{
2944 [self removePassiveKeyGrab : keyCode modifiers : modifiers];
2945 PassiveKeyGrab * const newGrab = [[PassiveKeyGrab alloc] initWithKey : keyCode
2946 modifiers : modifiers];
2947 [fPassiveKeyGrabs addObject : newGrab];
2948 [newGrab release];
2949}
2950
2951//______________________________________________________________________________
2952- (void) removePassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2953{
2954 const NSUInteger count = [fPassiveKeyGrabs count];
2955 for (NSUInteger i = 0; i < count; ++i) {
2956 PassiveKeyGrab *grab = [fPassiveKeyGrabs objectAtIndex : i];
2958 [fPassiveKeyGrabs removeObjectAtIndex : i];
2959 break;
2960 }
2961 }
2962}
2963
2964//______________________________________________________________________________
2965- (PassiveKeyGrab *) findPassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2966{
2967 NSEnumerator * const enumerator = [fPassiveKeyGrabs objectEnumerator];
2970 return grab;
2971 }
2972
2973 return nil;
2974}
2975
2976//______________________________________________________________________________
2977- (PassiveKeyGrab *) findPassiveKeyGrab : (unichar) keyCode
2978{
2979 //Do not check modifiers.
2980 NSEnumerator * const enumerator = [fPassiveKeyGrabs objectEnumerator];
2982 if ([grab matchKey : keyCode])
2983 return grab;
2984 }
2985
2986 return nil;
2987}
2988
2989#pragma mark - Painting mechanics.
2990
2991//______________________________________________________________________________
2992- (void) drawRect : (NSRect) dirtyRect
2993{
2994#pragma unused(dirtyRect)
2995
2996 using namespace X11;
2997
2998 if (fID) {
2999 if (TGWindow * const window = gClient->GetWindowById(fID)) {
3000 //It's never painted, parent renders child. true == check the parent also.
3002 return;
3003
3004 NSGraphicsContext * const nsContext = [NSGraphicsContext currentContext];
3005 assert(nsContext != nil && "-drawRect:, currentContext returned nil");
3006
3007 TGCocoa * const vx = (TGCocoa *)gVirtualX;
3008 vx->CocoaDrawON();
3009
3011 assert(fContext != 0 && "-drawRect:, graphicsPort returned null");
3012
3014
3015 //Non-rectangular windows.
3016 if (self.fQuartzWindow.fShapeCombineMask)
3018
3019 // This code used to use TObject::InheritsFrom, however since this is
3020 // run under the AppKit, we can not call core/meta functions, otherwise
3021 // we will run into deadlocks.
3022 if (dynamic_cast<const TGContainer*>(window))//It always has an ExposureMask.
3023 vx->GetEventTranslator()->GenerateExposeEvent(self, [self visibleRect]);
3024
3025 if (fEventMask & kExposureMask) {
3026 if (ViewIsTextView(self)) {
3027 //Send Expose event, using child view (this is how it's done in GUI :( ).
3028 [NSColor.whiteColor setFill];
3029 NSRect frame = self.frame;
3030 frame.origin = {};
3031 NSRectFill(frame);
3033 if (viewFrame)//Now we set fExposedRegion for TGView.
3034 vx->GetEventTranslator()->GenerateExposeEvent(viewFrame, viewFrame.visibleRect);
3035 }
3036
3037 if (ViewIsHtmlView(self)) {
3039 if (viewFrame)
3040 vx->GetEventTranslator()->GenerateExposeEvent(viewFrame, viewFrame.visibleRect);
3041 }
3042
3043 //Ask ROOT's widget/window to draw itself.
3044 gClient->NeedRedraw(window, kTRUE);
3045
3046 if (!fSnapshotDraw) {
3047 //If Cocoa repaints widget, cancel all ROOT's "outside of paint event"
3048 //rendering into this widget.
3049 gClient->CancelRedraw(window);
3050 vx->GetCommandBuffer()->RemoveGraphicsOperationsForWindow(fID);
3051 }
3052 }
3053
3054 if (fBackBuffer) {
3055 //Very "special" window.
3057 [self copy : fBackBuffer area : copyArea withMask : nil
3058 clipOrigin : X11::Point() toPoint : X11::Point()];
3059 }
3060
3061 vx->CocoaDrawOFF();
3062#ifdef DEBUG_ROOT_COCOA
3063 CGContextSetRGBStrokeColor(fContext, 1., 0., 0., 1.);
3065#endif
3066
3067 fContext = 0;
3068 } else {
3069#ifdef DEBUG_ROOT_COCOA
3070 NSLog(@"QuartzView: -drawRect: method, no window for id %u was found", fID);
3071#endif
3072 }
3073 }
3074}
3075
3076#pragma mark - Geometry.
3077
3078//______________________________________________________________________________
3079- (void) setFrame : (NSRect) newFrame
3080{
3081 //In case of TBrowser, setFrame started infinite recursion:
3082 //HandleConfigure for embedded main frame emits signal, slot
3083 //calls layout, layout calls setFrame -> HandleConfigure and etc. etc.
3084 if (NSEqualRects(newFrame, self.frame))
3085 return;
3086
3087 [super setFrame : newFrame];
3088}
3089
3090//______________________________________________________________________________
3091- (void) setFrameSize : (NSSize) newSize
3092{
3093 //Check, if setFrameSize calls setFrame.
3094
3095 [super setFrameSize : newSize];
3096
3097 if ((fEventMask & kStructureNotifyMask) && (self.fMapState == kIsViewable || fIsOverlapped == YES)) {
3098 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3099 "setFrameSize:, gVirtualX is either null or has a type, different from TGCocoa");
3100 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3101 vx->GetEventTranslator()->GenerateConfigureNotifyEvent(self, self.frame);
3102 }
3103
3104 [self setNeedsDisplay : YES];//?
3105}
3106
3107#pragma mark - Event handling.
3108
3109//______________________________________________________________________________
3110- (void) mouseDown : (NSEvent *) theEvent
3111{
3112 assert(fID != 0 && "-mouseDown:, fID is 0");
3113
3114 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3115 "-mouseDown:, gVirtualX is either null or has a type, different from TGCocoa");
3116 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3117 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton1);
3118}
3119
3120//______________________________________________________________________________
3121- (void) scrollWheel : (NSEvent*) theEvent
3122{
3123 assert(fID != 0 && "-scrollWheel:, fID is 0");
3124
3125
3126 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3127 "-scrollWheel:, gVirtualX is either null or has a type, different from TGCocoa");
3128
3129 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3130 const CGFloat deltaY = [theEvent deltaY];
3131 if (deltaY < 0) {
3132 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton5);
3133 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton5);
3134 } else if (deltaY > 0) {
3135 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton4);
3136 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton4);
3137 }
3138}
3139
3140#ifdef DEBUG_ROOT_COCOA
3141//______________________________________________________________________________
3142- (void) printViewInformation
3143{
3144 assert(fID != 0 && "-printWindowInformation, fID is 0");
3145 const TGWindow * const window = gClient->GetWindowById(fID);
3146 assert(window != 0 && "printWindowInformation, window not found");
3147
3148 NSLog(@"-----------------View %u info:---------------------", fID);
3149 NSLog(@"ROOT's window class is %s", window->IsA()->GetName());
3150 NSLog(@"event mask is:");
3152 NSLog(@"grab mask is:");
3154 NSLog(@"view's geometry: x == %g, y == %g, w == %g, h == %g", self.frame.origin.x,
3155 self.frame.origin.y, self.frame.size.width, self.frame.size.height);
3156 NSLog(@"----------------End of view info------------------");
3157}
3158#endif
3159
3160//______________________________________________________________________________
3161- (void) rightMouseDown : (NSEvent *) theEvent
3162{
3163 assert(fID != 0 && "-rightMouseDown:, fID is 0");
3164
3165#ifdef DEBUG_ROOT_COCOA
3166 [self printViewInformation];
3167#endif
3168
3169 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3170 "-rightMouseDown:, gVirtualX is either null or has type different from TGCocoa");
3171 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3172 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton3);
3173}
3174
3175//______________________________________________________________________________
3176- (void) otherMouseDown : (NSEvent *) theEvent
3177{
3178 assert(fID != 0 && "-otherMouseDown:, fID is 0");
3179
3180 //Funny enough, [theEvent buttonNumber] is not the same thing as button masked in [NSEvent pressedMouseButtons],
3181 //button number actually is a kind of right operand for bitshift for pressedMouseButtons.
3182 if ([theEvent buttonNumber] == 2) {//this '2' will correspond to '4' in pressedMouseButtons.
3183 //I do not care about mouse buttons after left/right/wheel - ROOT does not have
3184 //any code for this.
3185 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3186 "-otherMouseDown:, gVirtualX is either null or has type different from TGCocoa");
3187 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3188 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton2);
3189 }
3190}
3191
3192//______________________________________________________________________________
3193- (void) mouseUp : (NSEvent *) theEvent
3194{
3195 assert(fID != 0 && "-mouseUp:, fID is 0");
3196
3197 assert(dynamic_cast<TGCocoa *>(gVirtualX) &&
3198 "-mouseUp:, gVirtualX is either null or has type different from TGCocoa");
3199 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3200 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton1);
3201}
3202
3203//______________________________________________________________________________
3204- (void) rightMouseUp : (NSEvent *) theEvent
3205{
3206
3207 assert(fID != 0 && "-rightMouseUp:, fID is 0");
3208
3209 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3210 "-rightMouseUp:, gVirtualX is either null or has type different from TGCocoa");
3211
3212 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3213 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton3);
3214}
3215
3216//______________________________________________________________________________
3217- (void) otherMouseUp : (NSEvent *) theEvent
3218{
3219 assert(fID != 0 && "-otherMouseUp:, fID is 0");
3220
3221 //Here I assume it's always kButton2.
3222 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3223 "-otherMouseUp:, gVirtualX is either null or has type different from TGCocoa");
3224 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3225 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton2);
3226}
3227
3228//______________________________________________________________________________
3229- (void) mouseEntered : (NSEvent *) theEvent
3230{
3231 assert(fID != 0 && "-mouseEntered:, fID is 0");
3232 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3233 "-mouseEntered:, gVirtualX is null or not of TGCocoa type");
3234
3235 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3236 vx->GetEventTranslator()->GenerateCrossingEvent(theEvent);
3237}
3238
3239//______________________________________________________________________________
3240- (void) mouseExited : (NSEvent *) theEvent
3241{
3242 assert(fID != 0 && "-mouseExited:, fID is 0");
3243
3244 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3245 "-mouseExited:, gVirtualX is null or not of TGCocoa type");
3246
3247 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3248 vx->GetEventTranslator()->GenerateCrossingEvent(theEvent);
3249}
3250
3251//______________________________________________________________________________
3252- (void) mouseMoved : (NSEvent *) theEvent
3253{
3254 assert(fID != 0 && "-mouseMoved:, fID is 0");
3255
3256 if (fParentView)//Suppress events in all views, except the top-level one.
3257 return;
3258
3259 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3260 "-mouseMoved:, gVirtualX is null or not of TGCocoa type");
3261
3262 TGCocoa *vx = static_cast<TGCocoa *>(gVirtualX);
3263 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3264}
3265
3266//______________________________________________________________________________
3267- (void) mouseDragged : (NSEvent *) theEvent
3268{
3269 assert(fID != 0 && "-mouseDragged:, fID is 0");
3270
3271 TGCocoa * const vx = dynamic_cast<TGCocoa *>(gVirtualX);
3272 assert(vx != 0 && "-mouseDragged:, gVirtualX is null or not of TGCocoa type");
3273
3274 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3275}
3276
3277//______________________________________________________________________________
3278- (void) rightMouseDragged : (NSEvent *) theEvent
3279{
3280 assert(fID != 0 && "-rightMouseDragged:, fID is 0");
3281
3282 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3283 "-rightMouseDragged:, gVirtualX is null or not of TGCocoa type");
3284
3285 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3286 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3287}
3288
3289//______________________________________________________________________________
3290- (void) otherMouseDragged : (NSEvent *) theEvent
3291{
3292 assert(fID != 0 && "-otherMouseDragged:, fID is 0");
3293
3294 if ([theEvent buttonNumber] == 2) {
3295 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3296 "-otherMouseDragged:, gVirtualX is null or not of TGCocoa type");
3297 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3298 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3299 }
3300}
3301
3302//______________________________________________________________________________
3303- (void) keyDown : (NSEvent *) theEvent
3304{
3305 assert(fID != 0 && "-keyDown:, fID is 0");
3306
3307 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3308 "-keyDown:, gVirtualX is null or not of TGCocoa type");
3309
3313
3314 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3315 vx->GetEventTranslator()->GenerateKeyPressEvent(eventView, theEvent);
3316}
3317
3318//______________________________________________________________________________
3319- (void) keyUp : (NSEvent *) theEvent
3320{
3321 assert(fID != 0 && "-keyUp:, fID is 0");
3322
3323 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3324 "-keyUp:, gVirtualX is null or not of TGCocoa type");
3325
3326 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3330
3331 vx->GetEventTranslator()->GenerateKeyReleaseEvent(eventView, theEvent);
3332}
3333
3334#pragma mark - First responder stuff.
3335
3336//______________________________________________________________________________
3337- (BOOL) acceptsFirstMouse : (NSEvent *) theEvent
3338{
3339#pragma unused(theEvent)
3340 return YES;
3341}
3342
3343//______________________________________________________________________________
3344- (BOOL) acceptsFirstResponder
3345{
3346 return YES;
3347}
3348
3349#pragma mark - Cursors.
3350
3351//______________________________________________________________________________
3352- (void) setFCurrentCursor : (ECursor) cursor
3353{
3354 if (cursor != fCurrentCursor) {
3356 [self.fQuartzWindow invalidateCursorRectsForView : self];
3357 }
3358}
3359
3360//______________________________________________________________________________
3362{
3363 const char *pngFileName = 0;
3364
3365 switch (fCurrentCursor) {
3366 case kMove:
3367 pngFileName = "move_cursor.png";
3368 break;
3369 case kArrowHor:
3370 pngFileName = "hor_arrow_cursor.png";
3371 break;
3372 case kArrowVer:
3373 pngFileName = "ver_arrow_cursor.png";
3374 break;
3375 case kArrowRight:
3376 pngFileName = "right_arrow_cursor.png";
3377 break;
3378 case kRotate:
3379 pngFileName = "rotate.png";
3380 break;
3381 case kBottomLeft:
3382 case kTopRight:
3383 pngFileName = "top_right_cursor.png";
3384 break;
3385 case kTopLeft:
3386 case kBottomRight:
3387 pngFileName = "top_left_cursor.png";
3388 break;
3389 default:;
3390 }
3391
3392 if (pngFileName) {
3393 const char * const path = gSystem->Which(TROOT::GetIconPath(), pngFileName, kReadPermission);
3395
3396 if (!path || path[0] == 0) {
3397 //File was not found.
3398 return nil;
3399 }
3400
3401 NSString *nsPath = [NSString stringWithFormat : @"%s", path];//in autorelease pool.
3402 NSImage * const cursorImage = [[NSImage alloc] initWithContentsOfFile : nsPath];
3403
3404 if (!cursorImage)
3405 return nil;
3406
3408 NSCursor * const customCursor = [[[NSCursor alloc] initWithImage : cursorImage
3409 hotSpot : hotSpot] autorelease];
3410
3411 [cursorImage release];
3412
3413 return customCursor;
3414 }
3415
3416 return nil;
3417}
3418
3419//______________________________________________________________________________
3420- (void) resetCursorRects
3421{
3423 [self addCursorRect : self.visibleRect cursor : cursor];
3424}
3425
3426//______________________________________________________________________________
3427- (void) cursorUpdate
3428{
3430 // NB: [window invalidateCursorRectsForView] called here has the
3431 // same problem as commented below in -cursorUpdate:.
3432 [cursor set];
3433 }
3434}
3435
3436//______________________________________________________________________________
3437- (void) cursorUpdate : (NSEvent *) event
3438{
3439#pragma unused(event)
3440 // It looks like [NSCursor set] method does not work properly when called from
3441 // cursorUpdate:, having, say, a parent frame with 'arrow' cursor and a child (completely
3442 // filling its parent's area) with 'cross', it happens the 'cross' cursor is not always
3443 // set correctly, for example:
3444 // if we have a TCanvas and resize it, cursor is 'arrow' inside this canvas,
3445 // though it must be 'cross'. This all, as it always happesn with "thinking different"
3446 // Apple is somehow related to run loop or something. As always, it's not documented,
3447 // so Apple can continue to think different. The idea with performSelector comes from:
3448 // http://stackoverflow.com/questions/8430236/nscursor-set-method-has-no-effect
3449 // Or may be it's just a bug:
3450 // http://stackoverflow.com/questions/13901232/nscursor-set-not-working-on-unfocused-window
3451 [self performSelector : @selector(cursorUpdate) withObject : nil afterDelay : 0.05f];
3452}
3453
3454#pragma mark - Emulated X11 properties.
3455
3456//______________________________________________________________________________
3457- (void) setProperty : (const char *) propName data : (unsigned char *) propData
3458 size : (unsigned) dataSize forType : (Atom_t) dataType format : (unsigned) format
3459{
3460 assert(propName != 0 && "-setProperty:data:size:forType:, parameter 'propName' is null");
3461 assert(propData != 0 && "-setProperty:data:size:forType:, parameter 'propData' is null");
3462 assert(dataSize != 0 && "-setProperty:data:size:forType:, parameter 'dataSize' is 0");
3463
3464 NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3466
3467 //At the moment (and I think this will never change) TGX11 always calls XChangeProperty with PropModeReplace.
3468 if (property)
3469 [property resetPropertyData : propData size : dataSize type : dataType format : format];
3470 else {
3471 //No property found, add a new one.
3472 property = [[QuartzWindowProperty alloc] initWithData : propData size : dataSize
3473 type : dataType format : format];
3474 [fX11Properties setObject : property forKey : key];
3475 [property release];
3476 }
3477}
3478
3479//______________________________________________________________________________
3480- (BOOL) hasProperty : (const char *) propName
3481{
3482 assert(propName != 0 && "-hasProperty:, propName parameter is null");
3483
3484 NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3486
3487 return property != nil;
3488}
3489
3490//______________________________________________________________________________
3491- (unsigned char *) getProperty : (const char *) propName returnType : (Atom_t *) type
3492 returnFormat : (unsigned *) format nElements : (unsigned *) nElements
3493{
3494 assert(propName != 0 &&
3495 "-getProperty:returnType:returnFormat:nElements:, parameter 'propName' is null");
3496 assert(type != 0 &&
3497 "-getProperty:returnType:returnFormat:nElements:, parameter 'type' is null");
3498 assert(format != 0 &&
3499 "-getProperty:returnType:returnFormat:nElements:, parameter 'format' is null");
3500 assert(nElements != 0 &&
3501 "-getProperty:returnType:returnFormat:nElements:, parameter 'nElements' is null");
3502
3503 NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3505 assert(property != 0 &&
3506 "-getProperty:returnType:returnFormat:nElements, property not found");
3507
3508 NSData * const propData = property.fPropertyData;
3509
3510 const NSUInteger dataSize = [propData length];
3511 unsigned char *buff = 0;
3512 try {
3513 buff = new unsigned char[dataSize]();
3514 } catch (const std::bad_alloc &) {
3515 //Hmm, can I log, if new failed? :)
3516 NSLog(@"QuartzWindow: -getProperty:returnType:returnFormat:nElements:,"
3517 " memory allocation failed");
3518 return 0;
3519 }
3520
3521 [propData getBytes : buff length : dataSize];
3522 *format = property.fFormat;
3523
3525
3526 if (*format == 16)
3527 *nElements= dataSize / 2;
3528 else if (*format == 32)
3529 *nElements = dataSize / 4;
3530
3531 *type = property.fType;
3532
3533 return buff;
3534}
3535
3536//______________________________________________________________________________
3537- (void) removeProperty : (const char *) propName
3538{
3539 assert(propName != 0 && "-removeProperty:, parameter 'propName' is null");
3540
3541 NSString * const key = [NSString stringWithCString : propName
3542 encoding : NSASCIIStringEncoding];
3543 [fX11Properties removeObjectForKey : key];
3544}
3545
3546//DND
3547//______________________________________________________________________________
3549{
3550 NSPasteboard * const pasteBoard = [sender draggingPasteboard];
3551 const NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
3552
3555
3556 return NSDragOperationNone;
3557}
3558
3559//______________________________________________________________________________
3560- (BOOL) performDragOperation : (id<NSDraggingInfo>) sender
3561{
3562 //We can drag some files (images, pdfs, source code files) from
3563 //finder to ROOT's window (mainly TCanvas or text editor).
3564 //The logic is totally screwed here :((( - ROOT will try to
3565 //read a property of some window (not 'self', unfortunately) -
3566 //this works since on Window all data is in a global clipboard
3567 //(on X11 it simply does not work at all).
3568 //I'm attaching the file name as a property for the top level window,
3569 //there is no other way to make this data accessible for ROOT.
3570
3571 NSPasteboard * const pasteBoard = [sender draggingPasteboard];
3572 const NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
3573
3575
3576 //Here I try to put string ("file://....") into window's property to make
3577 //it accesible from ROOT's GUI.
3578 const Atom_t textUriAtom = gVirtualX->InternAtom("text/uri-list", kFALSE);
3579
3580 NSArray * const files = [pasteBoard propertyListForType : NSFilenamesPboardType];
3581 for (NSString *path in files) {
3582 //ROOT can not process several files, use the first one.
3583 NSString * const item = [@"file://" stringByAppendingString : path];
3584 //Yes, only ASCII encoding, but after all, ROOT's not able to work with NON-ASCII strings.
3585 const NSUInteger len = [item lengthOfBytesUsingEncoding : NSASCIIStringEncoding] + 1;
3586 try {
3587 std::vector<unsigned char> propertyData(len);
3588 [item getCString : (char *)&propertyData[0] maxLength : propertyData.size()
3589 encoding : NSASCIIStringEncoding];
3590 //There is no any guarantee, that this will ever work, logic in TGDNDManager is totally crazy.
3591 NSView<X11Window> * const targetView = self.fQuartzWindow.fContentView;
3592 [targetView setProperty : "_XC_DND_DATA" data : &propertyData[0]
3593 size : propertyData.size() forType : textUriAtom format : 8];
3594 } catch (const std::bad_alloc &) {
3595 //Hehe, can I log something in case of bad_alloc??? ;)
3596 NSLog(@"QuartzView: -performDragOperation:, memory allocation failed");
3597 return NO;
3598 }
3599
3600 break;
3601 }
3602
3603 //Property is attached now.
3604
3605 //Gdk on windows creates three events on file drop (WM_DROPFILES): XdndEnter, XdndPosition, XdndDrop.
3606 //1. Dnd enter.
3607 Event_t event1 = {};
3608 event1.fType = kClientMessage;
3609 event1.fWindow = fID;
3610 event1.fHandle = gVirtualX->InternAtom("XdndEnter", kFALSE);
3611 event1.fUser[0] = long(fID);
3612 event1.fUser[2] = textUriAtom;//gVirtualX->InternAtom("text/uri-list", kFALSE);
3613 //
3614 gVirtualX->SendEvent(fID, &event1);
3615
3616 //2. Dnd position.
3617 Event_t event2 = {};
3618 event2.fType = kClientMessage;
3619 event2.fWindow = fID;
3620 event2.fHandle = gVirtualX->InternAtom("XdndPosition", kFALSE);
3621 event2.fUser[0] = long(fID);
3622 event2.fUser[2] = 0;//Here I have to pack x and y for drop coordinates, shifting by 16 bits.
3623 NSPoint dropPoint = [sender draggingLocation];
3624 //convertPointFromBase is deprecated.
3625 //dropPoint = [self convertPointFromBase : dropPoint];
3626 dropPoint = [self convertPoint : dropPoint fromView : nil];
3627 //
3629 event2.fUser[2] = UShort_t(dropPoint.y) | (UShort_t(dropPoint.x) << 16);
3630
3631 gVirtualX->SendEvent(fID, &event2);
3632
3633 Event_t event3 = {};
3634 event3.fType = kClientMessage;
3635 event3.fWindow = fID;
3636 event3.fHandle = gVirtualX->InternAtom("XdndDrop", kFALSE);
3637
3638 gVirtualX->SendEvent(fID, &event3);
3639 }
3640
3641 return YES;//Always ok, even if file type is not supported - no need in "animation".
3642}
3643
3644@end
Cppyy::TCppType_t fClass
Handle_t Atom_t
WM token.
Definition GuiTypes.h:38
@ kClientMessage
Definition GuiTypes.h:64
const Mask_t kWABorderPixel
Definition GuiTypes.h:143
const Mask_t kWAOverrideRedirect
Definition GuiTypes.h:150
const Mask_t kWABitGravity
Definition GuiTypes.h:145
const Mask_t kWADontPropagate
Definition GuiTypes.h:153
ECursor
Definition GuiTypes.h:373
@ kRightSide
Definition GuiTypes.h:374
@ kBottomSide
Definition GuiTypes.h:374
@ kArrowRight
Definition GuiTypes.h:376
@ kTopLeft
Definition GuiTypes.h:373
@ kBottomRight
Definition GuiTypes.h:373
@ kArrowVer
Definition GuiTypes.h:375
@ kCaret
Definition GuiTypes.h:376
@ kTopSide
Definition GuiTypes.h:374
@ kLeftSide
Definition GuiTypes.h:374
@ kWatch
Definition GuiTypes.h:376
@ kMove
Definition GuiTypes.h:375
@ kTopRight
Definition GuiTypes.h:373
@ kBottomLeft
Definition GuiTypes.h:373
@ kHand
Definition GuiTypes.h:375
@ kCross
Definition GuiTypes.h:375
@ kRotate
Definition GuiTypes.h:375
@ kArrowHor
Definition GuiTypes.h:375
@ kPointer
Definition GuiTypes.h:376
const Mask_t kWAColormap
Definition GuiTypes.h:154
const Mask_t kButtonMotionMask
Definition GuiTypes.h:165
const Mask_t kWABackingStore
Definition GuiTypes.h:147
const Mask_t kButtonPressMask
Definition GuiTypes.h:162
const Mask_t kExposureMask
Definition GuiTypes.h:166
const Mask_t kWAEventMask
Definition GuiTypes.h:152
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
const Mask_t kWASaveUnder
Definition GuiTypes.h:151
const Mask_t kWABackPixel
Definition GuiTypes.h:141
const Mask_t kWAWinGravity
Definition GuiTypes.h:146
const Mask_t kWABackingPixel
Definition GuiTypes.h:149
const Mask_t kPointerMotionMask
Definition GuiTypes.h:164
const Mask_t kLeaveWindowMask
Definition GuiTypes.h:169
const Mask_t kStructureNotifyMask
Definition GuiTypes.h:167
@ kIsViewable
Definition GuiTypes.h:47
@ kIsUnviewable
Definition GuiTypes.h:47
@ kIsUnmapped
Definition GuiTypes.h:47
@ kAlways
Definition GuiTypes.h:46
const Mask_t kButtonReleaseMask
Definition GuiTypes.h:163
const Mask_t kWABorderPixmap
Definition GuiTypes.h:142
const Mask_t kEnterWindowMask
Definition GuiTypes.h:168
const Mask_t kWACursor
Definition GuiTypes.h:155
@ kButton4
Definition GuiTypes.h:216
@ kButton2
Definition GuiTypes.h:215
@ kButton5
Definition GuiTypes.h:216
@ kButton3
Definition GuiTypes.h:215
@ kButton1
Definition GuiTypes.h:215
const Mask_t kWABackPixmap
Definition GuiTypes.h:140
const Mask_t kWABorderWidth
Definition GuiTypes.h:144
const Mask_t kWABackingPlanes
Definition GuiTypes.h:148
#define d(i)
Definition RSha256.hxx:102
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
unsigned short UShort_t
Unsigned Short integer 2 bytes (unsigned short)
Definition RtypesCore.h:54
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gClient
Definition TGClient.h:157
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t cursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t TranslateCoordinates
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t GetWindowAttributes
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t rect
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t win
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name CreateCursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t grab
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
Option_t Option_t TPoint TPoint const char y1
@ kReadPermission
Definition TSystem.h:55
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define gVirtualX
Definition TVirtualX.h:377
Fill Area Attributes class.
Definition TAttFill.h:21
Line Attributes class.
Definition TAttLine.h:21
Marker Attributes class.
Definition TAttMarker.h:21
Text Attributes class.
Definition TAttText.h:21
This class implements TVirtualX interface for MacOS X, using Cocoa and Quartz 2D.
Definition TGCocoa.h:57
static Atom_t fgDeleteWindowAtom
Definition TGCocoa.h:476
Manages a content area.
Definition TGCanvas.h:31
A TGTextView is a text viewer widget.
Definition TGTextView.h:22
ROOT GUI Window base class.
Definition TGWindow.h:23
@ kIsHtmlView
Definition TGWindow.h:69
TClass * IsA() const override
Definition TGWindow.h:128
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
SCoord_t fY
Definition TPoint.h:36
SCoord_t fX
Definition TPoint.h:35
static const TString & GetIconPath()
Get the icon path in the installation. Static utility function.
Definition TROOT.cxx:3486
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1563
Semi-Abstract base class defining a generic interface to the underlying, low level,...
Definition TVirtualX.h:46
TLine * line
NSUInteger fModifiers
unsigned fHeight
unsigned fWidth
QuartzPixmap * fBackBuffer
unsigned fPassiveGrabKeyModifiers
ECursor fCurrentCursor
void activateImplicitGrab()
BOOL fSnapshotDraw
NSMutableArray * fPassiveKeyGrabs
int fPassiveGrabButton
CGFloat fScaleFactor()
TAttLine * attLine
TAttFill fAttFill
current fill attributes
BOOL fActiveGrabOwnerEvents
TAttText fAttText
current text attribute
QuartzWindow * fQuartzWindow
void configureNotifyTree()
void activatePassiveGrab()
CGContextRef fContext
NSMutableDictionary * fX11Properties
BOOL fPassiveGrabOwnerEvents
BOOL fIsOpenGLWidget()
TAttMarker fAttMarker
current marker attribute
unsigned fWidth()
QuartzView * fParentView
TAttMarker * attMarker
unsigned fID
unsigned fPassiveGrabEventMask
QuartzImage * fBackgroundPixmap
ROOT::MacOSX::X11::PointerGrab fCurrentGrabType
BOOL fIsOverlapped
unsigned long fBackgroundPixel
TAttText * attText
unsigned fActiveGrabEventMask
unsigned fHeight()
BOOL fOverrideRedirect
NSView< X11Window > * fContentView
TAttFill * attFill
TAttLine fAttLine
current line attributes
unsigned long fBackgroundPixel
QuartzView * fParentView
unsigned fHeight()
CGFloat fScaleFactor()
BOOL fDelayedTransient
QuartzWindow * fQuartzWindow
XorDrawingWindow * findXorWindow()
XorDrawingWindow * addXorWindow()
QuartzWindow * fMainWindow
TVirtualX::EDrawMode fDrawMode
QuartzView * fContentView
unsigned fWidth()
QuartzImage * fShapeCombineMask
instancetype init()
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
const NSUInteger kMiniaturizableWindowMask
const NSEventType kLeftMouseDown
const NSEventType kRightMouseDown
const NSUInteger kTitledWindowMask
const NSUInteger kResizableWindowMask
const NSUInteger kClosableWindowMask
const NSUInteger kBorderlessWindowMask
NSCursor * CreateCustomCursor(ECursor currentCursor)
int GlobalYROOTToCocoa(CGFloat yROOT)
NSPoint ConvertPointFromScreenToBase(NSPoint screenPoint, NSWindow *window)
bool ViewIsHtmlViewFrame(NSView< X11Window > *view, bool checkParent)
int GlobalYCocoaToROOT(CGFloat yCocoa)
void PixelToRGB(Pixel_t pixelColor, CGFloat *rgb)
Definition X11Colors.mm:920
NSPoint ConvertPointFromBaseToScreen(NSWindow *window, NSPoint windowPoint)
NSPoint TranslateToScreen(NSView< X11Window > *from, NSPoint point)
CGImageRef CreateSubImage(QuartzImage *image, const Rectangle &area)
bool ScreenPointIsInView(NSView< X11Window > *view, Int_t x, Int_t y)
NSPoint GetCursorHotStop(NSImage *image, ECursor cursor)
void GetWindowGeometry(NSObject< X11Window > *win, WindowAttributes_t *dst)
void GetWindowAttributes(NSObject< X11Window > *window, WindowAttributes_t *dst)
NSView< X11Window > * FindDNDAwareViewInPoint(NSView *parentView, Window_t dragWinID, Window_t inputWinID, Int_t x, Int_t y, Int_t maxDepth)
NSView< X11Window > * FrameForHtmlView(NSView< X11Window > *htmlView)
QuartzWindow * FindWindowInPoint(Int_t x, Int_t y)
int GlobalXCocoaToROOT(CGFloat xCocoa)
void WindowLostFocus(Window_t winID)
int LocalYROOTToCocoa(NSView< X11Window > *parentView, CGFloat yROOT)
NSView< X11Window > * FindViewForPointerEvent(NSEvent *pointerEvent)
NSView< X11Window > * FrameForTextView(NSView< X11Window > *textView)
NSComparisonResult CompareViewsToLower(id view1, id view2, void *context)
int LocalYCocoaToROOT(NSView< X11Window > *parentView, CGFloat yCocoa)
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)
NSView< X11Window > * FindViewUnderPointer()
void UnlockFocus(NSView< X11Window > *view)
int GlobalXROOTToCocoa(CGFloat xROOT)
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)
bool AdjustCropArea(const Rectangle &srcRect, Rectangle &cropArea)
QuartzWindow * FindWindowForPointerEvent(NSEvent *pointerEvent)
bool ViewIsTextView(unsigned viewID)
void GetRootWindowAttributes(WindowAttributes_t *attr)
bool ViewIsHtmlView(unsigned viewID)
QuartzWindow * FindWindowUnderPointer()
bool ViewIsTextViewFrame(NSView< X11Window > *view, bool checkParent)
NSPoint TranslateFromScreen(NSPoint point, NSView< X11Window > *to)
void ClipToShapeMask(NSView< X11Window > *view, CGContextRef ctx)
void SetWindowAttributes(const SetWindowAttributes_t *attr, NSObject< X11Window > *window)
NSCursor * CreateCursor(ECursor currentCursor)
bool LockFocus(NSView< X11Window > *view)
NSComparisonResult CompareViewsToRaise(id view1, id view2, void *context)
std::vector< unsigned char > DownscaledImageData(unsigned w, unsigned h, CGImageRef image)
Event structure.
Definition GuiTypes.h:175
Attributes that can be used when creating or changing a window.
Definition GuiTypes.h:94
Window attributes that can be inquired.
Definition GuiTypes.h:115