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