diff --git a/graf2d/cocoa/inc/QuartzWindow.h b/graf2d/cocoa/inc/QuartzWindow.h index 831ad330f45be75d609aefb02620bc7cae8f5ccb..be6e9c1f934094dc93ec53bc41752fb3e2353cb1 100644 --- a/graf2d/cocoa/inc/QuartzWindow.h +++ b/graf2d/cocoa/inc/QuartzWindow.h @@ -245,6 +245,10 @@ NSPoint TranslateToScreen(NSView<X11Window> *from, NSPoint point); NSPoint TranslateFromScreen(NSPoint point, NSView<X11Window> *to); NSPoint TranslateCoordinates(NSView<X11Window> *fromView, NSView<X11Window> *toView, NSPoint sourcePoint); +bool ViewIsTextViewFrame(NSView<X11Window> *view, bool checkParent); +bool LockFocus(NSView<X11Window> *view); +void UnlockFocus(NSView<X11Window> *view);//For symmetry only. + }//X11 }//MacOSX }//ROOT diff --git a/graf2d/cocoa/src/QuartzWindow.mm b/graf2d/cocoa/src/QuartzWindow.mm index 7e3573605642966d1d8d765d77cfc4823d3a742b..83095b433e3bde73ceefeea712b12fa67921b93d 100644 --- a/graf2d/cocoa/src/QuartzWindow.mm +++ b/graf2d/cocoa/src/QuartzWindow.mm @@ -347,6 +347,94 @@ NSPoint GetCursorHotStop(NSImage *image, ECursor cursor) return CGPointMake(imageSize.width / 2, imageSize.height / 2); } +//TGTextView is a very special window: it's a TGCompositeFrame, +//which has TGCompositeFrame inside (TGViewFrame). This TGViewFrame +//delegates Expose events to its parent, and parent tries to draw +//inside a TGViewFrame. This does not work with default +//QuartzView -drawRect/TGCocoa. So I need a trick to identify +//this special window. + +//______________________________________________________________________________ +bool ViewIsTextView(unsigned viewID) +{ + TGWindow *window = gClient->GetWindowById(viewID); + if (!window) + return false; + return window->InheritsFrom("TGTextView"); +} + +//______________________________________________________________________________ +bool ViewIsTextView(NSView<X11Window> *view) +{ + assert(view != nil && "ViewIsTextView, view parameter is nil"); + + return ViewIsTextView(view.fID); +} + +//______________________________________________________________________________ +bool ViewIsTextViewFrame(NSView<X11Window> *view, bool checkParent) +{ + assert(view != nil && "ViewIsTextViewFrame, view parameter is nil"); + + TGWindow *window = gClient->GetWindowById(view.fID); + if (!window) + return false; + + if (!window->InheritsFrom("TGViewFrame")) + return false; + + if (!checkParent) + return true; + + if (!view.fParentView) + return false; + + return ViewIsTextView(view.fParentView); +} + +//______________________________________________________________________________ +NSView<X11Window> *FrameForTextView(NSView<X11Window> *textView) +{ + assert(textView != nil && "FrameForTextView, textView parameter is nil"); + + for (NSView<X11Window> *child in [textView subviews]) { + if (ViewIsTextViewFrame(child, false)) + return child; + } + + return nil; +} + +//______________________________________________________________________________ +bool LockFocus(NSView<X11Window> *view) +{ + assert(view != nil && "LockFocus, view parameter is nil"); + assert([view isKindOfClass : [QuartzView class]] && "LockFocus, QuartzView is expected"); + + if ([view lockFocusIfCanDraw]) { + NSGraphicsContext *nsContext = [NSGraphicsContext currentContext]; + assert(nsContext != nil && "LockFocus, currentContext is nil"); + CGContextRef currContext = (CGContextRef)[nsContext graphicsPort]; + assert(currContext != 0 && "LockFocus, graphicsPort is null");//remove this assert? + + ((QuartzView *)view).fContext = currContext; + + return true; + } + + return false; +} + +//______________________________________________________________________________ +void UnlockFocus(NSView<X11Window> *view) +{ + assert(view != nil && "UnlockFocus, view parameter is nil"); + assert([view isKindOfClass : [QuartzView class]] && "UnlockFocus, QuartzView is expected"); + + [view unlockFocus]; + ((QuartzView *)view).fContext = 0; +} + } } } @@ -1632,10 +1720,15 @@ void print_mask_info(ULong_t mask) //______________________________________________________________________________ - (void) drawRect : (NSRect) dirtyRect { + using namespace ROOT::MacOSX::X11; + (void)dirtyRect; if (fID) { if (TGWindow *window = gClient->GetWindowById(fID)) { + if (ViewIsTextViewFrame(self, true))//It's never painted, parent renders child. true == check the parent also. + return; + NSGraphicsContext *nsContext = [NSGraphicsContext currentContext]; assert(nsContext != nil && "drawRect, currentContext returned nil"); @@ -1651,6 +1744,13 @@ void print_mask_info(ULong_t mask) vx->GetEventTranslator()->GenerateExposeEvent(self, [self visibleRect]); if (fEventMask & kExposureMask) { + if (ViewIsTextView(self)) { + //Send Expose event, using child view (this is how it's done in GUI :( ). + NSView<X11Window> *viewFrame = FrameForTextView(self); + if (viewFrame) + vx->GetEventTranslator()->GenerateExposeEvent(viewFrame, [viewFrame visibleRect]);//Now we set fExposedRegion for TGView. + } + //Ask ROOT's widget/window to draw itself. gClient->NeedRedraw(window, kTRUE); diff --git a/graf2d/cocoa/src/TGCocoa.mm b/graf2d/cocoa/src/TGCocoa.mm index 5fdada601bb81eed8486936ea6d49a3b783c6f28..fd549abfe9425a6d59c419e3e2e2915dc656f467 100644 --- a/graf2d/cocoa/src/TGCocoa.mm +++ b/graf2d/cocoa/src/TGCocoa.mm @@ -230,6 +230,17 @@ void SetFillPattern(CGContextRef ctx, const PatternContext *patternContext) CGContextSetPatternPhase(ctx, patternContext->fPhase); } +//______________________________________________________________________________ +bool ParentRendersToChild(NSView<X11Window> *child) +{ + assert(child != nil && "ParentRendersToChild, child parameter is nil"); + + //Adovo poluchaetsia, tashhem-ta! ;) + return X11::ViewIsTextViewFrame(child, true) && !child.fContext && + child.fMapState == kIsViewable && child.fParentView.fContext && + !child.fIsOverlapped; +} + } //______________________________________________________________________________ @@ -1173,6 +1184,15 @@ void TGCocoa::DrawLine(Drawable_t wid, GContext_t gc, Int_t x1, Int_t y1, Int_t if (!drawable.fIsPixmap) { NSObject<X11Window> *window = (NSObject<X11Window> *)drawable; QuartzView *view = (QuartzView *)window.fContentView; + + if (ParentRendersToChild(view)) { + if (X11::LockFocus(view)) { + DrawLineAux(view.fID, gcVals, x1, y1, x2, y2); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddDrawLine(wid, gcVals, x1, y1, x2, y2); @@ -1216,6 +1236,15 @@ void TGCocoa::DrawSegments(Drawable_t wid, GContext_t gc, Segment_t *segments, I if (!drawable.fIsPixmap) { QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView; + + if (ParentRendersToChild(view)) { + if (X11::LockFocus(view)) { + DrawSegmentsAux(view.fID, gcVals, segments, nSegments); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddDrawSegments(wid, gcVals, segments, nSegments); @@ -1274,6 +1303,15 @@ void TGCocoa::DrawRectangle(Drawable_t wid, GContext_t gc, Int_t x, Int_t y, UIn if (!drawable.fIsPixmap) { NSObject<X11Window> *window = (NSObject<X11Window> *)drawable; QuartzView *view = (QuartzView *)window.fContentView; + + if (ParentRendersToChild(view)) { + if (X11::LockFocus(view)) { + DrawRectangleAux(view.fID, gcVals, x, y, w, h); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddDrawRectangle(wid, gcVals, x, y, w, h); @@ -1344,6 +1382,15 @@ void TGCocoa::FillRectangle(Drawable_t wid, GContext_t gc, Int_t x, Int_t y, UIn if (!drawable.fIsPixmap) { NSObject<X11Window> *window = (NSObject<X11Window> *)drawable; QuartzView *view = (QuartzView *)window.fContentView; + + if (ParentRendersToChild(view)) { + if (X11::LockFocus(view)) { + FillRectangleAux(view.fID, gcVals, x, y, w, h); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddFillRectangle(wid, gcVals, x, y, w, h); @@ -1429,6 +1476,15 @@ void TGCocoa::FillPolygon(Window_t wid, GContext_t gc, Point_t *polygon, Int_t n if (!drawable.fIsPixmap) { QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView; + + if (ParentRendersToChild(view)) { + if (X11::LockFocus(view)) { + FillPolygonAux(view.fID, gcVals, polygon, nPoints); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddFillPolygon(wid, gcVals, polygon, nPoints); @@ -1500,6 +1556,15 @@ void TGCocoa::CopyArea(Drawable_t src, Drawable_t dst, GContext_t gc, Int_t srcX if (!drawable.fIsPixmap) { QuartzView *view = (QuartzView *)fPimpl->GetWindow(dst).fContentView; + + if (ParentRendersToChild(view)) { + if (X11::LockFocus(view)) { + CopyAreaAux(src, dst, gcVals, srcX, srcY, width, height, dstX, dstY); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddCopyArea(src, dst, gcVals, srcX, srcY, width, height, dstX, dstY); @@ -1557,7 +1622,6 @@ void TGCocoa::DrawStringAux(Drawable_t wid, const GCValues_t &gcVals, Int_t x, I void TGCocoa::DrawString(Drawable_t wid, GContext_t gc, Int_t x, Int_t y, const char *text, Int_t len) { //Can be called by ROOT directly, or indirectly by AppKit. - if (!wid)//from TGX11. return; @@ -1568,14 +1632,24 @@ void TGCocoa::DrawString(Drawable_t wid, GContext_t gc, Int_t x, Int_t y, const const GCValues_t &gcVals = fX11Contexts[gc - 1]; assert(gcVals.fMask & kGCFont && "DrawString, font is not set in a context"); - if (!drawable.fIsPixmap) { + if (!drawable.fIsPixmap) { QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView; + + if (ParentRendersToChild(view)) {//Ufff. + if (X11::LockFocus(view)) { + DrawStringAux(view.fID, gcVals, x, y, text, len); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddDrawString(wid, gcVals, x, y, text, len); else DrawStringAux(wid, gcVals, x, y, text, len); } + } else { if (!IsCocoaDraw()) fPimpl->fX11CommandBuffer.AddDrawString(wid, gcVals, x, y, text, len); @@ -1618,6 +1692,15 @@ void TGCocoa::ClearArea(Window_t wid, Int_t x, Int_t y, UInt_t w, UInt_t h) assert(!fPimpl->IsRootWindow(wid) && "ClearArea, called for the 'root' window"); QuartzView *view = (QuartzView *)fPimpl->GetWindow(wid).fContentView;//If wid is pixmap or image, this will crush. + + if (ParentRendersToChild(view)) { + if (X11::LockFocus(view)) { + ClearAreaAux(view.fID, x, y, w, h); + X11::UnlockFocus(view); + return; + } + } + if (!view.fIsOverlapped && view.fMapState == kIsViewable) { if (!view.fContext) fPimpl->fX11CommandBuffer.AddClearArea(wid, x, y, w, h); diff --git a/gui/gui/src/TGView.cxx b/gui/gui/src/TGView.cxx index 271df1d33cc397f662b043122f40b829d501186b..a43ed6ee07c5ee841c5f92f1040042abe656dbde 100644 --- a/gui/gui/src/TGView.cxx +++ b/gui/gui/src/TGView.cxx @@ -42,6 +42,8 @@ // // ////////////////////////////////////////////////////////////////////////// +#include <iostream> + #include "TGView.h" #include "TGScrollBar.h" #include "TGResourcePool.h"