Background: I want to port my app from GTK3 to Qt6. The only blocker is, Wayland does not seem to allow app opacity to be controlled by the app itself for Qt apps. But it works for GTK3 or GTK4 apps.
Since my app is a beautiful weather widget, I want to control its opacity from within the app (this has been a long time feature), and it is possible with GTK3+wayland (and instead of switching to GTK4, I want to switch to Qt).
I am using KDE 6.6.0 with Wayland.
Here are two examples. Just run python wayland_opacity_gtk4.py and python wayland_opacity_qt6.py: The GTK4 app works flawlessly. The Qt6 app prints
This plugin does not support setting window opacity
Here is the GTK4 example
#!/usr/bin/env python3
"""Minimal GTK4 opacity demo for Wayland/X11 bug reports."""
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gdk, Gtk
class OpacityDemo(Gtk.ApplicationWindow):
def __init__(self, app):
super().__init__(application=app, title="GTK4 Opacity Demo")
self.set_default_size(420, 220)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
box.set_margin_top(12)
box.set_margin_bottom(12)
box.set_margin_start(12)
box.set_margin_end(12)
self.set_child(box)
self.label = Gtk.Label(label="Opacity: 1.00")
self.slider = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 0.10, 1.00, 0.01)
self.slider.set_value(1.00)
self.slider.connect("value-changed", self.on_change)
box.append(self.label)
box.append(self.slider)
def on_change(self, _slider):
opacity = self.slider.get_value()
self.label.set_text(f"Opacity: {opacity:.2f}")
self.set_opacity(opacity)
class DemoApp(Gtk.Application):
def __init__(self):
super().__init__(application_id="io.github.archisman.typhoon.gtk4opacitydemo")
def do_activate(self):
display = Gdk.Display.get_default()
backend = display.get_name() if display else "unknown"
print(f"GTK4 display backend: {backend}")
win = OpacityDemo(self)
win.present()
def main():
app = DemoApp()
app.run(None)
if __name__ == "__main__":
main()
Here is the Qt6 example
#!/usr/bin/env python3
"""Minimal Qt opacity demo for Wayland/X11 bug reports."""
import sys
try:
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QLabel, QSlider, QVBoxLayout, QWidget
except ImportError:
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QSlider, QVBoxLayout, QWidget
class OpacityDemo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Qt Opacity Demo")
self.resize(420, 220)
self.label = QLabel("Opacity: 1.00")
self.slider = QSlider(Qt.Orientation.Horizontal)
self.slider.setMinimum(10)
self.slider.setMaximum(100)
self.slider.setValue(100)
self.slider.valueChanged.connect(self.on_change)
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.slider)
def on_change(self, value: int):
opacity = value / 100.0
self.label.setText(f"Opacity: {opacity:.2f}")
self.setWindowOpacity(opacity)
def main():
app = QApplication(sys.argv)
print(f"Qt platform: {app.platformName()}")
window = OpacityDemo()
window.show()
if hasattr(app, "exec"):
sys.exit(app.exec())
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Does anyone know any workaround?
The Qt6 code does work in X11.