Paint events don't always refresh on Catalina

  1. 8 weeks ago

    Tim J

    Feb 10 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    I did a quick search, but Feedback provided nothing.

    Have any of you run into issue where Canvas Paint events execute, but the canvas contents do not update in the UI?

    I have a container that acts as a custom tab bar for an app. I draw the tab border around the inside of the clicked canvas to indicate which tab is selected along with changing the label text color. On Windows, Linux, and other macOS versions, this works as expected. On Catalina, however, the text color of the label changes, but the DrawRoundRect call result does not update in the GUI. All of the code runs in the main loop.

    I've tried adding a timer calling Canvas.Invaildate just to try to force a refresh with no difference.

    Logic specifics:

    • TGToolBar is a Container
    • The container has up to 8 "tab" canvas controls
    • Each tab canvas control has a Label
    • The Canvases are part of a control array
    • The tabs are used to select a page on a PagePanel (the TGToolBar is NOT a child of the PagePanel)
    • The MouseDown event for the control array resets the background (which also doesn't take affect) and assigns a variable "tbIndex"
    • The Paint event then uses the tbIndex value to either clear the background (thus removing the previous outline) and call DrawRoundedRect to draw the outline on the clicked tab.

    As I mentioned, this has worked as expected for a very long time on Windows XP - 10 and maltose Server version, Linux, and all previous versions os OS X / macOS.

    Any thoughts?

  2. Tim J

    Feb 10 Pre-Release Testers, Xojo Pro N. Phoenix, AZ
    Edited 8 weeks ago

    Here's what it SHOULD look like:

    -image-

    Here's the MouseDown event code:

    // check for the user clicking the button they are on
    If index = WMain.ppMainPage.Value Or index = WMain.ppMainPage.Value + 6 Then 
      Return True
    End If
    
    // Reset the text to unselected
    cvToolButton(0).Backdrop = Backup32x32
    lBackup.TextColor = &c2F2F2F00
    If Not LoadingArchives Then
      cvToolButton(1).Backdrop = Restore32x32
      lRestore.TextColor = &c2F2F2F00
      cvToolButton(2).Backdrop = Verify32x32
      lVerify.TextColor = &c2F2F2F00
    End If
    cvToolButton(3).Backdrop = DataManager32x32
    lDataManager.TextColor = &c2F2F2F00
    cvToolButton(4).Backdrop = Tools32x32
    lTools.TextColor = &c2F2F2F00
    
    // Set the text to the active color
    // The low half is the icon canvas, the higher half is the main canvas for the tab
    Select Case Index
    Case 0, 6
      lBackup.TextColor = &c3249B500
      WMain.ppMainPage.Value = 0
      tbIndex = 6
    Case 1, 7
      If Not LoadingArchives Then
        lRestore.TextColor = &c3249B500
        WMain.ppMainPage.Value = 1
        tbIndex = 7
      End If
    Case 2, 8
      If Not LoadingArchives Then
        lVerify.TextColor = &c3249B500
        WMain.ppMainPage.Value = 2
        tbIndex = 8
      End If
    Case 3, 9
      lDataManager.TextColor = &c3249B500
      WMain.ppMainPage.Value = 3
      tbIndex = 9
    Case 4, 10
      lTools.TextColor = &c3249B500
      WMain.ppMainPage.Value = 4
      tbIndex = 10
    End Select
    Return True

    Here's the Paint code:

    // draw the faux frame around the tab in the parent cannvas
    If index = tbIndex Then
      #If TargetMacOS
        // Clear the previous outline
        g.ForeColor = &cE7E7E700
        g.FillRoundRect(0, 0, g.Width, g.Height + 11 , 10, 10)
      #endif
      g.PenWidth = .5
      g.PenHeight = .5
      g.ForeColor = &c7B7B7E00
      g.DrawRoundRect(0,0,g.Width, g.Height + 11, 10, 10)
    ElseIf index > 5 Then
      g.ForeColor = &cE7E7E700
      g.FillRect(0, 0, g.Width, g.Height + 3)
    End If

    Also, this applies to apps built with 19r1.1, 19r2.1, and 19r3,1,

  3. Michel B

    Feb 10 Pre-Release Testers, Xojo Pro

    I suppose you have verified with a system.debuglog() that the paint event actually fires ?

  4. Tim J

    Feb 10 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    Yes - and by adding a breakpoint in the paint event.

  5. Jürg O

    Feb 10 Pre-Release Testers, Xojo Pro
    Edited 8 weeks ago

    @Tim Jones Any thoughts?

    Xojo 2018r3 has updated the macOS SDK (in order to support DarkMode).
    All I remember is that this had some effects when it comes to drawing. And somehow a different behavior of ClearRect has come to mind.

    In our code I've found this in a "similar situation":

    #if (XojoVersion >= 2018.03) and TargetMacOS then
      'it seems with this newer Xojo Version we need to clear first
      g.ClearRect(0, 0, g.Width, g.Height)
    #endif

    @Tim J I've tried adding a timer calling Canvas.Invalidate just to try to force a refresh with no difference.

    Again just a situation I think to remember... that in some places we had to switch from .Invalidate (which we've used a lot in the windows-flickering time) back to .Refresh, because otherwise the ReDrawing would not occur (or much later than expected).

    @Tim J Yes - and by adding a breakpoint in the paint event.

    Oh, only do that when RemoteDebugging.
    Otherwise your app gets (De)Activated when swiching to Xojo/Debugger. And that will cause different Paint-Events obviously for the entire app, compared to when it's staying "frontmost" the whole time.
    Use DebugLog in such a situation, or some other means (filling a property, writing to a file, whatever).

    I don't know if this pieces I think to remember will help, or if they do apply to your app, too...
    In your situation I'd try to see what happens if you do a .ClearRect in the appropriate Paint-Events before drawing.

  6. Beatrix W

    Feb 10 Pre-Release Testers, Third Party Store Europe (Germany)

    Try to use the paint event and not a backdrop.

  7. Tim J

    Feb 10 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    @Beatrix W Try to use the paint event and not a backdrop.

    Tried that, and then the icon didn't get drawn, either ...

  8. Beatrix W

    Feb 10 Pre-Release Testers, Third Party Store Europe (Germany)

    As usual: you must be doing something wrong. You got an example? Why are you using multiple canvases and not one? Today I uploaded an updated version of some old code that does something similar to what you do. Can you try to run the code? http://www.mothsoftware.com/downloads/tabbar.zip

  9. Jürg O

    Feb 10 Pre-Release Testers, Xojo Pro

    @Tim J Tried that, and then the icon didn't get drawn, either ...

    I don't see where you are .Invalidate-ing or .Refresh-ing in your "MouseDown event code".
    But I'm sure you've added that when trying to avoid .BackDrop. ;)

    And just another thing that has come to mind when reading "MouseDown event code" containing WMain.ppMainPage.Value = x...
    ...I don't expect and don't want a "(Toolbar)Button" to execute an "Action" in MouseDown!
    MouseDown should indicate it's "in a pushed state" (while the mouse is "inside"), the Action only gets executed in MouseUp (if it's still "inside"). So one can click on a Button, keep the Mouse Button pushed down, decide otherwise by moving out of the Button, then release the Mouse Button - with no action being executed.

    So if you're going to refactor this anyway, then please keep that in mind, too...

  10. Tim J

    Feb 10 Pre-Release Testers, Xojo Pro N. Phoenix, AZ
    Edited 8 weeks ago

    @Jürg O And just another thing that has come to mind when reading "MouseDown event code" containing WMain.ppMainPage.Value = x...
    ...I don't expect and don't want a "(Toolbar)Button" to execute an "Action" in MouseDown!

    That was a shift to try to reduce the time between the click and the paint events. In my real code, I have a method that does what I show above in the MouseDown that is actually called in the MouseUp Named "UpdateTabGraphics".

    I have tried invalidate, refresh, and I even went so far as to place a DoEvents call in as a last resort. Again, the code works properly on all other platforms (I've even now tested on a Raspberry Pi).

    @Beatrix W Can you try to run the code? http://www.mothsoftware.com/downloads/tabbar.zip

    Hi Trixi, that does work and I'm comparing your workflow with mine. I will report back.

  11. Sam R

    Feb 10 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    There are several things I can think of.

    1. You have a declare or plugin that it modifying how the window paints, the most common way is some UI API enables Layer-Backed views, which you'll need to ask the CALayer to update. It was a huge problem for me back in the days of 10.10, but I don't see it so much now.
    2. You may be getting a NSException somewhere in your code, recent macOS versions, simply stop the current thread and swallow the execution. One of the worst changes that Apple have made in recent years, sure the application doesn't crash, but no-one knows that there's a problem except some things simply don't work right.

    I would recommend everyone who uses declares or plugins to follow the advice on this page. https://forum.xojo.com/58302-crash-an-application-on-nsexception/p1#p473604

    Then when an NSException is raised, you a) know about it, b) Know what it is and c) know where it is.

  12. Tim J

    Feb 10 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    Thank you Sam! This is exactly what I'm witnessing on 3 other apps under Catalina. However, I wrote a very quick Exception Handler Window with that setting applied and now I'm getting the exception backtrace that was not being seen by the apps previous. I ran a quick test and the Catalina run of this specific app is not caught up in that idiocy.

  13. 7 weeks ago

    Sam R

    Feb 11 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    @Tim Jones Thank you Sam! This is exactly what I'm witnessing on 3 other apps under Catalina. However, I wrote a very quick Exception Handler Window with that setting applied and now I'm getting the exception backtrace that was not being seen by the apps previous.

    Glad I could help.

    If you're on twitter; make sure you hit up @steipete and let him know it helped. I wouldn't have found this tip without him. I'd started trying to get into the depths of handling NSExceptions myself, simply so that I was aware when, where and what was happening.

    @Tim J I ran a quick test and the Catalina run of this specific app is not caught up in that idiocy.

    Oh well, it was worth a shot, was hoping it might give some indicators.

  14. Tim J

    Feb 11 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    I'm refactoring taking into account Trixi's class and another version of this same code that doesn't exhibit the issue on Catalina.

    It's just very odd that the problem doesn't manifest on any platform BUT Catalina.

  15. Tim J

    Feb 11 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    @Beatrix W Can you try to run the code? http://www.mothsoftware.com/downloads/tabbar.zip

    Interesting that you're actually doing the same thing that I'm doing, just you've created a class that is reusable and mine is fixed and dependent on the number of tabs I physically code.

    As I mentioned to Sam above, I've also tried drawing my icons in the primary canvas, but in that case, I then lose the icon, as well.

    However, in extending what I was writing to System.Log in the Paint event and my MouseUp event, I see something very odd - the index in the Paint event when called AFTER the click is always 0 instead of the Canvas clicked:

    1:09:16 PM : ccMainTools.cvToolButton.MouseUp: Index is 1, tbIndex is 1
                 ccMainTools.cvToolButton.Paint: Index is 0, tbIndex is 1
    1:09:18 PM : ccMainTools.cvToolButton.MouseUp: Index is 2, tbIndex is 2
                 ccMainTools.cvToolButton.Paint: Index is 0, tbIndex is 2
    1:09:19 PM : ccMainTools.cvToolButton.MouseUp: Index is 3, tbIndex is 3
                 ccMainTools.cvToolButton.Paint: Index is 0, tbIndex is 3
    1:09:20 PM : ccMainTools.cvToolButton.MouseUp: Index is 4, tbIndex is 4
                 ccMainTools.cvToolButton.Paint: Index is 0, tbIndex is 4
    1:09:21 PM : ccMainTools.cvToolButton.MouseUp: Index is 0, tbIndex is 0
                 ccMainTools.cvToolButton.Paint: Index is 0, tbIndex is 0
  16. Tim J

    Feb 11 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    Here's a simple one-window project that I created in 19r3.1 to test this. Do any of you see what I'm missing?

    TabTestCatalina

    As before, it works as expected on all platforms except Catalina.

  17. Norman P

    Feb 11 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    I think I see what the issue is but I'm not on catalina right now

  18. Tim J

    Feb 11 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    @Norman P I think I see what the issue is but I'm not on catalina right now

    C'mon, give! Is it a Tim-oops, or something else? I'm slowly going bald here :D

  19. Scott C

    Feb 11 Pre-Release Testers, Xojo Pro twitter.com/ScottCadillac
    Edited 7 weeks ago

    I don't know much about Control Sets, but I do see the visual difference on Catalina you describe Tim, verses what I see on Mojave.

    One observation I noticed, is the log on Catalina only outputs the following when I click on the "Data Manager" tab (for each OS):

    ccMainTools.cvToolButton.MouseUp: Index is 3, tbIndex is 3
    ccMainTools.cvToolButton.Paint: Index is 0, tbIndex is 3

    Whereas on Mojave I see:

    ccMainTools.cvToolButton.MouseUp: Index is 3, tbIndex is 3
    ccMainTools.cvToolButton.Paint: Index is 0, tbIndex is 3
    ccMainTools.cvToolButton.Paint: Index is 4, tbIndex is 3
    ccMainTools.cvToolButton.Paint: Index is 3, tbIndex is 3
    ccMainTools.cvToolButton.Paint: Index is 2, tbIndex is 3
    ccMainTools.cvToolButton.Paint: Index is 1, tbIndex is 3

    Does that help?
    Edit to add: So more occurrences of the Paint event on Mojave with each click?

  20. Tim J

    Feb 11 Pre-Release Testers, Xojo Pro N. Phoenix, AZ

    Yes - and it explains exactly what I see. All of the controls in the array are not repainted under Catalina. So, that looks like a Xojo thing. I feel much better now.

    It appears that I'll need to force a refresh of each member of the control array on MouseUp to get it sorted on Catalina.

    Thanks, Scott!

  21. Newer ›

or Sign Up to reply!