plasma-applet-active-window-control
plasma-applet-active-window-control copied to clipboard
Feature request: Drag the application name to move (maximized) windows
This request is to be able to move the current window by dragging the applet. This is a nice complement for the option to hide the title bar for maximized windows. In such case there is no title bar to drag (and unmaximize) the window. Kwin has the option in the right click menu to move the window, so I assume it would be possible. Unity allows a similar behavior, where the top panel really feels like the "maximized window decoration". If you prefer this could be enabled with an option, and even the option could restrict to maximized windows only.
I know, I know, I want this feature, too. I'll look into it, thanks for suggestion :).
That would certainly be a nice add :)
Or add a "Move" button/menu entry, like what is available in the taskbar's right click menu > More Actions.
I would love this so gosh darn much! Any updates, @kotelnik?
Any updates? 😋
The taskmanager widget can ask to "move the selected window".
https://github.com/KDE/plasma-desktop/blob/6ae9528c1ce91d72eabdb31fe5e623ad559f32cd/applets/taskmanager/package/contents/ui/ContextMenu.qml#L568
I've managed to get this sorta working with:
MouseArea {
onClicked: {
tasksModel.requestMove(tasksModel.activeTask)
}
}
Video: https://streamable.com/vziac
However if I try triggering the requestMove
in the middle of a drag, it foobars when the mouse is released. Mouse clicks are no longer registered.
I need to hit the global shortcut for KRunner
to get input to work. I can also press Esc
to fix it, but the window moves back to it's original location (which is a hint that it's KWin's state that's messed up instead of the plasmashell widget).
MouseArea {
Item {
id: dragTarget
anchors.fill: parent
}
drag.target: dragTarget
drag.onActiveChanged: console.log('drag.onActiveChanged', drag.active)
onContainsMouseChanged: {
console.log('onContainsMouseChanged', containsMouse)
if (!containsMouse) {
if (drag.active) {
console.log('!containsMouse && drag.active')
console.log('requestMove', tasksModel.activeTask)
tasksModel.requestMove(tasksModel.activeTask)
console.log('after tasksModel.requestMove')
}
}
}
}
Video: https://streamable.com/weraq
Should it be possible to trigger it during a drag without breaking, we also need to make requestMouse
not move the mouse to the center of the window.
The code for the X11 libtaskmanager is here:
https://github.com/KDE/plasma-workspace/blob/master/libtaskmanager/xwindowtasksmodel.cpp#L719
void XWindowTasksModel::requestMove(const QModelIndex &index)
{
if (!index.isValid() || index.model() != this || index.row() < 0 || index.row() >= d->windows.count()) {
return;
}
const WId window = d->windows.at(index.row());
const KWindowInfo *info = d->windowInfo(window);
bool onCurrent = info->isOnCurrentDesktop();
if (!onCurrent) {
KWindowSystem::setCurrentDesktop(info->desktop());
KWindowSystem::forceActiveWindow(window);
}
if (info->isMinimized()) {
KWindowSystem::unminimizeWindow(window);
}
const QRect &geom = info->geometry();
NETRootInfo ri(QX11Info::connection(), NET::WMMoveResize);
ri.moveResizeRequest(window, geom.center().x(), geom.center().y(), NET::Move);
}
Note the geom.center()
. We'll need to ship our own C++ function that triggers the move at the current mouse coordinates so the mouse doesn't jump to the center.
- https://github.com/KDE/kwin/blob/2e868c50df0aab40e4814724ee090ded6bd9072e/events.cpp#L1168
if (direction == NET::Move) {
// move cursor to the provided position to prevent the window jumping there on first movement
// the expectation is that the cursor is already at the provided position,
// thus it's more a safety measurement
Cursor::setPos(QPoint(x_root, y_root));
performMouseCommand(Options::MouseMove, QPoint(x_root, y_root));
- https://github.com/KDE/kwin/blob/master/abstract_client.cpp#L998
case Options::MouseMove:
case Options::MouseUnrestrictedMove: {
if (!isMovableAcrossScreens())
break;
if (isMoveResize())
finishMoveResize(false);
setMoveResizePointerMode(PositionCenter);
setMoveResizePointerButtonDown(true);
setMoveOffset(QPoint(globalPos.x() - x(), globalPos.y() - y())); // map from global
setInvertedMoveOffset(rect().bottomRight() - moveOffset());
setUnrestrictedMoveResize((cmd == Options::MouseActivateRaiseAndUnrestrictedMove
|| cmd == Options::MouseUnrestrictedMove));
if (!startMoveResize())
setMoveResizePointerButtonDown(false);
updateCursor();
break;
}
Note:
-
onClicked
(aka mouse button is up) will:- the mouse will move the mouse to the center when
requestMove
is called - the window will follow the mouse
- let me move the mouse with keyboard arrow keys (which moves the window)
- If you press
Esc
the window resets to it's original position - If you press
Alt+Space
, it opens KRunner and you can type into it.Esc will close Krunner and cancel the drag
. - If you click, it will finish the move
- the mouse will move the mouse to the center when
-
onPressed
(aka mouse button is still down) will:- move the mouse to the center when
requestMove
is called - the window does not follow the mouse
- while the button is still down, you can use the keyboard arrow keys to control the mouse
- when the button is released, the window will move to where the mouse is
- after it's released, you can still control the mouse with the keyboard arrow keys. The window does not follow the mouse.
- after it's released, you can move the mouse, but clicking does nothing
- If you press
Esc
the window resets to it's original position - If you press
Meta
the Menu will appear, but you can't type anything or click it. - If you press
Alt+Space
to open KRunner, while KRunner doesn't show, you will regain control and mouse clicks start working again. Eg: If you doAlt+Space
a second time, it will open KRunner.
- move the mouse to the center when
Wonderful work @Zren, thanks for your interest, code and time spent on this! I'll dive in right away.
I can reproduce the bug with the "Window Move" global shortcut, so I think this might be a KWin bug.
https://bugs.kde.org/show_bug.cgi?id=392784
So according to the KWin maintainer, it seems we need to "ungrab" the mouse before calling tasksModel.requestMove(tasksModel.activeTask)
.
I recently found KDeclarative's EventGenerator class, but I can't seem to get any good results. It's still buggy.
import org.kde.kquickcontrolsaddons 2.0 // EventGenerator
MouseArea {
EventGenerator {
id: eventGenerator
}
onPressed: {
eventGenerator.sendGrabEvent(mouseArea, EventGenerator.UngrabMouse)
tasksModel.requestMove(tasksModel.activeTask)
}
}
- https://github.com/KDE/kdeclarative/blob/master/src/qmlcontrols/kquickcontrolsaddons/eventgenerator.h
Wasn't able to get it working with kdeclariative's MouseEventListener either.
- https://github.com/KDE/kdeclarative/blob/master/src/qmlcontrols/kquickcontrolsaddons/mouseeventlistener.h
Hi! I have the same problem. Some apps can be dragged from maximized status(firefox) but konsole, vscode ..... can`t dragged directorly.