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