Skip to content

Commit

Permalink
Add drag-and-drop assist.
Browse files Browse the repository at this point in the history
Switch windows by dragging and holding item on dock.
Cycle windows if more than one. Launch app if pinned but not running.
Fixes issue #278
  • Loading branch information
Valent-in committed Jan 3, 2022
1 parent 39e5597 commit 8a68a7d
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
15 changes: 15 additions & 0 deletions appIcons.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,19 @@ var DockAbstractAppIcon = GObject.registerClass({

this._previewMenuManager = null;
this._previewMenu = null;

let globalDnd = Meta.get_backend().get_dnd();
let globalDndSignals = [];

this.globalDnd = {
connect: function (s, f) {
globalDndSignals.push(globalDnd.connect(s, f))
},

disconnectIcon: function () {
globalDndSignals.forEach((e) => globalDnd.disconnect(e))
}
}
}

_onDestroy() {
Expand All @@ -201,6 +214,8 @@ var DockAbstractAppIcon = GObject.registerClass({
// It can be safely removed once it get solved upstrea.
if (this._menu)
this._menu.close(false);

this.globalDnd.disconnectIcon();
}

ownsWindow(window) {
Expand Down
98 changes: 98 additions & 0 deletions dash.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,70 @@ var DockDash = GObject.registerClass({
}
});

let switchTimerId = { id: 0 };
let isDndTarget = false;

// Detect dragging over icon (Wayland)
appIcon.connect('motion-event', (obj, event) => {
let [modifier] = event.get_state_full();
let mask = Clutter.ModifierType.BUTTON1_MASK;

if ((modifier & mask) && !isDndTarget) {
isDndTarget = true;
switchTimerId = this._setWindowSwitchTimeout(appIcon);
}
});

appIcon.connect('leave-event', () => {
resetTimer(switchTimerId);
isDndTarget = false;
});

appIcon.globalDnd.connect('dnd-enter', () => {
resetTimer(switchTimerId);
isDndTarget = false;
});

appIcon.globalDnd.connect('dnd-leave', () => {
resetTimer(switchTimerId);
isDndTarget = false;
});

// Detect dragging over icon (X11)
appIcon.globalDnd.connect('dnd-position-change', (obj, x, y) => {
if (isCoordsInActor(x, y, this._scrollView) && isCoordsInActor(x, y, item)) {

if (isDndTarget)
return
isDndTarget = true;

switchTimerId = this._setWindowSwitchTimeout(appIcon);

this._ensureAppIconVisibilityTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, 100, () => {
ensureActorVisibleInScrollView(this._scrollView, appIcon);
this._ensureAppIconVisibilityTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});

} else {
resetTimer(switchTimerId);
isDndTarget = false;
}
});

function resetTimer(timerIdObj) {
if (timerIdObj.id > 0) {
GLib.source_remove(timerIdObj.id);
timerIdObj.id = 0;
}
}

function isCoordsInActor(x, y, actor) {
let [gotPos, lx, ly] = actor.transform_stage_point(x, y);
return gotPos && lx > 0 && lx < actor.width && ly > 0 && ly < actor.height;
}

// Override default AppIcon label_actor, now the
// accessible_name is set at DashItemContainer.setLabelText
appIcon.label_actor = null;
Expand All @@ -539,6 +603,40 @@ var DockDash = GObject.registerClass({
return item;
}

_setWindowSwitchTimeout(appIconObj) {
const windowSwitchTimeout = 1000;
let windows = appIconObj.getInterestingWindows();
let index = windows.length > 0 && windows[0].has_focus() ? 1 : 0;
let timerIdObj = { id: 0 };

timerIdObj.id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, windowSwitchTimeout, function timeoutHandler() {
if (windows.length > 1) {
if (windows[index])
Main.activateWindow(windows[index]);

if (++index < windows.length) {
timerIdObj.id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, windowSwitchTimeout, timeoutHandler);
} else {
timerIdObj.id = 0;
}
} else {
timerIdObj.id = 0;
let appIsRunning = appIconObj && appIconObj.app && appIconObj.app.state == Shell.AppState.RUNNING
&& windows.length > 0;

if (appIsRunning) {
appIconObj.activate();
} else {
appIconObj.launchNewWindow();
}
}

return GLib.SOURCE_REMOVE;
});

return timerIdObj;
}

_requireVisibility() {
this.requiresVisibility = true;

Expand Down

0 comments on commit 8a68a7d

Please sign in to comment.