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