Yosemite and OverlayMBS: fadetransition can't capture vibrancy

I’m using code from an example project of MBS plugins:
/Examples/MacOSX/Self made Window Fade Transition.xojo_binary_project

It worked fine on Mavericks but on Yosemite it can’t capture vibrancy. It makes use of a screenshot which lacks transparency, or is not able to capture the first window as it is seen on the screen. This somehow destroys the smooth fading to a new window.

I wonder if there is something I could do in order to keep the overlay fade transition effect also on Yosemite?

To illustrate what I mean, I put a screencast up here:
http://osswald.com/xojo/mbs/overlay/

I think the problem comes from this line of code:

pic=w.ScreenshotWindowMBS

It looks like it cannot capture the Window as it is actually seen on screen:

First a correct screenshot:

This is the sceenshot done by ScreenshotWindowMBS:

It looks like the screencast link above gets blocked once in a while, here an alternative link :
http://www.seminar.pro/xojo/mbs/overlay/

well, ScreenshotWindowMBS reads the window back buffer. Maybe transparency is added later?

Did you try ScreenshotRectMBS instead?

When I create a screenshot using the Window.DrawInto method, then at least the colors are not as awkward as when using ScreenshotWindowMBS. But the vibrancy still gets lost.

Is there a way to make a screenshot of a “vibrancy” Window on Yosemite, which is actually able to capture what is seen on screen?

[quote=147900:@Christian Schmitz]well, ScreenshotWindowMBS reads the window back buffer. Maybe transparency is added later?
Did you try ScreenshotRectMBS instead?[/quote]

I’ll give it a try.

@Oliver: Your App looks great. Have you made your Toolbar with MBS?

THanks Tomas! Yes, with MBS. The plugins come with an example project for this: Toolbar buttons.xojo_binary_project

It looks like this would do the trick to capture what is seen on screen.

However, on a retina screen it does not autoscale and it comes back to big. I will try to manually scale it myself, then it will probably do what I want.

Christian: Do you have a method to do fast scaling, or can I scale as usual?

what you get is a 144 dpi image and that should not be scaled. Simply draw it with half the size destination rectangle.

I’m struggling with this and I’m not getting it straight on a retina screen. ScreenShotRectMBS does produce a picture as it is seen on a Yosemite screen, but then I have difficulties to get the right size on a Retina screen.

This slightly changed code from the examples (“Self made Window Fade Transition”) does work on standard screens, but not on retina:

[code]Sub Constructor(w as window)
mode=0

if w=nil then Return

win=w

'pic=w.ScreenshotWindowMBS
pic=ScreenshotRectMBS(w.Left,w.Top,w.Width,w.Height) // <<== Use this to capture on Yosemite

if pic=nil then Return

dim mask as Picture

mask=NewPicture(pic.Width,pic.Height,32)
if mask=nil then Return

dim g as Graphics

g=mask.graphics // mask must be black
g.forecolor=&c000000
g.fillrect 0,0,g.width,g.height

CGImage=CGCreateImageMBS(pic,mask)

Overlay=new FadeTransitionWindow
if 0=Overlay.Create(w.left,w.Top,w.Width,w.Height) then
dim c as CGContextMBS

Overlay.IgnoreClicks=true
Overlay.Show

c=Overlay.Context
c.DrawPicture(CGImage,CGMakeRectMBS(0,0,CGImage.Width,CGImage.Height))
c.Flush

else
// cancel
Overlay=nil
CGImage=nil
mask=nil
win=nil
end if

Exception

End Sub
[/code]

So where would I “draw it with half the size destination rectangle” to make it work?

c.DrawPicture(CGImage,CGMakeRectMBS(0,0,CGImage.Width,CGImage.Height))

you draw here with size of image, but you should draw with size of destination graphics port.

[quote=147963:@Christian Schmitz]c.DrawPicture(CGImage,CGMakeRectMBS(0,0,CGImage.Width,CGImage.Height))
you draw here with size of image, but you should draw with size of destination graphics port.[/quote]

Yes, I tried to make changes here before, but it does not work as expected on retina. My problem is that I am not familiar with CoreGraphics, so I do not really understand what you are doing in this example code.

I run your example “Self made Window Fade Transition.xojo_binary_project” with NSHighResolutionCapable set to YES and then it shows the same size problem.

I think I would need an example which works on retina, to understand on how to use CGContextMBS

Okay so the answer seems like a big fat nope, Apple own screen capture cmd-shift 4, then space bar doesn’t capture it and some code NS functions I use elsewhere don’t either.

You may have to do the fade another way.

[quote=147996:@Sam Rowlands]Okay so the answer seems like a big fat nope, Apple own screen capture cmd-shift 4, then space bar doesn’t capture it and some code NS functions I use elsewhere don’t either.

You may have to do the fade another way.[/quote]

Actually, when you do the Cmd+Shift+4 and then you capture a rectangle area around the window, then it captures vibrancy of a window. This is similar to what ScreenshotRectMBS(w.Left,w.Top,w.Width,w.Height) in the above code is doing.

The problem comes on Retina: I just haven’t figured out yet how to adjust the above example code in order to get a correctly scaled image at the beginning of the fade.

Pressing the space bar to capture the contents of the window (as opposed to the screen buffer) doesn’t capture transparency.

The following code will grab the control buffer and return a CGImageRef, although it creates a NSBitmapImageRep first. For our animation we use this function a lot and it returns a Retina image, however in my tests with Yosemite, I couldn’t get it to capture the background (although it capture translucency).

[code]Function CGImage(extends c as rectControl) As Ptr
#if TargetCocoa then
declare function bitmapImageRepForCachingDisplayInRect lib AppKit selector “bitmapImageRepForCachingDisplayInRect:” ( NSViewHandle as integer, rect as NSRect ) as Ptr
declare function bounds lib appKit selector “bounds” ( NSViewHandle as integer ) as NSRect

dim NSBitmapImageRep as Ptr = bitMapImageRepForCachingDisplayInRect( c.handle, bounds( c.handle ) )

if NSBitmapImageRep <> nil then
  declare sub cacheDisplayInRecttoBitmapImageRep lib AppKit selector "cacheDisplayInRect:toBitmapImageRep:" ( NSViewHandle as integer, rect as NSRect, bitmapImageRep as Ptr )
  cachedIsplayInRecttoBitmapImageRep( c.handle, bounds( c.handle ), NSBitmapImageRep )
  
  declare function CGImage lib AppKit selector "CGImage" ( NSBitmapImageRep as Ptr ) as Ptr
  return CGImage( NSBitmapImageRep )
  
else
  break
end if

#endif
End Function
[/code]