JuliaGraphics / Tk.jl

Julia interface to Tk windowing toolkit.
Other
53 stars 42 forks source link

Flipped / garbled display elements on OS X 10.8.3 #30

Closed rsrock closed 11 years ago

rsrock commented 11 years ago

I'm opening this issue to follow up on this discussion: Mac 0.2-pre binaries with graphics

and the possibly related issues I've had with Tim's ImageView package: https://github.com/timholy/ImageView.jl/issues/2

I've followed the first half of Tim's suggestion, and run the First real example from TkDocs in wish. It works as expected, even when resizing the window. That's true for both wish installed by Homebrew, and the wish found in my .julia/Tk/deps/usr/bin (installed from source thru Pkg.add). I have not tried to implement the example in julia yet.

As an aside, it looks like there are copies of Tcl/Tk all over the place on my system. which wish gives me /Applications/ccp4-6.3.0/bin/wish, and points to a Tcl/Tk ver 8.4.x that is linked to X11. CCP4 is an xray crystallography package that seems to like taking over the front of my path. Also, the default install of R will put it's own Tcl/Tk in /usr/local. I imagine that this may complicate debugging.

gregzuro commented 11 years ago

I haven't gotten as far as you with the examples (a simple jpg gets garbled on window resize).

I have three Tks on my system: XCode's 8.4 and 8.5 as well as homebrew's 8.6.

All the demos in all the wish versions run fine.

Winston works fine but for an occasional flip on display that corrects upon window resize.

ImageView is also throwing Bounds errors. Have you seen that?

gregzuro commented 11 years ago

I see that the latest Tk package is trying to force the use of 8.6. How can I confirm that this is happening?

staticfloat commented 11 years ago

While julia is open, try running lsof -p $(pgrep julia) and see what Tk libraries it's picking up.

gregzuro commented 11 years ago

Is this even helpful (just after doing display() with ImageView package)?

gz21:~ gregz$ lsof -p $(pgrep julia) | grep tk

julia-rel 34047 gregz  txt      REG                1,1     10136 5268606
/Applications/Julia.app/Contents/Resources/julia/lib/libtk_wrapper.dylib

julia-rel 34047 gregz  txt      REG                1,1   2624220 5268605
/Applications/Julia.app/Contents/Resources/julia/lib/libtk8.6.dylib
gz21:~ gregz$ lsof -p $(pgrep julia) | grep tcl

julia-rel 34047 gregz  txt      REG                1,1   2754640 5268604
/Applications/Julia.app/Contents/Resources/julia/lib/libtcl8.6.dylib
gz21:~ gregz$ lsof -p $(pgrep julia) | grep cairo

julia-rel 34047 gregz  txt      REG                1,1    111524 5268597
/Applications/Julia.app/Contents/Resources/julia/lib/libpangocairo-1.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1   1233312 5268565
/Applications/Julia.app/Contents/Resources/julia/lib/libcairo.2.dylib
gz21:~ gregz$ lsof -p $(pgrep julia) | grep Car

julia-rel 34047 gregz  txt      REG                1,1   5425538   23372
/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Resources/Extras2.rsrc

julia-rel 34047 gregz   18r     REG                1,1   5425538   23372
/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Resources/Extras2.rsrc

also:

gz21:~ gregz$ lsof -p $(pgrep julia) | grep libg

julia-rel 34047 gregz  txt      REG                1,1      9264 5268591
/Applications/Julia.app/Contents/Resources/julia/lib/libgthread-2.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1   1523008 5268536
/Applications/Julia.app/Contents/Resources/julia/lib/julia/libgfortran.3.dylib

julia-rel 34047 gregz  txt      REG                1,1    268944 5268535
/Applications/Julia.app/Contents/Resources/julia/lib/julia/libgcc_s.1.dylib

julia-rel 34047 gregz  txt      REG                1,1     16640 5268587
/Applications/Julia.app/Contents/Resources/julia/lib/libgmodule-2.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1    416480 5268589
/Applications/Julia.app/Contents/Resources/julia/lib/libgobject-2.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1     35512 5268539
/Applications/Julia.app/Contents/Resources/julia/lib/julia/libgrisu.dylib

julia-rel 34047 gregz  txt      REG                1,1   1454040 5268585
/Applications/Julia.app/Contents/Resources/julia/lib/libglib-2.0.0.dylib

On Wed, May 29, 2013 at 12:27 PM, Elliot Saba notifications@github.comwrote:

While julia is open, try running lsof -p $(pgrep julia) and see what Tk libraries it's picking up.

— Reply to this email directly or view it on GitHubhttps://github.com/JuliaLang/Tk.jl/issues/30#issuecomment-18640167 .

staticfloat commented 11 years ago

Your output is a little hard to read in this format. Try putting code tags around it by surrounding your output with triple-backticks. It looks like you're picking up the libtk inside of the Julia.app, which is great, so I'd say you are getting the proper library versions.

Keno commented 11 years ago

I tried fixing it in your comment, but I can't get it to show up right, so here:

gz21:~ gregz$ lsof -p $(pgrep julia) | grep tk

julia-rel 34047 gregz  txt      REG                1,1     10136 5268606
/Applications/Julia.app/Contents/Resources/julia/lib/libtk_wrapper.dylib

julia-rel 34047 gregz  txt      REG                1,1   2624220 5268605
/Applications/Julia.app/Contents/Resources/julia/lib/libtk8.6.dylib
gz21:~ gregz$ lsof -p $(pgrep julia) | grep tcl

julia-rel 34047 gregz  txt      REG                1,1   2754640 5268604
/Applications/Julia.app/Contents/Resources/julia/lib/libtcl8.6.dylib
gz21:~ gregz$ lsof -p $(pgrep julia) | grep cairo

julia-rel 34047 gregz  txt      REG                1,1    111524 5268597
/Applications/Julia.app/Contents/Resources/julia/lib/libpangocairo-1.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1   1233312 5268565
/Applications/Julia.app/Contents/Resources/julia/lib/libcairo.2.dylib
gz21:~ gregz$ lsof -p $(pgrep julia) | grep Car

julia-rel 34047 gregz  txt      REG                1,1   5425538   23372
/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Resources/Extras2.rsrc

julia-rel 34047 gregz   18r     REG                1,1   5425538   23372
/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Resources/Extras2.rsrc

also:

gz21:~ gregz$ lsof -p $(pgrep julia) | grep libg

julia-rel 34047 gregz  txt      REG                1,1      9264 5268591
/Applications/Julia.app/Contents/Resources/julia/lib/libgthread-2.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1   1523008 5268536
/Applications/Julia.app/Contents/Resources/julia/lib/julia/libgfortran.3.dylib

julia-rel 34047 gregz  txt      REG                1,1    268944 5268535
/Applications/Julia.app/Contents/Resources/julia/lib/julia/libgcc_s.1.dylib

julia-rel 34047 gregz  txt      REG                1,1     16640 5268587
/Applications/Julia.app/Contents/Resources/julia/lib/libgmodule-2.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1    416480 5268589
/Applications/Julia.app/Contents/Resources/julia/lib/libgobject-2.0.0.dylib

julia-rel 34047 gregz  txt      REG                1,1     35512 5268539
/Applications/Julia.app/Contents/Resources/julia/lib/julia/libgrisu.dylib

julia-rel 34047 gregz  txt      REG                1,1   1454040 5268585
/Applications/Julia.app/Contents/Resources/julia/lib/libglib-2.0.0.dylib
gregzuro commented 11 years ago

Backticks didn't work here... How did you do it?

On Wed, May 29, 2013 at 12:50 PM, Keno Fischer notifications@github.comwrote:

I tried fixing it in your comment, but I can't get it to show up right, so here:

gz21:~ gregz$ lsof -p $(pgrep julia) | grep tk

julia-rel 34047 gregz txt REG 1,1 10136 5268606 /Applications/Julia.app/Contents/Resources/j

Keno commented 11 years ago

Backticks. I originally tried to fixup your comment, but I couldn't get it to work either. Must be some kind of GitHub bug.

staticfloat commented 11 years ago

If you are replying via Email, github disables markdown. It's really annoying, and even editing your comment via the Github interface doesn't allow it to interpret the markdown. >:|

gregzuro commented 11 years ago

Okay. I'm not sooo crazy, then. Thanks,

rsrock commented 11 years ago

I get the following, which looks correct for the BinDeps install from source.

○ lsof -p $(pgrep julia) | grep tk                                                                                                                                                                              
julia-rel 66213 rrock  txt      REG                1,4     10136 9210092 /Users/rrock/.julia/Tk/deps/usr/lib/libtk_wrapper.dylib
julia-rel 66213 rrock  txt      REG                1,4   2624220 9209439 /Users/rrock/.julia/Tk/deps/usr/lib/libtk8.6.dylib
rsrock commented 11 years ago

I may have found something, but I'm not sure if it's related to this problem. I've started to work on some of the test code in this package to see how julia on the Mac handles it. Most of the code blocks generate the expected windows that resize just fine. The first problem occurs in the ## checkbox block at line 133. Resizing this window gives me the typical leftover image glitches like this (Described here):

munged-window

This minimal code has the problem:

w = Toplevel("Checkbutton")
check = Checkbutton(w, "check me"); pack(check)

And this code borrowed from the earlier sections cures the problem:

w = Toplevel("Checkbutton")
f = Frame(w); pack(f, expand=true, fill="both")
check = Checkbutton(f, "check me"); pack(check)

So it seems important to put everything in a Frame (or a Frame-like object, like a Notebook).

If you want to run the tests yourself, don't forget to remove the destroy(w) lines.

timholy commented 11 years ago

However, those glitches (and the fix) are not Mac-specific; I get them on Linux too.

ViralBShah commented 11 years ago

Flipping issue same as nolta/Winston.jl#55.

rsrock commented 11 years ago

To deal with the flipping issue, Tim suggested here (#36) that we should play with the lines around

CGContextScaleCTM (context, 1.0, -1.0);

towards the end of deps/tk_wrapper.c. Here's what I found:

CGContextTranslateCTM (context, 0.0, height);
CGContextScaleCTM (context, 1.0, -1.0);

The original. using Winston; plot(1:10) gives an upside down plot, that flips rightside up when the window is resized. Resizing can cause the window to flip and nuke parts of the titlebar as well.

CGContextTranslateCTM (context, 0.0, height);
CGContextScaleCTM (context, 1.0, 1.0);

A mess, a white window that completely nukes the titlebar and refuses to show the plot.

//CGContextTranslateCTM (context, 0.0, height);
CGContextScaleCTM (context, 1.0, 1.0);

A persistent upside down plot, but the resizing is smooth with no title bar problems that I could see.

//CGContextTranslateCTM (context, 0.0, height);
//CGContextScaleCTM (context, 1.0, 1.0);

Same as the last test.

FYI, I'm using homebrewed Tk (brew install tcl-tk, see #33). The only thing found in my .julia/Tk/deps is the tk_wrapper.

Note: I found it easiest to rm -rf my .julia/Tk/deps/usr before running Pkg.runbuildscript("Tk"). Otherwise, BinDeps doesn't rebuild the wrapper.

timholy commented 11 years ago

That was useful. Combined with some experiments by @jverzani and the comments in tk_wrapper.c, I'm (exceedingly slowly) becoming aware that the problem seems to be that OSX is changing something out from under you in between draws.

It's far from ideal as a fix, but what if one goes back to the original tk_wrapper.c and then in src/tkwidget.jl change getgc to:

function getgc(c::Canvas)
    wait_initialized(c)
    @osx_only begin
        c.initialized = false
        configure(c)
        c.initialized = true
    end
    c.backcc
end
ViralBShah commented 11 years ago

This kinda works. Now there is a flicker with the upside down plot, but it gets corrected after the flicker. However, upon resizing, it flickers, and ends up with upside down plots.

ViralBShah commented 11 years ago

Seems that only the first time getgc call for a plot window needs to do the extra configure step.

ViralBShah commented 11 years ago

After updating to the latest master, the flicker is no longer there with @timholy 's suggestion, but the resized plot is still upside down.

rsrock commented 11 years ago

Still only barely understanding this info.

It looks like if CGContextScaleCTM(context, 1.0, -1.0) is called multiple times, then the axes will be re-flipped. So if we call it an even number of times, we get the upside-down plots, but with an odd number of calls, we get rightside up. (However, I'm not sure if this applies to calls for a window, or a session...)

I'm trying to trace the calls, but probably someone else will understand this better. It looks like the tk_wrapper library (which contains CGContextScaleCTM(context, 1.0, -1.0)) is only called from cairo_surface_for(c.c) (aside: can that get a better field name than c?), which is only called from configure(c::Canvas). This is where I start to lose track, but configure() is called from init_canvas(c::Canvas) and also add_canvas_callbacks(c::Canvas). This is not counting Tim's suggested change a few hours ago.

I'm guessing the callback is the problem, because it could be triggered any number of times. Commenting it out leaves a plot that doesn't resize, however.

rsrock commented 11 years ago

Wait a minute, this is closer.

If I replace init_canvas with this:

function init_canvas(c::Canvas)
    c.initialized = true
    configure(c)
    @osx_only begin
        c.initialized = false
        configure(c)
        c.initialized = true
    end
    c
end

I get plots that are initially upside down, but then flip rightside up when I click the title bar. Resizing works. If I replot into the same window, it is upside down, but flips when I resize.

I still think the real problem is the callback, however.

jverzani commented 11 years ago

Not sure this is pertinent, but If I recall (and I can't check now) when I was trying things like this, one issue is the event gets called twice when the initial figure is drawn for the mac, and only once for linux. I tried to queue up these calls to Tk.configure so it was only called once, but had no luck with that approach.

This change to init_canvas should call Tk.configure 4 times: twice on the Map event and 1 time each for the configure events. The clicking on the title bar should be addressable by calling Tk.update() when all is done being drawn.

On Tue, Jun 18, 2013 at 3:25 PM, Ron Rock notifications@github.com wrote:

Wait a minute, this is closer.

If I replace init_canvas with this:

function init_canvas(c::Canvas) c.initialized = true configure(c) @osx_only begin c.initialized = false configure(c) c.initialized = true end c end

I get plots that are initially upside down, but then flip rightside up when I click the title bar. Resizing works. If I replot into the same window, it is upside down, but flips when I resize.

— Reply to this email directly or view it on GitHubhttps://github.com/JuliaLang/Tk.jl/issues/30#issuecomment-19634681 .

John Verzani Chair, Department of Mathematics College of Staten Island, CUNY verzani@math.csi.cuny.edu

ViralBShah commented 11 years ago

What if we add state to the wrapper so that the scaling is only done once per canvas? I believe we get a new canvas on every resize.

rsrock commented 11 years ago

Funny, I just tried something like that. I wrote a separate tk_wrapper function just for scaling only within init_canvas. Graph is upside down, rightside up after I click the titlebar, then upside down after resize...

rsrock commented 11 years ago

For posterity, here's what gets called when plotting in Winston. The first block is right after the plot. The second block is after a resize (two repeats shown out of many).


               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "help()" to list help topics
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.2.0-2085.r9f680b79
 _/ |\__'_|_|_|\__'_|  |  Commit 9f680b791e 2013-06-18 11:52:16
|__/                   |  x86_64-apple-darwin12.4.0

julia> using Winston

julia> plot(1:10)
MESSAGE: draw
MESSAGE: getgc
MESSAGE: configure
MESSAGE: init_canvas
MESSAGE: configure
MESSAGE: configure: destroy
MESSAGE: configure: initialized
MESSAGE: draw
MESSAGE: getgc
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: draw
MESSAGE: getgc
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
<plot>

julia> MESSAGE: configure
MESSAGE: configure: destroy
MESSAGE: configure: initialized
MESSAGE: draw
MESSAGE: getgc
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: configure
MESSAGE: configure: destroy
MESSAGE: configure: initialized
MESSAGE: draw
MESSAGE: getgc
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
MESSAGE: reveal
MESSAGE: cairo_surface
ViralBShah commented 11 years ago

Thanks all! Now only one case remains. If I do a plot, and then without closing the window, do another plot, the new plot is upside down in the old window. Resizing makes it right side up. I believe there is one more code path that needs to fix the axes.

timholy commented 11 years ago

Congratulations!

timholy commented 11 years ago

I'm sure you know this already, but the code that decides whether to reuse an old window is here: https://github.com/nolta/Winston.jl/blob/master/src/tk.jl#L24

ViralBShah commented 11 years ago

I did not know that. I meant to look around, but this made it easier. :-)

Calling Tk.configure() when reusing the Canvas makes the plot come out rightside up, but in some cases of repeated resizing and reusing the same window, I get an artefact once in a while - which gets fixed on resizing. In no case do I see an upside down plot now!

https://github.com/nolta/Winston.jl/commit/39dc54868e4f59d26880292fd12ff6a76933b9aa

jverzani commented 11 years ago

@ViralBShah Two things (not with new binaries, but up to date packages)

screen shot 2013-06-20 at 9 47 25 am

When the new width and height are not bigger something else happens:

These kind of things happened before when Tk.configure() was called after an image was drawn and no resizing takes place.

Somehow the new image is drawn with a geometry taken from the original. This just seems odd to me. I've tried checking on the Tk side where the width and height get set and it always matches the size of the parent frame.