Created
October 30, 2017 04:27
-
-
Save igormcoelho/e4913c167a6c912a747bfcdc025455b9 to your computer and use it in GitHub Desktop.
Small fixes over Gnome Shell plugin "Frippery Bottom Panel", to allow rearranging applications in bottom bar (as Gnome 2 did).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (C) 2011-2015 R M Yorston | |
// Licence: GPLv2+ | |
// Small fixes by Igor M. Coelho | |
const Clutter = imports.gi.Clutter; | |
const Gio = imports.gi.Gio; | |
const GLib = imports.gi.GLib; | |
const Lang = imports.lang; | |
const Mainloop = imports.mainloop; | |
const Meta = imports.gi.Meta; | |
const Pango = imports.gi.Pango; | |
const Shell = imports.gi.Shell; | |
const Signals = imports.signals; | |
const St = imports.gi.St; | |
const CheckBox = imports.ui.checkBox; | |
const Main = imports.ui.main; | |
const ModalDialog = imports.ui.modalDialog; | |
const PopupMenu = imports.ui.popupMenu; | |
const Tweener = imports.ui.tweener; | |
const WindowManager = imports.ui.windowManager; | |
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup; | |
const ExtensionUtils = imports.misc.extensionUtils; | |
const Me = ExtensionUtils.getCurrentExtension(); | |
const Convenience = Me.imports.convenience; | |
const _f = imports.gettext.domain('frippery-bottom-panel').gettext; | |
const BOTTOM_PANEL_TOOLTIP_SHOW_TIME = 0.15; | |
const BOTTOM_PANEL_TOOLTIP_HIDE_TIME = 0.1; | |
const BOTTOM_PANEL_HOVER_TIMEOUT = 300; | |
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides'; | |
const SETTINGS_NUM_ROWS = 'num-rows'; | |
const SETTINGS_SHOW_PANEL = 'show-panel'; | |
let show_panel = []; | |
/* | |
* This is a base class for containers that manage the tooltips of their | |
* children. Each child actor with a tooltip should be connected to | |
* the container hover handler: | |
* | |
* item.actor.connect('notify::hover', Lang.bind(this, function() { | |
* this._onHover(item); })); | |
* | |
*/ | |
const TooltipContainer = new Lang.Class({ | |
Name: 'TooltipContainer', | |
_init: function() { | |
this._showTooltipTimeoutId = 0; | |
this._resetHoverTimeoutId = 0; | |
this._tooltipShowing = false; | |
}, | |
_onHover: function(item) { | |
if ( item.actor.hover ) { | |
if (this._showTooltipTimeoutId == 0) { | |
let timeout = this._tooltipShowing ? | |
0 : BOTTOM_PANEL_HOVER_TIMEOUT; | |
this._showTooltipTimeoutId = Mainloop.timeout_add(timeout, | |
Lang.bind(this, function() { | |
this._tooltipShowing = true; | |
item.showTooltip(this); | |
this._showTooltipTimeoutId = 0; | |
return GLib.SOURCE_REMOVE; | |
})); | |
if (this._resetHoverTimeoutId > 0) { | |
Mainloop.source_remove(this._resetHoverTimeoutId); | |
this._resetHoverTimeoutId = 0; | |
} | |
} | |
} else { | |
if (this._showTooltipTimeoutId > 0) { | |
Mainloop.source_remove(this._showTooltipTimeoutId); | |
this._showTooltipTimeoutId = 0; | |
} | |
item.hideTooltip(); | |
if (this._tooltipShowing) { | |
this._resetHoverTimeoutId = Mainloop.timeout_add( | |
BOTTOM_PANEL_HOVER_TIMEOUT, | |
Lang.bind(this, function() { | |
this._tooltipShowing = false; | |
this._resetHoverTimeoutId = 0; | |
return GLib.SOURCE_REMOVE; | |
})); | |
} | |
} | |
} | |
}); | |
/* | |
* This is a base class for child items that have a tooltip and which allow | |
* the hover handler in the parent container class to show/hide the tooltip. | |
*/ | |
const TooltipChild = new Lang.Class({ | |
Name: 'TooltipChild', | |
_init: function() { | |
}, | |
showTooltip: function(container) { | |
this.tooltip.opacity = 0; | |
this.tooltip.show(); | |
let [stageX, stageY] = this.actor.get_transformed_position(); | |
let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1; | |
let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1; | |
let tooltipWidth = this.tooltip.get_width(); | |
let node = this.tooltip.get_theme_node(); | |
let yOffset = node.get_length('-y-offset'); | |
let y = stageY - itemHeight - yOffset; | |
let x = Math.floor(stageX + itemWidth/2 - tooltipWidth/2); | |
let parent = this.tooltip.get_parent(); | |
let parentWidth = parent.allocation.x2 - parent.allocation.x1; | |
if ( Clutter.get_default_text_direction() == Clutter.TextDirection.LTR ) { | |
// stop long tooltips falling off the right of the screen | |
x = Math.min(x, parentWidth-tooltipWidth-6); | |
// but whatever happens don't let them fall of the left | |
x = Math.max(x, 6); | |
} | |
else { | |
x = Math.max(x, 6); | |
x = Math.min(x, parentWidth-tooltipWidth-6); | |
} | |
this.tooltip.set_position(x, y); | |
Tweener.addTween(this.tooltip, | |
{ opacity: 255, | |
time: BOTTOM_PANEL_TOOLTIP_SHOW_TIME, | |
transition: 'easeOutQuad', | |
}); | |
}, | |
hideTooltip: function () { | |
this.tooltip.opacity = 255; | |
Tweener.addTween(this.tooltip, | |
{ opacity: 0, | |
time: BOTTOM_PANEL_TOOLTIP_HIDE_TIME, | |
transition: 'easeOutQuad', | |
onComplete: Lang.bind(this, function() { | |
this.tooltip.hide(); | |
}) | |
}); | |
} | |
}); | |
const MAX_BOTH = Meta.MaximizeFlags.HORIZONTAL | Meta.MaximizeFlags.VERTICAL; | |
// ========================= MENU ITEMS ESTAO AQUI ======================= | |
const WindowListItemMenu = new Lang.Class({ | |
Name: 'WindowListItemMenu', | |
Extends: PopupMenu.PopupMenu, | |
_init: function(myWindowList,metaWindow, actor) { | |
this.parent(actor, 0.0, St.Side.BOTTOM, 0); | |
this.myWindowList = myWindowList; | |
Main.uiGroup.add_actor(this.actor); | |
this.actor.hide(); | |
this.metaWindow = metaWindow; | |
this.connect('open-state-changed', Lang.bind(this, this._onToggled)); | |
let text = metaWindow.minimized ? _f('Unminimize') : _('Minimize'); | |
let item = new PopupMenu.PopupMenuItem(text); | |
item.connect('activate', Lang.bind(this, this._onMinimizeWindowActivate)); | |
this.addMenuItem(item); | |
this.itemMinimizeWindow = item; | |
text = metaWindow.get_maximized == MAX_BOTH ? | |
_('Unmaximize') : _('Maximize'); | |
item = new PopupMenu.PopupMenuItem(text); | |
item.connect('activate', Lang.bind(this, this._onMaximizeWindowActivate)); | |
this.addMenuItem(item); | |
this.itemMaximizeWindow = item; | |
item = new PopupMenu.PopupMenuItem(_('Always on Top')); | |
item.connect('activate', Lang.bind(this, this._onOnTopWindowToggle)); | |
if ( metaWindow.above ) { | |
item.setOrnament(PopupMenu.Ornament.DOT); | |
} | |
this.addMenuItem(item); | |
this.itemOnTopWindow = item; | |
/* | |
// ==================== EDITANDO TAMBEM | |
item = new PopupMenu.PopupMenuItem(_('Mover pra Esquerda')); | |
item.connect('activate', Lang.bind(this, this._onMoverEsquerda)); | |
this.addMenuItem(item); | |
this.itemOnTopWindow = item; | |
*/ | |
item = new PopupMenu.PopupMenuItem(_('Always on Visible Workspace')); | |
item.connect('activate', Lang.bind(this, this._onStickyWindowToggle)); | |
if ( metaWindow.is_on_all_workspaces() ) { | |
item.setOrnament(PopupMenu.Ornament.DOT); | |
} | |
this.addMenuItem(item); | |
this.itemStickyWindow = item; | |
// ========================================= | |
this.itemMove = []; | |
let directions = [ | |
{ text: _f('Move to Workspace Left'), | |
direction: Meta.MotionDirection.LEFT }, | |
{ text: _f('Move to Workspace Right'), | |
direction: Meta.MotionDirection.RIGHT }, | |
{ text: _('Move to Workspace Up'), | |
direction: Meta.MotionDirection.UP }, | |
{ text: _('Move to Workspace Down'), | |
direction: Meta.MotionDirection.DOWN } | |
]; | |
for ( let i=0; i<directions.length; ++i ) { | |
item = new PopupMenu.PopupMenuItem(directions[i].text); | |
item.direction = directions[i].direction; | |
item.connect('activate', Lang.bind(this, | |
this._onMoveWindowActivate)); | |
this.addMenuItem(item); | |
this.itemMove.push(item); | |
} | |
item = new PopupMenu.PopupSubMenuMenuItem( | |
_f('Move to Another Workspace')); | |
this.addMenuItem(item); | |
this._buildWorkspaceSubMenu(item.menu); | |
this.workspaceSubMenu = item.menu; | |
let separator = new PopupMenu.PopupSeparatorMenuItem(); | |
this.addMenuItem(separator); | |
item = new PopupMenu.PopupMenuItem(_('Close')); | |
item.connect('activate', Lang.bind(this, this._onCloseWindowActivate)); | |
this.addMenuItem(item); | |
}, | |
_buildWorkspaceSubMenu: function(submenu) { | |
for ( let j=0; j<global.screen.n_workspaces; ++j ) { | |
let active = global.screen.get_active_workspace_index(); | |
let item = new PopupMenu.PopupMenuItem( | |
Meta.prefs_get_workspace_name(j)); | |
item.index = j; | |
item.connect('activate', Lang.bind(this, this._onMoveToActivate)); | |
item.setSensitive(j != active); | |
submenu.addMenuItem(item, j); | |
} | |
}, | |
_onToggled: function(actor, state) { | |
if ( !state ) { | |
return; | |
} | |
let text = this.metaWindow.minimized ? | |
_f('Unminimize') : _('Minimize'); | |
this.itemMinimizeWindow.label.set_text(text); | |
text = this.metaWindow.get_maximized() == MAX_BOTH ? | |
_('Unmaximize') : _('Maximize'); | |
this.itemMaximizeWindow.label.set_text(text); | |
if ( this.metaWindow.is_above() ) { | |
this.itemOnTopWindow.setOrnament(PopupMenu.Ornament.DOT); | |
} | |
else { | |
this.itemOnTopWindow.setOrnament(PopupMenu.Ornament.NONE); | |
} | |
if ( this.metaWindow.is_on_all_workspaces() ) { | |
this.itemStickyWindow.setOrnament(PopupMenu.Ornament.DOT); | |
} | |
else { | |
this.itemStickyWindow.setOrnament(PopupMenu.Ornament.NONE); | |
} | |
let ws1 = global.screen.get_active_workspace(); | |
for ( let i=0; i<this.itemMove.length; ++i ) { | |
let ws2 = ws1.get_neighbor(this.itemMove[i].direction); | |
if ( ws1 != ws2 ) { | |
this.itemMove[i].actor.show(); | |
} | |
else { | |
this.itemMove[i].actor.hide(); | |
} | |
} | |
if ( this.workspaceSubMenu.numMenuItems != | |
global.screen.n_workspaces ) { | |
this.workspaceSubMenu.removeAll(); | |
this._buildWorkspaceSubMenu(this.workspaceSubMenu); | |
} | |
}, | |
_onMinimizeWindowActivate: function(actor, event) { | |
if ( this.metaWindow.minimized ) { | |
this.metaWindow.activate(global.get_current_time()); | |
this.itemMinimizeWindow.label.set_text(_('Minimize')); | |
} | |
else { | |
this.metaWindow.minimize(global.get_current_time()); | |
this.itemMinimizeWindow.label.set_text(_f('Unminimize')); | |
} | |
}, | |
_onMaximizeWindowActivate: function(actor, event) { | |
if ( this.metaWindow.get_maximized() == MAX_BOTH ) { | |
this.metaWindow.unmaximize(MAX_BOTH); | |
this.itemMaximizeWindow.label.set_text(_('Maximize')); | |
} | |
else { | |
this.metaWindow.maximize(MAX_BOTH); | |
this.itemMaximizeWindow.label.set_text(_('Unmaximize')); | |
} | |
}, | |
_onOnTopWindowToggle: function(item, event) { | |
if ( this.metaWindow.is_above() ) { | |
item.setOrnament(PopupMenu.Ornament.NONE); | |
this.metaWindow.unmake_above(); | |
} | |
else { | |
item.setOrnament(PopupMenu.Ornament.DOT); | |
this.metaWindow.make_above(); | |
} | |
}, | |
/* | |
// ================ EDITANDO AQUI =================== | |
// WindowListItemMenu::... | |
_onMoverEsquerda: function(item, event) { | |
// IGOR IGOR IGOR | |
//this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.metaWindow.get_stable_sequence()] = 2.5; | |
for(let i=0; i<this.myWindowList._windows.length; i++) | |
if(this.myWindowList._windows[i].metaWindow==this.metaWindow) { | |
// if i == 0, nothing to do! | |
if(i > 0) { | |
let curr_value = this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.metaWindow.get_stable_sequence()]; | |
let left_value = this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.myWindowList._windows[i-1].metaWindow.get_stable_sequence()]; | |
//this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.metaWindow.get_stable_sequence()] = (curr_value + left_value)/2.0; | |
this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.metaWindow.get_stable_sequence()] = left_value; | |
this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.myWindowList._windows[i-1].metaWindow.get_stable_sequence()] = curr_value; | |
//let tmp = this.myWindowList._windows[i-1]; | |
//this.myWindowList._windows[i-1] = this.myWindowList._windows[i]; | |
//this.myWindowList._windows[i] = tmp; | |
this.myWindowList._refreshItems(); | |
} | |
} | |
}, | |
*/ | |
_onStickyWindowToggle: function(item, event) { | |
if ( this.metaWindow.is_on_all_workspaces() ) { | |
item.setOrnament(PopupMenu.Ornament.NONE); | |
this.metaWindow.unstick(); | |
} | |
else { | |
item.setOrnament(PopupMenu.Ornament.DOT); | |
this.metaWindow.stick(); | |
} | |
}, | |
_onMoveWindowActivate: function(item, event) { | |
let ws1 = global.screen.get_active_workspace(); | |
let ws2 = ws1.get_neighbor(item.direction); | |
if ( ws2 && ws1 != ws2 ) { | |
this.metaWindow.change_workspace(ws2); // IGOR MEXEU ABAIXO! | |
//this.myWindowList.windowListUpdate[ws2.index()][this.metaWindow.get_stable_sequence()] = this.metaWindow.get_stable_sequence(); | |
} | |
}, | |
_onMoveToActivate: function(item, event) { | |
let ws1 = global.screen.get_active_workspace(); | |
let ws2 = global.screen.get_workspace_by_index(item.index); | |
if ( ws2 && ws1 != ws2 ) { | |
this.metaWindow.change_workspace(ws2); | |
} | |
}, | |
_onCloseWindowActivate: function(actor, event) { | |
this.metaWindow.delete(global.get_current_time()); | |
} | |
}); | |
// ========================================================================= | |
// ======================== DAQUI PRA BAIXO A COISA É SÉRIA ================ | |
// ========================================================================= | |
const WindowListItem = new Lang.Class({ | |
Name: 'WindowListItem', | |
Extends: TooltipChild, | |
// IGOR ADDED ONE MORE PARAMETER (myWindowList) | |
_init: function(myWindowList, app, metaWindow) { | |
this.parent(); | |
this.actor = new St.Bin({ reactive: true, | |
track_hover: true, | |
can_focus: true }); | |
this.actor._delegate = this; | |
let title = metaWindow.title ? metaWindow.title : ' '; | |
this.tooltip = new St.Label({ style_class: 'bottom-panel-tooltip'}); | |
// IGOR | |
this.metaWindow = metaWindow; | |
this.myWindowList = myWindowList; // IGOR ADDED | |
this.tooltip.set_text(title);//+metaWindow.get_stable_sequence()); | |
this.tooltip.hide(); | |
// tooltip é a mensagem que aparece acima do botão | |
Main.layoutManager.addChrome(this.tooltip); | |
this.actor.label_actor = this.tooltip; | |
this._itemBox = new St.BoxLayout({style_class: 'window-list-item-box'}); | |
this.actor.add_actor(this._itemBox); | |
this.icon = app ? app.create_icon_texture(16) : | |
new St.Icon({ icon_name: 'icon-missing', | |
icon_size: 16 }); | |
if ( !metaWindow.showing_on_its_workspace() ) { | |
title = '[' + title + ']'; | |
} | |
this.label = new St.Label({ style_class: 'window-list-item-label', | |
text: title }); | |
// this creates a label (button) for the window with the given title | |
this.label.clutter_text.ellipsize = Pango.EllipsizeMode.END; | |
this._itemBox.add(this.icon, { x_fill: false, y_fill: false }); | |
this._itemBox.add(this.label, { x_fill: true, y_fill: false }); | |
this.rightClickMenu = new WindowListItemMenu(myWindowList,metaWindow, this.actor); | |
this._notifyTitleId = metaWindow.connect('notify::title', | |
Lang.bind(this, this._onTitleChanged)); | |
this._notifyMinimizedId = metaWindow.connect('notify::minimized', | |
Lang.bind(this, this._onMinimizedChanged)); | |
this._notifyFocusId = | |
global.display.connect('notify::focus-window', | |
Lang.bind(this, this._onFocus)); | |
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | |
this.actor.connect('button-press-event', | |
Lang.bind(this, this._onButtonPress)); | |
this.actor.connect('button-release-event', // IGOR ADDED | |
Lang.bind(this, this._onButtonRelease)); | |
this.actor.connect('allocation-changed', | |
Lang.bind(this, this._updateIconGeometry)); | |
this._onFocus(); | |
}, | |
_onTitleChanged: function() { | |
let title = this.metaWindow.title; | |
this.tooltip.set_text(title); | |
if ( this.metaWindow.minimized ) { | |
title = '[' + title + ']'; | |
} | |
this.label.set_text(title); | |
}, | |
_onMinimizedChanged: function() { | |
if ( this.metaWindow.minimized ) { | |
this.icon.opacity = 127; | |
this.label.text = '[' + this.metaWindow.title + ']'; | |
} | |
else { | |
this.icon.opacity = 255; | |
this.label.text = this.metaWindow.title; | |
} | |
}, | |
_onDestroy: function() { | |
this.metaWindow.disconnect(this._notifyTitleId); | |
this.metaWindow.disconnect(this._notifyMinimizedId); | |
global.display.disconnect(this._notifyFocusId); | |
this.tooltip.destroy(); | |
this.rightClickMenu.destroy(); | |
}, | |
_onButtonPress: function(actor, event) { | |
let button = event.get_button(); | |
if ( this.rightClickMenu.isOpen ) { | |
// this.rightClickMenu.close(); | |
} | |
else if ( button == 1 ) { | |
this.myWindowList.whatDrag = this.metaWindow; | |
// start dragging (or click) | |
/* | |
if ( this.metaWindow.has_focus() ) { | |
this.metaWindow.minimize(global.get_current_time()); | |
} | |
else { | |
this.metaWindow.activate(global.get_current_time()); | |
} | |
*/ | |
} | |
else if ( button == 3 ) { | |
// this.hideTooltip(); | |
// this.rightClickMenu.open(); | |
} | |
}, | |
_onButtonRelease: function(actor, event) { | |
let button = event.get_button(); | |
if ( this.rightClickMenu.isOpen ) { | |
this.rightClickMenu.close(); | |
} | |
else if (button == 1) { | |
// do not drag if same window | |
if(this.metaWindow == this.myWindowList.whatDrag) { | |
this.myWindowList.whatDrag = null; | |
if ( this.metaWindow.has_focus() ) { | |
this.metaWindow.minimize(global.get_current_time()); | |
} | |
else { | |
this.metaWindow.activate(global.get_current_time()); | |
} | |
} | |
else // perform dragging | |
{ | |
let curr_value = this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.metaWindow.get_stable_sequence()]; | |
let other_value = this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.myWindowList.whatDrag.get_stable_sequence()]; | |
//this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.metaWindow.get_stable_sequence()] = (curr_value + left_value)/2.0; | |
this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.metaWindow.get_stable_sequence()] = other_value; | |
this.myWindowList.windowListUpdate[global.screen.get_active_workspace().index()][this.myWindowList.whatDrag.get_stable_sequence()] = curr_value; | |
//let tmp = this.myWindowList._windows[i-1]; | |
//this.myWindowList._windows[i-1] = this.myWindowList._windows[i]; | |
//this.myWindowList._windows[i] = tmp; | |
this.myWindowList._refreshItems(); | |
} | |
} | |
else if ( button == 3 ) { | |
this.hideTooltip(); | |
this.rightClickMenu.open(); | |
} | |
}, | |
_onFocus: function() { | |
if ( this.metaWindow.has_focus() ) { | |
this._itemBox.add_style_pseudo_class('focused'); | |
} | |
else { | |
this._itemBox.remove_style_pseudo_class('focused'); | |
} | |
if ( this.metaWindow.minimized ) { | |
this._itemBox.add_style_pseudo_class('minimized'); | |
} | |
else { | |
this._itemBox.remove_style_pseudo_class('minimized'); | |
} | |
}, | |
_updateIconGeometry: function() { | |
let rect = new Meta.Rectangle(); | |
[rect.x, rect.y] = this.actor.get_transformed_position(); | |
[rect.width, rect.height] = this.actor.get_transformed_size(); | |
this.metaWindow.set_icon_geometry(rect); | |
} | |
}); | |
// ====================================================== | |
// FINISH WindowListItem | |
// ====================================================== | |
// ====================================================== | |
// Begin Window List | |
// ====================================================== | |
const WindowList = new Lang.Class({ | |
Name: 'WindowList', | |
Extends: TooltipContainer, | |
_init: function() { | |
this.parent(); | |
this.actor = new St.BoxLayout({ name: 'windowList', | |
style_class: 'window-list-box' }); | |
this.actor._delegate = this; | |
this._windows = []; | |
this.whatDrag = null; // IGOR | |
this._onSwitchWorkspaceId = global.window_manager.connect( | |
'switch-workspace', | |
Lang.bind(this, this._refreshItems)); | |
this._workspaces = []; | |
this._changeWorkspaces(); | |
this._onNWorkspacesId = global.screen.connect('notify::n-workspaces', | |
Lang.bind(this, this._changeWorkspaces)); | |
this._menuManager = new PopupMenu.PopupMenuManager(this); | |
// IGOR UPDATE! | |
this.windowListUpdate = {}; | |
for(i=0;i<20;i++) this.windowListUpdate[i]={}; | |
this._refreshItems(); | |
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | |
}, | |
_onHover: function(item) { | |
if ( item.rightClickMenu.isOpen ) { | |
item.hideTooltip(); | |
} | |
else { | |
this.parent(item); | |
} | |
}, | |
_addListItem: function(metaWindow) { | |
if ( metaWindow && !metaWindow.skip_taskbar ) { | |
let tracker = Shell.WindowTracker.get_default(); | |
let app = tracker.get_window_app(metaWindow); | |
if ( app ) { | |
let item = new WindowListItem(this, app, metaWindow); // IGOR aumentou "this", passando WindowList | |
this._windows.push(item); | |
this.actor.add(item.actor); | |
item.actor.connect('notify::hover', | |
Lang.bind(this, function() { | |
this._onHover(item); | |
})); | |
this._menuManager.addMenu(item.rightClickMenu); | |
} | |
} | |
}, | |
_refreshItems: function() { | |
this.actor.destroy_all_children(); | |
this._windows = []; | |
let metaWorkspace = global.screen.get_active_workspace(); | |
let windows = metaWorkspace.list_windows(); | |
/* | |
windows.sort(function(w1, w2) { | |
var w1value = w1.get_stable_sequence(); | |
//if(this.windowListUpdate[global.screen.get_active_workspace().index()][w1value]) | |
// w1value = this.windowListUpdate[global.screen.get_active_workspace().index()][w1value]; | |
var w2value = w2.get_stable_sequence(); | |
//if(this.windowListUpdate[global.screen.get_active_workspace().index()][w2value]) | |
// w2value = this.windowListUpdate[global.screen.get_active_workspace().index()][w2value]; | |
return w1value - w2value; | |
//return w1.get_stable_sequence() - w2.get_stable_sequence(); | |
}); | |
*/ | |
// THIS SHOULD FIX WHEN WORKSPACE HAS A CHANGE... | |
for(let i=0;i<windows.length; i++) | |
if(!this.windowListUpdate[global.screen.get_active_workspace().index()][windows[i].get_stable_sequence()]) | |
this.windowListUpdate[global.screen.get_active_workspace().index()][windows[i].get_stable_sequence()] = windows[i].get_stable_sequence(); | |
// SELECTION SORT! O.o TODO: IMPROVE PLEASE! HAHAHA | |
for(let i=0;i<windows.length-1; i++) { | |
var winx = i; | |
//var bestvalue = windows[i].get_stable_sequence(); | |
//if(this.windowListUpdate[global.screen.get_active_workspace().index()][bestvalue]) | |
let bestvalue = this.windowListUpdate[global.screen.get_active_workspace().index()][windows[i].get_stable_sequence()]; | |
for(let j=i+1;j<windows.length; j++) { | |
//var sndvalue = windows[j].get_stable_sequence(); | |
//if(this.windowListUpdate[global.screen.get_active_workspace().index()][sndvalue]) | |
let sndvalue = this.windowListUpdate[global.screen.get_active_workspace().index()][windows[j].get_stable_sequence()]; | |
if(sndvalue < bestvalue) { | |
winx = j; | |
bestvalue = sndvalue; | |
} | |
} | |
if(winx != i) { | |
var tmp = windows[i]; | |
windows[i] = windows[winx]; | |
windows[winx] = tmp; | |
} | |
} | |
// IGOR | |
//this.windowListUpdate = {}; | |
//this.windowListUpdate[0] = 5; | |
// Create list items for each window | |
for ( let i = 0; i < windows.length; ++i ) { | |
this._addListItem(windows[i]); | |
//this.windowListUpdate[metaWorkspace.index()][windows[i].get_stable_sequence()] = windows[i].get_stable_sequence()+0.1; // IGOR | |
} | |
}, | |
_windowAdded: function(metaWorkspace, metaWindow) { | |
if ( metaWorkspace.index() != global.screen.get_active_workspace_index() ) { | |
return; | |
} | |
for ( let i=0; i<this._windows.length; ++i ) { | |
if ( this._windows[i].metaWindow == metaWindow ) { | |
return; | |
} | |
} | |
// IGOR ADICIONOU | |
this.windowListUpdate[metaWorkspace.index()][metaWindow.get_stable_sequence()] = metaWindow.get_stable_sequence();//+0.4; // IGOR | |
this._addListItem(metaWindow); | |
}, | |
_windowRemoved: function(metaWorkspace, metaWindow) { | |
if ( metaWorkspace.index() != global.screen.get_active_workspace_index() ) { | |
return; | |
} | |
for ( let i=0; i<this._windows.length; ++i ) { | |
if ( this._windows[i].metaWindow == metaWindow ) { | |
this.actor.remove_actor(this._windows[i].actor); | |
this._windows[i].actor.destroy(); | |
this._windows.splice(i, 1); | |
break; | |
} | |
} | |
}, | |
_changeWorkspaces: function() { | |
for ( let i=0; i<this._workspaces.length; ++i ) { | |
let ws = this._workspaces[i]; | |
ws.disconnect(ws._windowAddedId); | |
ws.disconnect(ws._windowRemovedId); | |
} | |
this._workspaces = []; | |
for ( let i=0; i<global.screen.n_workspaces; ++i ) { | |
let ws = global.screen.get_workspace_by_index(i); | |
this._workspaces[i] = ws; | |
ws._windowAddedId = ws.connect('window-added', | |
Lang.bind(this, this._windowAdded)); | |
ws._windowRemovedId = ws.connect('window-removed', | |
Lang.bind(this, this._windowRemoved)); | |
if ( i >= show_panel.length ) { | |
show_panel[i] = true; | |
} | |
} | |
}, | |
_onDestroy: function() { | |
for ( let i=0; i<this._workspaces.length; ++i ) { | |
let ws = this._workspaces[i]; | |
ws.disconnect(ws._windowAddedId); | |
ws.disconnect(ws._windowRemovedId); | |
} | |
global.window_manager.disconnect(this._onSwitchWorkspaceId); | |
global.screen.disconnect(this._onNWorkspacesId); | |
} | |
}); | |
let nrows = 1; | |
function get_ncols() { | |
let ncols = Math.floor(global.screen.n_workspaces/nrows); | |
if ( global.screen.n_workspaces%nrows != 0 ) | |
++ncols | |
return ncols; | |
} | |
const ToggleSwitch = new Lang.Class({ | |
Name: 'ToggleSwitch', | |
Extends: PopupMenu.Switch, | |
_init: function(state) { | |
this.parent(state); | |
this.actor.can_focus = true; | |
this.actor.reactive = true; | |
this.actor.add_style_class_name("bottom-panel-toggle-switch"); | |
this.actor.connect('button-release-event', | |
Lang.bind(this, this._onButtonReleaseEvent)); | |
this.actor.connect('key-press-event', | |
Lang.bind(this, this._onKeyPressEvent)); | |
this.actor.connect('key-focus-in', | |
Lang.bind(this, this._onKeyFocusIn)); | |
this.actor.connect('key-focus-out', | |
Lang.bind(this, this._onKeyFocusOut)); | |
}, | |
_onButtonReleaseEvent: function(actor, event) { | |
this.toggle(); | |
return true; | |
}, | |
_onKeyPressEvent: function(actor, event) { | |
let symbol = event.get_key_symbol(); | |
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) { | |
this.toggle(); | |
return true; | |
} | |
return false; | |
}, | |
_onKeyFocusIn: function(actor) { | |
actor.add_style_pseudo_class('active'); | |
}, | |
_onKeyFocusOut: function(actor) { | |
actor.remove_style_pseudo_class('active'); | |
} | |
}); | |
const DynamicWorkspacesSwitch = new Lang.Class({ | |
Name: 'DynamicWorkspacesSwitch', | |
Extends: ToggleSwitch, | |
_init: function() { | |
this._settings = new Gio.Settings({ schema: OVERRIDES_SCHEMA }); | |
let state = this._settings.get_boolean('dynamic-workspaces'); | |
this.parent(state); | |
}, | |
updateState: function() { | |
this.setToggleState(this._settings.get_boolean('dynamic-workspaces')); | |
}, | |
toggle: function() { | |
this.parent(); | |
this._settings.set_boolean('dynamic-workspaces', this.state); | |
} | |
}); | |
const WorkspaceDialog = new Lang.Class({ | |
Name: 'WorkspaceDialog', | |
Extends: ModalDialog.ModalDialog, | |
_init: function() { | |
this.parent({ styleClass: 'workspace-dialog' }); | |
let layout = new Clutter.TableLayout(); | |
let table = new St.Widget({reactive: true, | |
layout_manager: layout, | |
styleClass: 'workspace-dialog-table'}); | |
layout.hookup_style(table); | |
this.contentLayout.add(table, { y_align: St.Align.START }); | |
let label = new St.Label( | |
{ style_class: 'workspace-dialog-label', | |
text: _f('Number of Workspaces') }); | |
layout.pack(label, 0, 0); | |
let entry = new St.Entry({ style_class: 'workspace-dialog-entry', can_focus: true }); | |
this._workspaceEntry = entry.clutter_text; | |
layout.pack(entry, 1, 0); | |
this.setInitialKeyFocus(this._workspaceEntry); | |
label = new St.Label({ style_class: 'workspace-dialog-label', | |
text: _f('Rows in workspace switcher') }); | |
layout.pack(label, 0, 1); | |
entry = new St.Entry({ style_class: 'workspace-dialog-entry', can_focus: true }); | |
this._rowEntry = entry.clutter_text; | |
layout.pack(entry, 1, 1); | |
label = new St.Label({ style_class: 'workspace-dialog-label', | |
text: _f('Dynamic workspaces') }); | |
layout.pack(label, 0, 2); | |
this._dynamicWorkspaces = new DynamicWorkspacesSwitch(); | |
layout.pack(this._dynamicWorkspaces.actor, 1, 2); | |
label = new St.Label({ style_class: 'workspace-dialog-label', | |
text: _f('Panel visible in workspace') }); | |
layout.pack(label, 0, 3); | |
layout.child_set(label, { column_span: 2 }); | |
let cblayout = new Clutter.TableLayout(); | |
let cbtable = new St.Widget({reactive: true, | |
layout_manager: cblayout, | |
styleClass: 'workspace-dialog-table'}); | |
let ncols = get_ncols(); | |
this.cb = []; | |
for ( let r=0; r<nrows; ++r ) { | |
for ( let c=0; c<ncols; ++c ) { | |
let i = r*ncols + c; | |
if ( i < global.screen.n_workspaces ) { | |
this.cb[i] = new CheckBox.CheckBox(); | |
if ( i == 0 ) { | |
this.cb[i].actor.checked = true; | |
this.cb[i].actor.reactive = false; | |
this.cb[i].actor.can_focus = false; | |
} | |
else { | |
this.cb[i].actor.checked = show_panel[i]; | |
} | |
cblayout.pack(this.cb[i].actor, c, r); | |
cblayout.child_set(this.cb[i].actor, { x_fill: false }); | |
} | |
} | |
} | |
layout.pack(cbtable, 0, 4); | |
layout.child_set(cbtable, { column_span: 2 }); | |
let buttons = [{ action: Lang.bind(this, this.close), | |
label: _("Cancel"), | |
key: Clutter.Escape}, | |
{ action: Lang.bind(this, function() { | |
this._updateValues(); | |
this.close();}), | |
label: _("OK"), | |
default: true }]; | |
this.setButtons(buttons); | |
}, | |
open: function() { | |
this._workspaceEntry.set_text(''+global.screen.n_workspaces); | |
this._rowEntry.set_text(''+nrows); | |
this._dynamicWorkspaces.updateState(); | |
this.parent(); | |
}, | |
_updateValues: function() { | |
let changed = false; | |
for ( let i=0; i<this.cb.length; ++i ) { | |
if ( show_panel[i] != this.cb[i].actor.checked ) { | |
show_panel[i] = this.cb[i].actor.checked; | |
changed = true; | |
} | |
} | |
if ( changed ) { | |
let value = GLib.Variant.new('ab', show_panel); | |
bottomPanel._settings.set_value(SETTINGS_SHOW_PANEL, value); | |
} | |
let num = parseInt(this._workspaceEntry.get_text()); | |
if ( !isNaN(num) && num >= 2 && num <= 32 ) { | |
let old_num = global.screen.n_workspaces; | |
if ( num > old_num ) { | |
for ( let i=old_num; i<num; ++i ) { | |
global.screen.append_new_workspace(false, | |
global.get_current_time()); | |
} | |
} | |
else if ( num < old_num ) { | |
for ( let i=old_num-1; i>=num; --i ) { | |
let ws = global.screen.get_workspace_by_index(i); | |
global.screen.remove_workspace(ws, | |
global.get_current_time()); | |
} | |
} | |
} | |
let rows = parseInt(this._rowEntry.get_text()); | |
if ( !isNaN(rows) && rows > 0 && rows < 6 && rows != nrows ) { | |
if ( rows != nrows ) { | |
nrows = rows; | |
bottomPanel._settings.set_int(SETTINGS_NUM_ROWS, nrows); | |
} | |
} | |
} | |
}); | |
Signals.addSignalMethods(WorkspaceDialog.prototype); | |
const WorkspaceButton = new Lang.Class({ | |
Name: 'WorkspaceButton', | |
Extends: TooltipChild, | |
_init: function(index) { | |
this.parent(); | |
this.actor = new St.Button({ name: 'workspaceButton', | |
style_class: 'workspace-button', | |
reactive: true }); | |
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | |
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | |
this.label = new St.Label(); | |
this.actor.set_child(this.label); | |
this.tooltip = new St.Label({ style_class: 'bottom-panel-tooltip'}); | |
this.tooltip.hide(); | |
Main.layoutManager.addChrome(this.tooltip); | |
this.actor.label_actor = this.tooltip; | |
this.setIndex(index); | |
}, | |
_onClicked: function() { | |
if ( this.index >= 0 && this.index < global.screen.n_workspaces ) { | |
let metaWorkspace = global.screen.get_workspace_by_index(this.index); | |
metaWorkspace.activate(global.get_current_time()); | |
} | |
return true; | |
}, | |
_onDestroy: function() { | |
this.tooltip.destroy(); | |
}, | |
setIndex: function(index) { | |
if ( index < 0 || index >= global.screen.n_workspaces ) { | |
return; | |
} | |
this.index = index; | |
let active = global.screen.get_active_workspace_index(); | |
if ( index == active ) { | |
this.label.set_text('-' + (index+1).toString() + '-'); | |
this.actor.add_style_pseudo_class('outlined'); | |
} | |
else if ( index < global.screen.n_workspaces ) { | |
this.label.set_text((index+1).toString()); | |
this.actor.remove_style_pseudo_class('outlined'); | |
} | |
else { | |
this.label.set_text(''); | |
this.actor.remove_style_pseudo_class('outlined'); | |
} | |
this.tooltip.set_text(Meta.prefs_get_workspace_name(index)); | |
} | |
}); | |
const WorkspaceSwitcher = new Lang.Class({ | |
Name: 'WorkspaceSwitcher', | |
Extends: TooltipContainer, | |
_init: function() { | |
this.parent(); | |
this.actor = new St.BoxLayout({ name: 'workspaceSwitcher', | |
style_class: 'workspace-switcher', | |
reactive: true }); | |
this.actor.connect('button-release-event', this._showDialog); | |
this.actor.connect('scroll-event', this._onScroll); | |
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | |
this.actor._delegate = this; | |
this.button = []; | |
this._createButtons(); | |
this._onNWorkspacesId = global.screen.connect('notify::n-workspaces', | |
Lang.bind(this, this._createButtons)); | |
this._onSwitchWorkspaceId = global.window_manager.connect( | |
'switch-workspace', | |
Lang.bind(this, this._updateButtons)); | |
}, | |
_createButtons: function() { | |
this.actor.destroy_all_children(); | |
this.button = []; | |
this.row_indicator = null; | |
if ( nrows > 1 ) { | |
this.row_indicator = new St.DrawingArea({ reactive: true, | |
style_class: 'workspace-row-indicator' }); | |
this.row_indicator.connect('repaint', Lang.bind(this, this._draw)); | |
this.row_indicator.connect('button-press-event', Lang.bind(this, this._rowButtonPress)); | |
this.row_indicator.connect('scroll-event', Lang.bind(this, this._rowScroll)); | |
this.actor.add(this.row_indicator); | |
} | |
let ncols = get_ncols(); | |
let active = global.screen.get_active_workspace_index(); | |
let row = Math.floor(active/ncols); | |
let index = row*ncols; | |
for ( let i=0; i<ncols; ++i ) { | |
let btn = new WorkspaceButton(index++); | |
this.actor.add(btn.actor); | |
btn.actor.connect('notify::hover', | |
Lang.bind(this, function() { | |
this._onHover(btn); | |
})); | |
this.button[i] = btn; | |
} | |
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, | |
false, nrows, ncols); | |
}, | |
_updateButtons: function() { | |
let ncols = get_ncols(); | |
let active = global.screen.get_active_workspace_index(); | |
let row = Math.floor(active/ncols); | |
let index = row*ncols; | |
for ( let i=0; i<this.button.length; ++i ) { | |
this.button[i].setIndex(index++); | |
} | |
if ( this.row_indicator ) { | |
this.row_indicator.queue_repaint(); | |
} | |
}, | |
_showDialog: function(actor, event) { | |
if ( event.get_button() == 3 ) { | |
let _workspaceDialog = new WorkspaceDialog(); | |
_workspaceDialog.open(); | |
return true; | |
} | |
return false; | |
}, | |
_onScroll: function(actor, event) { | |
let direction = event.get_scroll_direction(); | |
let ncols = get_ncols(); | |
let active = global.screen.get_active_workspace_index(); | |
let index = global.screen.n_workspaces; | |
if ( direction == Clutter.ScrollDirection.UP ) { | |
if ( active%ncols > 0 ) { | |
index = active-1; | |
} | |
} | |
if ( direction == Clutter.ScrollDirection.DOWN ) { | |
if ( active < global.screen.n_workspaces-1 && | |
active%ncols != ncols-1 ) { | |
index = active+1; | |
} | |
} | |
if ( index >= 0 && index < global.screen.n_workspaces ) { | |
let metaWorkspace = global.screen.get_workspace_by_index(index); | |
metaWorkspace.activate(global.get_current_time()); | |
} | |
return true; | |
}, | |
_rowButtonPress: function(actor, event) { | |
if ( event.get_button() != 1 ) { | |
return false; | |
} | |
let ncols = get_ncols(); | |
let active = global.screen.get_active_workspace_index(); | |
let row = Math.floor(active/ncols); | |
let [x, y] = event.get_coords(); | |
let [wx, wy] = actor.get_transformed_position(); | |
let [w, h] = actor.get_size(); | |
y -= wy; | |
let new_row = Math.floor(nrows*y/h); | |
let index = global.screen.n_workspaces; | |
if ( new_row != row ) { | |
index = new_row*ncols + active%ncols; | |
} | |
if ( index >= 0 && index < global.screen.n_workspaces ) { | |
let metaWorkspace = global.screen.get_workspace_by_index(index); | |
metaWorkspace.activate(global.get_current_time()); | |
} | |
return true; | |
}, | |
_rowScroll: function(actor, event) { | |
let direction = event.get_scroll_direction(); | |
let ncols = get_ncols(); | |
let active = global.screen.get_active_workspace_index(); | |
let row = Math.floor(active/ncols); | |
let index = global.screen.n_workspaces; | |
if ( direction == Clutter.ScrollDirection.DOWN ) { | |
index = (row+1)*ncols + active%ncols; | |
} | |
if ( direction == Clutter.ScrollDirection.UP ) { | |
index = (row-1)*ncols + active%ncols; | |
} | |
if ( index >= 0 && index < global.screen.n_workspaces ) { | |
let metaWorkspace = global.screen.get_workspace_by_index(index); | |
metaWorkspace.activate(global.get_current_time()); | |
} | |
return true; | |
}, | |
_draw: function(area) { | |
let [width, height] = area.get_surface_size(); | |
let themeNode = this.row_indicator.get_theme_node(); | |
let cr = area.get_context(); | |
let active_color = themeNode.get_color('-active-color'); | |
let inactive_color = themeNode.get_color('-inactive-color'); | |
let ncols = get_ncols(); | |
let active = global.screen.get_active_workspace_index(); | |
let row = Math.floor(active/ncols); | |
for ( let i=0; i<nrows; ++i ) { | |
let y = (i+1)*height/(nrows+1); | |
cr.moveTo(0, y); | |
cr.lineTo(width, y); | |
let color = row == i ? active_color : inactive_color; | |
Clutter.cairo_set_source_color(cr, color); | |
cr.setLineWidth(2.0); | |
cr.stroke(); | |
} | |
}, | |
_onDestroy: function() { | |
global.screen.disconnect(this._onNWorkspacesId); | |
global.window_manager.disconnect(this._onSwitchWorkspaceId); | |
} | |
}); | |
const BottomPanel = new Lang.Class({ | |
Name: 'BottomPanel', | |
_init : function() { | |
this._settings = Convenience.getSettings(); | |
let rows = this._settings.get_int(SETTINGS_NUM_ROWS); | |
if ( !isNaN(rows) && rows > 0 && rows < 6 ) { | |
nrows = rows; | |
} | |
let b = this._settings.get_value(SETTINGS_SHOW_PANEL).deep_unpack(); | |
if ( b.length > 1 ) { | |
show_panel[0] = true; | |
for ( let i=1; i<b.length; ++i ) { | |
show_panel[i] = b[i]; | |
} | |
} | |
this.actor = new St.BoxLayout({ style_class: 'bottom-panel', | |
name: 'bottomPanel', | |
reactive: true }); | |
this.actor._delegate = this; | |
let windowList = new WindowList(); | |
this.actor.add(windowList.actor, { expand: true }); | |
this.workspaceSwitcher = new WorkspaceSwitcher(); | |
this.actor.add(this.workspaceSwitcher.actor); | |
Main.layoutManager.addChrome(this.actor, { affectsStruts: true, | |
trackFullscreen: true }); | |
Main.uiGroup.set_child_above_sibling(this.actor, | |
Main.layoutManager.panelBox); | |
this.actor.connect('style-changed', Lang.bind(this, this.relayout)); | |
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | |
this._monitorsChangedId = global.screen.connect('monitors-changed', | |
Lang.bind(this, this.relayout)); | |
this._sessionUpdatedId = Main.sessionMode.connect('updated', | |
Lang.bind(this, this._sessionUpdated)); | |
this._onSwitchWorkspaceId = global.window_manager.connect( | |
'switch-workspace', | |
Lang.bind(this, this.relayout)); | |
this._numRowsChangedId = this._settings.connect( | |
'changed::'+SETTINGS_NUM_ROWS, | |
Lang.bind(this, this._numRowsChanged)); | |
this._showPanelChangedId = this._settings.connect( | |
'changed::'+SETTINGS_SHOW_PANEL, | |
Lang.bind(this, this._showPanelChanged)); | |
}, | |
relayout: function() { | |
let bottom = Main.layoutManager.bottomMonitor; | |
let h = this.actor.get_theme_node().get_height(); | |
let active = global.screen.get_active_workspace_index(); | |
if ( !show_panel[active] ) h = -h; | |
this.actor.set_position(bottom.x, bottom.y+bottom.height-h); | |
this.actor.set_size(bottom.width, -1); | |
}, | |
_sessionUpdated: function() { | |
this.actor.visible = Main.sessionMode.hasWorkspaces; | |
}, | |
_numRowsChanged: function() { | |
let rows = this._settings.get_int(SETTINGS_NUM_ROWS); | |
if ( !isNaN(rows) && rows > 0 && rows < 6 ) { | |
nrows = rows; | |
this.workspaceSwitcher._createButtons(); | |
} | |
}, | |
_showPanelChanged: function() { | |
let b = this._settings.get_value(SETTINGS_SHOW_PANEL).deep_unpack(); | |
if ( b.length > 1 ) { | |
show_panel[0] = true; | |
for ( let i=1; i<b.length; ++i ) { | |
show_panel[i] = b[i]; | |
} | |
} | |
this.relayout(); | |
}, | |
_onDestroy: function() { | |
global.screen.disconnect(this._monitorsChangedId); | |
global.window_manager.disconnect(this._onSwitchWorkspaceId); | |
Main.sessionMode.disconnect(this._sessionUpdatedId); | |
if ( this._numRowsChangedId != 0 ) { | |
this._settings.disconnect(this._numRowsChangedId); | |
this._numRowsChangedId = 0; | |
} | |
if ( this._showPanelChangedId != 0 ) { | |
this._settings.disconnect(this._showPanelChangedId); | |
this._showPanelChangedId = 0; | |
} | |
} | |
}); | |
const FRIPPERY_TIMEOUT = 400; | |
const FripperySwitcherPopup = new Lang.Class({ | |
Name: 'FripperySwitcherPopup', | |
Extends: WorkspaceSwitcherPopup.WorkspaceSwitcherPopup, | |
_getPreferredHeight : function (actor, forWidth, alloc) { | |
let children = this._list.get_children(); | |
let workArea = Main.layoutManager.getWorkAreaForMonitor( | |
Main.layoutManager.primaryIndex); | |
let availHeight = workArea.height; | |
availHeight -= this.actor.get_theme_node().get_vertical_padding(); | |
availHeight -= this._container.get_theme_node().get_vertical_padding(); | |
availHeight -= this._list.get_theme_node().get_vertical_padding(); | |
let height = 0; | |
for (let i = 0; i < children.length; i++) { | |
let [childMinHeight, childNaturalHeight] = | |
children[i].get_preferred_height(-1); | |
height = Math.max(height, childNaturalHeight); | |
} | |
height = nrows * height; | |
let spacing = this._itemSpacing * (nrows - 1); | |
height += spacing; | |
height = Math.min(height, availHeight); | |
this._childHeight = (height - spacing) / nrows; | |
alloc.min_size = height; | |
alloc.natural_size = height; | |
}, | |
_getPreferredWidth : function (actor, forHeight, alloc) { | |
let children = this._list.get_children(); | |
let workArea = Main.layoutManager.getWorkAreaForMonitor( | |
Main.layoutManager.primaryIndex); | |
let availWidth = workArea.width; | |
availWidth -= this.actor.get_theme_node().get_horizontal_padding(); | |
availWidth -= this._container.get_theme_node().get_horizontal_padding(); | |
availWidth -= this._list.get_theme_node().get_horizontal_padding(); | |
let ncols = get_ncols(); | |
let height = 0; | |
for (let i = 0; i < children.length; i++) { | |
let [childMinHeight, childNaturalHeight] = | |
children[i].get_preferred_height(-1); | |
height = Math.max(height, childNaturalHeight); | |
} | |
let width = ncols * height * workArea.width/workArea.height; | |
let spacing = this._itemSpacing * (ncols - 1); | |
width += spacing; | |
width = Math.min(width, availWidth); | |
this._childWidth = (width - spacing) / ncols; | |
alloc.min_size = width; | |
alloc.natural_size = width; | |
}, | |
_allocate : function (actor, box, flags) { | |
let children = this._list.get_children(); | |
let childBox = new Clutter.ActorBox(); | |
let ncols = get_ncols(); | |
for ( let ir=0; ir<nrows; ++ir ) { | |
for ( let ic=0; ic<ncols; ++ic ) { | |
let i = ncols*ir + ic; | |
let x = box.x1 + ic * (this._childWidth + this._itemSpacing); | |
childBox.x1 = x; | |
childBox.x2 = x + this._childWidth; | |
let y = box.y1 + ir * (this._childHeight + this._itemSpacing); | |
childBox.y1 = y; | |
childBox.y2 = y + this._childHeight; | |
children[i].allocate(childBox, flags); | |
} | |
} | |
}, | |
_redisplay : function() { | |
this._list.destroy_all_children(); | |
for (let i = 0; i < global.screen.n_workspaces; i++) { | |
let indicator = null; | |
if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.LEFT) | |
indicator = new St.Bin({ style_class: 'ws-switcher-active-left' }); | |
else if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.RIGHT) | |
indicator = new St.Bin({ style_class: 'ws-switcher-active-right' }); | |
else if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.UP) | |
indicator = new St.Bin({ style_class: 'ws-switcher-active-up' }); | |
else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN) | |
indicator = new St.Bin({ style_class: 'ws-switcher-active-down' }); | |
else | |
indicator = new St.Bin({ style_class: 'ws-switcher-box' }); | |
this._list.add_actor(indicator); | |
} | |
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); | |
let [containerMinHeight, containerNatHeight] = this._container.get_preferred_height(global.screen_width); | |
let [containerMinWidth, containerNatWidth] = this._container.get_preferred_width(containerNatHeight); | |
this._container.x = workArea.x + Math.floor((workArea.width - containerNatWidth) / 2); | |
this._container.y = workArea.y + Math.floor((workArea.height - containerNatHeight) / 2); | |
}, | |
display : function(direction, activeWorkspaceIndex) { | |
this._direction = direction; | |
this._activeWorkspaceIndex = activeWorkspaceIndex; | |
this._redisplay(); | |
if (this._timeoutId != 0) | |
Mainloop.source_remove(this._timeoutId); | |
this._timeoutId = Mainloop.timeout_add(FRIPPERY_TIMEOUT, Lang.bind(this, this._onTimeout)); | |
this._show(); | |
} | |
}); | |
let myShowWorkspaceSwitcher, origShowWorkspaceSwitcher; | |
function init(extensionMeta) { | |
Convenience.initTranslations(); | |
origShowWorkspaceSwitcher = | |
WindowManager.WindowManager.prototype._showWorkspaceSwitcher; | |
myShowWorkspaceSwitcher = function(display, screen, window, binding) { | |
if (!Main.sessionMode.hasWorkspaces) | |
return; | |
if (screen.n_workspaces == 1) | |
return; | |
let [action,,,target] = binding.get_name().split('-'); | |
let newWs; | |
let direction; | |
if (isNaN(target)) { | |
direction = Meta.MotionDirection[target.toUpperCase()]; | |
newWs = screen.get_active_workspace().get_neighbor(direction); | |
} else if (target > 0) { | |
target--; | |
newWs = screen.get_workspace_by_index(target); | |
// FIXME add proper support for switching to numbered workspace | |
if (screen.get_active_workspace().index() > target) | |
direction = Meta.MotionDirection.UP; | |
else | |
direction = Meta.MotionDirection.DOWN; | |
} | |
if (action == 'switch') | |
this.actionMoveWorkspace(newWs); | |
else | |
this.actionMoveWindow(window, newWs); | |
if (!Main.overview.visible) { | |
if (this._workspaceSwitcherPopup == null) { | |
this._workspaceSwitcherPopup = new FripperySwitcherPopup(); | |
this._workspaceSwitcherPopup.connect('destroy', | |
Lang.bind(this, function() { | |
this._workspaceSwitcherPopup = null; | |
})); | |
} | |
this._workspaceSwitcherPopup.display(direction, newWs.index()); | |
} | |
}; | |
WindowManager.WindowManager.prototype._reset = function() { | |
Meta.keybindings_set_custom_handler('switch-to-workspace-left', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
Meta.keybindings_set_custom_handler('switch-to-workspace-right', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
Meta.keybindings_set_custom_handler('switch-to-workspace-up', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
Meta.keybindings_set_custom_handler('switch-to-workspace-down', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
Meta.keybindings_set_custom_handler('move-to-workspace-left', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
Meta.keybindings_set_custom_handler('move-to-workspace-right', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
Meta.keybindings_set_custom_handler('move-to-workspace-up', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
Meta.keybindings_set_custom_handler('move-to-workspace-down', | |
Lang.bind(this, this._showWorkspaceSwitcher)); | |
this._workspaceSwitcherPopup = null; | |
}; | |
} | |
let bottomPanel = null; | |
function enable() { | |
if ( Main.sessionMode.currentMode == 'classic' ) { | |
return; | |
} | |
WindowManager.WindowManager.prototype._showWorkspaceSwitcher = | |
myShowWorkspaceSwitcher; | |
Main.wm._reset(); | |
bottomPanel = new BottomPanel(); | |
bottomPanel.relayout(); | |
} | |
function disable() { | |
if ( Main.sessionMode.currentMode == 'classic' ) { | |
return; | |
} | |
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1); | |
WindowManager.WindowManager.prototype._showWorkspaceSwitcher = | |
origShowWorkspaceSwitcher; | |
Main.wm._reset(); | |
bottomPanel.actor.destroy(); | |
bottomPanel = null; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment