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