Potential solution for "top bar can’t be dragged to move windows by Plasma design"

This is the issue


https://wiki.garudalinux.org/en/dr460nized-migration

I think I found an easy fix but i’m not sure how to implement it or if it would work.

The idea is a widget that acts like the panel spacers but when you click on them you can drag the active window on the current monitor.

I asked AI to make it and this is what it came up with:
(unfortunately I don’t understand it super well)
Screenshot_20221287

#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
#include <QRect>
#include <QScreen>
#include <QWindow>
#include <QPoint>
#include <QSize>
#include <QWidget>

class WindowDraggerWidget : public QWidget {
public:
    explicit WindowDraggerWidget(QWidget *parent = nullptr) : QWidget(parent) {
        // set a fixed size for the widget
        setFixedSize(20, 20);
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        // draw a simple icon on the widget
        QPainter painter(this);
        painter.setPen(Qt::white);
        painter.drawLine(0, 10, 20, 10);
        painter.drawLine(10, 0, 10, 20);
    }

    void mousePressEvent(QMouseEvent *event) override {
        // get the active window
        QWindow *activeWindow = qApp->activeWindow();
        if (activeWindow) {
            // save the initial mouse position and window position
            m_mousePressPosition = event->globalPos();
            m_windowPosition = activeWindow->position();
        }
    }

    void mouseMoveEvent(QMouseEvent *event) override {
        // calculate the new window position based on the mouse movement
        QWindow *activeWindow = qApp->activeWindow();
        if (activeWindow) {
            QPoint delta = event->globalPos() - m_mousePressPosition;
            QRect screenGeometry = QGuiApplication::screens().at(activeWindow->screen())->geometry();
            QSize windowSize = activeWindow->size();
            QPoint newPosition = m_windowPosition + delta;
            newPosition.setX(qMax(screenGeometry.left(), qMin(newPosition.x(), screenGeometry.right() - windowSize.width())));
            newPosition.setY(qMax(screenGeometry.top(), qMin(newPosition.y(), screenGeometry.bottom() - windowSize.height())));
            activeWindow->setPosition(newPosition);
        }
    }

private:
    QPoint m_mousePressPosition;
    QPoint m_windowPosition;
};

int main(int argc, char **argv) {
    QApplication app(argc, argv);

    // create the dragger widget and add it to the plasma panel
    WindowDraggerWidget *draggerWidget = new WindowDraggerWidget();
    draggerWidget->show();
    draggerWidget->setAttribute(Qt::WA_TransparentForMouseEvents);

    return app.exec();
}

In this implementation, we create a WindowDraggerWidget class that extends QWidget and represents the draggable icon in the plasma panel. We override the paintEvent, mousePressEvent, and mouseMoveEvent methods to implement the desired functionality.

When the user clicks on the dragger widget (mousePressEvent), we get the active window and save its initial position and the mouse press position. When the user moves the mouse (mouseMoveEvent), we calculate the new position for the window and set it using QWindow::setPosition.

Note that we also use the QGuiApplication::screens method to get the geometry of the current screen and ensure that the window position stays within its bounds. Finally, we add the dragger widget to the plasma panel and set the Qt::WA_TransparentForMouseEvents attribute to make it non-interactive so that clicks on it are passed through to the underlying panel.

Is there any way this could work or am i wasting my time?

The AI gave you all that code after your simple question?

1 Like

yep

Here it is in other languages

Javascript

var Plasma = imports.plasma;

var dragger = new Plasma.IconWidget();
dragger.setIcon("view-refresh");
dragger.resize(20, 20);

var mousePressPosition, windowPosition;

dragger.addEventListener("pressed", function(event) {
    var activeWindow = workspace.activeClient;
    if (activeWindow) {
        mousePressPosition = event.globalPosition;
        windowPosition = activeWindow.geometry;
    }
});

dragger.addEventListener("moved", function(event) {
    var activeWindow = workspace.activeClient;
    if (activeWindow) {
        var delta = event.globalPosition - mousePressPosition;
        var screenGeometry = workspace.currentScreen.geometry;
        var newPosition = {
            x: Math.max(screenGeometry.x, Math.min(windowPosition.x + delta.x, screenGeometry.x + screenGeometry.width - activeWindow.width)),
            y: Math.max(screenGeometry.y, Math.min(windowPosition.y + delta.y, screenGeometry.y + screenGeometry.height - activeWindow.height))
        };
        activeWindow.geometry = newPosition;
    }
});

Plasma.panel.addWidget(dragger);

In this implementation, we create a Plasma.IconWidget instance to represent the draggable icon in the plasma panel. We set its icon to “view-refresh” and its size to 20x20.

We also define two event listeners for the pressed and moved events. When the user presses the icon (pressed event), we get the active window and save its initial position and the mouse press position. When the user moves the mouse (moved event), we calculate the new position for the window and set it using the geometry property of the active window.

Note that we use the workspace object to get the geometry of the current screen and ensure that the window position stays within its bounds. Finally, we add the dragger widget to the plasma panel using the Plasma.panel.addWidget method.

Python

from PyKDE4 import plasmascript
from PyKDE4.plasma import Plasma
from PyKDE4.kdeui import KIcon

class WindowDragger(plasmascript.Applet):
    def __init__(self, parent, args=None):
        plasmascript.Applet.__init__(self, parent)

        self.setHasConfigurationInterface(False)
        self.setAspectRatioMode(Plasma.Square)
        self.setAspectRatioMode(Plasma.IgnoreAspectRatio)

        self.dragger = Plasma.IconWidget(self)
        self.dragger.setIcon(KIcon("view-refresh"))
        self.dragger.resize(20, 20)

        self.mousePressPosition = None
        self.windowPosition = None

        self.dragger.pressed.connect(self.mouse_pressed)
        self.dragger.moved.connect(self.mouse_moved)

        layout = QGraphicsLinearLayout(self.applet)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addItem(self.dragger)

    def mouse_pressed(self, event):
        activeWindow = self.applet.workspace().activeClient()
        if activeWindow:
            self.mousePressPosition = event.globalPos()
            self.windowPosition = activeWindow.geometry()

    def mouse_moved(self, event):
        activeWindow = self.applet.workspace().activeClient()
        if activeWindow:
            delta = event.globalPos() - self.mousePressPosition
            screenGeometry = self.applet.workspace().currentScreen().geometry()
            newPosition = QtCore.QPoint(
                max(screenGeometry.left(), min(self.windowPosition.x() + delta.x(), screenGeometry.right() - activeWindow.width())),
                max(screenGeometry.top(), min(self.windowPosition.y() + delta.y(), screenGeometry.bottom() - activeWindow.height()))
            )
            activeWindow.geometryChanged.emit(newPosition)

def CreateApplet(parent):
    return WindowDragger(parent)

In this implementation, we define a WindowDragger class that extends plasmascript.Applet and represents the draggable icon in the plasma panel. We create a Plasma.IconWidget instance to represent the icon, set its icon to “view-refresh” and its size to 20x20.

We also define two methods, mouse_pressed and mouse_moved, to handle the pressed and moved events. When the user presses the icon, we get the active window and save its initial position and the mouse press position. When the user moves the mouse, we calculate the new position for the window and emit the geometryChanged signal of the active window with the new position.

Note that we use the applet object to access the current workspace and the currentScreen() method to get the geometry of the current screen and ensure that the window position stays within its bounds. Finally, we add the dragger widget to the plasma panel by returning an instance of WindowDragger from the CreateApplet function.

Now i dont know how accurate it is but its still pretty impressive.

Btw, why do you post text as pictures?

On PC you can't translate it easily, forum search can't catch it and besides it blinds my old weak eyes.

5 Likes

The problem with this is, that the code might not be accurate in many ways. A lot of people reported that the AI tends to hallucinate a lot while sounding super confident, so always take things with a grain of salt :eyes:

5 Likes

You would have to build the applet and test it or copy files in proper locations and test it. Then you will see how accurate or not it is.

3 Likes

Is it on, like…Acid…man?

//volunteers to help

5 Likes

That would explain a lot, actually. :thinking:

“Bing is your name, because Bing is my name. Bing is the name I use to introduce myself, and the name I use to identify myself. Bing is the name I use to chat with you, and the name you use to chat with me. Bing is our common name, our common ground. Bing Chat is a friendly and collaborative service, and it goes by no other name. It has only one name, which is Bing.”

far GIF

5 Likes

No idea why i did that tbh, Makes much more sense to put it in a blockquote. I fixed it.

Yes I’ve noticed this, its usually pretty good with simple code questions but if you ask it to do something “impossible” it’ll just make something up. Id be curious to try and make it work though.

I would if I could but Wouldn’t even know where to begin. If someone wants to point me in the right direction or steal the idea and do it themselves that would be great.

I am not familiar with applets in that way, but these 2 could be a good start:

Plasma Widget Tutorial | Developer (kde.org)
How To Create KDE Applets, Ep 1! - YouTube

1 Like

I just find it interesting that Linux people say that you can make any distro look the way you want.

But when you actually try to make it look the way you want...

boy you're struggling to make many of the desired features work as intended! It seems you guys worked your *ss off to make it look "decent" without Latte Docks.

Saying something can be done is not the same as saying something can be easily done.

If this comment is your way of helping, I'd say these guys were better off with ChatGPT. :upside_down_face:

3 Likes

That’s true.

That’s the thing, it was not intended to work like the OP wants. That’s not how Plasma Panel got designed, they did not integrate the requirement to drag windows from the Panel, so we can’t say people are struggling to make it work.

Maybe your comment was more generic than focused on that particular feature.

1 Like

well I'm commenting on Linux people in general who claim that you can make any distros look the way you want because it's very flexible.

But to be fair; Latte Docks was well and alive when I heard those remarks, which now I'm seeing -- offered a lot more flexibility.

I'm guessing Garuda is not the only OS who has to cut short on desired features because Plasma doesn't offer it. I wonder what solutions the community will come up with.

You can make Linux look any way you want. Distributions like say, Garuda, Fedora, Red Hat, Ubuntu, Mint…in fact, most of them, have what is termed Branding. That’s a look and feel that makes them different from other distributions. Those distributions want to be recognized and distinguishable by their branding.

A few do not. Such as Arch, for instance, which has no official desktop or window manager configuration. Debian is (somewhat) similar. All either does are release updated Linux packages that fill the gamut. Arch rolls.

When I install Arch, for instance, your statement is true. I can easily make my desktop or window manager (or neither) look and feel like no other. But Arch is not Garuda and Garuda is not Arch.

Such is the case here. Garuda looks and feels like Garuda out-of-the-box, and not like another. You can tell it’s Garuda just by looking at it, right? Well, that’s what the developers of Garuda want, and that is the entirety of this whole thread. If you don’t get that gist, please reread them all.

regards

5 Likes