wxWidgets / wxWidgets

Cross-Platform C++ GUI Library
https://www.wxwidgets.org/
6.06k stars 1.76k forks source link

MacOS: wxDC Clear() draws a static color #24006

Open willco007 opened 11 months ago

willco007 commented 11 months ago

Describe the bug: When background style is set to paint, if you call dc.Clear() on macOS it draws a static window background color. It should probably be a no-op to allow the window background color to show through as expected (see screenshot).

Expected vs observed behaviour: The actual window background color of the wxControl etc should show through the control.

Patch or snippet allowing to reproduce the problem:

When creating a control, set background style to paint:

SetBackgroundStyle(wxBG_STYLE_PAINT);

in the OnPaint() event, do this:

MyControl::OnPaint(wxPaintEvent& ev)
{
    wxAutoBufferedPaintDC dc(this);
    dc.Clear();
}

To Reproduce: Run app, observe control background color is static and doesn't match

Platform and version information

background
imciner2 commented 11 months ago

Sorry, but this seems to me like it is doing exactly what it says in the documentation here https://docs.wxwidgets.org/stable/classwx_d_c.html#acf301dfd75b0f31d969ecb9daec21e85

void wxDC::Clear ( )

Clears the device context using the current background brush.

Note that SetBackground() method must be used to set the brush used by Clear(), the brush used for filling the shapes set by SetBrush() is ignored by it.

If no background brush was set, solid white brush is used to clear the device context.

If you want it to be transparent, I believe you should be setting the brush to be wxTRANSPARENT_BRUSH before the clear call (https://docs.wxwidgets.org/stable/brush_8h.html#aa6cac71d7ee6ae54c3e6d2c87244d5b4)..

willco007 commented 11 months ago

Yes, by the letter of the law it's working as expected. However, IMHO, it should be smarter than this and be able to deal with dynamic backgrounds by default. In what scenario would you want this behavior?

Secondly, the fix using the transparent brush does work (which is what I had already come up with), however, setting the background to transparent doesn't work on Windows. So in all my drawing code I would need to ifdef Mac specific code. That is undesirable and something wx should abstract away automatically.

Perhaps a possible solution would to have the default background be transparent on macOS?

vadz commented 11 months ago

Is there a difference in behaviour between different ports? FWIW I agree that it seems fine for Clear() to, well, clear the DC. And unless it already doesn't do it somewhere, I don't see any problem with that.

If you don't want the window to be cleared shouldn't you just avoid calling Clear() in the first place?

willco007 commented 11 months ago

Backing up a step, drawing on Windows behaves differently and Clear() is required: 1) MacOS and Linux, calling Clear() is not necessary and will correctly draw 'nothing' (allow the window background to show through) in the drawing context by default 2) Windows, if you do not call Clear() the drawing context will draw with a black background

Therefore calling Clear() is necessary on Windows at the very least. Alternatively, Windows drawing could be fixed so calling Clear() isn't required to draw 'transparent'. Or MacOS drawing should be fixed so Clear() doesn't draw the window background color as per this bug. MacOS NSViews already invalidate their entire drawRect and do not need to be redrawn with the Window background color so the current version of Clear() is not necessary and is undesired with dynamic backgrounds.

I don't have a preference of how this issue is resolved (fixing Windows or fixing Clear on Mac), I would just like to be able to use the same drawing code on all platforms.

vadz commented 11 months ago

The issue of not requiring Clear() for transparent windows is something different. But as long as Clear() itself behaves in the same way under all platforms, I definitely don't see any good reason to change it.