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 std::unique_ptr<ROOT::MacOSX::X11::DrawLineXor> cmd(new 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 std::unique_ptr<ROOT::MacOSX::X11::DrawBoxXor> cmd(new 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//______________________________________________________________________________
1595- (void) setDrawMode : (TVirtualX::EDrawMode) newMode
1596{
1598 [self removeXorWindow];
1599
1601}
1602
1603//______________________________________________________________________________
1604- (TVirtualX::EDrawMode) getDrawMode
1605{
1606 return fDrawMode;
1607}
1608
1609
1610#pragma mark - X11Window protocol's implementation.
1611
1612//______________________________________________________________________________
1614{
1615 return nil;
1616}
1617
1618//______________________________________________________________________________
1619- (void) setFParentView : (QuartzView *) parent
1620{
1621#pragma unused(parent)
1622}
1623
1624//______________________________________________________________________________
1626{
1627 return fContentView;
1628}
1629
1630//______________________________________________________________________________
1632{
1633 return self;
1634}
1635
1636//... many forwards to fContentView.
1637
1638//______________________________________________________________________________
1639- (void) setFBackgroundPixel : (unsigned long) backgroundColor
1640{
1641 if (!fContentView)
1642 return;
1643
1644 if (!fShapeCombineMask) {
1645 CGFloat rgba[] = {0., 0., 0., 1.};
1647
1648 [self setBackgroundColor : [NSColor colorWithColorSpace : [NSColorSpace deviceRGBColorSpace] components : rgba count : 4]];
1649 }
1650
1652}
1653
1654//______________________________________________________________________________
1655- (unsigned long) fBackgroundPixel
1656{
1657 if (!fContentView)
1658 return 0;
1659
1661}
1662
1663//______________________________________________________________________________
1664- (int) fMapState
1665{
1666 //Top-level window can be only kIsViewable or kIsUnmapped (not unviewable).
1667 if (!fContentView)
1668 return kIsUnmapped;
1669
1670 if ([fContentView isHidden])
1671 return kIsUnmapped;
1672
1673 return kIsViewable;
1674}
1675
1676//______________________________________________________________________________
1677- (void) addChild : (NSView<X11Window> *) child
1678{
1679 assert(child != nil && "-addChild:, parameter 'child' is nil");
1680
1681 if (!fContentView) {
1682 //This can happen only in case of re-parent operation.
1684 "-addChild: gl view in a top-level window as content view is not supported");
1685
1687 [self setContentView : child];
1689 } else
1690 [fContentView addChild : child];
1691}
1692
1693//______________________________________________________________________________
1694- (void) getAttributes : (WindowAttributes_t *) attr
1695{
1696 if (!fContentView)
1697 return;
1698
1699 assert(attr && "-getAttributes:, parameter 'attr' is nil");
1700
1702}
1703
1704//______________________________________________________________________________
1705- (void) setAttributes : (const SetWindowAttributes_t *) attr
1706{
1707 assert(attr != 0 && "-setAttributes:, parameter 'attr' is null");
1708
1709#ifdef DEBUG_ROOT_COCOA
1710 log_attributes(attr, self.fID);
1711#endif
1712
1714}
1715
1716//______________________________________________________________________________
1717- (void) mapRaised
1718{
1719 if (!fContentView)
1720 return;
1721
1723
1724 [fContentView setHidden : NO];
1725 [self makeKeyAndOrderFront : self];
1726 [fContentView configureNotifyTree];
1727
1728 if (fDelayedTransient) {
1730 [fMainWindow addChildWindow : self ordered : NSWindowAbove];
1731 }
1732}
1733
1734//______________________________________________________________________________
1735- (void) mapWindow
1736{
1737 if (!fContentView)
1738 return;
1739
1741
1742 [fContentView setHidden : NO];
1743 [self makeKeyAndOrderFront : self];
1744 [fContentView configureNotifyTree];
1745
1746 if (fDelayedTransient) {
1748 [fMainWindow addChildWindow : self ordered : NSWindowAbove];
1749 }
1750}
1751
1752//______________________________________________________________________________
1753- (void) mapSubwindows
1754{
1755 if (!fContentView)
1756 return;
1757
1759
1760 [fContentView mapSubwindows];
1761 [fContentView configureNotifyTree];
1762}
1763
1764//______________________________________________________________________________
1765- (void) unmapWindow
1766{
1767 if (!fContentView)
1768 return;
1769
1770 [fContentView setHidden : YES];
1771 [self orderOut : self];
1772
1774 [fMainWindow removeChildWindow : self];
1775 fMainWindow = nil;
1776 }
1777}
1778
1779#pragma mark - Events.
1780
1781//______________________________________________________________________________
1782- (void) sendEvent : (NSEvent *) theEvent
1783{
1784 //With XQuartz, if you open a menu and try to move a window without closing this menu,
1785 //window does not move, menu closes, and after that you can start draggin a window again.
1786 //With Cocoa I can not do such a thing (window WILL move), but still can report button release event
1787 //to close a menu.
1788 if (!fContentView)
1789 return;
1790
1792 bool generateFakeRelease = false;
1793
1794 const NSPoint windowPoint = [theEvent locationInWindow];
1795
1796 if (windowPoint.x <= 4 || windowPoint.x >= self.fWidth - 4)
1797 generateFakeRelease = true;
1798
1799 if (windowPoint.y <= 4 || windowPoint.y >= self.fHeight - 4)
1800 generateFakeRelease = true;
1801
1802 const NSPoint viewPoint = [fContentView convertPoint : windowPoint fromView : nil];
1803
1804 if (viewPoint.y <= 0 && windowPoint.y >= 0)
1805 generateFakeRelease = true;
1806
1807 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1808 "-sendEvent:, gVirtualX is either null or not of TGCocoa type");
1809
1810 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
1811 if (vx->GetEventTranslator()->HasPointerGrab() && generateFakeRelease) {
1812 vx->GetEventTranslator()->GenerateButtonReleaseEvent(fContentView, theEvent,
1814 kButton1 : kButton3);
1815 //Yes, ignore this event completely (this means, you are not able to immediately start
1816 //resizing a window, if some popup is open. Actually, this is more or less
1817 //the same as with XQuartz and X11 version.
1818 return;
1819 }
1820 }
1821
1822 [super sendEvent : theEvent];
1823}
1824
1825#pragma mark - NSWindowDelegate's methods.
1826
1827//______________________________________________________________________________
1828- (BOOL) windowShouldClose : (id) sender
1829{
1830#pragma unused(sender)
1831 if (!fContentView)
1832 return NO;
1833
1834 if ([[self childWindows] count])
1835 return NO;
1836
1837 //Prepare client message for a window.
1838 Event_t closeEvent = {};
1839 closeEvent.fWindow = fContentView.fID;
1840 closeEvent.fType = kClientMessage;
1841 closeEvent.fFormat = 32;//Taken from GUI classes.
1844 //Place it into the queue.
1845 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1846 "-windowShouldClose:, gVirtualX is either null or has a type different from TGCocoa");
1847 ((TGCocoa *)gVirtualX)->SendEvent(fContentView.fID, &closeEvent);
1848
1849 //Do not let AppKit to close a window,
1850 //ROOT will do.
1851 return NO;
1852}
1853
1854//______________________________________________________________________________
1855- (void) windowDidBecomeKey : (NSNotification *) aNotification
1856{
1857#pragma unused(aNotification)
1858
1859 if (!fContentView)
1860 return;
1861
1863 fHasFocus = YES;
1864 //
1865 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
1866 "-windowDidBecomeKey:, gVirtualX is null or not of TGCocoa type");
1867 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
1868 vx->GetEventTranslator()->GenerateFocusChangeEvent(self.fContentView);
1869 }
1870}
1871
1872
1873//______________________________________________________________________________
1874- (void) windowDidResignKey : (NSNotification *) aNotification
1875{
1876#pragma unused(aNotification)
1877 fHasFocus = NO;
1878}
1879
1880@end
1881
1882#pragma mark - Passive key grab info.
1883
1884@implementation PassiveKeyGrab
1885
1886//______________________________________________________________________________
1887- (id) initWithKey : (unichar) keyCode modifiers : (NSUInteger) modifiers
1888{
1889 if (self = [super init]) {
1890 fKeyCode = keyCode;
1892 }
1893
1894 return self;
1895}
1896
1897//______________________________________________________________________________
1898- (BOOL) matchKey : (unichar) keyCode modifiers : (NSUInteger) modifiers
1899{
1900 return keyCode == fKeyCode && modifiers == fModifiers;
1901}
1902
1903//______________________________________________________________________________
1904- (BOOL) matchKey : (unichar) keyCode
1905{
1906 return keyCode == fKeyCode;
1907}
1908
1909//______________________________________________________________________________
1910- (unichar) fKeyCode
1911{
1912 return fKeyCode;
1913}
1914
1915//______________________________________________________________________________
1916- (NSUInteger) fModifiers
1917{
1918 return fModifiers;
1919}
1920
1921@end
1922
1923#pragma mark - X11 property emulation.
1924
1928 unsigned fFormat;
1929}
1930
1931@property (nonatomic, readonly) Atom_t fType;
1932
1933@end
1934
1935@implementation QuartzWindowProperty
1936
1937@synthesize fType;
1938
1939//______________________________________________________________________________
1940- (id) initWithData : (unsigned char *) data size : (unsigned) dataSize type : (Atom_t) type format : (unsigned) format
1941{
1942 if (self = [super init]) {
1943 //Memory is zero-initialized, but just to make it explicit:
1945 fType = 0;
1946 fFormat = 0;
1947
1948 [self resetPropertyData : data size : dataSize type : type format : format];
1949 }
1950
1951 return self;
1952}
1953
1954//______________________________________________________________________________
1955- (void) dealloc
1956{
1957 [fPropertyData release];
1958
1959 [super dealloc];
1960}
1961
1962//______________________________________________________________________________
1963- (void) resetPropertyData : (unsigned char *) data size : (unsigned) dataSize
1964 type : (Atom_t) type format : (unsigned) format
1965{
1966 [fPropertyData release];
1967
1968 fFormat = format;
1969 if (format == 16)
1970 dataSize *= 2;
1971 else if (format == 32)
1972 dataSize *= 4;
1973
1974 fPropertyData = [[NSData dataWithBytes : data length : dataSize] retain];
1975
1976 fType = type;
1977}
1978
1979//______________________________________________________________________________
1981{
1982 return fPropertyData;
1983}
1984
1985//______________________________________________________________________________
1986- (unsigned) fFormat
1987{
1988 return fFormat;
1989}
1990
1991@end
1992
1993#pragma mark - QuartzView.
1994
1995//
1996//QuartzView is a children view (also is a content view for a top-level QuartzWindow).
1997//
1998
1999@implementation QuartzView
2000
2001@synthesize fID;
2002@synthesize fContext;
2003/////////////////////
2004//SetWindowAttributes_t/WindowAttributes_t
2005@synthesize fEventMask;
2006@synthesize fClass;
2007@synthesize fDepth;
2008@synthesize fBitGravity;
2009@synthesize fWinGravity;
2010@synthesize fBackgroundPixel;
2011@synthesize fOverrideRedirect;
2012//SetWindowAttributes_t/WindowAttributes_t
2013/////////////////////
2014@synthesize fHasFocus;
2015@synthesize fParentView;
2016
2017@synthesize fPassiveGrabButton;
2018@synthesize fPassiveGrabEventMask;
2019@synthesize fPassiveGrabKeyModifiers;
2020@synthesize fActiveGrabEventMask;
2021@synthesize fPassiveGrabOwnerEvents;
2022@synthesize fSnapshotDraw;
2023@synthesize fCurrentCursor;
2024@synthesize fIsDNDAware;
2025
2026#pragma mark - Lifetime.
2027
2028//______________________________________________________________________________
2029- (id) initWithFrame : (NSRect) frame windowAttributes : (const SetWindowAttributes_t *)attr
2030{
2031 if (self = [super initWithFrame : frame]) {
2032 //Make this explicit (though memory is zero initialized).
2033 fBackBuffer = nil;
2034 fID = 0;
2035
2036 fDirectDraw = NO;
2037
2038 //Passive grab parameters.
2039 fPassiveGrabButton = -1;//0 is kAnyButton.
2042
2043 fPassiveKeyGrabs = [[NSMutableArray alloc] init];
2044
2045 [self setCanDrawConcurrently : NO];
2046
2047 [self setHidden : YES];
2048 //Actually, check if view need this.
2049 //
2050 if (attr)
2052
2054 fX11Properties = [[NSMutableDictionary alloc] init];
2055
2059 }
2060
2061 return self;
2062}
2063
2064//______________________________________________________________________________
2065- (void) dealloc
2066{
2067 [fBackBuffer release];
2068 [fPassiveKeyGrabs release];
2069 [fX11Properties release];
2070 [fBackgroundPixmap release];
2071 [super dealloc];
2072}
2073
2074#pragma mark - Tracking area.
2075
2076//Tracking area is required to ... track mouse motion events inside a view.
2077
2078//______________________________________________________________________________
2079- (void) updateTrackingAreas
2080{
2081 [super updateTrackingAreas];
2082
2083 if (!fID)
2084 return;
2085
2087
2089 const NSUInteger size = [trackingArray count];
2090 for (NSUInteger i = 0; i < size; ++i) {
2091 NSTrackingArea * const t = [trackingArray objectAtIndex : i];
2092 [self removeTrackingArea : t];
2093 }
2094 }
2095
2099
2100 NSRect frame = {};
2101 frame.size.width = self.fWidth;
2102 frame.size.height = self.fHeight;
2103
2104 NSTrackingArea * const tracker = [[NSTrackingArea alloc] initWithRect : frame
2105 options : trackerOptions owner : self userInfo : nil];
2106 [self addTrackingArea : tracker];
2107 [tracker release];
2108}
2109
2110//______________________________________________________________________________
2112{
2113 [self updateTrackingAreas];
2114
2117}
2118
2119#pragma mark - X11Drawable protocol.
2120
2121//______________________________________________________________________________
2122- (BOOL) fIsPixmap
2123{
2124 return NO;
2125}
2126
2127//______________________________________________________________________________
2128- (BOOL) fIsOpenGLWidget
2129{
2130 return NO;
2131}
2132
2133//______________________________________________________________________________
2134- (CGFloat) fScaleFactor
2135{
2136 return self.fQuartzWindow.fScaleFactor;
2137}
2138
2139//______________________________________________________________________________
2140- (int) fX
2141{
2142 return self.frame.origin.x;
2143}
2144
2145//______________________________________________________________________________
2146- (int) fY
2147{
2148 return self.frame.origin.y;
2149}
2150
2151//______________________________________________________________________________
2152- (unsigned) fWidth
2153{
2154 return self.frame.size.width;
2155}
2156
2157//______________________________________________________________________________
2158- (unsigned) fHeight
2159{
2160 return self.frame.size.height;
2161}
2162
2163//______________________________________________________________________________
2164- (void) setDrawableSize : (NSSize) newSize
2165{
2166 assert(!(newSize.width < 0) && "-setDrawableSize, width is negative");
2167 assert(!(newSize.height < 0) && "-setDrawableSize, height is negative");
2168
2169 //This will cause redraw(?)
2170
2171 //In X11, resize changes the size, but upper-left corner is not changed.
2172 //In Cocoa, bottom-left is fixed.
2173 NSRect frame = self.frame;
2174 frame.size = newSize;
2175
2176 self.frame = frame;
2177}
2178
2179//______________________________________________________________________________
2180- (TAttLine *) attLine
2181{
2182 return &fAttLine;
2183}
2184
2185//______________________________________________________________________________
2186- (TAttFill *) attFill
2187{
2188 return &fAttFill;
2189}
2190
2191//______________________________________________________________________________
2193{
2194 return &fAttMarker;
2195}
2196
2197//______________________________________________________________________________
2198- (TAttText *) attText
2199{
2200 return &fAttText;
2201}
2202
2203//______________________________________________________________________________
2204- (void) setDrawMode : (TVirtualX::EDrawMode) newMode
2205{
2206 [self.fQuartzWindow setDrawMode:newMode];
2207}
2208
2209//______________________________________________________________________________
2210- (TVirtualX::EDrawMode) getDrawMode
2211{
2212 return [self.fQuartzWindow getDrawMode];
2213}
2214
2215//______________________________________________________________________________
2216- (void) setDirectDraw : (BOOL) mode
2217{
2218 fDirectDraw = mode;
2219
2220 // while painting operates with the pixmap, set direct flag for it too
2221 if (fBackBuffer)
2222 [fBackBuffer setDirectDraw : mode];
2223}
2224
2225//______________________________________________________________________________
2226- (BOOL) isDirectDraw
2227{
2228 return fDirectDraw;
2229}
2230
2231//______________________________________________________________________________
2232- (void) setX : (int) x Y : (int) y width : (unsigned) w height : (unsigned) h
2233{
2234 NSRect newFrame = {};
2235 newFrame.origin.x = x;
2236 newFrame.origin.y = y;
2237 newFrame.size.width = w;
2238 newFrame.size.height = h;
2239
2240 self.frame = newFrame;
2241}
2242
2243//______________________________________________________________________________
2244- (void) setX : (int) x Y : (int) y
2245{
2246 NSRect newFrame = self.frame;
2247 newFrame.origin.x = x;
2248 newFrame.origin.y = y;
2249
2250 self.frame = newFrame;
2251}
2252
2253//______________________________________________________________________________
2254- (void) copyImage : (QuartzImage *) srcImage area : (X11::Rectangle) area
2255 withMask : (QuartzImage *) mask clipOrigin : (X11::Point) clipXY
2256 toPoint : (X11::Point) dstPoint
2257{
2258 //Check parameters.
2259 assert(srcImage != nil &&
2260 "-copyImage:area:withMask:clipOrigin:toPoint:, parameter 'srcImage' is nil");
2261 assert(srcImage.fImage != nil &&
2262 "-copyImage:area:withMask:clipOrigin:toPoint:, srcImage.fImage is nil");
2263
2264 //Check self.
2265 assert(self.fContext != 0 &&
2266 "-copyImage:area:withMask:clipOrigin:toPoint:, self.fContext is null");
2267
2269 NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2270 " srcRect and copyRect do not intersect");
2271 return;
2272 }
2273
2274 //No RAII for subImage, since it can be really subimage or image itself and
2275 //in these cases there is no need to release image.
2276 CGImageRef subImage = 0;
2277 bool needSubImage = false;
2278 if (area.fX || area.fY || area.fWidth != srcImage.fWidth || area.fHeight != srcImage.fHeight) {
2279 needSubImage = true;
2281 if (!subImage) {
2282 NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2283 " subimage creation failed");
2284 return;
2285 }
2286 } else
2287 subImage = srcImage.fImage;
2288
2289 //Save context state.
2290 const Quartz::CGStateGuard ctxGuard(self.fContext);
2291
2292 //Scale and translate to undo isFlipped.
2293 CGContextTranslateCTM(self.fContext, 0., self.fHeight);
2294 CGContextScaleCTM(self.fContext, 1., -1.);
2295 //Set clip mask on a context.
2296
2297 if (mask) {
2298 assert(mask.fImage != nil &&
2299 "-copyImage:area:withMask:clipOrigin:toPoint:, mask.fImage is nil");
2300 assert(CGImageIsMask(mask.fImage) == true &&
2301 "-copyImage:area:withMask:clipOrigin:toPoint:, mask.fImage is not a mask");
2302 //clipXY.fY = X11::LocalYROOTToCocoa(self, clipXY.fY + mask.fHeight);
2303 const CGFloat clipY = X11::LocalYROOTToCocoa(self, CGFloat(clipXY.fY) + mask.fHeight);
2304 //const CGRect clipRect = CGRectMake(clipXY.fX, clipXY.fY, mask.fWidth, mask.fHeight);
2305 const CGRect clipRect = CGRectMake(clipXY.fX, clipY, mask.fWidth, mask.fHeight);
2306 CGContextClipToMask(self.fContext, clipRect, mask.fImage);
2307 }
2308
2309 //Convert from X11 to Cocoa (as soon as we scaled y * -1).
2310 //dstPoint.fY = X11::LocalYROOTToCocoa(self, dstPoint.fY + area.fHeight);
2311 const CGFloat dstY = X11::LocalYROOTToCocoa(self, CGFloat(dstPoint.fY) + area.fHeight);
2312 //const CGRect imageRect = CGRectMake(dstPoint.fX, dstPoint.fY, area.fWidth, area.fHeight);
2313 const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2315
2316 if (needSubImage)
2318}
2319
2320//______________________________________________________________________________
2321- (void) copyView : (QuartzView *) srcView area : (X11::Rectangle) area toPoint : (X11::Point) dstPoint
2322{
2323 //To copy one "window" to another "window", I have to ask source QuartzView to draw intself into
2324 //bitmap, and copy this bitmap into the destination view.
2325
2326 assert(srcView != nil && "-copyView:area:toPoint:, parameter 'srcView' is nil");
2327
2328 const NSRect frame = [srcView frame];
2329 //imageRep is in autorelease pool now.
2330 NSBitmapImageRep * const imageRep = [srcView bitmapImageRepForCachingDisplayInRect : frame];
2331 if (!imageRep) {
2332 NSLog(@"QuartzView: -copyView:area:toPoint failed");
2333 return;
2334 }
2335
2336 assert(srcView != nil && "-copyView:area:toPoint:, parameter 'srcView' is nil");
2337 assert(self.fContext != 0 && "-copyView:area:toPoint, self.fContext is null");
2338
2339 //It can happen, that src and self are the same.
2340 //cacheDisplayInRect calls drawRect with bitmap context
2341 //(and this will reset self.fContext: I have to save/restore it.
2342 CGContextRef ctx = srcView.fContext;
2343 srcView.fSnapshotDraw = YES;
2344 [srcView cacheDisplayInRect : frame toBitmapImageRep : imageRep];
2345 srcView.fSnapshotDraw = NO;
2346 srcView.fContext = ctx;
2347
2348 const CGRect subImageRect = CGRectMake(area.fX, area.fY, area.fWidth, area.fHeight);
2350
2351 if (!subImage.Get()) {
2352 NSLog(@"QuartzView: -copyView:area:toPoint, CGImageCreateWithImageInRect failed");
2353 return;
2354 }
2355
2356 const Quartz::CGStateGuard ctxGuard(self.fContext);
2358 [self visibleRect].size.height - (CGFloat(dstPoint.fY) + area.fHeight),
2359 area.fWidth, area.fHeight);
2360
2361 CGContextTranslateCTM(self.fContext, 0., [self visibleRect].size.height);
2362 CGContextScaleCTM(self.fContext, 1., -1.);
2363
2364 CGContextDrawImage(self.fContext, imageRect, subImage.Get());
2365}
2366
2367//______________________________________________________________________________
2368- (void) copyPixmap : (QuartzPixmap *) srcPixmap area : (X11::Rectangle) area
2369 withMask : (QuartzImage *) mask clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
2370{
2371 //Check parameters.
2372 assert(srcPixmap != nil && "-copyPixmap:area:withMask:clipOrigin:toPoint:, parameter 'srcPixmap' is nil");
2373
2375 NSLog(@"QuartzView: -copyPixmap:area:withMask:clipOrigin:toPoint,"
2376 " no intersection between pixmap rectangle and cropArea");
2377 return;
2378 }
2379
2380 //Check self.
2381 assert(self.fContext != 0 &&
2382 "-copyPixmap:area:withMask:clipOrigin:toPoint:, self.fContext is null");
2383
2384 //Save context state.
2385 const Quartz::CGStateGuard ctxGuard(self.fContext);
2386
2387 CGContextTranslateCTM(self.fContext, 0., self.frame.size.height);//???
2388 CGContextScaleCTM(self.fContext, 1., -1.);
2389
2390 const Util::CFScopeGuard<CGImageRef> imageFromPixmap([srcPixmap createImageFromPixmap]);
2391 assert(imageFromPixmap.Get() != 0 &&
2392 "-copyPixmap:area:withMask:clipOrigin:toPoint:, createImageFromPixmap failed");
2393
2394 CGImageRef subImage = 0;
2395 bool needSubImage = false;
2396 if (area.fX || area.fY || area.fWidth != srcPixmap.fWidth || area.fHeight != srcPixmap.fHeight) {
2397 needSubImage = true;
2398 const CGRect subImageRect = CGRectMake(area.fX, area.fY, area.fHeight, area.fWidth);
2400 if (!subImage) {
2401 NSLog(@"QuartzView: -copyImage:area:withMask:clipOrigin:toPoint:,"
2402 " subimage creation failed");
2403 return;
2404 }
2405 } else
2406 subImage = imageFromPixmap.Get();
2407
2408 if (mask) {
2409 assert(mask.fImage != nil &&
2410 "-copyPixmap:area:withMask:clipOrigin:toPoint:, mask.fImage is nil");
2411 assert(CGImageIsMask(mask.fImage) == true &&
2412 "-copyPixmap:area:withMask:clipOrigin:toPoint:, mask.fImage is not a mask");
2413
2414 //clipXY.fY = X11::LocalYROOTToCocoa(self, clipXY.fY + mask.fHeight);
2415 const CGFloat clipY = X11::LocalYROOTToCocoa(self, CGFloat(clipXY.fY) + mask.fHeight);
2416 //const CGRect clipRect = CGRectMake(clipXY.fX, clipXY.fY, mask.fWidth, mask.fHeight);
2417 const CGRect clipRect = CGRectMake(clipXY.fX, clipY, mask.fWidth, mask.fHeight);
2418 CGContextClipToMask(self.fContext, clipRect, mask.fImage);
2419 }
2420
2421 //dstPoint.fY = X11::LocalYCocoaToROOT(self, dstPoint.fY + area.fHeight);
2422 const CGFloat dstY = X11::LocalYCocoaToROOT(self, CGFloat(dstPoint.fY) + area.fHeight);
2423 const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2425
2426 if (needSubImage)
2428}
2429
2430
2431//______________________________________________________________________________
2432- (void) copyImage : (QuartzImage *) srcImage area : (X11::Rectangle) area
2433 toPoint : (X11::Point) dstPoint
2434{
2435 assert(srcImage != nil && "-copyImage:area:toPoint:, parameter 'srcImage' is nil");
2436 assert(srcImage.fImage != nil && "-copyImage:area:toPoint:, srcImage.fImage is nil");
2437 assert(self.fContext != 0 && "-copyImage:area:toPoint:, fContext is null");
2438
2440 NSLog(@"QuartzView: -copyImage:area:toPoint, image and copy area do not intersect");
2441 return;
2442 }
2443
2444 CGImageRef subImage = 0;
2445 bool needSubImage = false;
2446 if (area.fX || area.fY || area.fWidth != srcImage.fWidth || area.fHeight != srcImage.fHeight) {
2447 needSubImage = true;
2449 if (!subImage) {
2450 NSLog(@"QuartzView: -copyImage:area:toPoint:, subimage creation failed");
2451 return;
2452 }
2453 } else
2454 subImage = srcImage.fImage;
2455
2456 const Quartz::CGStateGuard ctxGuard(self.fContext);
2457
2458 CGContextTranslateCTM(self.fContext, 0., self.fHeight);
2459 CGContextScaleCTM(self.fContext, 1., -1.);
2460
2461 //dstPoint.fY = X11::LocalYCocoaToROOT(self, dstPoint.fY + area.fHeight);
2462 const CGFloat dstY = X11::LocalYCocoaToROOT(self, CGFloat(dstPoint.fY) + area.fHeight);
2463 //const CGRect imageRect = CGRectMake(dstPoint.fX, dstPoint.fY, area.fWidth, area.fHeight);
2464 const CGRect imageRect = CGRectMake(dstPoint.fX, dstY, area.fWidth, area.fHeight);
2466
2467 if (needSubImage)
2469}
2470
2471//______________________________________________________________________________
2472- (void) copy : (NSObject<X11Drawable> *) src area : (X11::Rectangle) area
2473 withMask : (QuartzImage *)mask clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint
2474{
2475 assert(src != nil && "-copy:area:withMask:clipOrigin:toPoint:, parameter 'src' is nil");
2476 assert(area.fWidth && area.fHeight && "-copy:area:withMask:clipOrigin:toPoint:, area to copy is empty");
2477
2478 if ([src isKindOfClass : [QuartzWindow class]]) {
2479 //Forget about mask (can I have it???)
2480 QuartzWindow * const qw = (QuartzWindow *)src;
2481 //Will not work with OpenGL.
2482 [self copyView : (QuartzView *)qw.fContentView area : area toPoint : dstPoint];
2483 } else if ([src isKindOfClass : [QuartzView class]]) {
2484 //Forget about mask (can I have it???)
2485 [self copyView : (QuartzView *)src area : area toPoint : dstPoint];
2486 } else if ([src isKindOfClass : [QuartzPixmap class]]) {
2487 [self copyPixmap : (QuartzPixmap *)src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
2488 } else if ([src isKindOfClass : [QuartzImage class]]) {
2489 [self copyImage : (QuartzImage *)src area : area withMask : mask clipOrigin : clipXY toPoint : dstPoint];
2490 } else {
2491 assert(0 && "-copy:area:withMask:clipOrigin:toPoint:, src is of unknown type");
2492 }
2493}
2494
2495//______________________________________________________________________________
2496- (unsigned char *) readColorBits : (X11::Rectangle) area
2497{
2498 //This is quite a bad idea - to read pixels back from a view,
2499 //but our GUI does exactly this. In case of Cocoa it's expensive
2500 //and not guaranteed to work.
2501
2502 assert(area.fWidth && area.fHeight && "-readColorBits:, area to copy is empty");
2503
2504 //int, not unsigned or something - to keep it simple.
2505 NSRect visRect = [self visibleRect];
2506 // 'Sanitize' visible rect, which is different starting from macOS 14 -
2507 // in that it's considered to be visible even in a hidden part which has
2508 // no 'color bits' at all an result in reading arbitrary colored 'pixels',
2509 // probably black ones:
2510 if (visRect.origin.y < 0) {
2511 visRect.size.height += visRect.origin.y;
2512 visRect.origin.y = 0.;
2513 }
2514 if (visRect.origin.x < 0) {
2515 visRect.size.width += visRect.origin.x;
2516 visRect.origin.x = 0.;
2517 }
2518
2519 const X11::Rectangle srcRect(int(visRect.origin.x), int(visRect.origin.y),
2520 unsigned(visRect.size.width), unsigned(visRect.size.height));
2521
2523 NSLog(@"QuartzView: -readColorBits:, visible rect of view and copy area do not intersect");
2524 return nullptr;
2525 }
2526
2527 //imageRep is autoreleased.
2528 NSBitmapImageRep * const imageRep = [self bitmapImageRepForCachingDisplayInRect : visRect];
2529 if (!imageRep) {
2530 NSLog(@"QuartzView: -readColorBits:, bitmapImageRepForCachingDisplayInRect failed");
2531 return nullptr;
2532 }
2533
2534 CGContextRef ctx = self.fContext; //Save old context if any.
2535 [self cacheDisplayInRect : visRect toBitmapImageRep : imageRep];
2536 self.fContext = ctx; //Restore old context.
2537 //
2538 const NSInteger bitsPerPixel = [imageRep bitsPerPixel];
2539
2540 assert(bitsPerPixel == 32 && "-readColorBits:, no alpha channel???");
2541 const NSInteger bytesPerRow = [imageRep bytesPerRow];
2542 unsigned dataWidth = bytesPerRow / (bitsPerPixel / 8);//assume an octet :(
2543
2544 unsigned char *srcData = nullptr;
2545 std::vector<unsigned char> downscaled;
2546 if ([self.window.screen backingScaleFactor] > 1 && imageRep.CGImage) {
2547 downscaled = X11::DownscaledImageData(area.fWidth, area.fHeight, imageRep.CGImage);
2548 if (downscaled.size())
2549 srcData = &downscaled[0];
2550 dataWidth = area.fWidth;
2551 } else
2552 srcData = [imageRep bitmapData];
2553
2554 if (!srcData) {
2555 NSLog(@"QuartzView: -readColorBits:, failed to obtain backing store contents");
2556 return nullptr;
2557 }
2558
2559 //We have a source data now. Let's allocate buffer for ROOT's GUI and convert source data.
2560 unsigned char *data = nullptr;
2561
2562 try {
2563 data = new unsigned char[area.fWidth * area.fHeight * 4];//bgra?
2564 } catch (const std::bad_alloc &) {
2565 NSLog(@"QuartzView: -readColorBits:, memory allocation failed");
2566 return nullptr;
2567 }
2568
2569 unsigned char *dstPixel = data;
2570 const unsigned char *line = srcData + area.fY * dataWidth * 4;
2571 const unsigned char *srcPixel = line + area.fX * 4;
2572
2573 for (unsigned i = 0; i < area.fHeight; ++i) {
2574 for (unsigned j = 0; j < area.fWidth; ++j, srcPixel += 4, dstPixel += 4) {
2575 dstPixel[0] = srcPixel[2];
2576 dstPixel[1] = srcPixel[1];
2577 dstPixel[2] = srcPixel[0];
2578 dstPixel[3] = srcPixel[3];
2579 }
2580
2581 line += dataWidth * 4;
2582 srcPixel = line + area.fX * 4;
2583 }
2584
2585 return data;
2586}
2587
2588//______________________________________________________________________________
2589- (void) setFBackgroundPixmap : (QuartzImage *) pixmap
2590{
2591 if (fBackgroundPixmap != pixmap) {
2592 [fBackgroundPixmap release];
2593 if (pixmap)
2595 else
2597 }
2598}
2599
2600//______________________________________________________________________________
2602{
2603 //I do not autorelease, screw this idiom!
2604
2605 return fBackgroundPixmap;
2606}
2607
2608//______________________________________________________________________________
2609- (int) fMapState
2610{
2611 if ([self isHidden])
2612 return kIsUnmapped;
2613
2614 for (QuartzView *parent = fParentView; parent; parent = parent.fParentView) {
2615 if ([parent isHidden])
2616 return kIsUnviewable;
2617 }
2618
2619 return kIsViewable;
2620}
2621
2622//______________________________________________________________________________
2623- (BOOL) fHasFocus
2624{
2625 //With the latest update clang became a bit more stupid.
2626 //Let's write a stupid useless cargo cult code
2627 //to make IT SHUT THE F... UP.
2628 (void)fHasFocus;
2629 return NO;
2630}
2631
2632//______________________________________________________________________________
2633- (void) setFHasFocus : (BOOL) focus
2634{
2635#pragma unused(focus)
2636 //With the latest update clang became a bit more stupid.
2637 //Let's write a stupid useless cargo cult code
2638 //to make IT SHUT THE F... UP.
2639 (void)fHasFocus;
2640}
2641
2642//______________________________________________________________________________
2644{
2645 return fBackBuffer;//No autorelease, I know the object's lifetime myself.
2646}
2647
2648//______________________________________________________________________________
2649- (void) setFBackBuffer : (QuartzPixmap *) backBuffer
2650{
2651 if (fBackBuffer != backBuffer) {
2652 [fBackBuffer release];
2653
2654 if (backBuffer)
2655 fBackBuffer = [backBuffer retain];
2656 else
2657 fBackBuffer = nil;
2658 }
2659}
2660
2661//______________________________________________________________________________
2663{
2664 return self;
2665}
2666
2667//______________________________________________________________________________
2669{
2670 return (QuartzWindow *)[self window];
2671}
2672
2673//______________________________________________________________________________
2674- (void) activatePassiveGrab
2675{
2677}
2678
2679//______________________________________________________________________________
2680- (void) activateImplicitGrab
2681{
2683}
2684
2685//______________________________________________________________________________
2686- (void) activateGrab : (unsigned) eventMask ownerEvents : (BOOL) ownerEvents
2687{
2691}
2692
2693//______________________________________________________________________________
2694- (void) cancelGrab
2695{
2699}
2700
2701//______________________________________________________________________________
2702- (BOOL) acceptsCrossingEvents : (unsigned) eventMask
2703{
2704 bool accepts = fEventMask & eventMask;
2705
2706 //In ROOT passive grabs are always with owner_events == true.
2709
2713 else
2715 }
2716
2717 return accepts;
2718}
2719
2720//______________________________________________________________________________
2721- (void)didAddSubview:(NSView *)subview
2722{
2723 [super didAddSubview:subview];
2724 self.wantsLayer = YES;
2725 self.layer.masksToBounds = YES;
2726}
2727
2728//______________________________________________________________________________
2729- (void)willRemoveSubview:(NSView *)subview
2730{
2731 [super willRemoveSubview:subview];
2732 self.wantsLayer = YES;
2733 self.layer.masksToBounds = self.subviews.count > 1;
2734}
2735
2736//______________________________________________________________________________
2737- (void) addChild : (NSView<X11Window> *) child
2738{
2739 assert(child != nil && "-addChild:, parameter 'child' is nil");
2740
2741 [self addSubview : child];
2742 child.fParentView = self;
2743}
2744
2745//______________________________________________________________________________
2746- (void) getAttributes : (WindowAttributes_t *) attr
2747{
2748 assert(attr != 0 && "-getAttributes:, parameter 'attr' is null");
2749
2751}
2752
2753//______________________________________________________________________________
2754- (void) setAttributes : (const SetWindowAttributes_t *)attr
2755{
2756 assert(attr != 0 && "-setAttributes:, parameter 'attr' is null");
2757
2758#ifdef DEBUG_ROOT_COCOA
2760#endif
2761
2763}
2764
2765//______________________________________________________________________________
2766- (void) mapRaised
2767{
2768 //Move view to the top of subviews.
2769 QuartzView * const parent = fParentView;
2770 [self removeFromSuperview];
2771 [parent addSubview : self];
2772 [self setHidden : NO];
2773}
2774
2775//______________________________________________________________________________
2776- (void) mapWindow
2777{
2778 [self setHidden : NO];
2779}
2780
2781//______________________________________________________________________________
2782- (void) mapSubwindows
2783{
2784 for (QuartzView * v in [self subviews])
2785 [v setHidden : NO];
2786}
2787
2788//______________________________________________________________________________
2789- (void) unmapWindow
2790{
2791 [self setHidden : YES];
2792}
2793
2794//______________________________________________________________________________
2795- (BOOL) fIsOverlapped
2796{
2797 return fIsOverlapped;
2798}
2799
2800//______________________________________________________________________________
2801- (void) setOverlapped : (BOOL) overlap
2802{
2805 [child setOverlapped : overlap];
2806}
2807
2808//______________________________________________________________________________
2809- (void) raiseWindow
2810{
2811 //Now, I can not remove window and add it ...
2812 //For example, if you click on a tab, this:
2813 //1. Creates (potentially) a passive button grab
2814 //2. Raises this tab - changes the window order.
2815 //3. On a button release - grab is release.
2816 //The tough problem is, if I remove a view from subviews
2817 //and add it ... it will never receve the
2818 //release event thus a grab will 'hang' on
2819 //view leading to bugs and artifacts.
2820 //So instead I have to ... SORT!!!!!
2821
2822 using namespace X11;//Comparators.
2823
2825 if (self == sibling)
2826 continue;
2827 if ([sibling isHidden])
2828 continue;
2829
2830 if (NSEqualRects(sibling.frame, self.frame)) {
2831 [sibling setOverlapped : YES];
2832 [sibling setHidden : YES];
2833 }
2834 }
2835
2836 [self setOverlapped : NO];
2837 //
2838 [self setHidden : NO];
2839 //
2840 [fParentView sortSubviewsUsingFunction : CompareViewsToRaise context : (void *)self];
2841 //
2842 [self updateTrackingAreasAfterRaise];
2843 //
2844 [self setNeedsDisplay : YES];
2845}
2846
2847//______________________________________________________________________________
2848- (void) lowerWindow
2849{
2850 //See comment about sorting in -raiseWindow.
2851
2852 using namespace X11;
2853
2854 NSEnumerator * const reverseEnumerator = [[fParentView subviews] reverseObjectEnumerator];
2856 if (sibling == self)
2857 continue;
2858
2859 if (NSEqualRects(sibling.frame, self.frame)) {
2860 [sibling setOverlapped : NO];
2861 //
2862 [sibling setHidden : NO];
2863 //
2864 [sibling setNeedsDisplay : YES];
2865 [self setOverlapped : YES];
2866 //
2867 [self setHidden : YES];
2868 //
2869 break;
2870 }
2871 }
2872
2873 [fParentView sortSubviewsUsingFunction : CompareViewsToLower context : (void*)self];
2874}
2875
2876//______________________________________________________________________________
2877- (BOOL) isFlipped
2878{
2879 //Now view's placement, geometry, moving and resizing can be
2880 //done with ROOT's (X11) coordinates without conversion - we're are 'flipped'.
2881 return YES;
2882}
2883
2884//______________________________________________________________________________
2885- (void) configureNotifyTree
2886{
2887 if (self.fMapState == kIsViewable || fIsOverlapped == YES) {
2889 assert(dynamic_cast<TGCocoa *>(gVirtualX) &&
2890 "-configureNotifyTree, gVirtualX is either null or has type different from TGCocoa");
2891 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
2892 vx->GetEventTranslator()->GenerateConfigureNotifyEvent(self, self.frame);
2893 }
2894
2896 [v configureNotifyTree];
2897 }
2898}
2899
2900#pragma mark - Key grabs.
2901
2902//______________________________________________________________________________
2903- (void) addPassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2904{
2905 [self removePassiveKeyGrab : keyCode modifiers : modifiers];
2906 PassiveKeyGrab * const newGrab = [[PassiveKeyGrab alloc] initWithKey : keyCode
2907 modifiers : modifiers];
2908 [fPassiveKeyGrabs addObject : newGrab];
2909 [newGrab release];
2910}
2911
2912//______________________________________________________________________________
2913- (void) removePassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2914{
2915 const NSUInteger count = [fPassiveKeyGrabs count];
2916 for (NSUInteger i = 0; i < count; ++i) {
2917 PassiveKeyGrab *grab = [fPassiveKeyGrabs objectAtIndex : i];
2919 [fPassiveKeyGrabs removeObjectAtIndex : i];
2920 break;
2921 }
2922 }
2923}
2924
2925//______________________________________________________________________________
2926- (PassiveKeyGrab *) findPassiveKeyGrab : (unichar) keyCode modifiers : (NSUInteger) modifiers
2927{
2928 NSEnumerator * const enumerator = [fPassiveKeyGrabs objectEnumerator];
2931 return grab;
2932 }
2933
2934 return nil;
2935}
2936
2937//______________________________________________________________________________
2938- (PassiveKeyGrab *) findPassiveKeyGrab : (unichar) keyCode
2939{
2940 //Do not check modifiers.
2941 NSEnumerator * const enumerator = [fPassiveKeyGrabs objectEnumerator];
2943 if ([grab matchKey : keyCode])
2944 return grab;
2945 }
2946
2947 return nil;
2948}
2949
2950#pragma mark - Painting mechanics.
2951
2952//______________________________________________________________________________
2953- (void) drawRect : (NSRect) dirtyRect
2954{
2955#pragma unused(dirtyRect)
2956
2957 using namespace X11;
2958
2959 if (fID) {
2960 if (TGWindow * const window = gClient->GetWindowById(fID)) {
2961 //It's never painted, parent renders child. true == check the parent also.
2963 return;
2964
2965 NSGraphicsContext * const nsContext = [NSGraphicsContext currentContext];
2966 assert(nsContext != nil && "-drawRect:, currentContext returned nil");
2967
2968 TGCocoa * const vx = (TGCocoa *)gVirtualX;
2969 vx->CocoaDrawON();
2970
2972 assert(fContext != 0 && "-drawRect:, graphicsPort returned null");
2973
2975
2976 //Non-rectangular windows.
2977 if (self.fQuartzWindow.fShapeCombineMask)
2979
2980 // This code used to use TObject::InheritsFrom, however since this is
2981 // run under the AppKit, we can not call core/meta functions, otherwise
2982 // we will run into deadlocks.
2983 if (dynamic_cast<const TGContainer*>(window))//It always has an ExposureMask.
2984 vx->GetEventTranslator()->GenerateExposeEvent(self, [self visibleRect]);
2985
2986 if (fEventMask & kExposureMask) {
2987 if (ViewIsTextView(self)) {
2988 //Send Expose event, using child view (this is how it's done in GUI :( ).
2989 [NSColor.whiteColor setFill];
2990 NSRect frame = self.frame;
2991 frame.origin = {};
2992 NSRectFill(frame);
2994 if (viewFrame)//Now we set fExposedRegion for TGView.
2995 vx->GetEventTranslator()->GenerateExposeEvent(viewFrame, viewFrame.visibleRect);
2996 }
2997
2998 if (ViewIsHtmlView(self)) {
3000 if (viewFrame)
3001 vx->GetEventTranslator()->GenerateExposeEvent(viewFrame, viewFrame.visibleRect);
3002 }
3003
3004 //Ask ROOT's widget/window to draw itself.
3005 gClient->NeedRedraw(window, kTRUE);
3006
3007 if (!fSnapshotDraw) {
3008 //If Cocoa repaints widget, cancel all ROOT's "outside of paint event"
3009 //rendering into this widget.
3010 gClient->CancelRedraw(window);
3011 vx->GetCommandBuffer()->RemoveGraphicsOperationsForWindow(fID);
3012 }
3013 }
3014
3015 if (fBackBuffer) {
3016 //Very "special" window.
3018 [self copy : fBackBuffer area : copyArea withMask : nil
3019 clipOrigin : X11::Point() toPoint : X11::Point()];
3020 }
3021
3022 vx->CocoaDrawOFF();
3023#ifdef DEBUG_ROOT_COCOA
3024 CGContextSetRGBStrokeColor(fContext, 1., 0., 0., 1.);
3026#endif
3027
3028 fContext = 0;
3029 } else {
3030#ifdef DEBUG_ROOT_COCOA
3031 NSLog(@"QuartzView: -drawRect: method, no window for id %u was found", fID);
3032#endif
3033 }
3034 }
3035}
3036
3037#pragma mark - Geometry.
3038
3039//______________________________________________________________________________
3040- (void) setFrame : (NSRect) newFrame
3041{
3042 //In case of TBrowser, setFrame started infinite recursion:
3043 //HandleConfigure for embedded main frame emits signal, slot
3044 //calls layout, layout calls setFrame -> HandleConfigure and etc. etc.
3045 if (NSEqualRects(newFrame, self.frame))
3046 return;
3047
3048 [super setFrame : newFrame];
3049}
3050
3051//______________________________________________________________________________
3052- (void) setFrameSize : (NSSize) newSize
3053{
3054 //Check, if setFrameSize calls setFrame.
3055
3056 [super setFrameSize : newSize];
3057
3058 if ((fEventMask & kStructureNotifyMask) && (self.fMapState == kIsViewable || fIsOverlapped == YES)) {
3059 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3060 "setFrameSize:, gVirtualX is either null or has a type, different from TGCocoa");
3061 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3062 vx->GetEventTranslator()->GenerateConfigureNotifyEvent(self, self.frame);
3063 }
3064
3065 [self setNeedsDisplay : YES];//?
3066}
3067
3068#pragma mark - Event handling.
3069
3070//______________________________________________________________________________
3071- (void) mouseDown : (NSEvent *) theEvent
3072{
3073 assert(fID != 0 && "-mouseDown:, fID is 0");
3074
3075 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3076 "-mouseDown:, gVirtualX is either null or has a type, different from TGCocoa");
3077 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3078 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton1);
3079}
3080
3081//______________________________________________________________________________
3082- (void) scrollWheel : (NSEvent*) theEvent
3083{
3084 assert(fID != 0 && "-scrollWheel:, fID is 0");
3085
3086
3087 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3088 "-scrollWheel:, gVirtualX is either null or has a type, different from TGCocoa");
3089
3090 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3091 const CGFloat deltaY = [theEvent deltaY];
3092 if (deltaY < 0) {
3093 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton5);
3094 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton5);
3095 } else if (deltaY > 0) {
3096 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton4);
3097 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton4);
3098 }
3099}
3100
3101#ifdef DEBUG_ROOT_COCOA
3102//______________________________________________________________________________
3103- (void) printViewInformation
3104{
3105 assert(fID != 0 && "-printWindowInformation, fID is 0");
3106 const TGWindow * const window = gClient->GetWindowById(fID);
3107 assert(window != 0 && "printWindowInformation, window not found");
3108
3109 NSLog(@"-----------------View %u info:---------------------", fID);
3110 NSLog(@"ROOT's window class is %s", window->IsA()->GetName());
3111 NSLog(@"event mask is:");
3113 NSLog(@"grab mask is:");
3115 NSLog(@"view's geometry: x == %g, y == %g, w == %g, h == %g", self.frame.origin.x,
3116 self.frame.origin.y, self.frame.size.width, self.frame.size.height);
3117 NSLog(@"----------------End of view info------------------");
3118}
3119#endif
3120
3121//______________________________________________________________________________
3122- (void) rightMouseDown : (NSEvent *) theEvent
3123{
3124 assert(fID != 0 && "-rightMouseDown:, fID is 0");
3125
3126#ifdef DEBUG_ROOT_COCOA
3127 [self printViewInformation];
3128#endif
3129
3130 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3131 "-rightMouseDown:, gVirtualX is either null or has type different from TGCocoa");
3132 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3133 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton3);
3134}
3135
3136//______________________________________________________________________________
3137- (void) otherMouseDown : (NSEvent *) theEvent
3138{
3139 assert(fID != 0 && "-otherMouseDown:, fID is 0");
3140
3141 //Funny enough, [theEvent buttonNumber] is not the same thing as button masked in [NSEvent pressedMouseButtons],
3142 //button number actually is a kind of right operand for bitshift for pressedMouseButtons.
3143 if ([theEvent buttonNumber] == 2) {//this '2' will correspond to '4' in pressedMouseButtons.
3144 //I do not care about mouse buttons after left/right/wheel - ROOT does not have
3145 //any code for this.
3146 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3147 "-otherMouseDown:, gVirtualX is either null or has type different from TGCocoa");
3148 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3149 vx->GetEventTranslator()->GenerateButtonPressEvent(self, theEvent, kButton2);
3150 }
3151}
3152
3153//______________________________________________________________________________
3154- (void) mouseUp : (NSEvent *) theEvent
3155{
3156 assert(fID != 0 && "-mouseUp:, fID is 0");
3157
3158 assert(dynamic_cast<TGCocoa *>(gVirtualX) &&
3159 "-mouseUp:, gVirtualX is either null or has type different from TGCocoa");
3160 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3161 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton1);
3162}
3163
3164//______________________________________________________________________________
3165- (void) rightMouseUp : (NSEvent *) theEvent
3166{
3167
3168 assert(fID != 0 && "-rightMouseUp:, fID is 0");
3169
3170 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3171 "-rightMouseUp:, gVirtualX is either null or has type different from TGCocoa");
3172
3173 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3174 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton3);
3175}
3176
3177//______________________________________________________________________________
3178- (void) otherMouseUp : (NSEvent *) theEvent
3179{
3180 assert(fID != 0 && "-otherMouseUp:, fID is 0");
3181
3182 //Here I assume it's always kButton2.
3183 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3184 "-otherMouseUp:, gVirtualX is either null or has type different from TGCocoa");
3185 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3186 vx->GetEventTranslator()->GenerateButtonReleaseEvent(self, theEvent, kButton2);
3187}
3188
3189//______________________________________________________________________________
3190- (void) mouseEntered : (NSEvent *) theEvent
3191{
3192 assert(fID != 0 && "-mouseEntered:, fID is 0");
3193 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3194 "-mouseEntered:, gVirtualX is null or not of TGCocoa type");
3195
3196 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3197 vx->GetEventTranslator()->GenerateCrossingEvent(theEvent);
3198}
3199
3200//______________________________________________________________________________
3201- (void) mouseExited : (NSEvent *) theEvent
3202{
3203 assert(fID != 0 && "-mouseExited:, fID is 0");
3204
3205 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3206 "-mouseExited:, gVirtualX is null or not of TGCocoa type");
3207
3208 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3209 vx->GetEventTranslator()->GenerateCrossingEvent(theEvent);
3210}
3211
3212//______________________________________________________________________________
3213- (void) mouseMoved : (NSEvent *) theEvent
3214{
3215 assert(fID != 0 && "-mouseMoved:, fID is 0");
3216
3217 if (fParentView)//Suppress events in all views, except the top-level one.
3218 return;
3219
3220 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3221 "-mouseMoved:, gVirtualX is null or not of TGCocoa type");
3222
3223 TGCocoa *vx = static_cast<TGCocoa *>(gVirtualX);
3224 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3225}
3226
3227//______________________________________________________________________________
3228- (void) mouseDragged : (NSEvent *) theEvent
3229{
3230 assert(fID != 0 && "-mouseDragged:, fID is 0");
3231
3232 TGCocoa * const vx = dynamic_cast<TGCocoa *>(gVirtualX);
3233 assert(vx != 0 && "-mouseDragged:, gVirtualX is null or not of TGCocoa type");
3234
3235 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3236}
3237
3238//______________________________________________________________________________
3239- (void) rightMouseDragged : (NSEvent *) theEvent
3240{
3241 assert(fID != 0 && "-rightMouseDragged:, fID is 0");
3242
3243 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3244 "-rightMouseDragged:, gVirtualX is null or not of TGCocoa type");
3245
3246 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3247 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3248}
3249
3250//______________________________________________________________________________
3251- (void) otherMouseDragged : (NSEvent *) theEvent
3252{
3253 assert(fID != 0 && "-otherMouseDragged:, fID is 0");
3254
3255 if ([theEvent buttonNumber] == 2) {
3256 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3257 "-otherMouseDragged:, gVirtualX is null or not of TGCocoa type");
3258 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3259 vx->GetEventTranslator()->GeneratePointerMotionEvent(theEvent);
3260 }
3261}
3262
3263//______________________________________________________________________________
3264- (void) keyDown : (NSEvent *) theEvent
3265{
3266 assert(fID != 0 && "-keyDown:, fID is 0");
3267
3268 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3269 "-keyDown:, gVirtualX is null or not of TGCocoa type");
3270
3274
3275 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3276 vx->GetEventTranslator()->GenerateKeyPressEvent(eventView, theEvent);
3277}
3278
3279//______________________________________________________________________________
3280- (void) keyUp : (NSEvent *) theEvent
3281{
3282 assert(fID != 0 && "-keyUp:, fID is 0");
3283
3284 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
3285 "-keyUp:, gVirtualX is null or not of TGCocoa type");
3286
3287 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
3291
3292 vx->GetEventTranslator()->GenerateKeyReleaseEvent(eventView, theEvent);
3293}
3294
3295#pragma mark - First responder stuff.
3296
3297//______________________________________________________________________________
3298- (BOOL) acceptsFirstMouse : (NSEvent *) theEvent
3299{
3300#pragma unused(theEvent)
3301 return YES;
3302}
3303
3304//______________________________________________________________________________
3305- (BOOL) acceptsFirstResponder
3306{
3307 return YES;
3308}
3309
3310#pragma mark - Cursors.
3311
3312//______________________________________________________________________________
3313- (void) setFCurrentCursor : (ECursor) cursor
3314{
3315 if (cursor != fCurrentCursor) {
3317 [self.fQuartzWindow invalidateCursorRectsForView : self];
3318 }
3319}
3320
3321//______________________________________________________________________________
3323{
3324 const char *pngFileName = 0;
3325
3326 switch (fCurrentCursor) {
3327 case kMove:
3328 pngFileName = "move_cursor.png";
3329 break;
3330 case kArrowHor:
3331 pngFileName = "hor_arrow_cursor.png";
3332 break;
3333 case kArrowVer:
3334 pngFileName = "ver_arrow_cursor.png";
3335 break;
3336 case kArrowRight:
3337 pngFileName = "right_arrow_cursor.png";
3338 break;
3339 case kRotate:
3340 pngFileName = "rotate.png";
3341 break;
3342 case kBottomLeft:
3343 case kTopRight:
3344 pngFileName = "top_right_cursor.png";
3345 break;
3346 case kTopLeft:
3347 case kBottomRight:
3348 pngFileName = "top_left_cursor.png";
3349 break;
3350 default:;
3351 }
3352
3353 if (pngFileName) {
3354 const char * const path = gSystem->Which(TROOT::GetIconPath(), pngFileName, kReadPermission);
3356
3357 if (!path || path[0] == 0) {
3358 //File was not found.
3359 return nil;
3360 }
3361
3362 NSString *nsPath = [NSString stringWithFormat : @"%s", path];//in autorelease pool.
3363 NSImage * const cursorImage = [[NSImage alloc] initWithContentsOfFile : nsPath];
3364
3365 if (!cursorImage)
3366 return nil;
3367
3369 NSCursor * const customCursor = [[[NSCursor alloc] initWithImage : cursorImage
3370 hotSpot : hotSpot] autorelease];
3371
3372 [cursorImage release];
3373
3374 return customCursor;
3375 }
3376
3377 return nil;
3378}
3379
3380//______________________________________________________________________________
3381- (void) resetCursorRects
3382{
3384 [self addCursorRect : self.visibleRect cursor : cursor];
3385}
3386
3387//______________________________________________________________________________
3388- (void) cursorUpdate
3389{
3391 // NB: [window invalidateCursorRectsForView] called here has the
3392 // same problem as commented below in -cursorUpdate:.
3393 [cursor set];
3394 }
3395}
3396
3397//______________________________________________________________________________
3398- (void) cursorUpdate : (NSEvent *) event
3399{
3400#pragma unused(event)
3401 // It looks like [NSCursor set] method does not work properly when called from
3402 // cursorUpdate:, having, say, a parent frame with 'arrow' cursor and a child (completely
3403 // filling its parent's area) with 'cross', it happens the 'cross' cursor is not always
3404 // set correctly, for example:
3405 // if we have a TCanvas and resize it, cursor is 'arrow' inside this canvas,
3406 // though it must be 'cross'. This all, as it always happesn with "thinking different"
3407 // Apple is somehow related to run loop or something. As always, it's not documented,
3408 // so Apple can continue to think different. The idea with performSelector comes from:
3409 // http://stackoverflow.com/questions/8430236/nscursor-set-method-has-no-effect
3410 // Or may be it's just a bug:
3411 // http://stackoverflow.com/questions/13901232/nscursor-set-not-working-on-unfocused-window
3412 [self performSelector : @selector(cursorUpdate) withObject : nil afterDelay : 0.05f];
3413}
3414
3415#pragma mark - Emulated X11 properties.
3416
3417//______________________________________________________________________________
3418- (void) setProperty : (const char *) propName data : (unsigned char *) propData
3419 size : (unsigned) dataSize forType : (Atom_t) dataType format : (unsigned) format
3420{
3421 assert(propName != 0 && "-setProperty:data:size:forType:, parameter 'propName' is null");
3422 assert(propData != 0 && "-setProperty:data:size:forType:, parameter 'propData' is null");
3423 assert(dataSize != 0 && "-setProperty:data:size:forType:, parameter 'dataSize' is 0");
3424
3425 NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3427
3428 //At the moment (and I think this will never change) TGX11 always calls XChangeProperty with PropModeReplace.
3429 if (property)
3430 [property resetPropertyData : propData size : dataSize type : dataType format : format];
3431 else {
3432 //No property found, add a new one.
3433 property = [[QuartzWindowProperty alloc] initWithData : propData size : dataSize
3434 type : dataType format : format];
3435 [fX11Properties setObject : property forKey : key];
3436 [property release];
3437 }
3438}
3439
3440//______________________________________________________________________________
3441- (BOOL) hasProperty : (const char *) propName
3442{
3443 assert(propName != 0 && "-hasProperty:, propName parameter is null");
3444
3445 NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3447
3448 return property != nil;
3449}
3450
3451//______________________________________________________________________________
3452- (unsigned char *) getProperty : (const char *) propName returnType : (Atom_t *) type
3453 returnFormat : (unsigned *) format nElements : (unsigned *) nElements
3454{
3455 assert(propName != 0 &&
3456 "-getProperty:returnType:returnFormat:nElements:, parameter 'propName' is null");
3457 assert(type != 0 &&
3458 "-getProperty:returnType:returnFormat:nElements:, parameter 'type' is null");
3459 assert(format != 0 &&
3460 "-getProperty:returnType:returnFormat:nElements:, parameter 'format' is null");
3461 assert(nElements != 0 &&
3462 "-getProperty:returnType:returnFormat:nElements:, parameter 'nElements' is null");
3463
3464 NSString * const key = [NSString stringWithCString : propName encoding : NSASCIIStringEncoding];
3466 assert(property != 0 &&
3467 "-getProperty:returnType:returnFormat:nElements, property not found");
3468
3469 NSData * const propData = property.fPropertyData;
3470
3471 const NSUInteger dataSize = [propData length];
3472 unsigned char *buff = 0;
3473 try {
3474 buff = new unsigned char[dataSize]();
3475 } catch (const std::bad_alloc &) {
3476 //Hmm, can I log, if new failed? :)
3477 NSLog(@"QuartzWindow: -getProperty:returnType:returnFormat:nElements:,"
3478 " memory allocation failed");
3479 return 0;
3480 }
3481
3482 [propData getBytes : buff length : dataSize];
3483 *format = property.fFormat;
3484
3486
3487 if (*format == 16)
3488 *nElements= dataSize / 2;
3489 else if (*format == 32)
3490 *nElements = dataSize / 4;
3491
3492 *type = property.fType;
3493
3494 return buff;
3495}
3496
3497//______________________________________________________________________________
3498- (void) removeProperty : (const char *) propName
3499{
3500 assert(propName != 0 && "-removeProperty:, parameter 'propName' is null");
3501
3502 NSString * const key = [NSString stringWithCString : propName
3503 encoding : NSASCIIStringEncoding];
3504 [fX11Properties removeObjectForKey : key];
3505}
3506
3507//DND
3508//______________________________________________________________________________
3510{
3511 NSPasteboard * const pasteBoard = [sender draggingPasteboard];
3512 const NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
3513
3516
3517 return NSDragOperationNone;
3518}
3519
3520//______________________________________________________________________________
3521- (BOOL) performDragOperation : (id<NSDraggingInfo>) sender
3522{
3523 //We can drag some files (images, pdfs, source code files) from
3524 //finder to ROOT's window (mainly TCanvas or text editor).
3525 //The logic is totally screwed here :((( - ROOT will try to
3526 //read a property of some window (not 'self', unfortunately) -
3527 //this works since on Window all data is in a global clipboard
3528 //(on X11 it simply does not work at all).
3529 //I'm attaching the file name as a property for the top level window,
3530 //there is no other way to make this data accessible for ROOT.
3531
3532 NSPasteboard * const pasteBoard = [sender draggingPasteboard];
3533 const NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
3534
3536
3537 //Here I try to put string ("file://....") into window's property to make
3538 //it accesible from ROOT's GUI.
3539 const Atom_t textUriAtom = gVirtualX->InternAtom("text/uri-list", kFALSE);
3540
3541 NSArray * const files = [pasteBoard propertyListForType : NSFilenamesPboardType];
3542 for (NSString *path in files) {
3543 //ROOT can not process several files, use the first one.
3544 NSString * const item = [@"file://" stringByAppendingString : path];
3545 //Yes, only ASCII encoding, but after all, ROOT's not able to work with NON-ASCII strings.
3546 const NSUInteger len = [item lengthOfBytesUsingEncoding : NSASCIIStringEncoding] + 1;
3547 try {
3548 std::vector<unsigned char> propertyData(len);
3549 [item getCString : (char *)&propertyData[0] maxLength : propertyData.size()
3550 encoding : NSASCIIStringEncoding];
3551 //There is no any guarantee, that this will ever work, logic in TGDNDManager is totally crazy.
3552 NSView<X11Window> * const targetView = self.fQuartzWindow.fContentView;
3553 [targetView setProperty : "_XC_DND_DATA" data : &propertyData[0]
3554 size : propertyData.size() forType : textUriAtom format : 8];
3555 } catch (const std::bad_alloc &) {
3556 //Hehe, can I log something in case of bad_alloc??? ;)
3557 NSLog(@"QuartzView: -performDragOperation:, memory allocation failed");
3558 return NO;
3559 }
3560
3561 break;
3562 }
3563
3564 //Property is attached now.
3565
3566 //Gdk on windows creates three events on file drop (WM_DROPFILES): XdndEnter, XdndPosition, XdndDrop.
3567 //1. Dnd enter.
3568 Event_t event1 = {};
3569 event1.fType = kClientMessage;
3570 event1.fWindow = fID;
3571 event1.fHandle = gVirtualX->InternAtom("XdndEnter", kFALSE);
3572 event1.fUser[0] = long(fID);
3573 event1.fUser[2] = textUriAtom;//gVirtualX->InternAtom("text/uri-list", kFALSE);
3574 //
3575 gVirtualX->SendEvent(fID, &event1);
3576
3577 //2. Dnd position.
3578 Event_t event2 = {};
3579 event2.fType = kClientMessage;
3580 event2.fWindow = fID;
3581 event2.fHandle = gVirtualX->InternAtom("XdndPosition", kFALSE);
3582 event2.fUser[0] = long(fID);
3583 event2.fUser[2] = 0;//Here I have to pack x and y for drop coordinates, shifting by 16 bits.
3584 NSPoint dropPoint = [sender draggingLocation];
3585 //convertPointFromBase is deprecated.
3586 //dropPoint = [self convertPointFromBase : dropPoint];
3587 dropPoint = [self convertPoint : dropPoint fromView : nil];
3588 //
3590 event2.fUser[2] = UShort_t(dropPoint.y) | (UShort_t(dropPoint.x) << 16);
3591
3592 gVirtualX->SendEvent(fID, &event2);
3593
3594 Event_t event3 = {};
3595 event3.fType = kClientMessage;
3596 event3.fWindow = fID;
3597 event3.fHandle = gVirtualX->InternAtom("XdndDrop", kFALSE);
3598
3599 gVirtualX->SendEvent(fID, &event3);
3600 }
3601
3602 return YES;//Always ok, even if file type is not supported - no need in "animation".
3603}
3604
3605@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:368
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:58
static Atom_t fgDeleteWindowAtom
Definition TGCocoa.h:477
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:3506
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1559
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 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