Place a Window behind desktop icons using PyQt on Linux

I'm trying to develop a simple Wallpaper manager, but I am not able to find any method to place my PyQt Window between the current wallpaper and the desktop icons using XLib (on windows it's way easier and works perfectly using pywin32).

I tried to reparent the window, but it doesn't work (possibly it's not the right strategy). I have tried this on Ubuntu/Unity, Mint/Cinnamon and Raspbian, with no success.

EDIT: I tried changing the window properties (commented in my sample code), as well as creating a new window, change its properties as DESKTOP, and set that new window as the target window parent... with no success. In fact, the newly created window does not show behind desktop icons (see modified code below)

Any help or clue is welcome!!!

#!/usr/bin/python
# -*- coding: utf-8 -*-

import signal
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
import Xlib
import Xlib.X
import Xlib.display
import ewmh
import traceback

DISP = Xlib.display.Display()
SCREEN = DISP.screen()
ROOT = SCREEN.root
EWMH = ewmh.EWMH(_display=DISP, root=ROOT)


class Window(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        QtWidgets.QMainWindow.__init__(self, *args, **kwargs)

        caption = "TestIt"
        self.setWindowTitle(caption)

        self.setWindowFlags(QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.FramelessWindowHint)

        screenSize = QtWidgets.QApplication.primaryScreen().size()
        x = screenSize.width()
        y = screenSize.height()
        self.setGeometry(0, 0, x, y)

        self.bkg_label = QtWidgets.QLabel()
        self.bkg_label.setGeometry(0, 0, x, y)
        pixmap = resizeImageWithQT("resourcesB/Doom.jpg", x, y)
        self.bkg_label.setPixmap(pixmap)
        self.layout().addWidget(self.bkg_label)
        self.bkg_label.show()

        sendBehind(caption)


def resizeImageWithQT(src, width, height, keepAspect=True):
    try:
        pixmap = QtGui.QPixmap(src)
        if keepAspect:
            pixmap_resized = pixmap.scaled(int(width), int(height), QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation)
        else:
            pixmap_resized = pixmap.scaled(int(width), int(height), QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.SmoothTransformation)
    except:
        pixmap_resized = None
    return pixmap_resized


def sendBehind(name):

    def getAllWindows():
        # windows = EWMH.getClientList()  # This will return the "user" apps only
        windows = ROOT.query_tree().children
        return windows

    def getWindowsWithTitle(title):
        matches = []
        for win in getAllWindows():
            if title == EWMH.getWmName(win):
                matches.append(win)

        return matches

    def getActiveWindow():
        win_id = EWMH.getActiveWindow()
        if win_id:
            return win_id
        return None

    win = getWindowsWithTitle(name)
    if win:
        win = win[0]
        w = DISP.create_resource_object('window', win)

        # https://stackoverflow.com/questions/58885803/can-i-use-net-wm-window-type-dock-ewhm-extension-in-openbox
        # Does not sends current window below. It does with the new window, but not  behind the desktop icons
        # w.change_property(DISP.intern_atom('_NET_WM_WINDOW_TYPE'), Xlib.Xatom.ATOM,
        #                              32, [DISP.intern_atom("_NET_WM_WINDOW_TYPE_DESKTOP"), ],
        #                              Xlib.X.PropModeReplace)
        # w.map()
        # DISP.next_event()
        # DISP.next_event()

        newWin = ROOT.create_window(0, 0, 500, 500, 1, SCREEN.root_depth,
                                    background_pixel=SCREEN.black_pixel,
                                    event_mask=Xlib.X.ExposureMask | Xlib.X.KeyPressMask)
        newWin.change_property(DISP.intern_atom('_NET_WM_WINDOW_TYPE'), Xlib.Xatom.ATOM,
                               32, [DISP.intern_atom("_NET_WM_WINDOW_TYPE_DESKTOP"), ],
                               Xlib.X.PropModeReplace)
        newWin.map()
        DISP.next_event()
        DISP.next_event()
        w.reparent(newWin, 0, 0)


def sigint_handler(*args):
    # https://stackoverflow.com/questions/4938723/what-is-the-correct-way-to-make-my-pyqt-application-quit-when-killed-from-the-co
    app.closeAllWindows()


def exception_hook(exctype, value, tb):
    # https://stackoverflow.com/questions/56991627/how-does-the-sys-excepthook-function-work-with-pyqt5
    traceback_formated = traceback.format_exception(exctype, value, tb)
    traceback_string = "".join(traceback_formated)
    print(traceback_string, file=sys.stderr)
    sys.exit(1)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    if "python" in sys.executable.lower():
        # This will allow to manage Ctl-C interruption (e.g. when running from IDE)
        signal.signal(signal.SIGINT, sigint_handler)
        timer = QtCore.QTimer()
        timer.start(500)
        timer.timeout.connect(lambda: None)
        # This will allow to show some tracebacks (not all, anyway)
        sys._excepthook = sys.excepthook
        sys.excepthook = exception_hook
    win = Window()
    win.show()
    try:
        app.exec_()
    except:
        pass


from Recent Questions - Stack Overflow https://ift.tt/3kW2cJi
https://ift.tt/eA8V8J

Comments

Popular posts from this blog

Spring Elasticsearch Operations

Network Error and Timeout on Authorize.net JS

Object oriented programming concepts (OOPs)