View Issue Details

IDProjectCategoryView StatusLast Update
0036021LazarusWidgetsetpublic2019-09-20 04:13
ReporterChris RordenAssigned ToDmitry Boyarintsev 
PrioritynormalSeverityminorReproducibilityalways
Status confirmedResolutionopen 
PlatformMacBook AirOSDarwinOS Version10.15 beta 6
Product Version2.0.3 (SVN)Product Build61763 
Target VersionFixed in Version 
Summary0036021: Cocoa Catalina: ComboBox text appears upside down
DescriptionThis issue is specific to MacOS Catalina (10.15) - I compiled on 10.14 and the application runs fin on 10.14. The selected text of the ComboBox is drawn upside down. When the combo box is selected, the items are drawn normally.
TagsNo tags attached.
Fixed in Revision
LazTarget-
WidgetsetCocoa
Attached Files
  • CatalinaCombo.zip (109,904 bytes)
  • CatalinaCombo.png (26,960 bytes)
    CatalinaCombo.png (26,960 bytes)
  • CatalinaFlip.patch (1,599 bytes)
    Index: Lazarus/laz-src/lcl/interfaces/cocoa/cocoagdiobjects.pas
    ===================================================================
    --- Lazarus/laz-src/lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 24234)
    +++ Lazarus/laz-src/lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 24235)
    @@ -400,6 +400,7 @@
         // Also, because of bug 28015 FClipped cannot use ctx.Restore(Save)GraphicsState;
         // it will use CGContextRestore(Save)GState(CGContext()); to save/restore DC instead
         FClipped: Boolean;
    +    FFlipped: Boolean;
         FClipRegion: TCocoaRegion;
         FSavedDCList: TFPObjectList;
         FPenPos: TPoint;
    @@ -476,6 +477,7 @@
         function CopyClipRegion(ADstRegion: TCocoaRegion): TCocoaRegionType;
     
         property Clipped: Boolean read FClipped;
    +    property Flipped: Boolean read FFlipped;
         property PenPos: TPoint read FPenPos write FPenPos;
         property ROP2: Integer read FROP2 write SetROP2;
         property Size: TSize read FSize;
    @@ -1758,6 +1760,7 @@
       FSavedDCList := nil;
       FText := TCocoaTextLayout.Create;
       FClipped := False;
    +  FFlipped := False;
     end;
     
     destructor TCocoaContext.Destroy;
    @@ -1776,8 +1779,11 @@
     
       FBkBrush.Free;
     
    -  if Assigned(ctx) then
    +  if Assigned(ctx) then begin
    +    if Assigned(CGContext()) and Flipped then
    +      CGContextRestoreGState(CGContext());
         ctx.release;
    +    end;
       if Assigned(boxview) then boxview.release;
       inherited Destroy;
     end;
    @@ -1840,6 +1846,9 @@
       Result := Assigned(cg);
       if not Result then Exit;
     
    +  CGContextSaveGState(cg);
    +  FFlipped := True;
    +
       FSize.cx := width;
       FSize.cy := height;
     
    
    CatalinaFlip.patch (1,599 bytes)

Activities

Chris Rorden

2019-08-27 21:21

reporter  

CatalinaCombo.zip (109,904 bytes)

Chris Rorden

2019-08-27 21:21

reporter  

CatalinaCombo.png (26,960 bytes)
CatalinaCombo.png (26,960 bytes)

Dmitry Boyarintsev

2019-08-27 21:27

developer   ~0117860

Last edited: 2019-08-27 21:28

View 2 revisions

this was not happening in Beta 5. (or earlier)
the issue was introduce in Catalina Beta 6.
So there's an incentive to wait for Beta 7 (without taking any action).

Zoë Peterson

2019-08-29 21:06

reporter   ~0117869

Beta 7 was released yesterday and still has problems with upside down controls. I haven't tested the sample project, and we're a bit out of sync, but we're seeing it in a bunch of places in our app too.

David Jenkins

2019-08-30 22:36

reporter   ~0117885

Here is a patch

CatalinaFlip.patch (1,599 bytes)
Index: Lazarus/laz-src/lcl/interfaces/cocoa/cocoagdiobjects.pas
===================================================================
--- Lazarus/laz-src/lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 24234)
+++ Lazarus/laz-src/lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 24235)
@@ -400,6 +400,7 @@
     // Also, because of bug 28015 FClipped cannot use ctx.Restore(Save)GraphicsState;
     // it will use CGContextRestore(Save)GState(CGContext()); to save/restore DC instead
     FClipped: Boolean;
+    FFlipped: Boolean;
     FClipRegion: TCocoaRegion;
     FSavedDCList: TFPObjectList;
     FPenPos: TPoint;
@@ -476,6 +477,7 @@
     function CopyClipRegion(ADstRegion: TCocoaRegion): TCocoaRegionType;
 
     property Clipped: Boolean read FClipped;
+    property Flipped: Boolean read FFlipped;
     property PenPos: TPoint read FPenPos write FPenPos;
     property ROP2: Integer read FROP2 write SetROP2;
     property Size: TSize read FSize;
@@ -1758,6 +1760,7 @@
   FSavedDCList := nil;
   FText := TCocoaTextLayout.Create;
   FClipped := False;
+  FFlipped := False;
 end;
 
 destructor TCocoaContext.Destroy;
@@ -1776,8 +1779,11 @@
 
   FBkBrush.Free;
 
-  if Assigned(ctx) then
+  if Assigned(ctx) then begin
+    if Assigned(CGContext()) and Flipped then
+      CGContextRestoreGState(CGContext());
     ctx.release;
+    end;
   if Assigned(boxview) then boxview.release;
   inherited Destroy;
 end;
@@ -1840,6 +1846,9 @@
   Result := Assigned(cg);
   if not Result then Exit;
 
+  CGContextSaveGState(cg);
+  FFlipped := True;
+
   FSize.cx := width;
   FSize.cy := height;
 
CatalinaFlip.patch (1,599 bytes)

David Jenkins

2019-08-30 22:48

reporter   ~0117887

The problem appears to be related to the flip transform that is done in TCocoaContext.InitDraw. Prior to Catalina beta 6 the flip didn't affect the drawing of any other controls. Now the transform isn't cleared out and it affects other drawing code. So fix is to save context state before flip transform and then restore it when context use is done. Patch above does this by calling cgcontextsavegstate() in InitDraw and setting a FFlipped flag. In TCocoaContext.destroy if FFlipped is true cgcontextrestoregstate() is called.

I notice that there are already several save/restore blocks in TCocoaContext and that there are some mantis that resulted from it not being quite right. So if the patch isn't quite right here are some other ways I solved the issue:

The specific spot that has this specific mantis problem is in TLCLCommonCallback.Draw. A TCocoaContext is created, InitDraw flips it, and then TCocoaContext is freed. However, the transformed cgcontext sticks around and causes problems.

I was able to resolve the issue by, in TLCLCommonCallback.Draw, calling ControlContext.classSaveContextState before the call to TCocoaContext.Create() and then calling ControlContext.classRestoreContextState in the finally block after the freeandNil(fcontext).

However, since InitDraw is called in other places it seemed important to restore any transformed cgcontext so a similar issue wouldn't pop up. So my next attempt put a cgcontextsavegstate() in InitDraw and then I created TCocoaContext.EndDraw that called cgcontextrestoregstate(). By placing a call to EndDraw in TLCLCommonCallback.Draw at the end of the 'if FContext.InitDraw begin/end' block I also got the problem to resolve. But then I started looking for all the other places .InitDraw is called so I could pair up an appropriate .EndDraw. This doesn't work well because there are some calls to .InitDraw where the closing isn't obvious.

So I created the above patch. However, if that patch were to cause problems because it ends of causing save/restore problems. A patch isolated to TLCLCommonCallback.Draw would work for this particulare mantis.

Chris Rorden

2019-09-19 16:12

reporter   ~0118119

My software and the demo I provide above both work well with Catalina Beta 8. It seems that Dmitry's wait and see approach has paid off. The problem resolved without applying David's patch. Perhaps David and Zoë can both confirm that Beta 8 resolves any issues they have experienced. My sense is that this bug can be closed.

Alexey Tor.

2019-09-19 19:40

reporter   ~0118120

Good work, anyway, Scooter Software.

David Jenkins

2019-09-19 22:22

reporter   ~0118122

We can confirm that Catalina Beta 8 resolves the flipping.

However.... In my opinion it would be worth examining whether a version of the patch should still be applied. We apply transforms to a context and then leave them there (with no easy indication that it has been done). Fortunately OSX (except for a couple beta versions of Catalina) clean that up for us. I wonder if it wouldn't be appropriate for us to clean up after ourselves and not rely on OSX to always do it.

Dmitry Boyarintsev

2019-09-20 04:11

developer   ~0118128

I'd be hoping that nothing else broke in Beta 8, and nothing else will break in Beta 9 or release itself

I don't really see a need to indicate if the context has been flipped or not. Instead, inside LCL it should always be considered as LCL compatible (aka flipped in AppKit terms).
The issues seems to be originating from Cocoa's layer method of drawing (where the context is heavily shared across controls). Yet, Apple should make their own API backwards compatible.

Also, the issue is not the first one "beta" issue. Another one was the problem with dialogs not opening. I also wonder if the first Catalina Beta patch (application loop initiation) should be reversed as well.

Dmitry Boyarintsev

2019-09-20 04:13

developer   ~0118129

David, could you please start Cocoa WS improvement suggestions wiki page?

I'd think the graphic system requires the revise in general. At some point of time, the compatibility with macOS 10.6 will be dropped, meaning that the newer API should be used more often.

Issue History

Date Modified Username Field Change
2019-08-27 21:21 Chris Rorden New Issue
2019-08-27 21:21 Chris Rorden File Added: CatalinaCombo.zip
2019-08-27 21:21 Chris Rorden File Added: CatalinaCombo.png
2019-08-27 21:27 Dmitry Boyarintsev Note Added: 0117860
2019-08-27 21:27 Dmitry Boyarintsev Assigned To => Dmitry Boyarintsev
2019-08-27 21:27 Dmitry Boyarintsev Status new => confirmed
2019-08-27 21:27 Dmitry Boyarintsev LazTarget => -
2019-08-27 21:28 Dmitry Boyarintsev Note Edited: 0117860 View Revisions
2019-08-29 21:06 Zoë Peterson Note Added: 0117869
2019-08-30 22:36 David Jenkins File Added: CatalinaFlip.patch
2019-08-30 22:36 David Jenkins Note Added: 0117885
2019-08-30 22:48 David Jenkins Note Added: 0117887
2019-09-19 16:12 Chris Rorden Note Added: 0118119
2019-09-19 19:40 Alexey Tor. Note Added: 0118120
2019-09-19 22:22 David Jenkins Note Added: 0118122
2019-09-20 04:11 Dmitry Boyarintsev Note Added: 0118128
2019-09-20 04:13 Dmitry Boyarintsev Note Added: 0118129