Logo ROOT  
Reference Guide
TGCocoa.mm
Go to the documentation of this file.
1// @(#)root/graf2d:$Id$
2// Author: Timur Pocheptsov 22/11/2011
3
4/*************************************************************************
5 * Copyright (C) 1995-2012, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//#define NDEBUG
13
14#include "TGCocoa.h"
15
16// We want to pickup ROOT's glew and not the system OpenGL coming from:
17// ROOTOpenGLView.h ->QuartzWindow.h->Cocoa.h
18// Allowing TU's which include the system GL and then glew (from TGLIncludes)
19// leads to gltypes.h redefinition errors.
20#include "TGLIncludes.h"
21
22#include "ROOTOpenGLView.h"
23#include "CocoaConstants.h"
24#include "TMacOSXSystem.h"
25#include "CocoaPrivate.h"
26#include "QuartzWindow.h"
27#include "QuartzPixmap.h"
28#include "QuartzUtils.h"
29#include "X11Drawable.h"
30#include "QuartzText.h"
31#include "CocoaUtils.h"
32#include "MenuLoader.h"
33#include "TVirtualGL.h"
34#include "X11Events.h"
35#include "X11Buffer.h"
36#include "TGClient.h"
37#include "TGWindow.h"
38#include "TSystem.h"
39#include "TGFrame.h"
40#include "TError.h"
41#include "TColor.h"
42#include "TROOT.h"
43#include "TEnv.h"
44#include "TVirtualMutex.h"
45
46#include <ApplicationServices/ApplicationServices.h>
47#include <OpenGL/OpenGL.h>
48#include <Cocoa/Cocoa.h>
49
50#include <algorithm>
51#include <stdexcept>
52#include <cassert>
53#include <cstring>
54#include <cstddef>
55#include <limits>
56#include <memory>
57
58//Style notes: I'm using a lot of asserts to check pre-conditions - mainly function parameters.
59//In asserts, expression always looks like 'p != 0' for "C++ pointer" (either object of built-in type
60//or C++ class), and 'p != nil' for object from Objective-C. There is no difference, this is to make
61//asserts more explicit. In conditional statement, it'll always be 'if (p)' or 'if (!p)' for both
62//C++ and Objective-C pointers/code.
63
64//I never use const qualifier for pointers to Objective-C objects since they are useless:
65//there are no cv-qualified methods (member-functions in C++) in Objective-C, and I do not use
66//'->' operator to access instance variables (data-members in C++) of Objective-C's object.
67//I also declare pointer as a const, if it's const:
68//NSWindow * const topLevelWindow = ... (and note, not pointer to const - no use with Obj-C).
69
70//Asserts on drawables ids usually only check, that it's not a 'root' window id (unless operation
71//is permitted on a 'root' window):
72//a) assert(!fPimpl->IsRootWindow(windowID)) and later I also check that windowID != 0 (kNone).
73//b) assert(drawableID > fPimpl->GetRootWindowID()) so drawableID can not be kNone and
74// can not be a 'root' window.
75
76//ROOT window has id 1. So if id > 1 (id > fPimpl->GetRootWindowID())
77//id is considered as valid (if it's out of range and > maximum valid id, this will be
78//caught by CocoaPrivate.
79
81namespace Util = ROOT::MacOSX::Util;
82namespace X11 = ROOT::MacOSX::X11;
83namespace Quartz = ROOT::Quartz;
85
86namespace {
87
88#pragma mark - Display configuration management.
89
90//______________________________________________________________________________
91void DisplayReconfigurationCallback(CGDirectDisplayID /*display*/, CGDisplayChangeSummaryFlags flags, void * /*userInfo*/)
92{
93 if (flags & kCGDisplayBeginConfigurationFlag)
94 return;
95
96 if (flags & kCGDisplayDesktopShapeChangedFlag) {
97 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 && "DisplayReconfigurationCallback, gVirtualX"
98 " is either null or has a wrong type");
99 TGCocoa * const gCocoa = static_cast<TGCocoa *>(gVirtualX);
100 gCocoa->ReconfigureDisplay();
101 }
102}
103
104#pragma mark - Aux. functions called from GUI-rendering part.
105
106//______________________________________________________________________________
107void SetStrokeForegroundColorFromX11Context(CGContextRef ctx, const GCValues_t &gcVals)
108{
109 assert(ctx != 0 && "SetStrokeForegroundColorFromX11Context, parameter 'ctx' is null");
110
111 CGFloat rgb[3] = {};
112 if (gcVals.fMask & kGCForeground)
113 X11::PixelToRGB(gcVals.fForeground, rgb);
114 else
115 ::Warning("SetStrokeForegroundColorFromX11Context",
116 "x11 context does not have line color information");
117
118 CGContextSetRGBStrokeColor(ctx, rgb[0], rgb[1], rgb[2], 1.);
119}
120
121//______________________________________________________________________________
122void SetStrokeDashFromX11Context(CGContextRef ctx, const GCValues_t &gcVals)
123{
124 //Set line dash pattern (X11's LineOnOffDash line style).
125 assert(ctx != 0 && "SetStrokeDashFromX11Context, ctx parameter is null");
126
127 SetStrokeForegroundColorFromX11Context(ctx, gcVals);
128
129 static const std::size_t maxLength = sizeof gcVals.fDashes / sizeof gcVals.fDashes[0];
130 assert(maxLength >= std::size_t(gcVals.fDashLen) &&
131 "SetStrokeDashFromX11Context, x11 context has bad dash length > sizeof(fDashes)");
132
133 CGFloat dashes[maxLength] = {};
134 for (Int_t i = 0; i < gcVals.fDashLen; ++i)
135 dashes[i] = gcVals.fDashes[i];
136
137 CGContextSetLineDash(ctx, gcVals.fDashOffset, dashes, gcVals.fDashLen);
138}
139
140//______________________________________________________________________________
141void SetStrokeDoubleDashFromX11Context(CGContextRef /*ctx*/, const GCValues_t & /*gcVals*/)
142{
143 //assert(ctx != 0 && "SetStrokeDoubleDashFromX11Context, ctx parameter is null");
144 ::Warning("SetStrokeDoubleDashFromX11Context", "Not implemented yet, kick tpochep!");
145}
146
147//______________________________________________________________________________
148void SetStrokeParametersFromX11Context(CGContextRef ctx, const GCValues_t &gcVals)
149{
150 //Set line width and color from GCValues_t object.
151 //(GUI rendering).
152 assert(ctx != 0 && "SetStrokeParametersFromX11Context, parameter 'ctx' is null");
153
154 const Mask_t mask = gcVals.fMask;
155 if ((mask & kGCLineWidth) && gcVals.fLineWidth > 1)
156 CGContextSetLineWidth(ctx, gcVals.fLineWidth);
157 else
158 CGContextSetLineWidth(ctx, 1.);
159
160 CGContextSetLineDash(ctx, 0., 0, 0);
161
162 if (mask & kGCLineStyle) {
163 if (gcVals.fLineStyle == kLineSolid)
164 SetStrokeForegroundColorFromX11Context(ctx, gcVals);
165 else if (gcVals.fLineStyle == kLineOnOffDash)
166 SetStrokeDashFromX11Context(ctx, gcVals);
167 else if (gcVals.fLineStyle == kLineDoubleDash)
168 SetStrokeDoubleDashFromX11Context(ctx ,gcVals);
169 else {
170 ::Warning("SetStrokeParametersFromX11Context", "line style bit is set,"
171 " but line style is unknown");
172 SetStrokeForegroundColorFromX11Context(ctx, gcVals);
173 }
174 } else
175 SetStrokeForegroundColorFromX11Context(ctx, gcVals);
176}
177
178//______________________________________________________________________________
179void SetFilledAreaColorFromX11Context(CGContextRef ctx, const GCValues_t &gcVals)
180{
181 //Set fill color from "foreground" pixel color.
182 //(GUI rendering).
183 assert(ctx != 0 && "SetFilledAreaColorFromX11Context, parameter 'ctx' is null");
184
185 CGFloat rgb[3] = {};
186 if (gcVals.fMask & kGCForeground)
187 X11::PixelToRGB(gcVals.fForeground, rgb);
188 else
189 ::Warning("SetFilledAreaColorFromX11Context", "no fill color found in x11 context");
190
191 CGContextSetRGBFillColor(ctx, rgb[0], rgb[1], rgb[2], 1.);
192}
193
194struct PatternContext {
195 PatternContext(Mask_t mask = {}, Int_t fillStyle = {}, Int_t foreground = 0, Int_t background = 0,
196 NSObject<X11Drawable> *image = nil, CGSize phase = {})
197 : fMask(mask), fFillStyle(fillStyle), fForeground(foreground), fBackground(background), fPhase(phase)
198 {
199 fImage = [image retain];
200 }
201 ~PatternContext()
202 {
203 [fImage release];
204 }
205
206 PatternContext(const PatternContext &) = delete;
207 PatternContext(PatternContext &&) = delete;
208 PatternContext &operator = (const PatternContext &) = delete;
209 PatternContext &operator = (PatternContext &&) = delete;
210
211 void SetImage(NSObject<X11Drawable> *image)
212 {
213 if (image != fImage) {
214 [fImage release];
215 fImage = [image retain];
216 }
217 }
218
219 Mask_t fMask = {};
220 Int_t fFillStyle = 0;
221 ULong_t fForeground = 0;
222 ULong_t fBackground = 0;
223 NSObject<X11Drawable> *fImage = nil;//Either stipple or tile image.
224 CGSize fPhase = {};
225};
226
227
228//______________________________________________________________________________
229bool HasFillTiledStyle(Mask_t mask, Int_t fillStyle)
230{
231 return (mask & kGCFillStyle) && (fillStyle == kFillTiled);
232}
233
234//______________________________________________________________________________
235bool HasFillTiledStyle(const GCValues_t &gcVals)
236{
237 return HasFillTiledStyle(gcVals.fMask, gcVals.fFillStyle);
238}
239
240//______________________________________________________________________________
241bool HasFillStippledStyle(Mask_t mask, Int_t fillStyle)
242{
243 return (mask & kGCFillStyle) && (fillStyle == kFillStippled);
244}
245
246//______________________________________________________________________________
247bool HasFillStippledStyle(const GCValues_t &gcVals)
248{
249 return HasFillStippledStyle(gcVals.fMask, gcVals.fFillStyle);
250}
251
252//______________________________________________________________________________
253bool HasFillOpaqueStippledStyle(Mask_t mask, Int_t fillStyle)
254{
255 return (mask & kGCFillStyle) && (fillStyle == kFillOpaqueStippled);
256}
257
258//______________________________________________________________________________
259bool HasFillOpaqueStippledStyle(const GCValues_t &gcVals)
260{
261 return HasFillOpaqueStippledStyle(gcVals.fMask, gcVals.fFillStyle);
262}
263
264//______________________________________________________________________________
265void DrawTile(NSObject<X11Drawable> *patternImage, CGContextRef ctx)
266{
267 assert(patternImage != nil && "DrawTile, parameter 'patternImage' is nil");
268 assert(ctx != 0 && "DrawTile, ctx parameter is null");
269
270 const CGRect patternRect = CGRectMake(0, 0, patternImage.fWidth, patternImage.fHeight);
271 if ([patternImage isKindOfClass : [QuartzImage class]]) {
272 CGContextDrawImage(ctx, patternRect, ((QuartzImage *)patternImage).fImage);
273 } else if ([patternImage isKindOfClass : [QuartzPixmap class]]){
274 const Util::CFScopeGuard<CGImageRef> imageFromPixmap([((QuartzPixmap *)patternImage) createImageFromPixmap]);
275 assert(imageFromPixmap.Get() != 0 && "DrawTile, createImageFromPixmap failed");
276 CGContextDrawImage(ctx, patternRect, imageFromPixmap.Get());
277 } else
278 assert(0 && "DrawTile, pattern is neither a QuartzImage, nor a QuartzPixmap");
279}
280
281//______________________________________________________________________________
282void DrawPattern(void *info, CGContextRef ctx)
283{
284 //Pattern callback, either use foreground (and background, if any)
285 //color and stipple mask to draw a pattern, or use pixmap
286 //as a pattern image.
287 //(GUI rendering).
288 assert(info != 0 && "DrawPattern, parameter 'info' is null");
289 assert(ctx != 0 && "DrawPattern, parameter 'ctx' is null");
290
291 const PatternContext * const patternContext = (PatternContext *)info;
292 const Mask_t mask = patternContext->fMask;
293 const Int_t fillStyle = patternContext->fFillStyle;
294
295 NSObject<X11Drawable> * const patternImage = patternContext->fImage;
296 assert(patternImage != nil && "DrawPattern, pattern (stipple) image is nil");
297 const CGRect patternRect = CGRectMake(0, 0, patternImage.fWidth, patternImage.fHeight);
298
299 if (HasFillTiledStyle(mask, fillStyle)) {
300 DrawTile(patternImage, ctx);
301 } else if (HasFillStippledStyle(mask, fillStyle) || HasFillOpaqueStippledStyle(mask, fillStyle)) {
302 assert([patternImage isKindOfClass : [QuartzImage class]] &&
303 "DrawPattern, stipple must be a QuartzImage object");
304 QuartzImage * const image = (QuartzImage *)patternImage;
305 assert(image.fIsStippleMask == YES && "DrawPattern, image is not a stipple mask");
306
307 CGFloat rgb[3] = {};
308
309 if (HasFillOpaqueStippledStyle(mask,fillStyle)) {
310 //Fill background first.
311 assert((mask & kGCBackground) &&
312 "DrawPattern, fill style is FillOpaqueStippled, but background color is not set in a context");
313 X11::PixelToRGB(patternContext->fBackground, rgb);
314 CGContextSetRGBFillColor(ctx, rgb[0], rgb[1], rgb[2], 1.);
315 CGContextFillRect(ctx, patternRect);
316 }
317
318 //Fill rectangle with foreground colour, using stipple mask.
319 assert((mask & kGCForeground) && "DrawPattern, foreground color is not set");
320 X11::PixelToRGB(patternContext->fForeground, rgb);
321 CGContextSetRGBFillColor(ctx, rgb[0], rgb[1], rgb[2], 1.);
322 CGContextClipToMask(ctx, patternRect, image.fImage);
323 CGContextFillRect(ctx, patternRect);
324 } else {
325 //This can be a window background pixmap
326 DrawTile(patternImage, ctx);
327 }
328}
329
330//______________________________________________________________________________
331void PatternRelease(void *info)
332{
333 delete static_cast<PatternContext *>(info);
334}
335
336//______________________________________________________________________________
337void SetFillPattern(CGContextRef ctx, const PatternContext *patternContext)
338{
339 //Create CGPatternRef to fill GUI elements with pattern.
340 //Pattern is a QuartzImage object, it can be either a mask,
341 //or pattern image itself.
342 //(GUI-rendering).
343 assert(ctx != 0 && "SetFillPattern, parameter 'ctx' is null");
344 assert(patternContext != 0 && "SetFillPattern, parameter 'patternContext' is null");
345 assert(patternContext->fImage != nil && "SetFillPattern, pattern image is nil");
346
347 const Util::CFScopeGuard<CGColorSpaceRef> patternColorSpace(CGColorSpaceCreatePattern(0));
348 CGContextSetFillColorSpace(ctx, patternColorSpace.Get());
349
350 CGPatternCallbacks callbacks = {};
351 callbacks.drawPattern = DrawPattern;
352 callbacks.releaseInfo = PatternRelease;
353 const CGRect patternRect = CGRectMake(0, 0, patternContext->fImage.fWidth, patternContext->fImage.fHeight);
354 const Util::CFScopeGuard<CGPatternRef> pattern(CGPatternCreate((void *)patternContext, patternRect, CGAffineTransformIdentity,
355 patternContext->fImage.fWidth, patternContext->fImage.fHeight,
356 kCGPatternTilingNoDistortion, true, &callbacks));
357 const CGFloat alpha = 1.;
358 CGContextSetFillPattern(ctx, pattern.Get(), &alpha);
359 CGContextSetPatternPhase(ctx, patternContext->fPhase);
360}
361
362//______________________________________________________________________________
363bool ParentRendersToChild(NSView<X11Window> *child)
364{
365 assert(child != nil && "ParentRendersToChild, parameter 'child' is nil");
366
367 //Adovo poluchaetsia, tashhem-ta! ;)
368 return (X11::ViewIsTextViewFrame(child, true) || X11::ViewIsHtmlViewFrame(child, true)) && !child.fContext &&
369 child.fMapState == kIsViewable && child.fParentView.fContext &&
370 !child.fIsOverlapped;
371}
372
373class ViewFixer final {
374public:
375 ViewFixer(QuartzView *&viewToFix, Drawable_t &widToFix)
376 {
377 if (ParentRendersToChild(viewToFix) && [viewToFix.fParentView isKindOfClass:[QuartzView class]]) {
378 const auto origin = viewToFix.frame.origin;
379 viewToFix = viewToFix.fParentView;
380 widToFix = viewToFix.fID;
381 if ((context = viewToFix.fContext)) {
382 CGContextSaveGState(context);
383 CGContextTranslateCTM(context, origin.x, origin.y);
384 }
385 }
386 }
387 ~ViewFixer()
388 {
389 if (context)
390 CGContextRestoreGState(context);
391 }
392 ViewFixer(const ViewFixer &rhs) = delete;
393 ViewFixer &operator = (const ViewFixer &) = delete;
394
395private:
396 CGContextRef context = nullptr;
397};
398
399//______________________________________________________________________________
400bool IsNonPrintableAsciiCharacter(UniChar c)
401{
402 if (c == 9 || (c >= 32 && c < 127))
403 return false;
404
405 return true;
406}
407
408//______________________________________________________________________________
409void FixAscii(std::vector<UniChar> &text)
410{
411 //GUI text is essentially ASCII. Our GUI
412 //calculates text metrix 'per-symbol', this means,
413 //it never asks about 'Text' metrics, but 'T', 'e', 'x', 't'.
414 //Obviously, text does not fit any widget because of
415 //this and I have to place all glyphs manually.
416 //And here I have another problem from our GUI - it
417 //can easily feed TGCocoa with non-printable symbols
418 //(this is a bug). Obviously, I do not have glyphs for, say, form feed
419 //or 'data link escape'. So I have to fix ascii text before
420 //manual glyph rendering: DLE symbol - replaced by space (this
421 //is done in TGText, but due to a bug it fails to replace them all)
422 //Other non-printable symbols simply removed (and thus ignored).
423
424 //Replace remaining ^P symbols with whitespaces, I have not idea why
425 //TGTextView replaces only part of them and not all of them.
426 std::replace(text.begin(), text.end(), UniChar(16), UniChar(' '));
427
428 //Now, remove remaining non-printable characters (no glyphs exist for them).
429 text.erase(std::remove_if(text.begin(), text.end(), IsNonPrintableAsciiCharacter), text.end());
430}
431
432}
433
435
437
438//______________________________________________________________________________
440 : fSelectedDrawable(0),
441 fCocoaDraw(0),
442 fDrawMode(kCopy),
443 fDirectDraw(false),
444 fForegroundProcess(false),
445 fSetApp(true),
446 fDisplayShapeChanged(true)
447{
448 assert(dynamic_cast<TMacOSXSystem *>(gSystem) != nullptr &&
449 "TGCocoa, gSystem is eihter null or has a wrong type");
450 TMacOSXSystem * const system = (TMacOSXSystem *)gSystem;
451
452 if (!system->CocoaInitialized())
453 system->InitializeCocoa();
454
455 fPimpl.reset(new Details::CocoaPrivate);
456
458 fgDeleteWindowAtom = FindAtom("WM_DELETE_WINDOW", true);
459
460 CGDisplayRegisterReconfigurationCallback (DisplayReconfigurationCallback, 0);
461}
462
463//______________________________________________________________________________
464TGCocoa::TGCocoa(const char *name, const char *title)
465 : TVirtualX(name, title),
466 fSelectedDrawable(0),
467 fCocoaDraw(0),
468 fDrawMode(kCopy),
469 fDirectDraw(false),
470 fForegroundProcess(false),
471 fSetApp(true),
472 fDisplayShapeChanged(true)
473{
474 assert(dynamic_cast<TMacOSXSystem *>(gSystem) != nullptr &&
475 "TGCocoa, gSystem is eihter null or has a wrong type");
476 TMacOSXSystem * const system = (TMacOSXSystem *)gSystem;
477
478 if (!system->CocoaInitialized())
479 system->InitializeCocoa();
480
481 fPimpl.reset(new Details::CocoaPrivate);
482
484 fgDeleteWindowAtom = FindAtom("WM_DELETE_WINDOW", true);
485
486 CGDisplayRegisterReconfigurationCallback (DisplayReconfigurationCallback, 0);
487}
488
489//______________________________________________________________________________
491{
492 //
493 CGDisplayRemoveReconfigurationCallback (DisplayReconfigurationCallback, 0);
494}
495
496//General part (empty, since it's not an X server.
497
498//______________________________________________________________________________
499Bool_t TGCocoa::Init(void * /*display*/)
500{
501 //Nothing to initialize here, return true to make
502 //a caller happy.
503 return kTRUE;
504}
505
506
507//______________________________________________________________________________
508Int_t TGCocoa::OpenDisplay(const char * /*dpyName*/)
509{
510 // return <0 in case of "error". The only error we have is: no interactive
511 // session, i.e no windows message handler etc.
512 if (CGMainDisplayID() == kCGNullDirectDisplay)
513 return -1;
514 return 0;
515}
516
517//______________________________________________________________________________
518const char *TGCocoa::DisplayName(const char *)
519{
520 //Noop.
521 return "dummy";
522}
523
524//______________________________________________________________________________
526{
527 //No, thank you, I'm not supporting any of X11 extensions!
528 return -1;
529}
530
531//______________________________________________________________________________
533{
534 //Noop.
535}
536
537//______________________________________________________________________________
539{
540 //Noop.
541 return 0;
542}
543
544//______________________________________________________________________________
546{
547 //Noop.
548 return 0;
549}
550
551//______________________________________________________________________________
553{
554 //Noop.
555 return 0;
556}
557
558//______________________________________________________________________________
560{
561 //Comment from TVirtualX:
562 // Returns the width of the screen in millimeters.
563 //End of comment.
564
565 return CGDisplayScreenSize(CGMainDisplayID()).width;
566}
567
568//______________________________________________________________________________
570{
571 //Comment from TVirtualX:
572 // Returns depth of screen (number of bit planes).
573 // Equivalent to GetPlanes().
574 //End of comment.
575
576 NSArray * const screens = [NSScreen screens];
577 assert(screens != nil && "screens array is nil");
578
579 NSScreen * const mainScreen = [screens objectAtIndex : 0];
580 assert(mainScreen != nil && "screen with index 0 is nil");
581
582 return NSBitsPerPixelFromDepth([mainScreen depth]);
583}
584
585//______________________________________________________________________________
587{
589
590 if (mode == 2) {
591 assert(gClient != 0 && "Update, gClient is null");
592 gClient->DoRedraw();//Call DoRedraw for all widgets, who need to be updated.
593 } else if (mode > 0) {
594 //Execute buffered commands.
595 fPimpl->fX11CommandBuffer.Flush(fPimpl.get());
596 }
597
598 if (fDirectDraw && mode != 2)
599 fPimpl->fX11CommandBuffer.FlushXOROps(fPimpl.get());
600}
601
602//______________________________________________________________________________
604{
606}
607
608//______________________________________________________________________________
610{
612 NSArray * const screens = [NSScreen screens];
613 assert(screens != nil && screens.count != 0 && "GetDisplayGeometry, no screens found");
614
615 NSRect frame = [(NSScreen *)[screens objectAtIndex : 0] frame];
616 CGFloat xMin = frame.origin.x, xMax = xMin + frame.size.width;
617 CGFloat yMin = frame.origin.y, yMax = yMin + frame.size.height;
618
619 for (NSUInteger i = 1, e = screens.count; i < e; ++i) {
620 frame = [(NSScreen *)[screens objectAtIndex : i] frame];
621 xMin = std::min(xMin, frame.origin.x);
622 xMax = std::max(xMax, frame.origin.x + frame.size.width);
623 yMin = std::min(yMin, frame.origin.y);
624 yMax = std::max(yMax, frame.origin.y + frame.size.height);
625 }
626
627 fDisplayRect.fX = int(xMin);
628 fDisplayRect.fY = int(yMin);
629 fDisplayRect.fWidth = unsigned(xMax - xMin);
630 fDisplayRect.fHeight = unsigned(yMax - yMin);
631
632 fDisplayShapeChanged = false;
633 }
634
635 return fDisplayRect;
636}
637
638#pragma mark - Window management part.
639
640//______________________________________________________________________________
642{
643 //Index, fixed and used only by 'root' window.
644 return fPimpl->GetRootWindowID();
645}
646
647//______________________________________________________________________________
649{
650 //InitWindow is a bad name, since this function
651 //creates a window, but this name comes from the TVirtualX interface.
652 //Actually, there is no special need in this function,
653 //it's a kind of simplified CreateWindow (with only
654 //one parameter). This function is called by TRootCanvas,
655 //to create a special window inside TGCanvas (thus parentID must be a valid window ID).
656 //TGX11/TGWin32 have internal array of such special windows,
657 //they return index into this array, instead of drawable's ids.
658 //I simply re-use CreateWindow and return a drawable's id.
659
660 assert(parentID != 0 && "InitWindow, parameter 'parentID' is 0");
661
662 //Use parent's attributes (as it's done in TGX11).
664 if (fPimpl->IsRootWindow(parentID))
666 else
667 [fPimpl->GetWindow(parentID) getAttributes : &attr];
668
669 return CreateWindow(parentID, 0, 0, attr.fWidth, attr.fHeight, 0, attr.fDepth, attr.fClass, 0, 0, 0);
670}
671
672//______________________________________________________________________________
674{
675 //In case of TGX11/TGWin32, there is a mixture of
676 //casted X11 ids (Window_t) and indices in some internal array, which
677 //contains such an id. On Mac I always have indices. Yes, I'm smart.
678 return windowID;
679}
680
681//______________________________________________________________________________
683{
684 //This function can be called from pad/canvas, both for window and for pixmap.
685 fSelectedDrawable = windowID;
686}
687
688//______________________________________________________________________________
690{
691 //Clear the selected drawable OR pixmap (the name - from TVirtualX interface - is bad).
692 assert(fSelectedDrawable > fPimpl->GetRootWindowID() &&
693 "ClearWindow, fSelectedDrawable is invalid");
694
695 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(fSelectedDrawable);
696 if (drawable.fIsPixmap) {
697 //Pixmaps are white by default.
698 //This is bad - we can not have transparent sub-pads (in TCanvas)
699 //because of this. But there is no way how gVirtualX can
700 //obtain real pad's color and check for its transparency.
701 CGContextRef pixmapCtx = drawable.fContext;
702 assert(pixmapCtx != 0 && "ClearWindow, pixmap's context is null");
703 //const Quartz::CGStateGuard ctxGuard(pixmapCtx);
704 //CGContextSetRGBFillColor(pixmapCtx, 1., 1., 1., 1.);
705 //CGContextFillRect(pixmapCtx, CGRectMake(0, 0, drawable.fWidth, drawable.fHeight));
706 //Now we really clear!
707 CGContextClearRect(pixmapCtx, CGRectMake(0, 0, drawable.fWidth, drawable.fHeight));
708 } else {
709 //For a window ClearArea with w == 0 and h == 0 means the whole window.
710 ClearArea(fSelectedDrawable, 0, 0, 0, 0);
711 }
712}
713
714//______________________________________________________________________________
716{
717 //In TGX11, GetGeometry works with special windows, created by InitWindow
718 //(thus this function is called from TCanvas/TGCanvas/TRootCanvas).
719
720 //IMPORTANT: this function also translates x and y
721 //from parent's coordinates into screen coordinates - so, again, name "GetGeometry"
722 //from the TVirtualX interface is bad and misleading.
723
724 if (windowID < 0 || fPimpl->IsRootWindow(windowID)) {
725 //Comment in TVirtualX suggests, that wid can be < 0.
726 //This will be a screen's geometry.
729 x = attr.fX;
730 y = attr.fY;
731 w = attr.fWidth;
732 h = attr.fHeight;
733 } else {
734 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(windowID);
735 x = drawable.fX;
736 y = drawable.fY;
737 w = drawable.fWidth;
738 h = drawable.fHeight;
739
740 if (!drawable.fIsPixmap) {
741 NSObject<X11Window> * const window = (NSObject<X11Window> *)drawable;
742 NSPoint srcPoint = {};
743 srcPoint.x = x;
744 srcPoint.y = y;
745 NSView<X11Window> * const view = window.fContentView.fParentView ? window.fContentView.fParentView : window.fContentView;
746 //View parameter for TranslateToScreen call must
747 //be parent view, since x and y are in parent's
748 //coordinate system.
749 const NSPoint dstPoint = X11::TranslateToScreen(view, srcPoint);
750 x = dstPoint.x;
751 y = dstPoint.y;
752 }
753 }
754}
755
756//______________________________________________________________________________
758{
759 //windowID is either kNone or a valid window id.
760 //x and y are coordinates of a top-left corner relative to the parent's coordinate system.
761
762 assert(!fPimpl->IsRootWindow(windowID) && "MoveWindow, called for root window");
763
764 if (!windowID)//From TGX11.
765 return;
766
767 [fPimpl->GetWindow(windowID) setX : x Y : y];
768}
769
770//______________________________________________________________________________
771void TGCocoa::RescaleWindow(Int_t /*wid*/, UInt_t /*w*/, UInt_t /*h*/)
772{
773 //This function is for TRootCanvas and related stuff, never gets
774 //called/used from/by any our GUI class.
775 //Noop.
776}
777
778//______________________________________________________________________________
780{
781 //This function does not resize window (it was done already by layout management?),
782 //it resizes "back buffer" if any.
783
784 if (!windowID)//From TGX11.
785 return;
786
787 assert(!fPimpl->IsRootWindow(windowID) &&
788 "ResizeWindow, parameter 'windowID' is a root window's id");
789
790 const Util::AutoreleasePool pool;
791
792 NSObject<X11Window> * const window = fPimpl->GetWindow(windowID);
793 if (window.fBackBuffer) {
794 const Drawable_t currentDrawable = fSelectedDrawable;
795 fSelectedDrawable = windowID;
797 fSelectedDrawable = currentDrawable;
798 }
799}
800
801//______________________________________________________________________________
803{
804 //This function is used by TCanvas/TPad:
805 //draw "back buffer" image into the view.
806 //fContentView (destination) MUST be a QuartzView.
807
808 //Basic es-guarantee: X11Buffer::AddUpdateWindow modifies vector with commands,
809 //if the following call to TGCocoa::Update will produce an exception dusing X11Buffer::Flush,
810 //initial state of X11Buffer can not be restored, but it still must be in some valid state.
811
812 assert(fSelectedDrawable > fPimpl->GetRootWindowID() &&
813 "UpdateWindow, fSelectedDrawable is not a valid window id");
814
815 //Have no idea, why this can happen with ROOT - done by TGDNDManager :(
816 if (fPimpl->GetDrawable(fSelectedDrawable).fIsPixmap == YES)
817 return;
818
819 NSObject<X11Window> * const window = fPimpl->GetWindow(fSelectedDrawable);
820
821 if (QuartzPixmap * const pixmap = window.fBackBuffer) {
822 assert([window.fContentView isKindOfClass : [QuartzView class]] && "UpdateWindow, content view is not a QuartzView");
823 QuartzView *dstView = (QuartzView *)window.fContentView;
824
825 if (dstView.fIsOverlapped)
826 return;
827
828 if (dstView.fContext) {
829 //We can draw directly.
830 const X11::Rectangle copyArea(0, 0, pixmap.fWidth, pixmap.fHeight);
831 [dstView copy : pixmap area : copyArea withMask : nil clipOrigin : X11::Point() toPoint : X11::Point()];
832 } else {
833 //Have to wait.
834 fPimpl->fX11CommandBuffer.AddUpdateWindow(dstView);
835 Update(1);
836 }
837 }
838}
839
840//______________________________________________________________________________
842{
843 //Window selected by SelectWindow.
844 return fSelectedDrawable;
845}
846
847//______________________________________________________________________________
849{
850 //Deletes selected window.
851}
852
853//______________________________________________________________________________
855{
856 //Should register a window created by Qt as a ROOT window,
857 //but since Qt-ROOT does not work on Mac and will never work,
858 //especially with version 4.8 - this implementation will always
859 //be empty.
860 return 0;
861}
862
863//______________________________________________________________________________
865{
866 //Remove window, created by Qt.
867}
868
869//______________________________________________________________________________
871 UInt_t clss, void *visual, SetWindowAttributes_t *attr, UInt_t wtype)
872{
873 //Create new window (top-level == QuartzWindow + QuartzView, or child == QuartzView)
874
875 //Strong es-guarantee - exception can be only during registration, class state will remain
876 //unchanged, no leaks (scope guards).
877
878 const Util::AutoreleasePool pool;
879
880 if (fPimpl->IsRootWindow(parentID)) {//parent == root window.
881 //Can throw:
882 QuartzWindow * const newWindow = X11::CreateTopLevelWindow(x, y, w, h, border,
883 depth, clss, visual, attr, wtype);
884 //Something like unique_ptr would perfectly solve the problem with raw pointer + a separate
885 //guard for this pointer, but it requires move semantics.
886 const Util::NSScopeGuard<QuartzWindow> winGuard(newWindow);
887 const Window_t result = fPimpl->RegisterDrawable(newWindow);//Can throw.
888 newWindow.fID = result;
889 [newWindow setAcceptsMouseMovedEvents : YES];
890
891 return result;
892 } else {
893 NSObject<X11Window> * const parentWin = fPimpl->GetWindow(parentID);
894 //OpenGL view can not have children.
895 assert([parentWin.fContentView isKindOfClass : [QuartzView class]] &&
896 "CreateWindow, parent view must be QuartzView");
897
898 //Can throw:
899 QuartzView * const childView = X11::CreateChildView((QuartzView *)parentWin.fContentView,
900 x, y, w, h, border, depth, clss, visual, attr, wtype);
901 const Util::NSScopeGuard<QuartzView> viewGuard(childView);
902 const Window_t result = fPimpl->RegisterDrawable(childView);//Can throw.
903 childView.fID = result;
904 [parentWin addChild : childView];
905
906 return result;
907 }
908}
909
910//______________________________________________________________________________
912{
913 //The XDestroyWindow function destroys the specified window as well as all of its subwindows
914 //and causes the X server to generate a DestroyNotify event for each window. The window
915 //should never be referenced again. If the window specified by the w argument is mapped,
916 //it is unmapped automatically. The ordering of the
917 //DestroyNotify events is such that for any given window being destroyed, DestroyNotify is generated
918 //on any inferiors of the window before being generated on the window itself. The ordering
919 //among siblings and across subhierarchies is not otherwise constrained.
920 //If the window you specified is a root window, no windows are destroyed. Destroying a mapped window
921 //will generate Expose events on other windows that were obscured by the window being destroyed.
922
923 //No-throw guarantee???
924
925 //I have NO idea why ROOT's GUI calls DestroyWindow with illegal
926 //window id, but it does.
927
928 if (!wid)
929 return;
930
931 if (fPimpl->IsRootWindow(wid))
932 return;
933
934 BOOL needFocusChange = NO;
935
936 {//Block to force autoreleasepool to drain.
937 const Util::AutoreleasePool pool;
938
939 fPimpl->fX11EventTranslator.CheckUnmappedView(wid);
940
941 assert(fPimpl->GetDrawable(wid).fIsPixmap == NO &&
942 "DestroyWindow, can not be called for QuartzPixmap or QuartzImage object");
943
944 NSObject<X11Window> * const window = fPimpl->GetWindow(wid);
945 if (fPimpl->fX11CommandBuffer.BufferSize())
946 fPimpl->fX11CommandBuffer.RemoveOperationsForDrawable(wid);
947
948 //TEST: "fix" a keyboard focus.
949 if ((needFocusChange = window == window.fQuartzWindow && window.fQuartzWindow.fHasFocus))
950 window.fHasFocus = NO;//If any.
951
953 if (window.fEventMask & kStructureNotifyMask)
954 fPimpl->fX11EventTranslator.GenerateDestroyNotify(wid);
955
956 //Interrupt modal loop (TGClient::WaitFor).
957 if (gClient->GetWaitForEvent() == kDestroyNotify && wid == gClient->GetWaitForWindow())
958 gClient->SetWaitForWindow(kNone);
959
960 fPimpl->DeleteDrawable(wid);
961 }
962
963 //"Fix" a keyboard focus.
964 if (needFocusChange)
966}
967
968//______________________________________________________________________________
970{
971 // The DestroySubwindows function destroys all inferior windows of the
972 // specified window, in bottom-to-top stacking order.
973
974 //No-throw guarantee??
975
976 //From TGX11:
977 if (!wid)
978 return;
979
980 if (fPimpl->IsRootWindow(wid))
981 return;
982
983 const Util::AutoreleasePool pool;
984
985 assert(fPimpl->GetDrawable(wid).fIsPixmap == NO &&
986 "DestroySubwindows, can not be called for QuartzPixmap or QuartzImage object");
987
988 NSObject<X11Window> *window = fPimpl->GetWindow(wid);
989
990 //I can not iterate on subviews array directly, since it'll be modified
991 //during this iteration - create a copy (and it'll also increase references,
992 //which will be decreased by guard's dtor).
993 const Util::NSScopeGuard<NSArray> children([[window.fContentView subviews] copy]);
994
995 for (NSView<X11Window> *child in children.Get())
996 DestroyWindow(child.fID);
997}
998
999//______________________________________________________________________________
1001{
1002 //No-throw guarantee.
1003
1004 if (!wid)//X11's None?
1005 return;
1006
1007 if (fPimpl->IsRootWindow(wid))
1009 else
1010 [fPimpl->GetWindow(wid) getAttributes : &attr];
1011}
1012
1013//______________________________________________________________________________
1015{
1016 //No-throw guarantee.
1017
1018 if (!wid)//From TGX11
1019 return;
1020
1021 const Util::AutoreleasePool pool;
1022
1023 assert(!fPimpl->IsRootWindow(wid) && "ChangeWindowAttributes, called for root window");
1024 assert(attr != 0 && "ChangeWindowAttributes, parameter 'attr' is null");
1025
1026 [fPimpl->GetWindow(wid) setAttributes : attr];
1027}
1028
1029//______________________________________________________________________________
1030void TGCocoa::SelectInput(Window_t windowID, UInt_t eventMask)
1031{
1032 //No-throw guarantee.
1033
1034 // Defines which input events the window is interested in. By default
1035 // events are propageted up the window stack. This mask can also be
1036 // set at window creation time via the SetWindowAttributes_t::fEventMask
1037 // attribute.
1038
1039 //TGuiBldDragManager selects input on a 'root' window.
1040 //TGWin32 has a check on windowID == 0.
1041 if (windowID <= fPimpl->GetRootWindowID())
1042 return;
1043
1044 NSObject<X11Window> * const window = fPimpl->GetWindow(windowID);
1045 //XSelectInput overrides a previous mask.
1046 window.fEventMask = eventMask;
1047}
1048
1049//______________________________________________________________________________
1051{
1052 //Reparent view.
1053 using namespace Details;
1054
1055 assert(!fPimpl->IsRootWindow(wid) && "ReparentChild, can not re-parent root window");
1056
1057 const Util::AutoreleasePool pool;
1058
1059 NSView<X11Window> * const view = fPimpl->GetWindow(wid).fContentView;
1060 if (fPimpl->IsRootWindow(pid)) {
1061 //Make a top-level view from a child view.
1062 [view retain];
1063 [view removeFromSuperview];
1064 view.fParentView = nil;
1065
1066 NSRect frame = view.frame;
1067 frame.origin = NSPoint();
1068
1070 if (!view.fOverrideRedirect)
1071 styleMask |= kTitledWindowMask;
1072
1073 QuartzWindow * const newTopLevel = [[QuartzWindow alloc] initWithContentRect : frame
1074 styleMask : styleMask
1075 backing : NSBackingStoreBuffered
1076 defer : NO];
1077 [view setX : x Y : y];
1078 [newTopLevel addChild : view];
1079
1080 fPimpl->ReplaceDrawable(wid, newTopLevel);
1081
1082 [view release];
1083 [newTopLevel release];
1084 } else {
1085 [view retain];
1086 [view removeFromSuperview];
1087 //
1088 NSObject<X11Window> * const newParent = fPimpl->GetWindow(pid);
1089 assert(newParent.fIsPixmap == NO && "ReparentChild, pixmap can not be a new parent");
1090 [view setX : x Y : y];
1091 [newParent addChild : view];//It'll also update view's level, no need to call updateLevel.
1092 [view release];
1093 }
1094}
1095
1096//______________________________________________________________________________
1098{
1099 //Reparent top-level window.
1100 //I have to delete QuartzWindow here and place in its slot content view +
1101 //reparent this view into pid.
1102 if (fPimpl->IsRootWindow(pid))//Nothing to do, wid is already a top-level window.
1103 return;
1104
1105 const Util::AutoreleasePool pool;
1106
1107 NSView<X11Window> * const contentView = fPimpl->GetWindow(wid).fContentView;
1108 QuartzWindow * const topLevel = (QuartzWindow *)[contentView window];
1109 [contentView retain];
1110 [contentView removeFromSuperview];
1111 [topLevel setContentView : nil];
1112 fPimpl->ReplaceDrawable(wid, contentView);
1113 [contentView setX : x Y : y];
1114 [fPimpl->GetWindow(pid) addChild : contentView];//Will also replace view's level.
1115 [contentView release];
1116}
1117
1118//______________________________________________________________________________
1120{
1121 //Change window's parent (possibly creating new top-level window or destroying top-level window).
1122
1123 if (!wid) //From TGX11.
1124 return;
1125
1126 assert(!fPimpl->IsRootWindow(wid) && "ReparentWindow, can not re-parent root window");
1127
1128 NSView<X11Window> * const view = fPimpl->GetWindow(wid).fContentView;
1129 if (view.fParentView)
1130 ReparentChild(wid, pid, x, y);
1131 else
1132 //wid is a top-level window (or content view of such a window).
1133 ReparentTopLevel(wid, pid, x, y);
1134}
1135
1136//______________________________________________________________________________
1138{
1139 // Maps the window "wid" and all of its subwindows that have had map
1140 // requests. This function has no effect if the window is already mapped.
1141
1142 assert(!fPimpl->IsRootWindow(wid) && "MapWindow, called for root window");
1143
1144 const Util::AutoreleasePool pool;
1145
1147 [fPimpl->GetWindow(wid) mapWindow];
1148
1149 if (fSetApp) {
1152 fSetApp = false;
1153 }
1154}
1155
1156//______________________________________________________________________________
1158{
1159 // Maps all subwindows for the specified window "wid" in top-to-bottom
1160 // stacking order.
1161
1162 assert(!fPimpl->IsRootWindow(wid) && "MapSubwindows, called for 'root' window");
1163
1164 const Util::AutoreleasePool pool;
1165
1167 [fPimpl->GetWindow(wid) mapSubwindows];
1168}
1169
1170//______________________________________________________________________________
1172{
1173 // Maps the window "wid" and all of its subwindows that have had map
1174 // requests on the screen and put this window on the top of of the
1175 // stack of all windows.
1176
1177 assert(!fPimpl->IsRootWindow(wid) && "MapRaised, called for root window");
1178
1179 const Util::AutoreleasePool pool;
1180
1182 [fPimpl->GetWindow(wid) mapRaised];
1183
1184 if (fSetApp) {
1187 fSetApp = false;
1188 }
1189}
1190
1191//______________________________________________________________________________
1193{
1194 // Unmaps the specified window "wid". If the specified window is already
1195 // unmapped, this function has no effect. Any child window will no longer
1196 // be visible (but they are still mapped) until another map call is made
1197 // on the parent.
1198 assert(!fPimpl->IsRootWindow(wid) && "UnmapWindow, called for root window");
1199
1200 const Util::AutoreleasePool pool;
1201
1202 //If this window is a grab window or a parent of a grab window.
1203 fPimpl->fX11EventTranslator.CheckUnmappedView(wid);
1204
1205 NSObject<X11Window> * const win = fPimpl->GetWindow(wid);
1206 [win unmapWindow];
1207
1208 if (win == win.fQuartzWindow && win.fQuartzWindow.fHasFocus)
1210
1211 win.fHasFocus = NO;
1212
1213 //if (window.fEventMask & kStructureNotifyMask)
1214 // fPimpl->fX11EventTranslator.GenerateUnmapNotify(wid);
1215
1216 //Interrupt modal loop (TGClient::WaitForUnmap).
1217 if (gClient->GetWaitForEvent() == kUnmapNotify && gClient->GetWaitForWindow() == wid)
1218 gClient->SetWaitForWindow(kNone);
1219}
1220
1221//______________________________________________________________________________
1223{
1224 // Raises the specified window to the top of the stack so that no
1225 // sibling window obscures it.
1226
1227 if (!wid)//From TGX11.
1228 return;
1229
1230 assert(!fPimpl->IsRootWindow(wid) && "RaiseWindow, called for root window");
1231
1232 if (!fPimpl->GetWindow(wid).fParentView)
1233 return;
1234
1235 [fPimpl->GetWindow(wid) raiseWindow];
1236}
1237
1238//______________________________________________________________________________
1240{
1241 // Lowers the specified window "wid" to the bottom of the stack so
1242 // that it does not obscure any sibling windows.
1243
1244 if (!wid)//From TGX11.
1245 return;
1246
1247 assert(!fPimpl->IsRootWindow(wid) && "LowerWindow, called for root window");
1248
1249 if (!fPimpl->GetWindow(wid).fParentView)
1250 return;
1251
1252 [fPimpl->GetWindow(wid) lowerWindow];
1253}
1254
1255//______________________________________________________________________________
1257{
1258 // Moves the specified window to the specified x and y coordinates.
1259 // It does not change the window's size, raise the window, or change
1260 // the mapping state of the window.
1261 //
1262 // x, y - coordinates, which define the new position of the window
1263 // relative to its parent.
1264
1265 if (!wid)//From TGX11.
1266 return;
1267
1268 assert(!fPimpl->IsRootWindow(wid) && "MoveWindow, called for root window");
1269 const Util::AutoreleasePool pool;
1270 [fPimpl->GetWindow(wid) setX : x Y : y];
1271}
1272
1273//______________________________________________________________________________
1275{
1276 // Changes the size and location of the specified window "wid" without
1277 // raising it.
1278 //
1279 // x, y - coordinates, which define the new position of the window
1280 // relative to its parent.
1281 // w, h - the width and height, which define the interior size of
1282 // the window
1283
1284 if (!wid)//From TGX11.
1285 return;
1286
1287 assert(!fPimpl->IsRootWindow(wid) && "MoveResizeWindow, called for 'root' window");
1288
1289 const Util::AutoreleasePool pool;
1290 [fPimpl->GetWindow(wid) setX : x Y : y width : w height : h];
1291}
1292
1293//______________________________________________________________________________
1295{
1296 if (!wid)//From TGX11.
1297 return;
1298
1299 assert(!fPimpl->IsRootWindow(wid) && "ResizeWindow, called for 'root' window");
1300
1301 const Util::AutoreleasePool pool;
1302
1303 //We can have this unfortunately.
1304 const UInt_t siMax = std::numeric_limits<Int_t>::max();
1305 if (w > siMax || h > siMax)
1306 return;
1307
1308 NSSize newSize = {};
1309 newSize.width = w;
1310 newSize.height = h;
1311
1312 [fPimpl->GetWindow(wid) setDrawableSize : newSize];
1313}
1314
1315//______________________________________________________________________________
1317{
1318 // Iconifies the window "wid".
1319 if (!wid)
1320 return;
1321
1322 assert(!fPimpl->IsRootWindow(wid) && "IconifyWindow, can not iconify the root window");
1323 assert(fPimpl->GetWindow(wid).fIsPixmap == NO && "IconifyWindow, invalid window id");
1324
1325 NSObject<X11Window> * const win = fPimpl->GetWindow(wid);
1326 assert(win.fQuartzWindow == win && "IconifyWindow, can be called only for a top level window");
1327
1328 fPimpl->fX11EventTranslator.CheckUnmappedView(wid);
1329
1330 NSObject<X11Window> * const window = fPimpl->GetWindow(wid);
1331 if (fPimpl->fX11CommandBuffer.BufferSize())
1332 fPimpl->fX11CommandBuffer.RemoveOperationsForDrawable(wid);
1333
1334 if (window.fQuartzWindow.fHasFocus) {
1336 window.fQuartzWindow.fHasFocus = NO;
1337 }
1338
1339 [win.fQuartzWindow miniaturize : win.fQuartzWindow];
1340}
1341
1342//______________________________________________________________________________
1343void TGCocoa::TranslateCoordinates(Window_t srcWin, Window_t dstWin, Int_t srcX, Int_t srcY, Int_t &dstX, Int_t &dstY, Window_t &child)
1344{
1345 // Translates coordinates in one window to the coordinate space of another
1346 // window. It takes the "src_x" and "src_y" coordinates relative to the
1347 // source window's origin and returns these coordinates to "dest_x" and
1348 // "dest_y" relative to the destination window's origin.
1349
1350 // child - returns the child of "dest" if the coordinates
1351 // are contained in a mapped child of the destination
1352 // window; otherwise, child is set to 0
1353 child = 0;
1354 if (!srcWin || !dstWin)//This is from TGX11, looks like this can happen.
1355 return;
1356
1357 const bool srcIsRoot = fPimpl->IsRootWindow(srcWin);
1358 const bool dstIsRoot = fPimpl->IsRootWindow(dstWin);
1359
1360 if (srcIsRoot && dstIsRoot) {
1361 //This can happen with ROOT's GUI. Set dstX/Y equal to srcX/Y.
1362 //From man for XTranslateCoordinates it's not clear, what should be in child.
1363 dstX = srcX;
1364 dstY = srcY;
1365
1366 if (QuartzWindow * const qw = X11::FindWindowInPoint(srcX, srcY))
1367 child = qw.fID;
1368
1369 return;
1370 }
1371
1372 NSPoint srcPoint = {};
1373 srcPoint.x = srcX;
1374 srcPoint.y = srcY;
1375
1376 NSPoint dstPoint = {};
1377
1378
1379 if (dstIsRoot) {
1380 NSView<X11Window> * const srcView = fPimpl->GetWindow(srcWin).fContentView;
1381 dstPoint = X11::TranslateToScreen(srcView, srcPoint);
1382 } else if (srcIsRoot) {
1383 NSView<X11Window> * const dstView = fPimpl->GetWindow(dstWin).fContentView;
1384 dstPoint = X11::TranslateFromScreen(srcPoint, dstView);
1385
1386 if ([dstView superview]) {
1387 //hitTest requires a point in a superview's coordinate system.
1388 //Even contentView of QuartzWindow has a superview (NSThemeFrame),
1389 //so this should always work.
1390 dstPoint = [[dstView superview] convertPoint : dstPoint fromView : dstView];
1391 if (NSView<X11Window> * const view = (NSView<X11Window> *)[dstView hitTest : dstPoint]) {
1392 if (view != dstView && view.fMapState == kIsViewable)
1393 child = view.fID;
1394 }
1395 }
1396 } else {
1397 NSView<X11Window> * const srcView = fPimpl->GetWindow(srcWin).fContentView;
1398 NSView<X11Window> * const dstView = fPimpl->GetWindow(dstWin).fContentView;
1399
1400 dstPoint = X11::TranslateCoordinates(srcView, dstView, srcPoint);
1401 if ([dstView superview]) {
1402 //hitTest requires a point in a view's superview coordinate system.
1403 //Even contentView of QuartzWindow has a superview (NSThemeFrame),
1404 //so this should always work.
1405 const NSPoint pt = [[dstView superview] convertPoint : dstPoint fromView : dstView];
1406 if (NSView<X11Window> * const view = (NSView<X11Window> *)[dstView hitTest : pt]) {
1407 if (view != dstView && view.fMapState == kIsViewable)
1408 child = view.fID;
1409 }
1410 }
1411 }
1412
1413 dstX = dstPoint.x;
1414 dstY = dstPoint.y;
1415}
1416
1417//______________________________________________________________________________
1419{
1420 // Returns the location and the size of window "wid"
1421 //
1422 // x, y - coordinates of the upper-left outer corner relative to the
1423 // parent window's origin
1424 // w, h - the size of the window, not including the border.
1425
1426 //From GX11Gui.cxx:
1427 if (!wid)
1428 return;
1429
1430 if (fPimpl->IsRootWindow(wid)) {
1433 x = attr.fX;
1434 y = attr.fY;
1435 w = attr.fWidth;
1436 h = attr.fHeight;
1437 } else {
1438 NSObject<X11Drawable> *window = fPimpl->GetDrawable(wid);
1439 //ROOT can ask window size for ... non-window drawable.
1440 if (!window.fIsPixmap) {
1441 x = window.fX;
1442 y = window.fY;
1443 } else {
1444 x = 0;
1445 y = 0;
1446 }
1447
1448 w = window.fWidth;
1449 h = window.fHeight;
1450 }
1451}
1452
1453//______________________________________________________________________________
1455{
1456 //From TGX11:
1457 if (!wid)
1458 return;
1459
1460 assert(!fPimpl->IsRootWindow(wid) && "SetWindowBackground, can not set color for root window");
1461
1462 fPimpl->GetWindow(wid).fBackgroundPixel = color;
1463}
1464
1465//______________________________________________________________________________
1467{
1468 // Sets the background pixmap of the window "wid" to the specified
1469 // pixmap "pxm".
1470
1471 //From TGX11/TGWin32:
1472 if (!windowID)
1473 return;
1474
1475 assert(!fPimpl->IsRootWindow(windowID) &&
1476 "SetWindowBackgroundPixmap, can not set background for a root window");
1477 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
1478 "SetWindowBackgroundPixmap, invalid window id");
1479
1480 NSObject<X11Window> * const window = fPimpl->GetWindow(windowID);
1481 if (pixmapID == kNone) {
1482 window.fBackgroundPixmap = nil;
1483 return;
1484 }
1485
1486 assert(pixmapID > fPimpl->GetRootWindowID() &&
1487 "SetWindowBackgroundPixmap, parameter 'pixmapID' is not a valid pixmap id");
1488 assert(fPimpl->GetDrawable(pixmapID).fIsPixmap == YES &&
1489 "SetWindowBackgroundPixmap, bad drawable");
1490
1491 NSObject<X11Drawable> * const pixmapOrImage = fPimpl->GetDrawable(pixmapID);
1492 //X11 doc says, that pixmap can be freed immediately after call
1493 //XSetWindowBackgroundPixmap, so I have to copy a pixmap.
1494 Util::NSScopeGuard<QuartzImage> backgroundImage;
1495
1496 if ([pixmapOrImage isKindOfClass : [QuartzPixmap class]]) {
1497 backgroundImage.Reset([[QuartzImage alloc] initFromPixmap : (QuartzPixmap *)pixmapOrImage]);
1498 if (backgroundImage.Get())
1499 window.fBackgroundPixmap = backgroundImage.Get();//the window is retaining the image.
1500 } else {
1501 backgroundImage.Reset([[QuartzImage alloc] initFromImage : (QuartzImage *)pixmapOrImage]);
1502 if (backgroundImage.Get())
1503 window.fBackgroundPixmap = backgroundImage.Get();//the window is retaining the image.
1504 }
1505
1506 if (!backgroundImage.Get())
1507 //Detailed error message was issued by QuartzImage at this point.
1508 Error("SetWindowBackgroundPixmap", "QuartzImage initialization failed");
1509}
1510
1511//______________________________________________________________________________
1513{
1514 // Returns the parent of the window "windowID".
1515
1516 //0 or root (checked in TGX11):
1517 if (windowID <= fPimpl->GetRootWindowID())
1518 return windowID;
1519
1520 NSView<X11Window> *view = fPimpl->GetWindow(windowID).fContentView;
1521 return view.fParentView ? view.fParentView.fID : fPimpl->GetRootWindowID();
1522}
1523
1524//______________________________________________________________________________
1526{
1527 if (!wid || !name)//From TGX11.
1528 return;
1529
1530 const Util::AutoreleasePool pool;
1531
1532 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1533
1534 if ([(NSObject *)drawable isKindOfClass : [NSWindow class]]) {
1535 NSString * const windowTitle = [NSString stringWithCString : name encoding : NSASCIIStringEncoding];
1536 [(NSWindow *)drawable setTitle : windowTitle];
1537 }
1538}
1539
1540//______________________________________________________________________________
1541void TGCocoa::SetIconName(Window_t /*wid*/, char * /*name*/)
1542{
1543 //Noop.
1544}
1545
1546//______________________________________________________________________________
1548{
1549 //Noop.
1550}
1551
1552//______________________________________________________________________________
1553void TGCocoa::SetClassHints(Window_t /*wid*/, char * /*className*/, char * /*resourceName*/)
1554{
1555 //Noop.
1556}
1557
1558//______________________________________________________________________________
1559void TGCocoa::ShapeCombineMask(Window_t windowID, Int_t /*x*/, Int_t /*y*/, Pixmap_t pixmapID)
1560{
1561 //Comment from TVirtualX:
1562 // The Nonrectangular Window Shape Extension adds nonrectangular
1563 // windows to the System.
1564 // This allows for making shaped (partially transparent) windows
1565
1566 assert(!fPimpl->IsRootWindow(windowID) &&
1567 "ShapeCombineMask, windowID parameter is a 'root' window");
1568 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
1569 "ShapeCombineMask, windowID parameter is a bad window id");
1570 assert([fPimpl->GetDrawable(pixmapID) isKindOfClass : [QuartzImage class]] &&
1571 "ShapeCombineMask, pixmapID parameter must point to QuartzImage object");
1572
1573 if (fPimpl->GetWindow(windowID).fContentView.fParentView)
1574 return;
1575
1576 QuartzImage * const srcImage = (QuartzImage *)fPimpl->GetDrawable(pixmapID);
1577 assert(srcImage.fIsStippleMask == YES && "ShapeCombineMask, source image is not a stipple mask");
1578
1579 // There is some kind of problems with shape masks and
1580 // flipped views, I have to do an image flip here.
1581 const Util::NSScopeGuard<QuartzImage> image([[QuartzImage alloc] initFromImageFlipped : srcImage]);
1582 if (image.Get()) {
1583 QuartzWindow * const qw = fPimpl->GetWindow(windowID).fQuartzWindow;
1584 qw.fShapeCombineMask = image.Get();
1585 [qw setOpaque : NO];
1586 [qw setBackgroundColor : [NSColor clearColor]];
1587 }
1588}
1589
1590#pragma mark - "Window manager hints" set of functions.
1591
1592//______________________________________________________________________________
1594{
1595 // Sets decoration style.
1596 using namespace Details;
1597
1598 assert(!fPimpl->IsRootWindow(wid) && "SetMWMHints, called for 'root' window");
1599
1600 QuartzWindow * const qw = fPimpl->GetWindow(wid).fQuartzWindow;
1601 NSUInteger newMask = 0;
1602
1603 if ([qw styleMask] & kTitledWindowMask) {//Do not modify this.
1604 newMask |= kTitledWindowMask;
1605 newMask |= kClosableWindowMask;
1606 }
1607
1608 if (value & kMWMFuncAll) {
1610 } else {
1612 newMask |= kMiniaturizableWindowMask;
1613 if (funcs & kMWMFuncResize)
1614 newMask |= kResizableWindowMask;
1615 }
1616
1617 [qw setStyleMask : newMask];
1618
1619 if (funcs & kMWMDecorAll) {
1620 if (!qw.fMainWindow) {//Do not touch buttons for transient window.
1621 [[qw standardWindowButton : NSWindowZoomButton] setEnabled : YES];
1622 [[qw standardWindowButton : NSWindowMiniaturizeButton] setEnabled : YES];
1623 }
1624 } else {
1625 if (!qw.fMainWindow) {//Do not touch transient window's titlebar.
1626 [[qw standardWindowButton : NSWindowZoomButton] setEnabled : funcs & kMWMDecorMaximize];
1627 [[qw standardWindowButton : NSWindowMiniaturizeButton] setEnabled : funcs & kMWMDecorMinimize];
1628 }
1629 }
1630}
1631
1632//______________________________________________________________________________
1633void TGCocoa::SetWMPosition(Window_t /*wid*/, Int_t /*x*/, Int_t /*y*/)
1634{
1635 //Noop.
1636}
1637
1638//______________________________________________________________________________
1639void TGCocoa::SetWMSize(Window_t /*wid*/, UInt_t /*w*/, UInt_t /*h*/)
1640{
1641 //Noop.
1642}
1643
1644//______________________________________________________________________________
1645void TGCocoa::SetWMSizeHints(Window_t wid, UInt_t wMin, UInt_t hMin, UInt_t wMax, UInt_t hMax, UInt_t /*wInc*/, UInt_t /*hInc*/)
1646{
1647 using namespace Details;
1648
1649 assert(!fPimpl->IsRootWindow(wid) && "SetWMSizeHints, called for root window");
1650
1652 const NSRect minRect = [NSWindow frameRectForContentRect : NSMakeRect(0., 0., wMin, hMin) styleMask : styleMask];
1653 const NSRect maxRect = [NSWindow frameRectForContentRect : NSMakeRect(0., 0., wMax, hMax) styleMask : styleMask];
1654
1655 QuartzWindow * const qw = fPimpl->GetWindow(wid).fQuartzWindow;
1656 [qw setMinSize : minRect.size];
1657 [qw setMaxSize : maxRect.size];
1658}
1659
1660//______________________________________________________________________________
1662{
1663 //Noop.
1664}
1665
1666//______________________________________________________________________________
1668{
1669 //Comment from TVirtualX:
1670 // Tells window manager that the window "wid" is a transient window
1671 // of the window "main_id". A window manager may decide not to decorate
1672 // a transient window or may treat it differently in other ways.
1673 //End of TVirtualX's comment.
1674
1675 //TGTransientFrame uses this hint to attach a window to some "main" window,
1676 //so that transient window is alway above the main window. This is used for
1677 //dialogs and dockable panels.
1678 assert(wid > fPimpl->GetRootWindowID() && "SetWMTransientHint, wid parameter is not a valid window id");
1679
1680 if (fPimpl->IsRootWindow(mainWid))
1681 return;
1682
1683 QuartzWindow * const mainWindow = fPimpl->GetWindow(mainWid).fQuartzWindow;
1684
1685 if (![mainWindow isVisible])
1686 return;
1687
1688 QuartzWindow * const transientWindow = fPimpl->GetWindow(wid).fQuartzWindow;
1689
1690 if (mainWindow != transientWindow) {
1691 if (transientWindow.fMainWindow) {
1692 if (transientWindow.fMainWindow != mainWindow)
1693 Error("SetWMTransientHint", "window is already transient for other window");
1694 } else {
1695 [[transientWindow standardWindowButton : NSWindowZoomButton] setEnabled : NO];
1696 [mainWindow addTransientWindow : transientWindow];
1697 }
1698 } else
1699 Warning("SetWMTransientHint", "transient and main windows are the same window");
1700}
1701
1702#pragma mark - GUI-rendering part.
1703
1704//______________________________________________________________________________
1706{
1707 //Can be called directly of when flushing command buffer.
1708 assert(!fPimpl->IsRootWindow(wid) && "DrawLineAux, called for root window");
1709
1710 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1711 CGContextRef ctx = drawable.fContext;
1712 assert(ctx != 0 && "DrawLineAux, context is null");
1713
1714 const Quartz::CGStateGuard ctxGuard(ctx);//Will restore state back.
1715 //Draw a line.
1716 //This draw line is a special GUI method, it's used not by ROOT's graphics, but
1717 //widgets. The problem is:
1718 //-I have to switch off anti-aliasing, since if anti-aliasing is on,
1719 //the line is thick and has different color.
1720 //-As soon as I switch-off anti-aliasing, and line is precise, I can not
1721 //draw a line [0, 0, -> w, 0].
1722 //I use a small translation, after all, this is ONLY gui method and it
1723 //will not affect anything except GUI.
1724
1725 CGContextSetAllowsAntialiasing(ctx, false);//Smoothed line is of wrong color and in a wrong position - this is bad for GUI.
1726
1727 if (!drawable.fIsPixmap)
1728 CGContextTranslateCTM(ctx, 0.5, 0.5);
1729 else {
1730 //Pixmap uses native Cocoa's left-low-corner system.
1731 y1 = Int_t(X11::LocalYROOTToCocoa(drawable, y1));
1732 y2 = Int_t(X11::LocalYROOTToCocoa(drawable, y2));
1733 }
1734
1735 SetStrokeParametersFromX11Context(ctx, gcVals);
1736 CGContextBeginPath(ctx);
1737 CGContextMoveToPoint(ctx, x1, y1);
1738 CGContextAddLineToPoint(ctx, x2, y2);
1739 CGContextStrokePath(ctx);
1740
1741 CGContextSetAllowsAntialiasing(ctx, true);//Somehow, it's not saved/restored, this affects ... window's titlebar.
1742}
1743
1744//______________________________________________________________________________
1746{
1747 //This function can be called:
1748 //a)'normal' way - from view's drawRect method.
1749 //b) for 'direct rendering' - operation was initiated by ROOT's GUI, not by
1750 // drawRect.
1751
1752 //From TGX11:
1753 if (!wid)
1754 return;
1755
1756 assert(!fPimpl->IsRootWindow(wid) && "DrawLine, called for root window");
1757 assert(gc > 0 && gc <= fX11Contexts.size() && "DrawLine, invalid context index");
1758
1759 const GCValues_t &gcVals = fX11Contexts[gc - 1];
1760
1761 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1762 if (!drawable.fIsPixmap) {
1763 NSObject<X11Window> * const window = (NSObject<X11Window> *)drawable;
1764 QuartzView *view = (QuartzView *)window.fContentView;
1765 const ViewFixer fixer(view, wid);
1766 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
1767 if (!view.fContext)
1768 fPimpl->fX11CommandBuffer.AddDrawLine(wid, gcVals, x1, y1, x2, y2);
1769 else
1770 DrawLineAux(wid, gcVals, x1, y1, x2, y2);
1771 }
1772 } else {
1773 if (!IsCocoaDraw()) {
1774 fPimpl->fX11CommandBuffer.AddDrawLine(wid, gcVals, x1, y1, x2, y2);
1775 } else {
1776 DrawLineAux(wid, gcVals, x1, y1, x2, y2);
1777 }
1778 }
1779}
1780
1781//______________________________________________________________________________
1782void TGCocoa::DrawSegmentsAux(Drawable_t wid, const GCValues_t &gcVals, const Segment_t *segments, Int_t nSegments)
1783{
1784 assert(!fPimpl->IsRootWindow(wid) && "DrawSegmentsAux, called for root window");
1785 assert(segments != 0 && "DrawSegmentsAux, segments parameter is null");
1786 assert(nSegments > 0 && "DrawSegmentsAux, nSegments <= 0");
1787
1788 for (Int_t i = 0; i < nSegments; ++i)
1789 DrawLineAux(wid, gcVals, segments[i].fX1, segments[i].fY1 - 3, segments[i].fX2, segments[i].fY2 - 3);
1790}
1791
1792//______________________________________________________________________________
1794{
1795 //Draw multiple line segments. Each line is specified by a pair of points.
1796
1797 //From TGX11:
1798 if (!wid)
1799 return;
1800
1801 assert(!fPimpl->IsRootWindow(wid) && "DrawSegments, called for root window");
1802 assert(gc > 0 && gc <= fX11Contexts.size() && "DrawSegments, invalid context index");
1803 assert(segments != 0 && "DrawSegments, parameter 'segments' is null");
1804 assert(nSegments > 0 && "DrawSegments, number of segments <= 0");
1805
1806 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1807 const GCValues_t &gcVals = fX11Contexts[gc - 1];
1808
1809 if (!drawable.fIsPixmap) {
1810 QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView;
1811 const ViewFixer fixer(view, wid);
1812
1813 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
1814 if (!view.fContext)
1815 fPimpl->fX11CommandBuffer.AddDrawSegments(wid, gcVals, segments, nSegments);
1816 else
1817 DrawSegmentsAux(wid, gcVals, segments, nSegments);
1818 }
1819 } else {
1820 if (!IsCocoaDraw())
1821 fPimpl->fX11CommandBuffer.AddDrawSegments(wid, gcVals, segments, nSegments);
1822 else
1823 DrawSegmentsAux(wid, gcVals, segments, nSegments);
1824 }
1825}
1826
1827//______________________________________________________________________________
1829{
1830 //Can be called directly or during flushing command buffer.
1831 assert(!fPimpl->IsRootWindow(wid) && "DrawRectangleAux, called for root window");
1832
1833 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1834
1835 if (!drawable.fIsPixmap) {
1836 //I can not draw a line at y == 0, shift the rectangle to 1 pixel (and reduce its height).
1837 if (!y) {
1838 y = 1;
1839 if (h)
1840 h -= 1;
1841 }
1842 } else {
1843 //Pixmap has native Cocoa's low-left-corner system.
1844 y = Int_t(X11::LocalYROOTToCocoa(drawable, y + h));
1845 }
1846
1847 CGContextRef ctx = fPimpl->GetDrawable(wid).fContext;
1848 assert(ctx && "DrawRectangleAux, context is null");
1849 const Quartz::CGStateGuard ctxGuard(ctx);//Will restore context state.
1850
1851 CGContextSetAllowsAntialiasing(ctx, false);
1852 //Line color from X11 context.
1853 SetStrokeParametersFromX11Context(ctx, gcVals);
1854
1855 const CGRect rect = CGRectMake(x, y, w, h);
1856 CGContextStrokeRect(ctx, rect);
1857
1858 CGContextSetAllowsAntialiasing(ctx, true);
1859}
1860
1861//______________________________________________________________________________
1863{
1864 //Can be called in a 'normal way' - from drawRect method (QuartzView)
1865 //or directly by ROOT.
1866
1867 if (!wid)//From TGX11.
1868 return;
1869
1870 assert(!fPimpl->IsRootWindow(wid) && "DrawRectangle, called for root window");
1871 assert(gc > 0 && gc <= fX11Contexts.size() && "DrawRectangle, invalid context index");
1872
1873 const GCValues_t &gcVals = fX11Contexts[gc - 1];
1874
1875 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1876
1877 if (!drawable.fIsPixmap) {
1878 NSObject<X11Window> * const window = (NSObject<X11Window> *)drawable;
1879 QuartzView *view = (QuartzView *)window.fContentView;
1880 const ViewFixer fixer(view, wid);
1881
1882 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
1883 if (!view.fContext)
1884 fPimpl->fX11CommandBuffer.AddDrawRectangle(wid, gcVals, x, y, w, h);
1885 else
1886 DrawRectangleAux(wid, gcVals, x, y, w, h);
1887 }
1888 } else {
1889 if (!IsCocoaDraw())
1890 fPimpl->fX11CommandBuffer.AddDrawRectangle(wid, gcVals, x, y, w, h);
1891 else
1892 DrawRectangleAux(wid, gcVals, x, y, w, h);
1893 }
1894}
1895
1896//______________________________________________________________________________
1898{
1899 //Can be called directly or when flushing command buffer.
1900 //Can be called directly or when flushing command buffer.
1901
1902 //From TGX11:
1903 if (!wid)
1904 return;
1905
1906 assert(!fPimpl->IsRootWindow(wid) && "FillRectangleAux, called for root window");
1907
1908 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1909 CGContextRef ctx = drawable.fContext;
1910 CGSize patternPhase = {};
1911
1912 if (drawable.fIsPixmap) {
1913 //Pixmap has low-left-corner based system.
1914 y = Int_t(X11::LocalYROOTToCocoa(drawable, y + h));
1915 }
1916
1917 const CGRect fillRect = CGRectMake(x, y, w, h);
1918
1919 if (!drawable.fIsPixmap) {
1920 QuartzView * const view = (QuartzView *)fPimpl->GetWindow(wid).fContentView;
1921 if (view.fParentView) {
1922 const NSPoint origin = [view.fParentView convertPoint : view.frame.origin toView : nil];
1923 patternPhase.width = origin.x;
1924 patternPhase.height = origin.y;
1925 }
1926 }
1927
1928 const Quartz::CGStateGuard ctxGuard(ctx);//Will restore context state.
1929
1930 if (HasFillStippledStyle(gcVals) || HasFillOpaqueStippledStyle(gcVals) || HasFillTiledStyle(gcVals)) {
1931 std::unique_ptr<PatternContext> patternContext(new PatternContext(gcVals.fMask, gcVals.fFillStyle,
1932 0, 0, nil, patternPhase));
1933 if (HasFillStippledStyle(gcVals) || HasFillOpaqueStippledStyle(gcVals)) {
1934 assert(gcVals.fStipple != kNone &&
1935 "FillRectangleAux, fill_style is FillStippled/FillOpaqueStippled,"
1936 " but no stipple is set in a context");
1937
1938 patternContext->fForeground = gcVals.fForeground;
1939 patternContext->SetImage(fPimpl->GetDrawable(gcVals.fStipple));
1940
1941 if (HasFillOpaqueStippledStyle(gcVals))
1942 patternContext->fBackground = gcVals.fBackground;
1943 } else {
1944 assert(gcVals.fTile != kNone &&
1945 "FillRectangleAux, fill_style is FillTiled, but not tile is set in a context");
1946
1947 patternContext->SetImage(fPimpl->GetDrawable(gcVals.fTile));
1948 }
1949
1950 SetFillPattern(ctx, patternContext.get());
1951 patternContext.release();
1952 CGContextFillRect(ctx, fillRect);
1953
1954 return;
1955 }
1956
1957 SetFilledAreaColorFromX11Context(ctx, gcVals);
1958 CGContextFillRect(ctx, fillRect);
1959}
1960
1961//______________________________________________________________________________
1963{
1964 //Can be called in a 'normal way' - from drawRect method (QuartzView)
1965 //or directly by ROOT.
1966
1967 //From TGX11:
1968 if (!wid)
1969 return;
1970
1971 assert(!fPimpl->IsRootWindow(wid) && "FillRectangle, called for root window");
1972 assert(gc > 0 && gc <= fX11Contexts.size() && "FillRectangle, invalid context index");
1973
1974 const GCValues_t &gcVals = fX11Contexts[gc - 1];
1975 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
1976
1977 if (!drawable.fIsPixmap) {
1978 NSObject<X11Window> * const window = (NSObject<X11Window> *)drawable;
1979 QuartzView *view = (QuartzView *)window.fContentView;
1980 const ViewFixer fixer(view, wid);
1981 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
1982 if (!view.fContext)
1983 fPimpl->fX11CommandBuffer.AddFillRectangle(wid, gcVals, x, y, w, h);
1984 else
1985 FillRectangleAux(wid, gcVals, x, y, w, h);
1986 }
1987 } else
1988 FillRectangleAux(wid, gcVals, x, y, w, h);
1989}
1990
1991//______________________________________________________________________________
1992void TGCocoa::FillPolygonAux(Window_t wid, const GCValues_t &gcVals, const Point_t *polygon, Int_t nPoints)
1993{
1994 //Can be called directly or when flushing command buffer.
1995
1996 //From TGX11:
1997 if (!wid)
1998 return;
1999
2000 assert(!fPimpl->IsRootWindow(wid) && "FillPolygonAux, called for root window");
2001 assert(polygon != 0 && "FillPolygonAux, parameter 'polygon' is null");
2002 assert(nPoints > 0 && "FillPolygonAux, number of points must be positive");
2003
2004 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
2005 CGContextRef ctx = drawable.fContext;
2006
2007 CGSize patternPhase = {};
2008
2009 if (!drawable.fIsPixmap) {
2010 QuartzView * const view = (QuartzView *)fPimpl->GetWindow(wid).fContentView;
2011 const NSPoint origin = [view convertPoint : view.frame.origin toView : nil];
2012 patternPhase.width = origin.x;
2013 patternPhase.height = origin.y;
2014 }
2015
2016 const Quartz::CGStateGuard ctxGuard(ctx);//Will restore context state.
2017
2018 CGContextSetAllowsAntialiasing(ctx, false);
2019
2020 if (HasFillStippledStyle(gcVals) || HasFillOpaqueStippledStyle(gcVals) || HasFillTiledStyle(gcVals)) {
2021 std::unique_ptr<PatternContext> patternContext(new PatternContext(gcVals.fMask, gcVals.fFillStyle, 0, 0, nil, patternPhase));
2022
2023 if (HasFillStippledStyle(gcVals) || HasFillOpaqueStippledStyle(gcVals)) {
2024 assert(gcVals.fStipple != kNone &&
2025 "FillRectangleAux, fill style is FillStippled/FillOpaqueStippled,"
2026 " but no stipple is set in a context");
2027
2028 patternContext->fForeground = gcVals.fForeground;
2029 patternContext->SetImage(fPimpl->GetDrawable(gcVals.fStipple));
2030
2031 if (HasFillOpaqueStippledStyle(gcVals))
2032 patternContext->fBackground = gcVals.fBackground;
2033 } else {
2034 assert(gcVals.fTile != kNone &&
2035 "FillRectangleAux, fill_style is FillTiled, but not tile is set in a context");
2036
2037 patternContext->SetImage(fPimpl->GetDrawable(gcVals.fTile));
2038 }
2039
2040 SetFillPattern(ctx, patternContext.get());
2041 patternContext.release();
2042 } else
2043 SetFilledAreaColorFromX11Context(ctx, gcVals);
2044
2045 //This +2 -2 shit is the result of ROOT's GUI producing strange coordinates out of ....
2046 // - first noticed on checkmarks in a menu - they were all shifted.
2047
2048 CGContextBeginPath(ctx);
2049 if (!drawable.fIsPixmap) {
2050 CGContextMoveToPoint(ctx, polygon[0].fX, polygon[0].fY - 2);
2051 for (Int_t i = 1; i < nPoints; ++i)
2052 CGContextAddLineToPoint(ctx, polygon[i].fX, polygon[i].fY - 2);
2053 } else {
2054 CGContextMoveToPoint(ctx, polygon[0].fX, X11::LocalYROOTToCocoa(drawable, polygon[0].fY + 2));
2055 for (Int_t i = 1; i < nPoints; ++i)
2056 CGContextAddLineToPoint(ctx, polygon[i].fX, X11::LocalYROOTToCocoa(drawable, polygon[i].fY + 2));
2057 }
2058
2059 CGContextFillPath(ctx);
2060 CGContextSetAllowsAntialiasing(ctx, true);
2061}
2062
2063//______________________________________________________________________________
2065{
2066 // Fills the region closed by the specified path. The path is closed
2067 // automatically if the last point in the list does not coincide with the
2068 // first point.
2069 //
2070 // Point_t *points - specifies an array of points
2071 // Int_t npnt - specifies the number of points in the array
2072 //
2073 // GC components in use: function, plane-mask, fill-style, fill-rule,
2074 // subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. GC
2075 // mode-dependent components: foreground, background, tile, stipple,
2076 // tile-stipple-x-origin, and tile-stipple-y-origin.
2077 // (see also the GCValues_t structure)
2078
2079 //From TGX11:
2080 if (!wid)
2081 return;
2082
2083 assert(polygon != 0 && "FillPolygon, parameter 'polygon' is null");
2084 assert(nPoints > 0 && "FillPolygon, number of points must be positive");
2085 assert(gc > 0 && gc <= fX11Contexts.size() && "FillPolygon, invalid context index");
2086
2087 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
2088 const GCValues_t &gcVals = fX11Contexts[gc - 1];
2089
2090 if (!drawable.fIsPixmap) {
2091 QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView;
2092 const ViewFixer fixer(view, wid);
2093
2094 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
2095 if (!view.fContext)
2096 fPimpl->fX11CommandBuffer.AddFillPolygon(wid, gcVals, polygon, nPoints);
2097 else
2098 FillPolygonAux(wid, gcVals, polygon, nPoints);
2099 }
2100 } else {
2101 if (!IsCocoaDraw())
2102 fPimpl->fX11CommandBuffer.AddFillPolygon(wid, gcVals, polygon, nPoints);
2103 else
2104 FillPolygonAux(wid, gcVals, polygon, nPoints);
2105 }
2106}
2107
2108//______________________________________________________________________________
2110 UInt_t width, UInt_t height, Int_t dstX, Int_t dstY)
2111{
2112 //Called directly or when flushing command buffer.
2113 if (!src || !dst)//Can this happen? From TGX11.
2114 return;
2115
2116 assert(!fPimpl->IsRootWindow(src) && "CopyAreaAux, src parameter is root window");
2117 assert(!fPimpl->IsRootWindow(dst) && "CopyAreaAux, dst parameter is root window");
2118
2119 //Some copy operations create autoreleased cocoa objects,
2120 //I do not want them to wait till run loop's iteration end to die.
2121 const Util::AutoreleasePool pool;
2122
2123 NSObject<X11Drawable> * const srcDrawable = fPimpl->GetDrawable(src);
2124 NSObject<X11Drawable> * const dstDrawable = fPimpl->GetDrawable(dst);
2125
2126 const X11::Point dstPoint(dstX, dstY);
2127 const X11::Rectangle copyArea(srcX, srcY, width, height);
2128
2129 QuartzImage *mask = nil;
2130 if ((gcVals.fMask & kGCClipMask) && gcVals.fClipMask) {
2131 assert(fPimpl->GetDrawable(gcVals.fClipMask).fIsPixmap == YES &&
2132 "CopyArea, mask is not a pixmap");
2133 mask = (QuartzImage *)fPimpl->GetDrawable(gcVals.fClipMask);
2134 }
2135
2136 X11::Point clipOrigin;
2137 if (gcVals.fMask & kGCClipXOrigin)
2138 clipOrigin.fX = gcVals.fClipXOrigin;
2139 if (gcVals.fMask & kGCClipYOrigin)
2140 clipOrigin.fY = gcVals.fClipYOrigin;
2141
2142 [dstDrawable copy : srcDrawable area : copyArea withMask : mask clipOrigin : clipOrigin toPoint : dstPoint];
2143}
2144
2145//______________________________________________________________________________
2147 UInt_t width, UInt_t height, Int_t dstX, Int_t dstY)
2148{
2149 if (!src || !dst)//Can this happen? From TGX11.
2150 return;
2151
2152 assert(!fPimpl->IsRootWindow(src) && "CopyArea, src parameter is root window");
2153 assert(!fPimpl->IsRootWindow(dst) && "CopyArea, dst parameter is root window");
2154 assert(gc > 0 && gc <= fX11Contexts.size() && "CopyArea, invalid context index");
2155
2156 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(dst);
2157 const GCValues_t &gcVals = fX11Contexts[gc - 1];
2158
2159 if (!drawable.fIsPixmap) {
2160 QuartzView *view = (QuartzView *)fPimpl->GetWindow(dst).fContentView;
2161 const ViewFixer fixer(view, dst);
2162
2163 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
2164 if (!view.fContext)
2165 fPimpl->fX11CommandBuffer.AddCopyArea(src, dst, gcVals, srcX, srcY, width, height, dstX, dstY);
2166 else
2167 CopyAreaAux(src, dst, gcVals, srcX, srcY, width, height, dstX, dstY);
2168 }
2169 } else {
2170 if (fPimpl->GetDrawable(src).fIsPixmap) {
2171 //Both are pixmaps, nothing is buffered for src (???).
2172 CopyAreaAux(src, dst, gcVals, srcX, srcY, width, height, dstX, dstY);
2173 } else {
2174 if (!IsCocoaDraw())
2175 fPimpl->fX11CommandBuffer.AddCopyArea(src, dst, gcVals, srcX, srcY, width, height, dstX, dstY);
2176 else
2177 CopyAreaAux(src, dst, gcVals, srcX, srcY, width, height, dstX, dstY);
2178 }
2179 }
2180}
2181
2182//______________________________________________________________________________
2184{
2185 //Can be called by ROOT directly, or indirectly by AppKit.
2186 assert(!fPimpl->IsRootWindow(wid) && "DrawStringAux, called for root window");
2187
2188 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
2189 CGContextRef ctx = drawable.fContext;
2190 assert(ctx != 0 && "DrawStringAux, context is null");
2191
2192 const Quartz::CGStateGuard ctxGuard(ctx);//Will reset parameters back.
2193
2194 CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
2195
2196 //View is flipped, I have to transform for text to work.
2197 if (!drawable.fIsPixmap) {
2198 CGContextTranslateCTM(ctx, 0., drawable.fHeight);
2199 CGContextScaleCTM(ctx, 1., -1.);
2200 }
2201
2202 //Text must be antialiased
2203 CGContextSetAllowsAntialiasing(ctx, true);
2204
2205 assert(gcVals.fMask & kGCFont && "DrawString, font is not set in a context");
2206
2207 if (len < 0)//Negative length can come from caller.
2208 len = std::strlen(text);
2209 //Text can be not black, for example, highlighted label.
2210 CGFloat textColor[4] = {0., 0., 0., 1.};//black by default.
2211 //I do not check the results here, it's ok to have a black text.
2212 if (gcVals.fMask & kGCForeground)
2213 X11::PixelToRGB(gcVals.fForeground, textColor);
2214
2215 CGContextSetRGBFillColor(ctx, textColor[0], textColor[1], textColor[2], textColor[3]);
2216
2217 //Do a simple text layout using CGGlyphs.
2218 //GUI uses non-ascii symbols, and does not care about signed/unsigned - just dump everything
2219 //into a char and be happy. I'm not.
2220 std::vector<UniChar> unichars((unsigned char *)text, (unsigned char *)text + len);
2221 FixAscii(unichars);
2222
2223 Quartz::DrawTextLineNoKerning(ctx, (CTFontRef)gcVals.fFont, unichars, x, X11::LocalYROOTToCocoa(drawable, y));
2224}
2225
2226//______________________________________________________________________________
2228{
2229 //Can be called by ROOT directly, or indirectly by AppKit.
2230 if (!wid)//from TGX11.
2231 return;
2232
2233 assert(!fPimpl->IsRootWindow(wid) && "DrawString, called for root window");
2234 assert(gc > 0 && gc <= fX11Contexts.size() && "DrawString, invalid context index");
2235
2236 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
2237 const GCValues_t &gcVals = fX11Contexts[gc - 1];
2238 assert(gcVals.fMask & kGCFont && "DrawString, font is not set in a context");
2239
2240 if (!drawable.fIsPixmap) {
2241 QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView;
2242 const ViewFixer fixer(view, wid);
2243
2244 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
2245 if (!view.fContext)
2246 fPimpl->fX11CommandBuffer.AddDrawString(wid, gcVals, x, y, text, len);
2247 else
2248 DrawStringAux(wid, gcVals, x, y, text, len);
2249 }
2250
2251 } else {
2252 if (!IsCocoaDraw())
2253 fPimpl->fX11CommandBuffer.AddDrawString(wid, gcVals, x, y, text, len);
2254 else
2255 DrawStringAux(wid, gcVals, x, y, text, len);
2256 }
2257}
2258
2259//______________________________________________________________________________
2261{
2262 assert(!fPimpl->IsRootWindow(windowID) && "ClearAreaAux, called for root window");
2263
2264 QuartzView * const view = (QuartzView *)fPimpl->GetWindow(windowID).fContentView;
2265 assert(view.fContext != 0 && "ClearAreaAux, view.fContext is null");
2266
2267 //w and h can be 0 (comment from TGX11) - clear the entire window.
2268 if (!w)
2269 w = view.fWidth;
2270 if (!h)
2271 h = view.fHeight;
2272
2273 if (!view.fBackgroundPixmap) {
2274 //Simple solid fill.
2275 CGFloat rgb[3] = {};
2277
2278 const Quartz::CGStateGuard ctxGuard(view.fContext);
2279 CGContextSetRGBFillColor(view.fContext, rgb[0], rgb[1], rgb[2], 1.);//alpha can be also used.
2280 CGContextFillRect(view.fContext, CGRectMake(x, y, w, h));
2281 } else {
2282 const CGRect fillRect = CGRectMake(x, y, w, h);
2283
2284 CGSize patternPhase = {};
2285 if (view.fParentView) {
2286 const NSPoint origin = [view.fParentView convertPoint : view.frame.origin toView : nil];
2287 patternPhase.width = origin.x;
2288 patternPhase.height = origin.y;
2289 }
2290 const Quartz::CGStateGuard ctxGuard(view.fContext);//Will restore context state.
2291
2292 std::unique_ptr<PatternContext> patternContext(new PatternContext({}, 0, 0, 0, view.fBackgroundPixmap, patternPhase));
2293 SetFillPattern(view.fContext, patternContext.get());
2294 patternContext.release();
2295 CGContextFillRect(view.fContext, fillRect);
2296 }
2297}
2298
2299//______________________________________________________________________________
2301{
2302 //Can be called from drawRect method and also by ROOT's GUI directly.
2303 //Should not be called for pixmap?
2304
2305 //From TGX11:
2306 if (!wid)
2307 return;
2308
2309 assert(!fPimpl->IsRootWindow(wid) && "ClearArea, called for root window");
2310
2311 //If wid is pixmap or image, this will crush.
2312 QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView;
2313 if (ParentRendersToChild(view))
2314 return;
2315
2316 if (!view.fIsOverlapped && view.fMapState == kIsViewable) {
2317 if (!view.fContext)
2318 fPimpl->fX11CommandBuffer.AddClearArea(wid, x, y, w, h);
2319 else
2320 ClearAreaAux(wid, x, y, w, h);
2321 }
2322}
2323
2324//______________________________________________________________________________
2326{
2327 //Clears the entire area in the specified window (comment from TGX11).
2328
2329 //From TGX11:
2330 if (!wid)
2331 return;
2332
2333 ClearArea(wid, 0, 0, 0, 0);
2334}
2335
2336#pragma mark - Pixmap management.
2337
2338//______________________________________________________________________________
2340{
2341 //Two stage creation.
2342 NSSize newSize = {};
2343 newSize.width = w;
2344 newSize.height = h;
2345
2346 Util::NSScopeGuard<QuartzPixmap> pixmap([[QuartzPixmap alloc] initWithW : w H : h
2347 scaleFactor : [[NSScreen mainScreen] backingScaleFactor]]);
2348 if (pixmap.Get()) {
2349 pixmap.Get().fID = fPimpl->RegisterDrawable(pixmap.Get());//Can throw.
2350 return (Int_t)pixmap.Get().fID;
2351 } else {
2352 //Detailed error message was issued by QuartzPixmap by this point:
2353 Error("OpenPixmap", "QuartzPixmap initialization failed");
2354 return -1;
2355 }
2356}
2357
2358//______________________________________________________________________________
2360{
2361 assert(!fPimpl->IsRootWindow(wid) && "ResizePixmap, called for root window");
2362
2363 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
2364 assert(drawable.fIsPixmap == YES && "ResizePixmap, invalid drawable");
2365
2366 QuartzPixmap *pixmap = (QuartzPixmap *)drawable;
2367 if (w == pixmap.fWidth && h == pixmap.fHeight)
2368 return 1;
2369
2370 if ([pixmap resizeW : w H : h scaleFactor : [[NSScreen mainScreen] backingScaleFactor]])
2371 return 1;
2372
2373 return -1;
2374}
2375
2376//______________________________________________________________________________
2378{
2379 assert(pixmapID > (Int_t)fPimpl->GetRootWindowID() &&
2380 "SelectPixmap, parameter 'pixmapID' is not a valid id");
2381
2382 fSelectedDrawable = pixmapID;
2383}
2384
2385//______________________________________________________________________________
2387{
2388 assert(pixmapID > (Int_t)fPimpl->GetRootWindowID() &&
2389 "CopyPixmap, parameter 'pixmapID' is not a valid id");
2390 assert(fSelectedDrawable > fPimpl->GetRootWindowID() &&
2391 "CopyPixmap, fSelectedDrawable is not a valid window id");
2392
2393 NSObject<X11Drawable> * const source = fPimpl->GetDrawable(pixmapID);
2394 assert([source isKindOfClass : [QuartzPixmap class]] &&
2395 "CopyPixmap, source is not a pixmap");
2396 QuartzPixmap * const pixmap = (QuartzPixmap *)source;
2397
2398 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(fSelectedDrawable);
2399 NSObject<X11Drawable> * destination = nil;
2400
2401 if (drawable.fIsPixmap) {
2402 destination = drawable;
2403 } else {
2404 NSObject<X11Window> * const window = fPimpl->GetWindow(fSelectedDrawable);
2405 if (window.fBackBuffer) {
2406 destination = window.fBackBuffer;
2407 } else {
2408 Warning("CopyPixmap", "Operation skipped, since destination"
2409 " window is not double buffered");
2410 return;
2411 }
2412 }
2413
2414 const X11::Rectangle copyArea(0, 0, pixmap.fWidth, pixmap.fHeight);
2415 const X11::Point dstPoint(x, y);
2416
2417 [destination copy : pixmap area : copyArea withMask : nil clipOrigin : X11::Point() toPoint : dstPoint];
2418}
2419
2420//______________________________________________________________________________
2422{
2423 // Deletes current pixmap.
2424 assert(fSelectedDrawable > fPimpl->GetRootWindowID() && "ClosePixmap, no drawable selected");
2425 assert(fPimpl->GetDrawable(fSelectedDrawable).fIsPixmap == YES && "ClosePixmap, selected drawable is not a pixmap");
2426
2429}
2430
2431#pragma mark - Different functions to create pixmap from different data sources. Used by GUI.
2432#pragma mark - These functions implement TVirtualX interface, some of them dupilcate others.
2433
2434//______________________________________________________________________________
2436{
2437 //
2438 return OpenPixmap(w, h);
2439}
2440
2441//______________________________________________________________________________
2443 ULong_t foregroundPixel, ULong_t backgroundPixel, Int_t depth)
2444{
2445 //Create QuartzImage, using bitmap and foregroundPixel/backgroundPixel,
2446 //if depth is one - create an image mask instead.
2447
2448 assert(bitmap != 0 && "CreatePixmap, parameter 'bitmap' is null");
2449 assert(width > 0 && "CreatePixmap, parameter 'width' is 0");
2450 assert(height > 0 && "CreatePixmap, parameter 'height' is 0");
2451
2452 std::vector<unsigned char> imageData (depth > 1 ? width * height * 4 : width * height);
2453
2454 X11::FillPixmapBuffer((unsigned char*)bitmap, width, height, foregroundPixel,
2455 backgroundPixel, depth, &imageData[0]);
2456
2457 //Now we can create CGImageRef.
2459
2460 if (depth > 1)
2461 image.Reset([[QuartzImage alloc] initWithW : width H : height data: &imageData[0]]);
2462 else
2463 image.Reset([[QuartzImage alloc] initMaskWithW : width H : height bitmapMask : &imageData[0]]);
2464
2465 if (!image.Get()) {
2466 Error("CreatePixmap", "QuartzImage initialization failed");//More concrete message was issued by QuartzImage.
2467 return kNone;
2468 }
2469
2470 image.Get().fID = fPimpl->RegisterDrawable(image.Get());//This can throw.
2471 return image.Get().fID;
2472}
2473
2474//______________________________________________________________________________
2476{
2477 //Create QuartzImage, using "bits" (data in bgra format).
2478 assert(bits != 0 && "CreatePixmapFromData, data parameter is null");
2479 assert(width != 0 && "CreatePixmapFromData, width parameter is 0");
2480 assert(height != 0 && "CreatePixmapFromData, height parameter is 0");
2481
2482 //I'm not using vector here, since I have to pass this pointer to Obj-C code
2483 //(and Obj-C object will own this memory later).
2484 std::vector<unsigned char> imageData(bits, bits + width * height * 4);
2485
2486 //Convert bgra to rgba.
2487 unsigned char *p = &imageData[0];
2488 for (unsigned i = 0, e = width * height; i < e; ++i, p += 4)
2489 std::swap(p[0], p[2]);
2490
2491 //Now we can create CGImageRef.
2492 Util::NSScopeGuard<QuartzImage> image([[QuartzImage alloc] initWithW : width
2493 H : height data : &imageData[0]]);
2494
2495 if (!image.Get()) {
2496 //Detailed error message was issued by QuartzImage.
2497 Error("CreatePixmapFromData", "QuartzImage initialziation failed");
2498 return kNone;
2499 }
2500
2501 image.Get().fID = fPimpl->RegisterDrawable(image.Get());//This can throw.
2502 return image.Get().fID;
2503}
2504
2505//______________________________________________________________________________
2507{
2508 //Create QuartzImage with image mask.
2509 assert(std::numeric_limits<unsigned char>::digits == 8 && "CreateBitmap, ASImage requires octets");
2510
2511 //I'm not using vector here, since I have to pass this pointer to Obj-C code
2512 //(and Obj-C object will own this memory later).
2513
2514 //TASImage has a bug, it calculates size in pixels (making a with to multiple-of eight and
2515 //allocates memory as each bit occupies one byte, and later packs bits into bytes.
2516
2517 std::vector<unsigned char> imageData(width * height);
2518
2519 //TASImage assumes 8-bit bytes and packs mask bits.
2520 for (unsigned i = 0, j = 0, e = width / 8 * height; i < e; ++i) {
2521 for(unsigned bit = 0; bit < 8; ++bit, ++j) {
2522 if (bitmap[i] & (1 << bit))
2523 imageData[j] = 0;//Opaque.
2524 else
2525 imageData[j] = 255;//Masked out bit.
2526 }
2527 }
2528
2529 //Now we can create CGImageRef.
2530 Util::NSScopeGuard<QuartzImage> image([[QuartzImage alloc] initMaskWithW : width
2531 H : height bitmapMask : &imageData[0]]);
2532 if (!image.Get()) {
2533 //Detailed error message was issued by QuartzImage.
2534 Error("CreateBitmap", "QuartzImage initialization failed");
2535 return kNone;
2536 }
2537
2538 image.Get().fID = fPimpl->RegisterDrawable(image.Get());//This can throw.
2539 return image.Get().fID;
2540}
2541
2542//______________________________________________________________________________
2544{
2545 fPimpl->DeleteDrawable(pixmapID);
2546}
2547
2548//______________________________________________________________________________
2550{
2551 // Explicitely deletes the pixmap resource "pmap".
2552 assert(fPimpl->GetDrawable(pixmapID).fIsPixmap == YES && "DeletePixmap, object is not a pixmap");
2553 fPimpl->fX11CommandBuffer.AddDeletePixmap(pixmapID);
2554}
2555
2556//______________________________________________________________________________
2558{
2559 // Registers a pixmap created by TGLManager as a ROOT pixmap
2560 //
2561 // w, h - the width and height, which define the pixmap size
2562 return 0;
2563}
2564
2565//______________________________________________________________________________
2567{
2568 //Can be also in a window management part, since window is also drawable.
2569 if (fPimpl->IsRootWindow(wid)) {
2570 Warning("GetColorBits", "Called for root window");
2571 } else {
2572 assert(x >= 0 && "GetColorBits, parameter 'x' is negative");
2573 assert(y >= 0 && "GetColorBits, parameter 'y' is negative");
2574 assert(w != 0 && "GetColorBits, parameter 'w' is 0");
2575 assert(h != 0 && "GetColorBits, parameter 'h' is 0");
2576
2577 const X11::Rectangle area(x, y, w, h);
2578 return [fPimpl->GetDrawable(wid) readColorBits : area];//readColorBits can throw std::bad_alloc, no resource will leak.
2579 }
2580
2581 return 0;
2582}
2583
2584#pragma mark - XImage emulation.
2585
2586//______________________________________________________________________________
2588{
2589 // Allocates the memory needed for a drawable.
2590 //
2591 // width - the width of the image, in pixels
2592 // height - the height of the image, in pixels
2593 return OpenPixmap(width, height);
2594}
2595
2596//______________________________________________________________________________
2598{
2599 // Returns the width and height of the image wid
2600 assert(wid > fPimpl->GetRootWindowID() && "GetImageSize, parameter 'wid' is invalid");
2601
2602 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(wid);
2603 width = drawable.fWidth;
2604 height = drawable.fHeight;
2605}
2606
2607//______________________________________________________________________________
2609{
2610 // Overwrites the pixel in the image with the specified pixel value.
2611 // The image must contain the x and y coordinates.
2612 //
2613 // imageID - specifies the image
2614 // x, y - coordinates
2615 // pixel - the new pixel value
2616
2617 assert([fPimpl->GetDrawable(imageID) isKindOfClass : [QuartzPixmap class]] &&
2618 "PutPixel, parameter 'imageID' is a bad pixmap id");
2619 assert(x >= 0 && "PutPixel, parameter 'x' is negative");
2620 assert(y >= 0 && "PutPixel, parameter 'y' is negative");
2621
2622 QuartzPixmap * const pixmap = (QuartzPixmap *)fPimpl->GetDrawable(imageID);
2623
2624 unsigned char rgb[3] = {};
2625 X11::PixelToRGB(pixel, rgb);
2626 [pixmap putPixel : rgb X : x Y : y];
2627}
2628
2629//______________________________________________________________________________
2630void TGCocoa::PutImage(Drawable_t drawableID, GContext_t gc, Drawable_t imageID, Int_t dstX, Int_t dstY,
2631 Int_t srcX, Int_t srcY, UInt_t width, UInt_t height)
2632{
2633 //TGX11 uses ZPixmap in CreateImage ... so background/foreground
2634 //in gc can NEVER be used (and the depth is ALWAYS > 1).
2635 //This means .... I can call CopyArea!
2636
2637 CopyArea(imageID, drawableID, gc, srcX, srcY, width, height, dstX, dstY);
2638}
2639
2640//______________________________________________________________________________
2642{
2643 // Deallocates the memory associated with the image img
2644 assert([fPimpl->GetDrawable(imageID) isKindOfClass : [QuartzPixmap class]] &&
2645 "DeleteImage, imageID parameter is not a valid image id");
2646 DeletePixmap(imageID);
2647}
2648
2649#pragma mark - Mouse related code.
2650
2651//______________________________________________________________________________
2653 Window_t /*confine*/, Cursor_t /*cursor*/, Bool_t grab)
2654{
2655 //Emulate "passive grab" feature of X11 (similar to "implicit grab" in Cocoa
2656 //and implicit grab on X11, the difference is that "implicit grab" works as
2657 //if owner_events parameter for XGrabButton was False, but in ROOT
2658 //owner_events for XGrabButton is _always_ True.
2659 //Confine will never be used - no such feature on MacOSX and
2660 //I'm not going to emulate it..
2661 //This function also does ungrab.
2662
2663 //From TGWin32:
2664 if (!wid)
2665 return;
2666
2667 assert(!fPimpl->IsRootWindow(wid) && "GrabButton, called for 'root' window");
2668
2669 NSObject<X11Window> * const widget = fPimpl->GetWindow(wid);
2670
2671 if (grab) {
2672 widget.fPassiveGrabOwnerEvents = YES; //This is how TGX11 works.
2673 widget.fPassiveGrabButton = button;
2674 widget.fPassiveGrabEventMask = eventMask;
2675 widget.fPassiveGrabKeyModifiers = keyModifiers;
2676 //Set the cursor.
2677 } else {
2678 widget.fPassiveGrabOwnerEvents = NO;
2679 widget.fPassiveGrabButton = -1;//0 is kAnyButton.
2680 widget.fPassiveGrabEventMask = 0;
2681 widget.fPassiveGrabKeyModifiers = 0;
2682 }
2683}
2684
2685//______________________________________________________________________________
2686void TGCocoa::GrabPointer(Window_t wid, UInt_t eventMask, Window_t /*confine*/, Cursor_t /*cursor*/, Bool_t grab, Bool_t ownerEvents)
2687{
2688 //Emulate pointer grab from X11.
2689 //Confine will never be used - no such feature on MacOSX and
2690 //I'm not going to emulate it..
2691 //This function also does ungrab.
2692
2693 if (grab) {
2694 NSView<X11Window> * const view = fPimpl->GetWindow(wid).fContentView;
2695 assert(!fPimpl->IsRootWindow(wid) && "GrabPointer, called for 'root' window");
2696 //set the cursor.
2697 //set active grab.
2698 fPimpl->fX11EventTranslator.SetPointerGrab(view, eventMask, ownerEvents);
2699 } else {
2700 //unset cursor?
2701 //cancel grab.
2702 fPimpl->fX11EventTranslator.CancelPointerGrab();
2703 }
2704}
2705
2706//______________________________________________________________________________
2708{
2709 // Changes the specified dynamic parameters if the pointer is actively
2710 // grabbed by the client and if the specified time is no earlier than the
2711 // last-pointer-grab time and no later than the current X server time.
2712 //Noop.
2713}
2714
2715//______________________________________________________________________________
2717{
2718 // Turns key auto repeat on (kTRUE) or off (kFALSE).
2719 //Noop.
2720}
2721
2722//______________________________________________________________________________
2723void TGCocoa::GrabKey(Window_t wid, Int_t keyCode, UInt_t rootKeyModifiers, Bool_t grab)
2724{
2725 //Comment from TVirtualX:
2726 // Establishes a passive grab on the keyboard. In the future, the
2727 // keyboard is actively grabbed, the last-keyboard-grab time is set
2728 // to the time at which the key was pressed (as transmitted in the
2729 // KeyPress event), and the KeyPress event is reported if all of the
2730 // following conditions are true:
2731 // - the keyboard is not grabbed and the specified key (which can
2732 // itself be a modifier key) is logically pressed when the
2733 // specified modifier keys are logically down, and no other
2734 // modifier keys are logically down;
2735 // - either the grab window "id" is an ancestor of (or is) the focus
2736 // window, or "id" is a descendant of the focus window and contains
2737 // the pointer;
2738 // - a passive grab on the same key combination does not exist on any
2739 // ancestor of grab_window
2740 //
2741 // id - window id
2742 // keycode - specifies the KeyCode or AnyKey
2743 // modifier - specifies the set of keymasks or AnyModifier; the mask is
2744 // the bitwise inclusive OR of the valid keymask bits
2745 // grab - a switch between grab/ungrab key
2746 // grab = kTRUE grab the key and modifier
2747 // grab = kFALSE ungrab the key and modifier
2748 //End of comment.
2749
2750
2751 //Key code already must be Cocoa's key code, this is done by GUI classes,
2752 //they call KeySymToKeyCode.
2753 assert(!fPimpl->IsRootWindow(wid) && "GrabKey, called for root window");
2754
2755 NSView<X11Window> * const view = fPimpl->GetWindow(wid).fContentView;
2756 const NSUInteger cocoaKeyModifiers = X11::GetCocoaKeyModifiersFromROOTKeyModifiers(rootKeyModifiers);
2757
2758 if (grab)
2759 [view addPassiveKeyGrab : keyCode modifiers : cocoaKeyModifiers];
2760 else
2761 [view removePassiveKeyGrab : keyCode modifiers : cocoaKeyModifiers];
2762}
2763
2764//______________________________________________________________________________
2766{
2767 // Converts the "keysym" to the appropriate keycode. For example,
2768 // keysym is a letter and keycode is the matching keyboard key (which
2769 // is dependend on the current keyboard mapping). If the specified
2770 // "keysym" is not defined for any keycode, returns zero.
2771
2772 return X11::MapKeySymToKeyCode(keySym);
2773}
2774
2775//______________________________________________________________________________
2777{
2778 // Returns the window id of the window having the input focus.
2779
2780 return fPimpl->fX11EventTranslator.GetInputFocus();
2781}
2782
2783//______________________________________________________________________________
2785{
2786 // Changes the input focus to specified window "wid".
2787 assert(!fPimpl->IsRootWindow(wid) && "SetInputFocus, called for root window");
2788
2789 if (wid == kNone)
2790 fPimpl->fX11EventTranslator.SetInputFocus(nil);
2791 else
2792 fPimpl->fX11EventTranslator.SetInputFocus(fPimpl->GetWindow(wid).fContentView);
2793}
2794
2795//______________________________________________________________________________
2797{
2798 // Converts the keycode from the event structure to a key symbol (according
2799 // to the modifiers specified in the event structure and the current
2800 // keyboard mapping). In "buf" a null terminated ASCII string is returned
2801 // representing the string that is currently mapped to the key code.
2802 //
2803 // event - specifies the event structure to be used
2804 // buf - returns the translated characters
2805 // buflen - the length of the buffer
2806 // keysym - returns the "keysym" computed from the event
2807 // if this argument is not NULL
2808 assert(buf != 0 && "LookupString, parameter 'buf' is null");
2809 assert(length >= 2 && "LookupString, parameter 'length' - not enough memory to return null-terminated ASCII string");
2810
2811 X11::MapUnicharToKeySym(event->fCode, buf, length, keysym);
2812}
2813
2814#pragma mark - Font management.
2815
2816//______________________________________________________________________________
2818{
2819 //fontName is in XLFD format:
2820 //-foundry-family- ..... etc., some components can be omitted and replaced by *.
2821 assert(fontName != 0 && "LoadQueryFont, fontName is null");
2822
2823 X11::XLFDName xlfd;
2824 if (ParseXLFDName(fontName, xlfd)) {
2825 //Make names more flexible: fFamilyName can be empty or '*'.
2826 if (!xlfd.fFamilyName.length() || xlfd.fFamilyName == "*")
2827 xlfd.fFamilyName = "Courier";//Up to me, right?
2828 if (!xlfd.fPixelSize)
2829 xlfd.fPixelSize = 11;//Again, up to me.
2830 return fPimpl->fFontManager.LoadFont(xlfd);
2831 }
2832
2833 return FontStruct_t();
2834}
2835
2836//______________________________________________________________________________
2838{
2839 return (FontH_t)fs;
2840}
2841
2842//______________________________________________________________________________
2844{
2845 fPimpl->fFontManager.UnloadFont(fs);
2846}
2847
2848//______________________________________________________________________________
2850{
2851 // Returns True when TrueType fonts are used
2852 //No, we use Core Text and do not want TTF to calculate metrics.
2853 return kFALSE;
2854}
2855
2856//______________________________________________________________________________
2858{
2859 // Return lenght of the string "s" in pixels. Size depends on font.
2860 return fPimpl->fFontManager.GetTextWidth(font, s, len);
2861}
2862
2863//______________________________________________________________________________
2864void TGCocoa::GetFontProperties(FontStruct_t font, Int_t &maxAscent, Int_t &maxDescent)
2865{
2866 // Returns the font properties.
2867 fPimpl->fFontManager.GetFontProperties(font, maxAscent, maxDescent);
2868}
2869
2870//______________________________________________________________________________
2872{
2873 // Retrieves the associated font structure of the font specified font
2874 // handle "fh".
2875 //
2876 // Free returned FontStruct_t using FreeFontStruct().
2877
2878 return (FontStruct_t)fh;
2879}
2880
2881//______________________________________________________________________________
2883{
2884 // Frees the font structure "fs". The font itself will be freed when
2885 // no other resource references it.
2886 //Noop.
2887}
2888
2889//______________________________________________________________________________
2890char **TGCocoa::ListFonts(const char *fontName, Int_t maxNames, Int_t &count)
2891{
2892 count = 0;
2893
2894 if (fontName && fontName[0]) {
2895 X11::XLFDName xlfd;
2896 if (X11::ParseXLFDName(fontName, xlfd))
2897 return fPimpl->fFontManager.ListFonts(xlfd, maxNames, count);
2898 }
2899
2900 return 0;
2901}
2902
2903//______________________________________________________________________________
2904void TGCocoa::FreeFontNames(char **fontList)
2905{
2906 // Frees the specified the array of strings "fontlist".
2907 if (!fontList)
2908 return;
2909
2910 fPimpl->fFontManager.FreeFontNames(fontList);
2911}
2912
2913#pragma mark - Color management.
2914
2915//______________________________________________________________________________
2916Bool_t TGCocoa::ParseColor(Colormap_t /*cmap*/, const char *colorName, ColorStruct_t &color)
2917{
2918 //"Color" passed as colorName, can be one of the names, defined in X11/rgb.txt,
2919 //or rgb triplet, which looks like: #rgb #rrggbb #rrrgggbbb #rrrrggggbbbb,
2920 //where r, g, and b - are hex digits.
2921 return fPimpl->fX11ColorParser.ParseColor(colorName, color);
2922}
2923
2924//______________________________________________________________________________
2926{
2927 const unsigned red = unsigned(double(color.fRed) / 0xFFFF * 0xFF);
2928 const unsigned green = unsigned(double(color.fGreen) / 0xFFFF * 0xFF);
2929 const unsigned blue = unsigned(double(color.fBlue) / 0xFFFF * 0xFF);
2930 color.fPixel = red << 16 | green << 8 | blue;
2931 return kTRUE;
2932}
2933
2934//______________________________________________________________________________
2936{
2937 // Returns the current RGB value for the pixel in the "color" structure
2938 color.fRed = (color.fPixel >> 16 & 0xFF) * 0xFFFF / 0xFF;
2939 color.fGreen = (color.fPixel >> 8 & 0xFF) * 0xFFFF / 0xFF;
2940 color.fBlue = (color.fPixel & 0xFF) * 0xFFFF / 0xFF;
2941}
2942
2943//______________________________________________________________________________
2944void TGCocoa::FreeColor(Colormap_t /*cmap*/, ULong_t /*pixel*/)
2945{
2946 // Frees color cell with specified pixel value.
2947}
2948
2949//______________________________________________________________________________
2951{
2952 ULong_t pixel = 0;
2953 if (const TColor * const color = gROOT->GetColor(rootColorIndex)) {
2954 Float_t red = 0.f, green = 0.f, blue = 0.f;
2955 color->GetRGB(red, green, blue);
2956 pixel = unsigned(red * 255) << 16;
2957 pixel |= unsigned(green * 255) << 8;
2958 pixel |= unsigned(blue * 255);
2959 }
2960
2961 return pixel;
2962}
2963
2964//______________________________________________________________________________
2966{
2967 //Implemented as NSBitsPerPixelFromDepth([mainScreen depth]);
2968 nPlanes = GetDepth();
2969}
2970
2971//______________________________________________________________________________
2972void TGCocoa::GetRGB(Int_t /*index*/, Float_t &/*r*/, Float_t &/*g*/, Float_t &/*b*/)
2973{
2974 // Returns RGB values for color "index".
2975}
2976
2977//______________________________________________________________________________
2978void TGCocoa::SetRGB(Int_t /*cindex*/, Float_t /*r*/, Float_t /*g*/, Float_t /*b*/)
2979{
2980 // Sets color intensities the specified color index "cindex".
2981 //
2982 // cindex - color index
2983 // r, g, b - the red, green, blue intensities between 0.0 and 1.0
2984}
2985
2986//______________________________________________________________________________
2988{
2989 return Colormap_t();
2990}
2991
2992#pragma mark - Graphical context management.
2993
2994//______________________________________________________________________________
2996{
2997 //Here I have to imitate graphics context that exists in X11.
2998 fX11Contexts.push_back(*gval);
2999 return fX11Contexts.size();
3000}
3001
3002//______________________________________________________________________________
3004{
3005 // Sets the foreground color for the specified GC (shortcut for ChangeGC
3006 // with only foreground mask set).
3007 //
3008 // gc - specifies the GC
3009 // foreground - the foreground you want to set
3010 // (see also the GCValues_t structure)
3011
3012 assert(gc <= fX11Contexts.size() && gc > 0 && "ChangeGC, invalid context id");
3013
3014 GCValues_t &x11Context = fX11Contexts[gc - 1];
3015 x11Context.fMask |= kGCForeground;
3016 x11Context.fForeground = foreground;
3017}
3018
3019//______________________________________________________________________________
3021{
3022 //
3023 assert(gc <= fX11Contexts.size() && gc > 0 && "ChangeGC, invalid context id");
3024 assert(gval != 0 && "ChangeGC, gval parameter is null");
3025
3026 GCValues_t &x11Context = fX11Contexts[gc - 1];
3027 const Mask_t &mask = gval->fMask;
3028 x11Context.fMask |= mask;
3029
3030 //Not all of GCValues_t members are used, but
3031 //all can be copied/set without any problem.
3032
3033 if (mask & kGCFunction)
3034 x11Context.fFunction = gval->fFunction;
3035 if (mask & kGCPlaneMask)
3036 x11Context.fPlaneMask = gval->fPlaneMask;
3037 if (mask & kGCForeground)
3038 x11Context.fForeground = gval->fForeground;
3039 if (mask & kGCBackground)
3040 x11Context.fBackground = gval->fBackground;
3041 if (mask & kGCLineWidth)
3042 x11Context.fLineWidth = gval->fLineWidth;
3043 if (mask & kGCLineStyle)
3044 x11Context.fLineStyle = gval->fLineStyle;
3045 if (mask & kGCCapStyle)//nobody uses
3046 x11Context.fCapStyle = gval->fCapStyle;
3047 if (mask & kGCJoinStyle)//nobody uses
3048 x11Context.fJoinStyle = gval->fJoinStyle;
3049 if (mask & kGCFillRule)//nobody uses
3050 x11Context.fFillRule = gval->fFillRule;
3051 if (mask & kGCArcMode)//nobody uses
3052 x11Context.fArcMode = gval->fArcMode;
3053 if (mask & kGCFillStyle)
3054 x11Context.fFillStyle = gval->fFillStyle;
3055 if (mask & kGCTile)
3056 x11Context.fTile = gval->fTile;
3057 if (mask & kGCStipple)
3058 x11Context.fStipple = gval->fStipple;
3060 x11Context.fTsXOrigin = gval->fTsXOrigin;
3062 x11Context.fTsYOrigin = gval->fTsYOrigin;
3063 if (mask & kGCFont)
3064 x11Context.fFont = gval->fFont;
3065 if (mask & kGCSubwindowMode)
3066 x11Context.fSubwindowMode = gval->fSubwindowMode;
3068 x11Context.fGraphicsExposures = gval->fGraphicsExposures;
3069 if (mask & kGCClipXOrigin)
3070 x11Context.fClipXOrigin = gval->fClipXOrigin;
3071 if (mask & kGCClipYOrigin)
3072 x11Context.fClipYOrigin = gval->fClipYOrigin;
3073 if (mask & kGCClipMask)
3074 x11Context.fClipMask = gval->fClipMask;
3075 if (mask & kGCDashOffset)
3076 x11Context.fDashOffset = gval->fDashOffset;
3077 if (mask & kGCDashList) {
3078 const unsigned nDashes = sizeof x11Context.fDashes / sizeof x11Context.fDashes[0];
3079 for (unsigned i = 0; i < nDashes; ++i)
3080 x11Context.fDashes[i] = gval->fDashes[i];
3081 x11Context.fDashLen = gval->fDashLen;
3082 }
3083}
3084
3085//______________________________________________________________________________
3087{
3088 assert(src <= fX11Contexts.size() && src > 0 && "CopyGC, bad source context");
3089 assert(dst <= fX11Contexts.size() && dst > 0 && "CopyGC, bad destination context");
3090
3091 GCValues_t srcContext = fX11Contexts[src - 1];
3092 srcContext.fMask = mask;
3093
3094 ChangeGC(dst, &srcContext);
3095}
3096
3097//______________________________________________________________________________
3099{
3100 // Returns the components specified by the mask in "gval" for the
3101 // specified GC "gc" (see also the GCValues_t structure)
3102 const GCValues_t &gcVal = fX11Contexts[gc - 1];
3103 gval = gcVal;
3104}
3105
3106//______________________________________________________________________________
3108{
3109 // Deletes the specified GC "gc".
3110}
3111
3112#pragma mark - Cursor management.
3113
3114//______________________________________________________________________________
3116{
3117 // Creates the specified cursor. (just return cursor from cursor pool).
3118 // The cursor can be:
3119 //
3120 // kBottomLeft, kBottomRight, kTopLeft, kTopRight,
3121 // kBottomSide, kLeftSide, kTopSide, kRightSide,
3122 // kMove, kCross, kArrowHor, kArrowVer,
3123 // kHand, kRotate, kPointer, kArrowRight,
3124 // kCaret, kWatch
3125
3126 return Cursor_t(cursor + 1);//HAHAHAHAHA!!! CREATED!!!
3127}
3128
3129//______________________________________________________________________________
3131{
3132 // The cursor "cursor" will be used when the pointer is in the
3133 // window "wid".
3134 assert(!fPimpl->IsRootWindow(wid) && "SetCursor, called for root window");
3135
3136 NSView<X11Window> * const view = fPimpl->GetWindow(wid).fContentView;
3137 view.fCurrentCursor = cursor;
3138}
3139
3140//______________________________________________________________________________
3142{
3143 // Sets the cursor "curid" to be used when the pointer is in the
3144 // window "wid".
3145 if (cursorID > 0)
3146 SetCursor(Int_t(wid), ECursor(cursorID - 1));
3147 else
3149}
3150
3151//______________________________________________________________________________
3153{
3154 // Returns the pointer position.
3155
3156 //I ignore fSelectedDrawable here. If you have any problems with this, hehe, you can ask me :)
3157 const NSPoint screenPoint = [NSEvent mouseLocation];
3158 x = X11::GlobalXCocoaToROOT(screenPoint.x);
3159 y = X11::GlobalYCocoaToROOT(screenPoint.y);
3160}
3161
3162//______________________________________________________________________________
3163void TGCocoa::QueryPointer(Window_t winID, Window_t &rootWinID, Window_t &childWinID,
3164 Int_t &rootX, Int_t &rootY, Int_t &winX, Int_t &winY, UInt_t &mask)
3165{
3166 //Emulate XQueryPointer.
3167
3168 //From TGX11/TGWin32:
3169 if (!winID)
3170 return;//Neither TGX11, nor TGWin32 set any of out parameters.
3171
3172 //We have only one root window.
3173 rootWinID = fPimpl->GetRootWindowID();
3174 //Find cursor position (screen coordinates).
3175 NSPoint screenPoint = [NSEvent mouseLocation];
3176 screenPoint.x = X11::GlobalXCocoaToROOT(screenPoint.x);
3177 screenPoint.y = X11::GlobalYCocoaToROOT(screenPoint.y);
3178 rootX = screenPoint.x;
3179 rootY = screenPoint.y;
3180
3181 //Convert a screen point to winID's coordinate system.
3182 if (winID > fPimpl->GetRootWindowID()) {
3183 NSObject<X11Window> * const window = fPimpl->GetWindow(winID);
3184 const NSPoint winPoint = X11::TranslateFromScreen(screenPoint, window.fContentView);
3185 winX = winPoint.x;
3186 winY = winPoint.y;
3187 } else {
3188 winX = screenPoint.x;
3189 winY = screenPoint.y;
3190 }
3191
3192 //Find child window in these coordinates (?).
3193 if (QuartzWindow * const childWin = X11::FindWindowInPoint(screenPoint.x, screenPoint.y)) {
3194 childWinID = childWin.fID;
3196 } else {
3197 childWinID = 0;
3198 mask = 0;
3199 }
3200}
3201
3202#pragma mark - OpenGL management.
3203
3204//______________________________________________________________________________
3206{
3207 //Scaling factor to let our OpenGL code know, that we probably
3208 //work on a retina display.
3209
3210 return [[NSScreen mainScreen] backingScaleFactor];
3211}
3212
3213//______________________________________________________________________________
3215 const std::vector<std::pair<UInt_t, Int_t> > &formatComponents)
3216{
3217 //ROOT never creates GL widgets with 'root' as a parent (so not top-level gl-windows).
3218 //If this change, assert must be deleted.
3219 typedef std::pair<UInt_t, Int_t> component_type;
3220 typedef std::vector<component_type>::size_type size_type;
3221
3222 //Convert pairs into Cocoa's GL attributes.
3223 std::vector<NSOpenGLPixelFormatAttribute> attribs;
3224 for (size_type i = 0, e = formatComponents.size(); i < e; ++i) {
3225 const component_type &comp = formatComponents[i];
3226
3227 if (comp.first == Rgl::kDoubleBuffer) {
3228 attribs.push_back(NSOpenGLPFADoubleBuffer);
3229 } else if (comp.first == Rgl::kDepth) {
3230 attribs.push_back(NSOpenGLPFADepthSize);
3231 attribs.push_back(comp.second > 0 ? comp.second : 32);
3232 } else if (comp.first == Rgl::kAccum) {
3233 attribs.push_back(NSOpenGLPFAAccumSize);
3234 attribs.push_back(comp.second > 0 ? comp.second : 1);
3235 } else if (comp.first == Rgl::kStencil) {
3236 attribs.push_back(NSOpenGLPFAStencilSize);
3237 attribs.push_back(comp.second > 0 ? comp.second : 8);
3238 } else if (comp.first == Rgl::kMultiSample) {
3239 attribs.push_back(NSOpenGLPFAMultisample);
3240 attribs.push_back(NSOpenGLPFASampleBuffers);
3241 attribs.push_back(1);
3242 attribs.push_back(NSOpenGLPFASamples);
3243 attribs.push_back(comp.second ? comp.second : 8);
3244 }
3245 }
3246
3247 attribs.push_back(0);
3248
3249 NSOpenGLPixelFormat * const pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes : &attribs[0]];
3250 const Util::NSScopeGuard<NSOpenGLPixelFormat> formatGuard(pixelFormat);
3251
3252 NSView<X11Window> *parentView = nil;
3253 if (!fPimpl->IsRootWindow(parentID)) {
3254 parentView = fPimpl->GetWindow(parentID).fContentView;
3255 assert([parentView isKindOfClass : [QuartzView class]] &&
3256 "CreateOpenGLWindow, parent view must be QuartzView");
3257 }
3258
3259 NSRect viewFrame = {};
3260 viewFrame.size.width = width;
3261 viewFrame.size.height = height;
3262
3263 ROOTOpenGLView * const glView = [[ROOTOpenGLView alloc] initWithFrame : viewFrame pixelFormat : pixelFormat];
3264 const Util::NSScopeGuard<ROOTOpenGLView> viewGuard(glView);
3265
3266 Window_t glID = kNone;
3267
3268 if (parentView) {
3269 [parentView addChild : glView];
3270 glID = fPimpl->RegisterDrawable(glView);
3271 glView.fID = glID;
3272 } else {
3273 //"top-level glview".
3274 //Create a window to be parent of this gl-view.
3275 QuartzWindow *parent = [[QuartzWindow alloc] initWithGLView : glView];
3276 const Util::NSScopeGuard<QuartzWindow> winGuard(parent);
3277
3278
3279 if (!parent) {
3280 Error("CreateOpenGLWindow", "QuartzWindow allocation/initialization"
3281 " failed for a top-level GL widget");
3282 return kNone;
3283 }
3284
3285 glID = fPimpl->RegisterDrawable(parent);
3286 parent.fID = glID;
3287 }
3288
3289 return glID;
3290}
3291
3292//______________________________________________________________________________
3294{
3295 assert(!fPimpl->IsRootWindow(windowID) &&
3296 "CreateOpenGLContext, parameter 'windowID' is a root window");
3297 assert([fPimpl->GetWindow(windowID).fContentView isKindOfClass : [ROOTOpenGLView class]] &&
3298 "CreateOpenGLContext, view is not an OpenGL view");
3299
3300 NSOpenGLContext * const sharedContext = fPimpl->GetGLContextForHandle(sharedID);
3301 ROOTOpenGLView * const glView = (ROOTOpenGLView *)fPimpl->GetWindow(windowID);
3302
3304 newContext([[NSOpenGLContext alloc] initWithFormat : glView.pixelFormat shareContext : sharedContext]);
3305 glView.fOpenGLContext = newContext.Get();
3306 const Handle_t ctxID = fPimpl->RegisterGLContext(newContext.Get());
3307
3308 return ctxID;
3309}
3310
3311//______________________________________________________________________________
3313{
3314 // Creates OpenGL context for window "wid"
3315}
3316
3317//______________________________________________________________________________
3319{
3320 using namespace Details;
3321
3322 assert(ctxID > 0 && "MakeOpenGLContextCurrent, invalid context id");
3323
3324 NSOpenGLContext * const glContext = fPimpl->GetGLContextForHandle(ctxID);
3325 if (!glContext) {
3326 Error("MakeOpenGLContextCurrent", "No OpenGL context found for id %d", int(ctxID));
3327
3328 return kFALSE;
3329 }
3330
3331 ROOTOpenGLView * const glView = (ROOTOpenGLView *)fPimpl->GetWindow(windowID).fContentView;
3332
3333 if (OpenGL::GLViewIsValidDrawable(glView)) {
3334 if ([glContext view] != glView)
3335 [glContext setView : glView];
3336
3337 if (glView.fUpdateContext) {
3338 [glContext update];
3339 glView.fUpdateContext = NO;
3340 }
3341
3342 glView.fOpenGLContext = glContext;
3343 [glContext makeCurrentContext];
3344
3345 return kTRUE;
3346 } else {
3347 //Oh, here's the real black magic.
3348 //Our brilliant GL code is sure that MakeCurrent always succeeds.
3349 //But it does not: if view is not visible, context can not be attached,
3350 //gl operations will fail.
3351 //Funny enough, but if you have invisible window with visible view,
3352 //this trick works.
3353
3354 NSView *fakeView = nil;
3355 QuartzWindow *fakeWindow = fPimpl->GetFakeGLWindow();
3356
3357 if (!fakeWindow) {
3358 //We did not find any window. Create a new one.
3360 //100 - is just a stupid hardcoded value:
3361 const UInt_t width = std::max(glView.frame.size.width, CGFloat(100));
3362 const UInt_t height = std::max(glView.frame.size.height, CGFloat(100));
3363
3364 NSRect viewFrame = {};
3365 viewFrame.size.width = width;
3366 viewFrame.size.height = height;
3367
3368 const NSUInteger styleMask = kTitledWindowMask | kClosableWindowMask |
3370
3371 //NOTE: defer parameter is 'NO', otherwise this trick will not help.
3372 fakeWindow = [[QuartzWindow alloc] initWithContentRect : viewFrame styleMask : styleMask
3373 backing : NSBackingStoreBuffered defer : NO windowAttributes : &attr];
3374 Util::NSScopeGuard<QuartzWindow> winGuard(fakeWindow);
3375
3376 fakeView = fakeWindow.fContentView;
3377 [fakeView setHidden : NO];//!
3378
3379 fPimpl->SetFakeGLWindow(fakeWindow);//Can throw.
3380 winGuard.Release();
3381 } else {
3382 fakeView = fakeWindow.fContentView;
3383 [fakeView setHidden : NO];
3384 }
3385
3386 glView.fOpenGLContext = nil;
3387 [glContext setView : fakeView];
3388 [glContext makeCurrentContext];
3389 }
3390
3391 return kTRUE;
3392}
3393
3394//______________________________________________________________________________
3396{
3397 NSOpenGLContext * const currentContext = [NSOpenGLContext currentContext];
3398 if (!currentContext) {
3399 Error("GetCurrentOpenGLContext", "The current OpenGL context is null");
3400 return kNone;
3401 }
3402
3403 const Handle_t contextID = fPimpl->GetHandleForGLContext(currentContext);
3404 if (!contextID)
3405 Error("GetCurrentOpenGLContext", "The current OpenGL context was"
3406 " not created/registered by TGCocoa");
3407
3408 return contextID;
3409}
3410
3411//______________________________________________________________________________
3413{
3414 assert(ctxID > 0 && "FlushOpenGLBuffer, invalid context id");
3415
3416 NSOpenGLContext * const glContext = fPimpl->GetGLContextForHandle(ctxID);
3417 assert(glContext != nil && "FlushOpenGLBuffer, bad context id");
3418
3419 if (glContext != [NSOpenGLContext currentContext])//???
3420 return;
3421
3422 glFlush();//???
3423 [glContext flushBuffer];
3424}
3425
3426//______________________________________________________________________________
3428{
3429 //Historically, DeleteOpenGLContext was accepting window id,
3430 //now it's a context id. DeleteOpenGLContext is not used in ROOT,
3431 //only in TGLContext for Cocoa.
3432 NSOpenGLContext * const glContext = fPimpl->GetGLContextForHandle(ctxID);
3433 if (NSView * const v = [glContext view]) {
3434 if ([v isKindOfClass : [ROOTOpenGLView class]])
3435 ((ROOTOpenGLView *)v).fOpenGLContext = nil;
3436
3437 [glContext clearDrawable];
3438 }
3439
3440 if (glContext == [NSOpenGLContext currentContext])
3441 [NSOpenGLContext clearCurrentContext];
3442
3443 fPimpl->DeleteGLContext(ctxID);
3444}
3445
3446#pragma mark - Off-screen rendering for TPad/TCanvas.
3447
3448//______________________________________________________________________________
3450{
3451 //In ROOT, canvas has a "double buffer" - pixmap attached to 'wid'.
3452 assert(windowID > (Int_t)fPimpl->GetRootWindowID() && "SetDoubleBuffer called for root window");
3453
3454 if (windowID == 999) {//Comment in TVirtaulX suggests, that 999 means all windows.
3455 Warning("SetDoubleBuffer", "called with wid == 999");
3456 //Window with id 999 can not exists - this is checked in CocoaPrivate.
3457 } else {
3458 fSelectedDrawable = windowID;
3460 }
3461}
3462
3463//______________________________________________________________________________
3465{
3466 fDirectDraw = true;
3467}
3468
3469//______________________________________________________________________________
3471{
3472 //Attach pixmap to the selected window (view).
3473 fDirectDraw = false;
3474
3475 assert(fSelectedDrawable > fPimpl->GetRootWindowID() &&
3476 "SetDoubleBufferON, called, but no correct window was selected before");
3477
3478 NSObject<X11Window> * const window = fPimpl->GetWindow(fSelectedDrawable);
3479
3480 if (!window) return;
3481
3482 assert(window.fIsPixmap == NO &&
3483 "SetDoubleBufferON, selected drawable is a pixmap, can not attach pixmap to pixmap");
3484
3485 const unsigned currW = window.fWidth;
3486 const unsigned currH = window.fHeight;
3487
3488 if (QuartzPixmap *const currentPixmap = window.fBackBuffer) {
3489 if (currH == currentPixmap.fHeight && currW == currentPixmap.fWidth)
3490 return;
3491 }
3492
3493 Util::NSScopeGuard<QuartzPixmap> pixmap([[QuartzPixmap alloc] initWithW : currW
3494 H : currH scaleFactor : [[NSScreen mainScreen] backingScaleFactor]]);
3495 if (pixmap.Get())
3496 window.fBackBuffer = pixmap.Get();
3497 else
3498 //Detailed error message was issued by QuartzPixmap.
3499 Error("SetDoubleBufferON", "QuartzPixmap initialization failed");
3500}
3501
3502//______________________________________________________________________________
3504{
3505 // Sets the drawing mode.
3506 //
3507 //EDrawMode{kCopy, kXor, kInvert};
3508 if (fDrawMode == kInvert && mode != kInvert) {
3509 // Remove previously added CrosshairWindow.
3510 auto windows = NSApplication.sharedApplication.windows;
3511 for (NSWindow *candidate : windows) {
3512 if ([candidate isKindOfClass:QuartzWindow.class])
3513 [(QuartzWindow *)candidate removeXorWindow];
3514 }
3515 fPimpl->fX11CommandBuffer.ClearXOROperations();
3516 }
3517
3518 fDrawMode = mode;
3519}
3520
3521#pragma mark - Event management part.
3522
3523//______________________________________________________________________________
3525{
3526 if (fPimpl->IsRootWindow(wid))//ROOT's GUI can send events to root window.
3527 return;
3528
3529 //From TGX11:
3530 if (!wid || !event)
3531 return;
3532
3533 Event_t newEvent = *event;
3534 newEvent.fWindow = wid;
3535 fPimpl->fX11EventTranslator.fEventQueue.push_back(newEvent);
3536}
3537
3538//______________________________________________________________________________
3540{
3541 assert(fPimpl->fX11EventTranslator.fEventQueue.size() > 0 && "NextEvent, event queue is empty");
3542
3543 event = fPimpl->fX11EventTranslator.fEventQueue.front();
3544 fPimpl->fX11EventTranslator.fEventQueue.pop_front();
3545}
3546
3547//______________________________________________________________________________
3549{
3550 return (Int_t)fPimpl->fX11EventTranslator.fEventQueue.size();
3551}
3552
3553
3554//______________________________________________________________________________
3556{
3557 typedef X11::EventQueue_t::iterator iterator_type;
3558
3559 iterator_type it = fPimpl->fX11EventTranslator.fEventQueue.begin();
3560 iterator_type eIt = fPimpl->fX11EventTranslator.fEventQueue.end();
3561
3562 for (; it != eIt; ++it) {
3563 const Event_t &queuedEvent = *it;
3564 if (queuedEvent.fWindow == windowID && queuedEvent.fType == type) {
3565 event = queuedEvent;
3566 fPimpl->fX11EventTranslator.fEventQueue.erase(it);
3567 return kTRUE;
3568 }
3569 }
3570
3571 return kFALSE;
3572}
3573
3574//______________________________________________________________________________
3576{
3577 //I can not give an access to the native event,
3578 //it even, probably, does not exist already.
3579 return kNone;
3580}
3581
3582#pragma mark - "Drag and drop", "Copy and paste", X11 properties.
3583
3584//______________________________________________________________________________
3585Atom_t TGCocoa::InternAtom(const char *name, Bool_t onlyIfExist)
3586{
3587 //X11 properties emulation.
3588
3589 assert(name != 0 && "InternAtom, parameter 'name' is null");
3590 return FindAtom(name, !onlyIfExist);
3591}
3592
3593//______________________________________________________________________________
3595{
3596 //Comment from TVirtualX:
3597 // Makes the window "wid" the current owner of the primary selection.
3598 // That is the window in which, for example some text is selected.
3599 //End of comment.
3600
3601 //It's not clear, why SetPrimarySelectionOwner and SetSelectionOwner have different return types.
3602
3603 if (!windowID)//From TGWin32.
3604 return;
3605
3606 assert(!fPimpl->IsRootWindow(windowID) &&
3607 "SetPrimarySelectionOwner, windowID parameter is a 'root' window");
3608 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3609 "SetPrimarySelectionOwner, windowID parameter is not a valid window");
3610
3611 const Atom_t primarySelectionAtom = FindAtom("XA_PRIMARY", false);
3612 assert(primarySelectionAtom != kNone &&
3613 "SetPrimarySelectionOwner, predefined XA_PRIMARY atom was not found");
3614
3615 fSelectionOwners[primarySelectionAtom] = windowID;
3616 //No events will be send - I do not have different clients, so nobody to send SelectionClear.
3617}
3618
3619//______________________________________________________________________________
3621{
3622 //Comment from TVirtualX:
3623 // Changes the owner and last-change time for the specified selection.
3624 //End of comment.
3625
3626 //It's not clear, why SetPrimarySelectionOwner and SetSelectionOwner have different return types.
3627
3628 if (!windowID)
3629 return kFALSE;
3630
3631 assert(!fPimpl->IsRootWindow(windowID) &&
3632 "SetSelectionOwner, windowID parameter is a 'root' window'");
3633 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3634 "SetSelectionOwner, windowID parameter is not a valid window");
3635
3636 fSelectionOwners[selection] = windowID;
3637 //No messages, since I do not have different clients.
3638
3639 return kTRUE;
3640}
3641
3642//______________________________________________________________________________
3644{
3645 //Comment from TVirtualX:
3646 // Returns the window id of the current owner of the primary selection.
3647 // That is the window in which, for example some text is selected.
3648 //End of comment.
3649 const Atom_t primarySelectionAtom = FindAtom("XA_PRIMARY", false);
3650 assert(primarySelectionAtom != kNone &&
3651 "GetPrimarySelectionOwner, predefined XA_PRIMARY atom was not found");
3652
3653 return fSelectionOwners[primarySelectionAtom];
3654}
3655
3656//______________________________________________________________________________
3658{
3659 //Comment from TVirtualX:
3660 // Causes a SelectionRequest event to be sent to the current primary
3661 // selection owner. This event specifies the selection property
3662 // (primary selection), the format into which to convert that data before
3663 // storing it (target = XA_STRING), the property in which the owner will
3664 // place the information (sel_property), the window that wants the
3665 // information (id), and the time of the conversion request (when).
3666 // The selection owner responds by sending a SelectionNotify event, which
3667 // confirms the selected atom and type.
3668 //End of comment.
3669
3670 //From TGWin32:
3671 if (!windowID)
3672 return;
3673
3674 assert(!fPimpl->IsRootWindow(windowID) &&
3675 "ConvertPrimarySelection, parameter 'windowID' is root window");
3676 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3677 "ConvertPrimarySelection, parameter windowID parameter is not a window id");
3678
3679 Atom_t primarySelectionAtom = FindAtom("XA_PRIMARY", false);
3680 assert(primarySelectionAtom != kNone &&
3681 "ConvertPrimarySelection, XA_PRIMARY predefined atom not found");
3682
3683 Atom_t stringAtom = FindAtom("XA_STRING", false);
3684 assert(stringAtom != kNone &&
3685 "ConvertPrimarySelection, XA_STRING predefined atom not found");
3686
3687 ConvertSelection(windowID, primarySelectionAtom, stringAtom, clipboard, when);
3688}
3689
3690//______________________________________________________________________________
3692 Atom_t &property, Time_t &/*timeStamp*/)
3693{
3694 // Requests that the specified selection be converted to the specified
3695 // target type.
3696
3697 // Requests that the specified selection be converted to the specified
3698 // target type.
3699
3700 if (!windowID)
3701 return;
3702
3703 assert(!fPimpl->IsRootWindow(windowID) &&
3704 "ConvertSelection, parameter 'windowID' is root window'");
3705 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3706 "ConvertSelection, parameter 'windowID' is not a window id");
3707
3708 Event_t newEvent = {};
3709 selection_iterator selIter = fSelectionOwners.find(selection);
3710
3711 if (selIter != fSelectionOwners.end())
3712 newEvent.fType = kSelectionRequest;
3713 else
3714 newEvent.fType = kSelectionNotify;
3715
3716 newEvent.fWindow = windowID;
3717 newEvent.fUser[0] = windowID;//requestor
3718 newEvent.fUser[1] = selection;
3719 newEvent.fUser[2] = target;
3720 newEvent.fUser[3] = property;
3721
3722 SendEvent(windowID, &newEvent);
3723}
3724
3725//______________________________________________________________________________
3727 Atom_t *actualType, Int_t *actualFormat, ULong_t *nItems,
3728 ULong_t *bytesAfterReturn, unsigned char **propertyReturn)
3729{
3730 //Comment from TVirtualX:
3731 // Returns the actual type of the property; the actual format of the property;
3732 // the number of 8-bit, 16-bit, or 32-bit items transferred; the number of
3733 // bytes remaining to be read in the property; and a pointer to the data
3734 // actually returned.
3735 //End of comment.
3736
3737 if (fPimpl->IsRootWindow(windowID))
3738 return 0;
3739
3740 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3741 "GetProperty, parameter 'windowID' is not a valid window id");
3742 assert(propertyID > 0 && propertyID <= fAtomToName.size() &&
3743 "GetProperty, parameter 'propertyID' is not a valid atom");
3744 assert(actualType != 0 && "GetProperty, parameter 'actualType' is null");
3745 assert(actualFormat != 0 && "GetProperty, parameter 'actualFormat' is null");
3746 assert(bytesAfterReturn != 0 && "GetProperty, parameter 'bytesAfterReturn' is null");
3747 assert(propertyReturn != 0 && "GetProperty, parameter 'propertyReturn' is null");
3748
3749 const Util::AutoreleasePool pool;
3750
3751 *bytesAfterReturn = 0;//In TGWin32 the value set to .. nItems?
3752 *propertyReturn = 0;
3753 *nItems = 0;
3754
3755 const std::string &atomName = fAtomToName[propertyID - 1];
3756 NSObject<X11Window> *window = fPimpl->GetWindow(windowID);
3757
3758 if (![window hasProperty : atomName.c_str()]) {
3759 Error("GetProperty", "Unknown property %s requested", atomName.c_str());
3760 return 0;//actually, 0 is ... Success (X11)?
3761 }
3762
3763 unsigned tmpFormat = 0, tmpElements = 0;
3764 *propertyReturn = [window getProperty : atomName.c_str() returnType : actualType
3765 returnFormat : &tmpFormat nElements : &tmpElements];
3766 *actualFormat = (Int_t)tmpFormat;
3767 *nItems = tmpElements;
3768
3769 return *nItems;//Success (X11) is 0?
3770}
3771
3772//______________________________________________________________________________
3774 Int_t &nChars, Bool_t clearBuffer)
3775{
3776 //Comment from TVirtualX:
3777 // Gets contents of the paste buffer "atom" into the string "text".
3778 // (nchar = number of characters) If "del" is true deletes the paste
3779 // buffer afterwards.
3780 //End of comment.
3781
3782 //From TGX11:
3783 if (!windowID)
3784 return;
3785
3786 assert(!fPimpl->IsRootWindow(windowID) &&
3787 "GetPasteBuffer, parameter 'windowID' is root window");
3788 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3789 "GetPasteBuffer, parameter 'windowID' is not a valid window");
3790 assert(propertyID && propertyID <= fAtomToName.size() &&
3791 "GetPasteBuffer, parameter 'propertyID' is not a valid atom");
3792
3793 const Util::AutoreleasePool pool;
3794
3795 const std::string &atomString = fAtomToName[propertyID - 1];
3796 NSObject<X11Window> *window = fPimpl->GetWindow(windowID);
3797
3798 if (![window hasProperty : atomString.c_str()]) {
3799 Error("GetPasteBuffer", "No property %s on a window", atomString.c_str());
3800 return;
3801 }
3802
3803 Atom_t tmpType = 0;
3804 unsigned tmpFormat = 0, nElements = 0;
3805
3807 propertyData((char *)[window getProperty : atomString.c_str()
3808 returnType : &tmpType returnFormat : &tmpFormat
3809 nElements : &nElements]);
3810
3811 assert(tmpFormat == 8 && "GetPasteBuffer, property has wrong format");
3812
3813 text.Insert(0, propertyData.Get(), nElements);
3814 nChars = (Int_t)nElements;
3815
3816 if (clearBuffer) {
3817 //For the moment - just remove the property
3818 //(anyway, ChangeProperty/ChangeProperties will re-create it).
3819 [window removeProperty : atomString.c_str()];
3820 }
3821}
3822
3823//______________________________________________________________________________
3826{
3827 //Comment from TVirtualX:
3828 // Alters the property for the specified window and causes the X server
3829 // to generate a PropertyNotify event on that window.
3830 //
3831 // wid - the window whose property you want to change
3832 // property - specifies the property name
3833 // type - the type of the property; the X server does not
3834 // interpret the type but simply passes it back to
3835 // an application that might ask about the window
3836 // properties
3837 // data - the property data
3838 // len - the length of the specified data format
3839 //End of comment.
3840
3841 //TGX11 always calls XChangeProperty with PropModeReplace.
3842 //I simply reset the property (or create a new one).
3843
3844 if (!windowID) //From TGWin32.
3845 return;
3846
3847 if (!data || !len) //From TGWin32.
3848 return;
3849
3850 assert(!fPimpl->IsRootWindow(windowID) &&
3851 "ChangeProperty, parameter 'windowID' is root window");
3852 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3853 "ChangeProperty, parameter 'windowID' is not a valid window id");
3854 assert(propertyID && propertyID <= fAtomToName.size() &&
3855 "ChangeProperty, parameter 'propertyID' is not a valid atom");
3856
3857 const Util::AutoreleasePool pool;
3858
3859 const std::string &atomString = fAtomToName[propertyID - 1];
3860
3861 NSObject<X11Window> * const window = fPimpl->GetWindow(windowID);
3862 [window setProperty : atomString.c_str() data : data size : len forType : type format : 8];
3863 //ROOT ignores PropertyNotify events.
3864}
3865
3866//______________________________________________________________________________
3869{
3870 //Comment from TVirtualX:
3871 // Alters the property for the specified window and causes the X server
3872 // to generate a PropertyNotify event on that window.
3873 //End of comment.
3874
3875 //TGX11 always calls XChangeProperty with PropModeReplace.
3876 //I simply reset the property (or create a new one).
3877
3878 if (!windowID)//From TGWin32.
3879 return;
3880
3881 if (!data || !len)//From TGWin32.
3882 return;
3883
3884 assert(!fPimpl->IsRootWindow(windowID) &&
3885 "ChangeProperties, parameter 'windowID' is root window");
3886 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3887 "ChangeProperties, parameter 'windowID' is not a valid window id");
3888 assert(propertyID && propertyID <= fAtomToName.size() &&
3889 "ChangeProperties, parameter 'propertyID' is not a valid atom");
3890
3891 const Util::AutoreleasePool pool;
3892
3893 const std::string &atomName = fAtomToName[propertyID - 1];
3894
3895 NSObject<X11Window> * const window = fPimpl->GetWindow(windowID);
3896 [window setProperty : atomName.c_str() data : data
3897 size : len forType : type format : format];
3898 //No property notify, ROOT does not know about this.
3899}
3900
3901//______________________________________________________________________________
3902void TGCocoa::DeleteProperty(Window_t windowID, Atom_t &propertyID)
3903{
3904 //Comment from TVirtualX:
3905 // Deletes the specified property only if the property was defined on the
3906 // specified window and causes the X server to generate a PropertyNotify
3907 // event on the window unless the property does not exist.
3908 //End of comment.
3909
3910 if (!windowID)//Can this happen?
3911 return;
3912
3913 //Strange signature - why propertyID is a reference?
3914 assert(!fPimpl->IsRootWindow(windowID) &&
3915 "DeleteProperty, parameter 'windowID' is root window");
3916 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3917 "DeleteProperty, parameter 'windowID' is not a valid window");
3918 assert(propertyID && propertyID <= fAtomToName.size() &&
3919 "DeleteProperty, parameter 'propertyID' is not a valid atom");
3920
3921 const std::string &atomString = fAtomToName[propertyID - 1];
3922 [fPimpl->GetWindow(windowID) removeProperty : atomString.c_str()];
3923}
3924
3925//______________________________________________________________________________
3926void TGCocoa::SetDNDAware(Window_t windowID, Atom_t *typeList)
3927{
3928 //Comment from TVirtaulX:
3929 // Add XdndAware property and the list of drag and drop types to the
3930 // Window win.
3931 //End of comment.
3932
3933
3934 //TGX11 first replaces XdndAware property for a windowID, and then appends atoms from a typelist.
3935 //I simply put all data for a property into a vector and set the property (either creating
3936 //a new property or replacing the existing).
3937
3938 assert(windowID > fPimpl->GetRootWindowID() &&
3939 "SetDNDAware, parameter 'windowID' is not a valid window id");
3940 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3941 "SetDNDAware, parameter 'windowID' is not a window");
3942
3943 const Util::AutoreleasePool pool;
3944
3945 QuartzView * const view = (QuartzView *)fPimpl->GetWindow(windowID).fContentView;
3946 NSArray * const supportedTypes = [NSArray arrayWithObjects : NSFilenamesPboardType, nil];//In a pool.
3947
3948 //Do this for Cocoa - to make it possible to drag something to a
3949 //ROOT's window (also this will change cursor shape while dragging).
3950 [view registerForDraggedTypes : supportedTypes];
3951 //Declared property - for convenience, not to check atoms/shmatoms or X11 properties.
3952 view.fIsDNDAware = YES;
3953
3954 FindAtom("XdndAware", true);//Add it, if not yet.
3955 const Atom_t xaAtomAtom = FindAtom("XA_ATOM", false);
3956
3957 assert(xaAtomAtom == 4 && "SetDNDAware, XA_ATOM is not defined");//This is a predefined atom.
3958
3959 //ROOT's GUI uses Atom_t, which is unsigned long, and it's 64-bit.
3960 //While calling XChangeProperty, it passes the address of this typelist
3961 //and format is ... 32. I have to pack data into unsigned and force the size:
3962 assert(sizeof(unsigned) == 4 && "SetDNDAware, sizeof(unsigned) must be 4");
3963
3964 std::vector<unsigned> propertyData;
3965 propertyData.push_back(4);//This '4' is from TGX11 (is it XA_ATOM???)
3966
3967 if (typeList) {
3968 for (unsigned i = 0; typeList[i]; ++i)
3969 propertyData.push_back(unsigned(typeList[i]));//hehe.
3970 }
3971
3972 [view setProperty : "XdndAware" data : (unsigned char *)&propertyData[0]
3973 size : propertyData.size() forType : xaAtomAtom format : 32];
3974}
3975
3976//______________________________________________________________________________
3978{
3979 //Checks if the Window is DND aware. typeList is ignored.
3980
3981 if (windowID <= fPimpl->GetRootWindowID())//kNone or root.
3982 return kFALSE;
3983
3984 assert(fPimpl->GetDrawable(windowID).fIsPixmap == NO &&
3985 "IsDNDAware, windowID parameter is not a window");
3986
3987 QuartzView * const view = (QuartzView *)fPimpl->GetWindow(windowID).fContentView;
3988 return view.fIsDNDAware;
3989}
3990
3991//______________________________________________________________________________
3993{
3994 // Add the list of drag and drop types to the Window win.
3995 //It's never called from GUI.
3996 ::Warning("SetTypeList", "Not implemented");
3997}
3998
3999//______________________________________________________________________________
4000Window_t TGCocoa::FindRWindow(Window_t winID, Window_t dragWinID, Window_t inputWinID, int x, int y, int maxDepth)
4001{
4002 //Comment from TVirtualX:
4003
4004 // Recursively search in the children of Window for a Window which is at
4005 // location x, y and is DND aware, with a maximum depth of maxd.
4006 // Ignore dragwin and input (???)
4007 //End of comment from TVirtualX.
4008
4009
4010 //Now my comments. The name of this function, as usually, says nothing about what it does.
4011 //It's searching for some window, probably child of winID, or may be winID itself(?) and
4012 //window must be DND aware. So the name should be FindDNDAwareWindowRecursively or something like this.
4013
4014 //This function is not documented, comments suck as soon as they are simply wrong - the
4015 //first return statement in X11 version contradicts with comments
4016 //about child. Since X11 version is more readable, I'm reproducing X11 version here,
4017 //and ... my code can't be wrong, since there is nothing right about this function.
4018
4020 fPimpl->IsRootWindow(winID) ? nil : fPimpl->GetWindow(winID).fContentView,
4021 dragWinID, inputWinID, x, y, maxDepth);
4022 if (testView)
4023 return testView.fID;
4024
4025 return kNone;
4026}
4027
4028#pragma mark - Noops.
4029
4030//______________________________________________________________________________
4031UInt_t TGCocoa::ExecCommand(TGWin32Command * /*code*/)
4032{
4033 // Executes the command "code" coming from the other threads (Win32)
4034 return 0;
4035}
4036
4037//______________________________________________________________________________
4039{
4040 // Queries the double buffer value for the window "wid".
4041 return 0;
4042}
4043
4044//______________________________________________________________________________
4046{
4047 // Returns character up vector.
4048 chupx = chupy = 0.f;
4049}
4050
4051//______________________________________________________________________________
4052Pixmap_t TGCocoa::ReadGIF(Int_t /*x0*/, Int_t /*y0*/, const char * /*file*/, Window_t /*id*/)
4053{
4054 // If id is NULL - loads the specified gif file at position [x0,y0] in the
4055 // current window. Otherwise creates pixmap from gif file
4056
4057 return kNone;
4058}
4059
4060//______________________________________________________________________________
4061Int_t TGCocoa::RequestLocator(Int_t /*mode*/, Int_t /*ctyp*/, Int_t &/*x*/, Int_t &/*y*/)
4062{
4063 // Requests Locator position.
4064 // x,y - cursor position at moment of button press (output)
4065 // ctyp - cursor type (input)
4066 // ctyp = 1 tracking cross
4067 // ctyp = 2 cross-hair
4068 // ctyp = 3 rubber circle
4069 // ctyp = 4 rubber band
4070 // ctyp = 5 rubber rectangle
4071 //
4072 // mode - input mode
4073 // mode = 0 request
4074 // mode = 1 sample
4075 //
4076 // The returned value is:
4077 // in request mode:
4078 // 1 = left is pressed
4079 // 2 = middle is pressed
4080 // 3 = right is pressed
4081 // in sample mode:
4082 // 11 = left is released
4083 // 12 = middle is released
4084 // 13 = right is released
4085 // -1 = nothing is pressed or released
4086 // -2 = leave the window
4087 // else = keycode (keyboard is pressed)
4088
4089 return 0;
4090}
4091
4092//______________________________________________________________________________
4093Int_t TGCocoa::RequestString(Int_t /*x*/, Int_t /*y*/, char * /*text*/)
4094{
4095 // Requests string: text is displayed and can be edited with Emacs-like
4096 // keybinding. Returns termination code (0 for ESC, 1 for RETURN)
4097 //
4098 // x,y - position where text is displayed
4099 // text - displayed text (as input), edited text (as output)
4100 return 0;
4101}
4102
4103//______________________________________________________________________________
4104void TGCocoa::SetCharacterUp(Float_t /*chupx*/, Float_t /*chupy*/)
4105{
4106 // Sets character up vector.
4107}
4108
4109//______________________________________________________________________________
4111{
4112 // Turns off the clipping for the window "wid".
4113}
4114
4115//______________________________________________________________________________
4116void TGCocoa::SetClipRegion(Int_t /*wid*/, Int_t /*x*/, Int_t /*y*/, UInt_t /*w*/, UInt_t /*h*/)
4117{
4118 // Sets clipping region for the window "wid".
4119 //
4120 // wid - window indentifier
4121 // x, y - origin of clipping rectangle
4122 // w, h - the clipping rectangle dimensions
4123
4124}
4125
4126//______________________________________________________________________________
4128{
4129 // Sets the current text magnification factor to "mgn"
4130}
4131
4132//______________________________________________________________________________
4133void TGCocoa::Sync(Int_t /*mode*/)
4134{
4135 // Set synchronisation on or off.
4136 // mode : synchronisation on/off
4137 // mode=1 on
4138 // mode<>0 off
4139}
4140
4141//______________________________________________________________________________
4143{
4144 // Sets the pointer position.
4145 // ix - new X coordinate of pointer
4146 // iy - new Y coordinate of pointer
4147 // Coordinates are relative to the origin of the window id
4148 // or to the origin of the current window if id == 0.
4149
4150 if (!winID)
4151 return;
4152
4153 NSPoint newCursorPosition = {};
4154 newCursorPosition.x = ix;
4155 newCursorPosition.y = iy;
4156
4157 if (fPimpl->GetRootWindowID() == winID) {
4158 //Suddenly .... top-left - based!
4159 newCursorPosition.x = X11::GlobalXROOTToCocoa(newCursorPosition.x);
4160 } else {
4161 assert(fPimpl->GetDrawable(winID).fIsPixmap == NO &&
4162 "Warp, drawable is not a window");
4163 newCursorPosition = X11::TranslateToScreen(fPimpl->GetWindow(winID).fContentView,
4164 newCursorPosition);
4165 }
4166
4167 CGWarpMouseCursorPosition(NSPointToCGPoint(newCursorPosition));
4168}
4169
4170//______________________________________________________________________________
4171Int_t TGCocoa::WriteGIF(char * /*name*/)
4172{
4173 // Writes the current window into GIF file.
4174 // Returns 1 in case of success, 0 otherwise.
4175
4176 return 0;
4177}
4178
4179//______________________________________________________________________________
4180void TGCocoa::WritePixmap(Int_t /*wid*/, UInt_t /*w*/, UInt_t /*h*/, char * /*pxname*/)
4181{
4182 // Writes the pixmap "wid" in the bitmap file "pxname".
4183 //
4184 // wid - the pixmap address
4185 // w, h - the width and height of the pixmap.
4186 // pxname - the file name
4187}
4188
4189//______________________________________________________________________________
4191{
4192 // Notify the low level GUI layer ROOT requires "tgwindow" to be
4193 // updated
4194 //
4195 // Returns kTRUE if the notification was desirable and it was sent
4196 //
4197 // At the moment only Qt4 layer needs that
4198 //
4199 // One needs explicitly cast the first parameter to TGWindow to make
4200 // it working in the implementation.
4201 //
4202 // One needs to process the notification to confine
4203 // all paint operations within "expose" / "paint" like low level event
4204 // or equivalent
4205
4206 return kFALSE;
4207}
4208
4209//______________________________________________________________________________
4211 const char * /*filename*/,
4212 Pixmap_t &/*pict*/,
4213 Pixmap_t &/*pict_mask*/,
4214 PictureAttributes_t &/*attr*/)
4215{
4216 // Creates a picture pict from data in file "filename". The picture
4217 // attributes "attr" are used for input and output. Returns kTRUE in
4218 // case of success, kFALSE otherwise. If the mask "pict_mask" does not
4219 // exist it is set to kNone.
4220
4221 return kFALSE;
4222}
4223
4224//______________________________________________________________________________
4226 Pixmap_t &/*pict*/,
4227 Pixmap_t &/*pict_mask*/,
4228 PictureAttributes_t & /*attr*/)
4229{
4230 // Creates a picture pict from data in bitmap format. The picture
4231 // attributes "attr" are used for input and output. Returns kTRUE in
4232 // case of success, kFALSE otherwise. If the mask "pict_mask" does not
4233 // exist it is set to kNone.
4234
4235 return kFALSE;
4236}
4237//______________________________________________________________________________
4238Bool_t TGCocoa::ReadPictureDataFromFile(const char * /*filename*/, char *** /*ret_data*/)
4239{
4240 // Reads picture data from file "filename" and store it in "ret_data".
4241 // Returns kTRUE in case of success, kFALSE otherwise.
4242
4243 return kFALSE;
4244}
4245
4246//______________________________________________________________________________
4247void TGCocoa::DeletePictureData(void * /*data*/)
4248{
4249 // Delete picture data created by the function ReadPictureDataFromFile.
4250}
4251
4252//______________________________________________________________________________
4253void TGCocoa::SetDashes(GContext_t /*gc*/, Int_t /*offset*/, const char * /*dash_list*/, Int_t /*n*/)
4254{
4255 // Sets the dash-offset and dash-list attributes for dashed line styles
4256 // in the specified GC. There must be at least one element in the
4257 // specified dash_list. The initial and alternating elements (second,
4258 // fourth, and so on) of the dash_list are the even dashes, and the
4259 // others are the odd dashes. Each element in the "dash_list" array
4260 // specifies the length (in pixels) of a segment of the pattern.
4261 //
4262 // gc - specifies the GC (see GCValues_t structure)
4263 // offset - the phase of the pattern for the dashed line-style you
4264 // want to set for the specified GC.
4265 // dash_list - the dash-list for the dashed line-style you want to set
4266 // for the specified GC
4267 // n - the number of elements in dash_list
4268 // (see also the GCValues_t structure)
4269}
4270
4271//______________________________________________________________________________
4272void TGCocoa::Bell(Int_t /*percent*/)
4273{
4274 // Sets the sound bell. Percent is loudness from -100% .. 100%.
4275}
4276
4277//______________________________________________________________________________
4279{
4280 // Tells WM to send message when window is closed via WM.
4281}
4282
4283//______________________________________________________________________________
4285 Rectangle_t * /*recs*/, Int_t /*n*/)
4286{
4287 // Sets clipping rectangles in graphics context. [x,y] specify the origin
4288 // of the rectangles. "recs" specifies an array of rectangles that define
4289 // the clipping mask and "n" is the number of rectangles.
4290 // (see also the GCValues_t structure)
4291}
4292
4293//______________________________________________________________________________
4295{
4296 // Creates a new empty region.
4297
4298 return 0;
4299}
4300
4301//______________________________________________________________________________
4303{
4304 // Destroys the region "reg".
4305}
4306
4307//______________________________________________________________________________
4309{
4310 // Updates the destination region from a union of the specified rectangle
4311 // and the specified source region.
4312 //
4313 // rect - specifies the rectangle
4314 // src - specifies the source region to be used
4315 // dest - returns the destination region
4316}
4317
4318//______________________________________________________________________________
4319Region_t TGCocoa::PolygonRegion(Point_t * /*points*/, Int_t /*np*/, Bool_t /*winding*/)
4320{
4321 // Returns a region for the polygon defined by the points array.
4322 //
4323 // points - specifies an array of points
4324 // np - specifies the number of points in the polygon
4325 // winding - specifies the winding-rule is set (kTRUE) or not(kFALSE)
4326
4327 return 0;
4328}
4329
4330//______________________________________________________________________________
4331void TGCocoa::UnionRegion(Region_t /*rega*/, Region_t /*regb*/, Region_t /*result*/)
4332{
4333 // Computes the union of two regions.
4334 //
4335 // rega, regb - specify the two regions with which you want to perform
4336 // the computation
4337 // result - returns the result of the computation
4338
4339}
4340
4341//______________________________________________________________________________
4342void TGCocoa::IntersectRegion(Region_t /*rega*/, Region_t /*regb*/, Region_t /*result*/)
4343{
4344 // Computes the intersection of two regions.
4345 //
4346 // rega, regb - specify the two regions with which you want to perform
4347 // the computation
4348 // result - returns the result of the computation
4349}
4350
4351//______________________________________________________________________________
4352void TGCocoa::SubtractRegion(Region_t /*rega*/, Region_t /*regb*/, Region_t /*result*/)
4353{
4354 // Subtracts regb from rega and stores the results in result.
4355}
4356
4357//______________________________________________________________________________
4358void TGCocoa::XorRegion(Region_t /*rega*/, Region_t /*regb*/, Region_t /*result*/)
4359{
4360 // Calculates the difference between the union and intersection of
4361 // two regions.
4362 //
4363 // rega, regb - specify the two regions with which you want to perform
4364 // the computation
4365 // result - returns the result of the computation
4366
4367}
4368
4369//______________________________________________________________________________
4371{
4372 // Returns kTRUE if the region reg is empty.
4373
4374 return kFALSE;
4375}
4376
4377//______________________________________________________________________________
4379{
4380 // Returns kTRUE if the point [x, y] is contained in the region reg.
4381
4382 return kFALSE;
4383}
4384
4385//______________________________________________________________________________
4387{
4388 // Returns kTRUE if the two regions have the same offset, size, and shape.
4389
4390 return kFALSE;
4391}
4392
4393//______________________________________________________________________________
4395{
4396 // Returns smallest enclosing rectangle.
4397}
4398
4399#pragma mark - Details and aux. functions.
4400
4401//______________________________________________________________________________
4403{
4404 return &fPimpl->fX11EventTranslator;
4405}
4406
4407//______________________________________________________________________________
4409{
4410 return &fPimpl->fX11CommandBuffer;
4411}
4412
4413//______________________________________________________________________________
4415{
4416 ++fCocoaDraw;
4417}
4418
4419//______________________________________________________________________________
4421{
4422 assert(fCocoaDraw > 0 && "CocoaDrawOFF, was already off");
4423 --fCocoaDraw;
4424}
4425
4426//______________________________________________________________________________
4428{
4429 return bool(fCocoaDraw);
4430}
4431
4432//______________________________________________________________________________
4434{
4435 NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(fSelectedDrawable);
4436 if (!drawable.fIsPixmap) {
4437 Error("GetCurrentContext", "TCanvas/TPad's internal error,"
4438 " selected drawable is not a pixmap!");
4439 return 0;
4440 }
4441
4442 return drawable.fContext;
4443}
4444
4445//______________________________________________________________________________
4447{
4448 //We start ROOT in a terminal window, so it's considered as a
4449 //background process. Background process has a lot of problems
4450 //if it tries to create and manage windows.
4451 //So, first time we convert process to foreground, next time
4452 //we make it front.
4453
4454 if (!fForegroundProcess) {
4455 ProcessSerialNumber psn = {0, kCurrentProcess};
4456
4457 const OSStatus res1 = TransformProcessType(&psn, kProcessTransformToForegroundApplication);
4458
4459 //When TGCocoa's functions are called from the python (Apple's system version),
4460 //TransformProcessType fails with paramErr (looks like process is _already_ foreground),
4461 //why is it a paramErr - I've no idea.
4462 if (res1 != noErr && res1 != paramErr) {
4463 Error("MakeProcessForeground", "TransformProcessType failed with code %d", int(res1));
4464 return false;
4465 }
4466#ifdef MAC_OS_X_VERSION_10_9
4467 //Instead of quite transparent Carbon calls we now have another black-box function.
4468 [[NSApplication sharedApplication] activateIgnoringOtherApps : YES];
4469#else
4470 const OSErr res2 = SetFrontProcess(&psn);
4471 if (res2 != noErr) {
4472 Error("MakeProcessForeground", "SetFrontProcess failed with code %d", res2);
4473 return false;
4474 }
4475#endif
4476
4477 fForegroundProcess = true;
4478 } else {
4479#ifdef MAC_OS_X_VERSION_10_9
4480 //Instead of quite transparent Carbon calls we now have another black-box function.
4481 [[NSApplication sharedApplication] activateIgnoringOtherApps : YES];
4482#else
4483 ProcessSerialNumber psn = {};
4484
4485 OSErr res = GetCurrentProcess(&psn);
4486 if (res != noErr) {
4487 Error("MakeProcessForeground", "GetCurrentProcess failed with code %d", res);
4488 return false;
4489 }
4490
4491 res = SetFrontProcess(&psn);
4492 if (res != noErr) {
4493 Error("MapProcessForeground", "SetFrontProcess failed with code %d", res);
4494 return false;
4495 }
4496#endif
4497 }
4498
4499 return true;
4500}
4501
4502//______________________________________________________________________________
4503Atom_t TGCocoa::FindAtom(const std::string &atomName, bool addIfNotFound)
4504{
4505 const std::map<std::string, Atom_t>::const_iterator it = fNameToAtom.find(atomName);
4506
4507 if (it != fNameToAtom.end())
4508 return it->second;
4509 else if (addIfNotFound) {
4510 //Create a new atom.
4511 fAtomToName.push_back(atomName);
4512 fNameToAtom[atomName] = Atom_t(fAtomToName.size());
4513
4514 return Atom_t(fAtomToName.size());
4515 }
4516
4517 return kNone;
4518}
4519
4520//______________________________________________________________________________
4522{
4523 if (gEnv) {
4524 const char * const iconDirectoryPath = gEnv->GetValue("Gui.IconPath",TROOT::GetIconPath());
4525 if (iconDirectoryPath) {
4526 const Util::ScopedArray<char> fileName(gSystem->Which(iconDirectoryPath, "Root6Icon.png", kReadPermission));
4527 if (fileName.Get()) {
4528 const Util::AutoreleasePool pool;
4529 //Aha, ASCII ;) do not install ROOT in ...
4530 NSString *cocoaStr = [NSString stringWithCString : fileName.Get() encoding : NSASCIIStringEncoding];
4531 NSImage *image = [[[NSImage alloc] initWithContentsOfFile : cocoaStr] autorelease];
4532 [NSApp setApplicationIconImage : image];
4533 }
4534 }
4535 }
4536}
Handle_t Atom_t
WM token.
Definition: GuiTypes.h:37
Handle_t Region_t
Region handle.
Definition: GuiTypes.h:32
const Mask_t kGCCapStyle
Definition: GuiTypes.h:292
const Mask_t kGCArcMode
Definition: GuiTypes.h:308
EGEventType
Definition: GuiTypes.h:59
@ kUnmapNotify
Definition: GuiTypes.h:62
@ kSelectionNotify
Definition: GuiTypes.h:63
@ kDestroyNotify
Definition: GuiTypes.h:62
@ kSelectionRequest
Definition: GuiTypes.h:63
const Mask_t kGCDashOffset
Definition: GuiTypes.h:306
const Mask_t kGCBackground
Definition: GuiTypes.h:289
const Mask_t kGCForeground
Definition: GuiTypes.h:288
const Mask_t kGCLineStyle
Definition: GuiTypes.h:291
const Mask_t kGCSubwindowMode
Definition: GuiTypes.h:301
const Mask_t kGCLineWidth
Definition: GuiTypes.h:290
ECursor
Definition: GuiTypes.h:372
@ kPointer
Definition: GuiTypes.h:375
Handle_t Pixmap_t
Pixmap handle.
Definition: GuiTypes.h:30
const Mask_t kGCTile
Definition: GuiTypes.h:296
const Mask_t kGCClipXOrigin
Definition: GuiTypes.h:303
Handle_t FontH_t
Font handle (as opposed to Font_t which is an index)
Definition: GuiTypes.h:35
Handle_t Visual_t
Visual handle.
Definition: GuiTypes.h:28
const Mask_t kGCDashList
Definition: GuiTypes.h:307
const Mask_t kGCFillStyle
Definition: GuiTypes.h:294
Handle_t Window_t
Window handle.
Definition: GuiTypes.h:29
const Mask_t kGCJoinStyle
Definition: GuiTypes.h:293
Handle_t Display_t
Display handle.
Definition: GuiTypes.h:27
const Mask_t kGCFunction
Definition: GuiTypes.h:286
ULong_t Time_t
Event time.
Definition: GuiTypes.h:42
Handle_t GContext_t
Graphics context handle.
Definition: GuiTypes.h:38
EInitialState
Initial window mapping state.
Definition: GuiTypes.h:345
const Mask_t kGCTileStipXOrigin
Definition: GuiTypes.h:298
Handle_t Drawable_t
Drawable handle.
Definition: GuiTypes.h:31
const Mask_t kGCFont
Definition: GuiTypes.h:300
Handle_t Cursor_t
Cursor handle.
Definition: GuiTypes.h:34
const Handle_t kNone
Definition: GuiTypes.h:88
const Mask_t kStructureNotifyMask
Definition: GuiTypes.h:166
@ kIsViewable
Definition: GuiTypes.h:46
@ kFillOpaqueStippled
Definition: GuiTypes.h:51
@ kLineDoubleDash
Definition: GuiTypes.h:48
@ kFillStippled
Definition: GuiTypes.h:51
@ kLineSolid
Definition: GuiTypes.h:48
@ kLineOnOffDash
Definition: GuiTypes.h:48
@ kFillTiled
Definition: GuiTypes.h:51
const Mask_t kGCFillRule
Definition: GuiTypes.h:295
const Mask_t kGCPlaneMask
Definition: GuiTypes.h:287
const Mask_t kGCStipple
Definition: GuiTypes.h:297
const Mask_t kGCGraphicsExposures
Definition: GuiTypes.h:302
const Mask_t kGCClipYOrigin
Definition: GuiTypes.h:304
const Mask_t kGCClipMask
Definition: GuiTypes.h:305
const Mask_t kGCTileStipYOrigin
Definition: GuiTypes.h:299
EMouseButton
Button names.
Definition: GuiTypes.h:214
Handle_t Colormap_t
Colormap handle.
Definition: GuiTypes.h:33
ULongptr_t Handle_t
Generic resource handle.
Definition: GuiTypes.h:26
Handle_t FontStruct_t
Pointer to font structure.
Definition: GuiTypes.h:39
#define c(i)
Definition: RSha256.hxx:101
#define h(i)
Definition: RSha256.hxx:106
#define e(i)
Definition: RSha256.hxx:103
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Definition: RtypesCore.h:45
short Color_t
Definition: RtypesCore.h:92
unsigned char UChar_t
Definition: RtypesCore.h:38
const Bool_t kFALSE
Definition: RtypesCore.h:101
long Long_t
Definition: RtypesCore.h:54
float Float_t
Definition: RtypesCore.h:57
const Bool_t kTRUE
Definition: RtypesCore.h:100
unsigned long ULong_t
Definition: RtypesCore.h:55
#define ClassImp(name)
Definition: Rtypes.h:375
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition: TError.cxx:231
#define gClient
Definition: TGClient.h:157
@ kMWMFuncAll
Definition: TGFrame.h:49
@ kMWMFuncResize
Definition: TGFrame.h:50
@ kMWMDecorMaximize
Definition: TGFrame.h:69
@ kMWMDecorMinimize
Definition: TGFrame.h:68
@ kMWMDecorAll
Definition: TGFrame.h:63
winID h TVirtualViewer3D TVirtualGLPainter p
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 chupy
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 pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void clipboard
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 target
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 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 length
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 value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void chupx
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void foreground
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 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 bitmap
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 funcs
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 grab
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void when
Option_t Option_t width
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 fs
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 gval
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 GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void gc
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t button
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition: TGX11.cxx:110
Binding & operator=(OUT(*fun)(void))
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
#define gROOT
Definition: TROOT.h:404
@ kReadPermission
Definition: TSystem.h:47
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
#define R__LOCKGUARD(mutex)
#define gVirtualX
Definition: TVirtualX.h:338
DerivedType * Get() const
Definition: CocoaUtils.h:136
void Reset(NSObject *object)
Definition: CocoaUtils.h:141
The color creation and management class.
Definition: TColor.h:19
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
This class implements TVirtualX interface for MacOS X, using Cocoa and Quartz 2D.
Definition: TGCocoa.h:58
virtual void SetClipRectangles(GContext_t gc, Int_t x, Int_t y, Rectangle_t *recs, Int_t n)
Sets clipping rectangles in graphics context.
Definition: TGCocoa.mm:4284
virtual const char * DisplayName(const char *)
Returns hostname on which the display is opened.
Definition: TGCocoa.mm:518
virtual void SetRGB(Int_t cindex, Float_t r, Float_t g, Float_t b)
Sets color intensities the specified color index "cindex".
Definition: TGCocoa.mm:2978
virtual void LowerWindow(Window_t wid)
Lowers the specified window "id" to the bottom of the stack so that it does not obscure any sibling w...
Definition: TGCocoa.mm:1239
virtual void FlushOpenGLBuffer(Handle_t ctxID)
Flushes OpenGL buffer.
Definition: TGCocoa.mm:3412
virtual Window_t GetWindowID(Int_t wid)
Returns the X11 window identifier.
Definition: TGCocoa.mm:673
virtual Int_t GetDoubleBuffer(Int_t wid)
Queries the double buffer value for the window "wid".
Definition: TGCocoa.mm:4038
virtual void GetGeometry(Int_t wid, Int_t &x, Int_t &y, UInt_t &w, UInt_t &h)
Returns position and size of window "wid".
Definition: TGCocoa.mm:715
std::vector< GCValues_t > fX11Contexts
Definition: TGCocoa.h:456
virtual void XorRegion(Region_t rega, Region_t regb, Region_t result)
Calculates the difference between the union and intersection of two regions.
Definition: TGCocoa.mm:4358
void DrawLineAux(Drawable_t wid, const GCValues_t &gcVals, Int_t x1, Int_t y1, Int_t x2, Int_t y2)
Definition: TGCocoa.mm:1705
virtual void GetWindowSize(Drawable_t wid, Int_t &x, Int_t &y, UInt_t &w, UInt_t &h)
Returns the location and the size of window "id".
Definition: TGCocoa.mm:1418
TGCocoa()
Definition: TGCocoa.mm:439
virtual Handle_t CreateOpenGLContext(Window_t windowID, Handle_t sharedContext)
Creates OpenGL context for window "windowID".
Definition: TGCocoa.mm:3293
virtual Pixmap_t ReadGIF(Int_t x0, Int_t y0, const char *file, Window_t wid)
If id is NULL - loads the specified gif file at position [x0,y0] in the current window.
Definition: TGCocoa.mm:4052
virtual UInt_t ScreenWidthMM() const
Returns the width of the screen in millimeters.
Definition: TGCocoa.mm:559
void ReparentTopLevel(Window_t wid, Window_t pid, Int_t x, Int_t y)
Definition: TGCocoa.mm:1097
Bool_t IsCocoaDraw() const
Definition: TGCocoa.mm:4427
void SetApplicationIcon()
Definition: TGCocoa.mm:4521
bool fDisplayShapeChanged
Definition: TGCocoa.h:465
virtual Bool_t EqualRegion(Region_t rega, Region_t regb)
Returns kTRUE if the two regions have the same offset, size, and shape.
Definition: TGCocoa.mm:4386
virtual Pixmap_t CreatePixmap(Drawable_t wid, UInt_t w, UInt_t h)
Creates a pixmap of the specified width and height and returns a pixmap ID that identifies it.
Definition: TGCocoa.mm:2435
virtual void ClosePixmap()
Deletes current pixmap.
Definition: TGCocoa.mm:2421
virtual Region_t PolygonRegion(Point_t *points, Int_t np, Bool_t winding)
Returns a region for the polygon defined by the points array.
Definition: TGCocoa.mm:4319
virtual void GetFontProperties(FontStruct_t font, Int_t &max_ascent, Int_t &max_descent)
Returns the font properties.
Definition: TGCocoa.mm:2864
virtual void MapSubwindows(Window_t wid)
Maps all subwindows for the specified window "id" in top-to-bottom stacking order.
Definition: TGCocoa.mm:1157
virtual Pixmap_t CreatePixmapFromData(unsigned char *bits, UInt_t width, UInt_t height)
create pixmap from RGB data.
Definition: TGCocoa.mm:2475
void FillRectangleAux(Drawable_t wid, const GCValues_t &gcVals, Int_t x, Int_t y, UInt_t w, UInt_t h)
Definition: TGCocoa.mm:1897
Atom_t FindAtom(const std::string &atomName, bool addIfNotFound)
Definition: TGCocoa.mm:4503
virtual void SetDoubleBufferON()
Turns double buffer mode on.
Definition: TGCocoa.mm:3470
ROOT::MacOSX::X11::CommandBuffer * GetCommandBuffer() const
Definition: TGCocoa.mm:4408
virtual void SubtractRegion(Region_t rega, Region_t regb, Region_t result)
Subtracts regb from rega and stores the results in result.
Definition: TGCocoa.mm:4352
virtual void GetGCValues(GContext_t gc, GCValues_t &gval)
Returns the components specified by the mask in "gval" for the specified GC "gc" (see also the GCValu...
Definition: TGCocoa.mm:3098
void CopyAreaAux(Drawable_t src, Drawable_t dst, const GCValues_t &gc, Int_t srcX, Int_t srcY, UInt_t width, UInt_t height, Int_t dstX, Int_t dstY)
Definition: TGCocoa.mm:2109
bool fForegroundProcess
Definition: TGCocoa.h:455
virtual void GrabPointer(Window_t wid, UInt_t evmask, Window_t confine, Cursor_t cursor, Bool_t grab=kTRUE, Bool_t owner_events=kTRUE)
Establishes an active pointer grab.
Definition: TGCocoa.mm:2686
void DrawRectangleAux(Drawable_t wid, const GCValues_t &gcVals, Int_t x, Int_t y, UInt_t w, UInt_t h)
Definition: TGCocoa.mm:1828
virtual void GetCharacterUp(Float_t &chupx, Float_t &chupy)
Returns character up vector.
Definition: TGCocoa.mm:4045
virtual void DrawLine(Drawable_t wid, GContext_t gc, Int_t x1, Int_t y1, Int_t x2, Int_t y2)
Uses the components of the specified GC to draw a line between the specified set of points (x1,...
Definition: TGCocoa.mm:1745
virtual FontStruct_t LoadQueryFont(const char *font_name)
Provides the most common way for accessing a font: opens (loads) the specified font and returns a poi...
Definition: TGCocoa.mm:2817
virtual char ** ListFonts(const char *fontname, Int_t max, Int_t &count)
Returns list of font names matching fontname regexp, like "-*-times-*".
Definition: TGCocoa.mm:2890
virtual void CopyPixmap(Int_t wid, Int_t xpos, Int_t ypos)
Copies the pixmap "wid" at the position [xpos,ypos] in the current window.
D