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