How to Create Transparent Widgets in Krita 6.0

Win11 krita-x64-6.0.0-prealpha-fb295161

While developing a plugin in the above environment, I discovered that creating transparent QWidgets is difficult in Krita 6.0.

self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground, False)
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)

Even after trying the above code, the widget did not become transparent but instead had a black background. However, when I wrote code using PyQt6-6.9.0 in a program unrelated to Krita, I was able to create a transparent widget.

Krita 6.0 appears to use PyQt6-6.8.1. I’ve determined that window transparency issues seem to occur or not depending on the Qt6 version.

Is there a scheduled timing for when Krita 6.0 will switch to a newer version of the Qt bindings?

Update: I have changed the topic title.

I don’t think this has anything to do with PyQt, but with wayland/HDR support on Linux.
I don’t understand the details, just that the canvas has to use a “native surface” that effectively bypasses Qt’s internal compositing for HDR support with Qt6.
This way of transparency simply doesn’t work anymore:

1 Like

I thought it was a PyQt version issue.
Is there a way to create transparent widgets in Krita 6.0? I don’t quite understand the concept of native surfaces.

I wanted to resurrect this topic, as there was no solution given, while this issue affects my plugin Shortcut Composer.

Also let me ping @dkazakov - I don’t like bothering people, but I’ve done some research on the topic, and it looks like I won’t be able to resolve this without help (and apparently he fixed this issue in popup palette) :slight_smile: .

As far as I understand this part of code from kis_popup_palette.cpp (mentioned above):

    /**
        * We use Qt::Popup on Wayland because it makes the popup receive a native
        * surface and render separately from the main HDR-canvas surface. We cannot
        * use this mode on all platforms, because:

        * 2) On Windows Qt::Popup + Qt::FramelessWindowHint + Qt::WA_TranslucentBackground
        *    just don't work. It shows black background instead. It also has some weird
        *    jumping when opened, because we call to move() **after** the popup becomes
        *    visible.
        */
        KisPlatformPluginInterfaceFactory::instance()->surfaceColorManagedByOS() ?
            Qt::Popup :
            Qt::FramelessWindowHint)
        setAttribute(Qt::WA_TranslucentBackground);

depending on OS, popup palette either receives a Popup (Windows) or FramelessWindowHint (Wayland) flag. Using this Popup flag from within python plugin does not seem to fix the black background issue (in fact no flag/attribute combination I’ve tried works). So my questions would be:

  1. Is there some obvious solution later in the code I’m missing (Popup flag should make the window a “native surface” and make the transparency work)?
  2. Is this “receiving a native surface” a result of some larger cpp system that is not available to python plugins (making it impossible to fix transparency in plugins like it was done with popup palette)?

I’d like to avoid redesigning the plugin GUI to not use transparency, unless there really is no other way.

Anyway, thanks in advance - I don’t expect any response during easter, but if somebody familiar with this topic could help afterwards - it would be great :slight_smile:

1 Like

Is there some obvious solution later in the code I’m missing (Popup flag should make the window a “native surface” and make the transparency work)?

No, it is just Qt being very weird when requested a transparent GUI. I don’t really remember the details. Btw, your explanation is reversed: Qt::Popup is used on native wayland, and Qt::FramelessWindowHint is used everywhere else. Can it be the reason of the issue?

Is this “receiving a native surface” a result of some larger cpp system that is not available to python plugins

Well, the presence of a native surface is controlled by a few Qt flags for the widget (and the window), so, theoretically, it is available for Python plugins. The only thing that is not available is KisPlatformPluginInterfaceFactory, but I guess your question is not related to that.

1 Like

I tried several flag combinations, but with no progress so far. But if the popup palette does not do anything special, and in theory it should be possible to achieve that in a plugin - I’ll try to dig deeper into this.

Thanks for help!

1 Like

@dk8

I got some progress on the issue.

The problem does not occur when krita uses OpenGL canvas acceleration. DirectX and native renderer both display transparency as black.

I tried several combinations of flags and attributes, with no success, but with OpenGL you don’t need to change anything in code from krita 5. FramelessWindow + Popup flag combo works just fine. Maybe the reason it still works on Linux is that it comes only with OpenGL renderer.

Unless somebody finds a better solution, on krita startup I’ll probably be detecting when OpenGL is not enabled and display a “don’t ask me again” warning suggesting a switch.

2 Likes

I checked it right away, and sure enough, I was able to create a transparent widget.
I’m glad it was such an easy fix. Thank you for letting me know.

2 Likes