Add window spread as click action

gh-1741
This commit is contained in:
Charles Gagnon
2025-02-11 18:26:49 -05:00
parent 7ae5e86e12
commit 0120770221
7 changed files with 113 additions and 20 deletions

View File

@@ -23,6 +23,7 @@
<value value='5' nick='QUIT'/> <value value='5' nick='QUIT'/>
<value value='6' nick='TOGGLE-SHOWPREVIEW'/> <value value='6' nick='TOGGLE-SHOWPREVIEW'/>
<value value='7' nick='TOGGLE-CYCLE'/> <value value='7' nick='TOGGLE-CYCLE'/>
<value value='8' nick='TOGGLE-SPREAD'/>
</enum> </enum>
<enum id='org.gnome.shell.extensions.dash-to-panel.scrollAction'> <enum id='org.gnome.shell.extensions.dash-to-panel.scrollAction'>
<value value='0' nick='NOTHING'/> <value value='0' nick='NOTHING'/>

View File

@@ -1156,17 +1156,21 @@ export const TaskbarAppIcon = GObject.registerClass(
if (this.window && !handleAsGrouped) { if (this.window && !handleAsGrouped) {
//ungrouped applications behaviors //ungrouped applications behaviors
switch (buttonAction) { switch (buttonAction) {
case 'RAISE': case 'LAUNCH':
case 'CYCLE': this._launchNewInstance()
case 'CYCLE-MIN': break
case 'MINIMIZE':
case 'TOGGLE-SHOWPREVIEW': case 'QUIT':
case 'TOGGLE-CYCLE': this.window.delete(global.get_current_time())
break
default:
if ( if (
!Main.overview._shown && !Main.overview._shown &&
(buttonAction == 'MINIMIZE' || (buttonAction == 'MINIMIZE' ||
buttonAction == 'TOGGLE-SHOWPREVIEW' || buttonAction == 'TOGGLE-SHOWPREVIEW' ||
buttonAction == 'TOGGLE-CYCLE' || buttonAction == 'TOGGLE-CYCLE' ||
buttonAction == 'TOGGLE-SPREAD' ||
buttonAction == 'CYCLE-MIN') && buttonAction == 'CYCLE-MIN') &&
(this._isFocusedWindow() || (this._isFocusedWindow() ||
(buttonAction == 'MINIMIZE' && (buttonAction == 'MINIMIZE' &&
@@ -1177,16 +1181,6 @@ export const TaskbarAppIcon = GObject.registerClass(
} else { } else {
Main.activateWindow(this.window) Main.activateWindow(this.window)
} }
break
case 'LAUNCH':
this._launchNewInstance()
break
case 'QUIT':
this.window.delete(global.get_current_time())
break
} }
} else { } else {
//grouped application behaviors //grouped application behaviors
@@ -1279,6 +1273,16 @@ export const TaskbarAppIcon = GObject.registerClass(
case 'QUIT': case 'QUIT':
closeAllWindows(this.app, monitor) closeAllWindows(this.app, monitor)
break break
case 'TOGGLE-SPREAD':
if (appCount == 1) {
if (appHasFocus && !Main.overview._shown)
minimizeWindow(this.app, false, monitor)
else activateFirstWindow(this.app, monitor)
} else
// return so the overview stays open if it already is
return this.dtpPanel.panelManager.showFocusedAppInOverview(
this.app,
)
} }
} }
} else { } else {
@@ -1680,8 +1684,9 @@ export const TaskbarAppIcon = GObject.registerClass(
// still visible. The border radius is large to make the shape circular // still visible. The border radius is large to make the shape circular
let panelSize = let panelSize =
this.dtpPanel.geom[this.dtpPanel.checkIfVertical() ? 'w' : 'h'] this.dtpPanel.geom[this.dtpPanel.checkIfVertical() ? 'w' : 'h']
let minFontSize = panelSize >= 32 ? 12 : 10
let fontSize = Math.round( let fontSize = Math.round(
Math.max(11, 0.3 * panelSize) / Utils.getScaleFactor(), Math.max(minFontSize, 0.3 * panelSize) / Utils.getScaleFactor(),
) )
let size = Math.round(fontSize * 1.3) let size = Math.round(fontSize * 1.3)
let style = ` let style = `
@@ -1713,10 +1718,10 @@ export const TaskbarAppIcon = GObject.registerClass(
this.window this.window
? Main.activateWindow(this.window) ? Main.activateWindow(this.window)
: activateFirstWindow(this.app, this.monitor) : activateFirstWindow(this.app, this.monitor)
} else this.dtpPanel.panelManager.showFocusedAppInOverview(this.app)
return DND.DragMotionResult.MOVE_DROP return DND.DragMotionResult.MOVE_DROP
} }
}
return DND.DragMotionResult.CONTINUE return DND.DragMotionResult.CONTINUE
} }

View File

@@ -451,8 +451,10 @@ export const Panel = GObject.registerClass(
if ( if (
source == Main.xdndHandler && source == Main.xdndHandler &&
Main.overview.shouldToggleByCornerOrButton() Main.overview.shouldToggleByCornerOrButton()
) ) {
this.panelManager.showFocusedAppInOverview(null)
Main.overview.show() Main.overview.show()
}
return DND.DragMotionResult.CONTINUE return DND.DragMotionResult.CONTINUE
} }

View File

@@ -46,6 +46,7 @@ import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js'
import * as Main from 'resource:///org/gnome/shell/ui/main.js' import * as Main from 'resource:///org/gnome/shell/ui/main.js'
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js' import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'
import { NotificationsMonitor } from './notificationsMonitor.js' import { NotificationsMonitor } from './notificationsMonitor.js'
import { Workspace } from 'resource:///org/gnome/shell/ui/workspace.js'
import * as Layout from 'resource:///org/gnome/shell/ui/layout.js' import * as Layout from 'resource:///org/gnome/shell/ui/layout.js'
import { InjectionManager } from 'resource:///org/gnome/shell/extensions/extension.js' import { InjectionManager } from 'resource:///org/gnome/shell/extensions/extension.js'
import { SETTINGS } from './extension.js' import { SETTINGS } from './extension.js'
@@ -54,6 +55,8 @@ import {
WorkspacesView, WorkspacesView,
} from 'resource:///org/gnome/shell/ui/workspacesView.js' } from 'resource:///org/gnome/shell/ui/workspacesView.js'
let tracker = Shell.WindowTracker.get_default()
export const PanelManager = class { export const PanelManager = class {
constructor() { constructor() {
this.overview = new Overview.Overview() this.overview = new Overview.Overview()
@@ -189,6 +192,13 @@ export const PanelManager = class {
Main.overview._overview._controls._workspacesDisplay, Main.overview._overview._controls._workspacesDisplay,
) )
Workspace.prototype._oldIsOverviewWindow =
Workspace.prototype._isOverviewWindow
Workspace.prototype._isOverviewWindow = (metaWindow) =>
!metaWindow.skip_taskbar &&
(!this.focusedApp ||
tracker.get_window_app(metaWindow) == this.focusedApp)
LookingGlass.LookingGlass.prototype._oldResize = LookingGlass.LookingGlass.prototype._oldResize =
LookingGlass.LookingGlass.prototype._resize LookingGlass.LookingGlass.prototype._resize
LookingGlass.LookingGlass.prototype._resize = _newLookingGlassResize LookingGlass.LookingGlass.prototype._resize = _newLookingGlassResize
@@ -363,6 +373,10 @@ export const PanelManager = class {
Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible = Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible =
this._oldSetPrimaryWorkspaceVisible this._oldSetPrimaryWorkspaceVisible
Workspace.prototype._isOverviewWindow =
Workspace.prototype._oldIsOverviewWindow
delete Workspace.prototype._oldIsOverviewWindow
LookingGlass.LookingGlass.prototype._resize = LookingGlass.LookingGlass.prototype._resize =
LookingGlass.LookingGlass.prototype._oldResize LookingGlass.LookingGlass.prototype._oldResize
delete LookingGlass.LookingGlass.prototype._oldResize delete LookingGlass.LookingGlass.prototype._oldResize
@@ -443,6 +457,69 @@ export const PanelManager = class {
} }
} }
showFocusedAppInOverview(app) {
if (app == this.focusedApp) return
this.focusedApp = app
if (!this._signalsHandler.hasLabel('overview-spread'))
this._signalsHandler.addWithLabel('overview-spread', [
Main.overview,
'hidden',
() => {
Utils.getCurrentWorkspace()
.list_windows()
.forEach((w) => {
if (
!w.minimized &&
!w.customJS_ding &&
tracker.get_window_app(w) != this.focusedApp
) {
let window = w.get_compositor_private()
;(window.get_first_child() || window).opacity = 0
Utils.animateWindowOpacity(window, {
opacity: 255,
time: 0.25,
transition: 'easeOutQuad',
})
}
})
this.focusedApp = null
this._signalsHandler.removeWithLabel('overview-spread')
},
])
if (Main.overview._shown) {
let workspaces = []
Main.overview._overview._controls._workspacesDisplay._workspacesViews.forEach(
(wv) =>
(workspaces = [
...workspaces,
...(wv._workspaces || []), // WorkspacesDisplay --> WorkspacesView (primary monitor)
...(wv._workspacesView?._workspaces || []), // WorkspacesDisplay --> SecondaryMonitorDisplay --> WorkspacesView
...(wv._workspacesView?._workspace // WorkspacesDisplay --> SecondaryMonitorDisplay --> ExtraWorkspaceView
? [wv._workspacesView?._workspace]
: []),
]),
)
workspaces.forEach((w) => {
let metaWorkspace =
w.metaWorkspace ||
Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace()
w._container.layout_manager._windows.forEach((info, preview) =>
preview.destroy(),
)
metaWorkspace.list_windows().forEach((mw) => w._doAddWindow(mw))
})
} else Main.overview.show()
}
_newSetPrimaryWorkspaceVisible(visible) { _newSetPrimaryWorkspaceVisible(visible) {
if (this._primaryVisible === visible) return if (this._primaryVisible === visible) return

View File

@@ -79,6 +79,10 @@ export const BasicHandler = class {
} }
} }
hasLabel(label) {
return !!this._storage[label]
}
/* Virtual methods to be implemented by subclass */ /* Virtual methods to be implemented by subclass */
// create single element to be stored in the storage structure // create single element to be stored in the storage structure
_create() { _create() {

View File

@@ -29,6 +29,7 @@
<item id="CYCLE-MIN" translatable="yes">Cycle windows + minimize</item> <item id="CYCLE-MIN" translatable="yes">Cycle windows + minimize</item>
<item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item> <item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item>
<item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item> <item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item>
<item id="TOGGLE-SPREAD" translatable="yes">Toggle single / Spread multiple</item>
<item id="QUIT" translatable="yes">Quit</item> <item id="QUIT" translatable="yes">Quit</item>
</items> </items>
</object> </object>
@@ -57,6 +58,7 @@
<item id="CYCLE-MIN" translatable="yes">Cycle windows + minimize</item> <item id="CYCLE-MIN" translatable="yes">Cycle windows + minimize</item>
<item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item> <item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item>
<item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item> <item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item>
<item id="TOGGLE-SPREAD" translatable="yes">Toggle single / Spread multiple</item>
<item id="QUIT" translatable="yes">Quit</item> <item id="QUIT" translatable="yes">Quit</item>
</items> </items>
</object> </object>
@@ -85,6 +87,7 @@
<item id="CYCLE-MIN" translatable="yes">Cycle windows + minimize</item> <item id="CYCLE-MIN" translatable="yes">Cycle windows + minimize</item>
<item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item> <item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item>
<item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item> <item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item>
<item id="TOGGLE-SPREAD" translatable="yes">Toggle single / Spread multiple</item>
<item id="QUIT" translatable="yes">Quit</item> <item id="QUIT" translatable="yes">Quit</item>
</items> </items>
</object> </object>

View File

@@ -37,6 +37,7 @@
<item id="CYCLE" translatable="yes">Cycle through windows</item> <item id="CYCLE" translatable="yes">Cycle through windows</item>
<item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item> <item id="TOGGLE-SHOWPREVIEW" translatable="yes">Toggle single / Preview multiple</item>
<item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item> <item id="TOGGLE-CYCLE" translatable="yes">Toggle single / Cycle multiple</item>
<item id="TOGGLE-SPREAD" translatable="yes">Toggle single / Spread multiple</item>
<item id="MINIMIZE" translatable="yes">Toggle windows</item> <item id="MINIMIZE" translatable="yes">Toggle windows</item>
<item id="RAISE" translatable="yes">Raise windows</item> <item id="RAISE" translatable="yes">Raise windows</item>
<item id="LAUNCH" translatable="yes">Launch new instance</item> <item id="LAUNCH" translatable="yes">Launch new instance</item>