Add option to ungroup the application instances and show their window titles

New features
 - ungroup aplication instances, while keeping them grouped by application
 - when ungrouped, display the window titles and allow the customization of their font-size and width
 - when ungrouped, optionally have the favorite application icons serve as launchers
 - customize the focused application indicator's color and opacity

Bug fixes
 - fix icons not showing up immediately when lauching an application
 - fix message "g_signal_handler_disconnect: assertion 'handler_id > 0" occurring when destroying an icon
 - fix message "st_widget_get_theme_node called on the widget [# StIcon:last-child first-child] which is not in the stage." occurring after disabling the extension
 - fix message "[.../dash-to-panel@jderose9.github.com/windowPreview.js 1008]: reference to undefined property 0" occurring when restarting gnome-shell
 - fix message "[.../dash-to-panel@jderose9.github.com/taskbar.js 753]: reference to undefined property 0" occurring when restarting gnome-shell
This commit is contained in:
Charles Gagnon
2018-01-14 13:53:58 -05:00
parent 9b5f2649b3
commit f7bf526a55
12 changed files with 1128 additions and 368 deletions

View File

@@ -3,7 +3,7 @@
UUID = dash-to-panel@jderose9.github.com
BASE_MODULES = extension.js stylesheet.css metadata.json COPYING README.md
EXTRA_MODULES = appIcons.js convenience.js panel.js panelStyle.js overview.js taskbar.js windowPreview.js prefs.js Settings.ui
EXTRA_IMAGES = highlight_bg.svg highlight_stacked_bg.svg
EXTRA_IMAGES = highlight_stacked_bg.svg
TOLOCALIZE = prefs.js appIcons.js
MSGSRC = $(wildcard po/*.po)
ifeq ($(strip $(DESTDIR)),)

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.2 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkAdjustment" id="appicon_margin_adjustment">
@@ -8,6 +8,12 @@
<property name="step_increment">0.01</property>
<property name="page_increment">0.10000000000000001</property>
</object>
<object class="GtkAdjustment" id="focus_highlight_opacity_adjustment">
<property name="lower">5</property>
<property name="upper">100</property>
<property name="step_increment">5</property>
<property name="page_increment">5</property>
</object>
<object class="GtkBox" id="box_middle_click_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -408,6 +414,7 @@
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="row_spacing">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="focus_highlight_label">
@@ -434,6 +441,59 @@
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="focus_highlight_color_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Highlight color</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkColorButton" id="focus_highlight_color_colorbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="focus_highlight_opacity_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Highlight opacity</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="focus_highlight_opacity_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">focus_highlight_opacity_adjustment</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
</child>
</object>
@@ -457,7 +517,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Height (px)</property>
<property name="label" translatable="yes">Indicator height (px)</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -504,7 +564,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Color - Override Theme</property>
<property name="label" translatable="yes">Indicator color - Override Theme</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -547,7 +607,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">1 window open</property>
<property name="label" translatable="yes">1 window open (or ungrouped)</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -733,7 +793,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">1 window open</property>
<property name="label" translatable="yes">1 window open (or ungrouped)</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -888,6 +948,277 @@
<property name="step_increment">25</property>
<property name="page_increment">100</property>
</object>
<object class="GtkAdjustment" id="group_apps_label_font_size_adjustment">
<property name="lower">6</property>
<property name="upper">24</property>
<property name="step_increment">1</property>
<property name="page_increment">100</property>
</object>
<object class="GtkAdjustment" id="group_apps_label_max_width_adjustment">
<property name="lower">40</property>
<property name="upper">320</property>
<property name="step_increment">10</property>
<property name="page_increment">100</property>
</object>
<object class="GtkBox" id="box_group_apps_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame" id="frame_group_apps_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="listbox_group_apps_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
<child>
<object class="GtkListBoxRow" id="listbox_group_apps_label_font_size">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_group_apps_label_font_size">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkSpinButton" id="group_apps_label_font_size_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">group_apps_label_font_size_adjustment</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="group_apps_label_font_size_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Font size (px) of the application titles (default is 14)</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listbox_group_apps_label_max_width">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_group_apps_label_max_width">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="group_apps_label_max_width_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Maximum width (px) of the application titles (default is 160)</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="group_apps_label_max_width_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">group_apps_label_max_width_adjustment</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listbox_group_apps_use_fixed_width">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_group_apps_use_fixed_width">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="group_apps_use_fixed_width_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Use a fixed width for the application titles</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="group_apps_use_fixed_width_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="group_apps_use_fixed_width_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">The application titles all have the same width, even if their texts are shorter than the maximum width. The maximum width value is used as the fixed width.</property>
<property name="wrap">True</property>
<property name="max_width_chars">40</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listbox_group_apps_underline_unfocused">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_group_apps_underline_unfocused">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="group_apps_underline_unfocused_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Display running indicators on unfocused applications</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="group_apps_underline_unfocused_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listbox_group_apps_use_launchers">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_group_apps_use_launchers">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="group_apps_use_launchers_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Use the favorite icons as application launchers</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="group_apps_use_launchers_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<object class="GtkAdjustment" id="leave_timeout_adjustment">
<property name="upper">9999</property>
<property name="step_increment">25</property>
@@ -2300,8 +2631,8 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Show favorite applications</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
@@ -2659,6 +2990,87 @@
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="group_apps_row">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="isolate_workspaces_grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="group_apps_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Group applications</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="group_apps_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="show_group_apps_options_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="xalign">0.46000000834465027</property>
<child>
<object class="GtkImage" id="image_window_previews_options1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-system-symbolic</property>
</object>
</child>
<style>
<class name="circular"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="group_apps_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label_item">

View File

@@ -95,16 +95,40 @@ var taskbarAppIcon = new Lang.Class({
Name: 'DashToPanel.TaskbarAppIcon',
Extends: AppDisplay.AppIcon,
_init: function(settings, app, iconParams, onActivateOverride) {
_init: function(settings, appInfo, iconParams, onActivateOverride) {
// a prefix is required to avoid conflicting with the parent class variable
this._dtpSettings = settings;
this._nWindows = 0;
this.window = appInfo.window;
this.isLauncher = appInfo.isLauncher;
this.parent(app, iconParams, onActivateOverride);
this.parent(appInfo.app, iconParams, onActivateOverride);
this._dot.set_width(0);
this._focused = tracker.focus_app == this.app;
this._isGroupApps = this._dtpSettings.get_boolean('group-apps');
if (appInfo.window) {
let outbox = new St.Widget({ layout_manager: new Clutter.BinLayout() });
let box = new St.BoxLayout();
this._windowTitle = new St.Label({
y_align: Clutter.ActorAlign.CENTER,
x_align: Clutter.ActorAlign.START,
style_class: 'overview-label'
});
this._updateWindowTitle();
this._updateWindowTitleStyle();
this.actor.remove_actor(this._iconContainer);
box.add_child(this._iconContainer);
box.add_child(this._windowTitle);
outbox.add_child(box);
this.actor.set_child(outbox);
}
// Monitor windows-changes instead of app state.
// Keep using the same Id and function callback (that is extended)
@@ -113,38 +137,54 @@ var taskbarAppIcon = new Lang.Class({
this._stateChangedId = 0;
}
this._stateChangedId = this.app.connect('windows-changed',
Lang.bind(this, this.onWindowsChanged));
this._focusAppChangedId = tracker.connect('notify::focus-app',
Lang.bind(this, this._onFocusAppChanged));
if (!this.window) {
this._stateChangedId = this.app.connect('windows-changed',
Lang.bind(this, this.onWindowsChanged));
this._focusWindowChangedId = 0;
this._titleWindowChangeId = 0;
} else {
this._focusWindowChangedId = global.display.connect('notify::focus-window',
Lang.bind(this, this._onFocusAppChanged));
this._titleWindowChangeId = this.window.connect('notify::title',
Lang.bind(this, this._updateWindowTitle));
}
this._overviewWindowDragEndId = Main.overview.connect('window-drag-end',
Lang.bind(this, this._onOverviewWindowDragEnd));
this._switchWorkspaceId = global.window_manager.connect('switch-workspace',
Lang.bind(this, this._onSwitchWorkspace));
this._focusedDots = null;
this._unfocusedDots = null;
this._showDots();
this._dtpSettings.connect('changed::dot-position', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-size', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-style-focused', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-style-unfocused', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-override', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-1', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-2', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-3', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-4', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-unfocused-different', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-unfocused-1', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-unfocused-2', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-unfocused-3', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::dot-color-unfocused-4', Lang.bind(this, this._settingsChangeRefresh));
this._dtpSettings.connect('changed::focus-highlight', Lang.bind(this, this._settingsChangeRefresh));
this.windowPreview = null;
this._settingsConnectIds = [
this._dtpSettings.connect('changed::dot-position', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-size', Lang.bind(this, this._updateDotSize)),
this._dtpSettings.connect('changed::dot-style-focused', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-style-unfocused', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-override', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-1', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-2', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-3', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-4', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-unfocused-different', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-unfocused-1', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-unfocused-2', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-unfocused-3', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::dot-color-unfocused-4', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::focus-highlight', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::focus-highlight-color', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::focus-highlight-opacity', Lang.bind(this, this._settingsChangeRefresh)),
this._dtpSettings.connect('changed::group-apps-label-font-size', Lang.bind(this, this._updateWindowTitleStyle)),
this._dtpSettings.connect('changed::group-apps-label-max-width', Lang.bind(this, this._updateWindowTitleStyle)),
this._dtpSettings.connect('changed::group-apps-use-fixed-width', Lang.bind(this, this._updateWindowTitleStyle)),
this._dtpSettings.connect('changed::group-apps-underline-unfocused', Lang.bind(this, this._settingsChangeRefresh))
];
this.forcedOverview = false;
@@ -236,7 +276,7 @@ var taskbarAppIcon = new Lang.Class({
},
shouldShowTooltip: function() {
if (this._dtpSettings.get_boolean("show-window-previews") &&
if (!this.isLauncher && this._dtpSettings.get_boolean("show-window-previews") &&
getInterestingWindows(this.app, this._dtpSettings).length > 0) {
return false;
} else {
@@ -255,8 +295,20 @@ var taskbarAppIcon = new Lang.Class({
if(this._overviewWindowDragEndId)
Main.overview.disconnect(this._overviewWindowDragEndId);
if(this._focusWindowChangedId)
global.display.disconnect(this._focusWindowChangedId);
if(this._titleWindowChangeId)
this.window.disconnect(this._titleWindowChangeId);
if(this._switchWorkspaceId)
global.window_manager.disconnect(this._switchWorkspaceId);
for (let i = 0, l = this._settingsConnectIds.length; i < l; ++i) {
if (this._settingsConnectIds[i]) {
this._dtpSettings.disconnect(this._settingsConnectIds[i]);
}
}
},
onWindowsChanged: function() {
@@ -272,18 +324,17 @@ var taskbarAppIcon = new Lang.Class({
// resulting in an error when assigned to the a rect. This is a more like
// a workaround to prevent flooding the system with errors.
if (this.actor.get_stage() == null)
return
return;
let rect = new Meta.Rectangle();
[rect.x, rect.y] = this.actor.get_transformed_position();
[rect.width, rect.height] = this.actor.get_transformed_size();
let windows = this.app.get_windows();
let windows = this.window ? [this.window] : this.app.get_windows();
windows.forEach(function(w) {
w.set_icon_geometry(rect);
});
},
_showDots: function() {
@@ -293,7 +344,22 @@ var taskbarAppIcon = new Lang.Class({
return;
}
this._focusedDots = new St.DrawingArea({width:1, y_expand: true});
let container = this.actor.get_children()[0];
if (!this._isGroupApps) {
this._focusedDots = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true,
height: this._getRunningIndicatorHeight(),
visible: false
});
let mappedId = this.actor.connect('notify::mapped', () => {
this._displayProperIndicator();
this.actor.disconnect(mappedId);
});
} else {
this._focusedDots = new St.DrawingArea({ width:1, y_expand: true });
this._focusedDots._tweeningToWidth = null;
this._unfocusedDots = new St.DrawingArea({width:1, y_expand: true});
this._unfocusedDots._tweeningToWidth = null;
@@ -318,42 +384,83 @@ var taskbarAppIcon = new Lang.Class({
this._displayProperIndicator();
}));
this._iconContainer.add_child(this._focusedDots);
this._iconContainer.add_child(this._unfocusedDots);
container.add_child(this._unfocusedDots);
this._updateCounterClass();
}
container.add_child(this._focusedDots);
},
_updateDotSize: function() {
if (!this._isGroupApps) {
this._focusedDots.height = this._getRunningIndicatorHeight();
}
this._settingsChangeRefresh();
},
_settingsChangeRefresh: function() {
if (this._isGroupApps) {
this._updateCounterClass();
this._focusedDots.queue_repaint();
this._unfocusedDots.queue_repaint();
}
this._displayProperIndicator(true);
},
_setIconStyle: function() {
_updateWindowTitleStyle: function() {
if (this._windowTitle) {
let useFixedWidth = this._dtpSettings.get_boolean('group-apps-use-fixed-width');
let maxLabelWidth = this._dtpSettings.get_int('group-apps-label-max-width');
this._windowTitle.clutter_text.natural_width = useFixedWidth ? maxLabelWidth : 0;
this._windowTitle.clutter_text.natural_width_set = useFixedWidth;
this._windowTitle.set_style('font-size: ' + this._dtpSettings.get_int('group-apps-label-font-size') + 'px;' +
(useFixedWidth ? '' : 'max-width: ' + maxLabelWidth + 'px;'));
}
},
_updateWindowTitle: function() {
if (this._windowTitle.text != this.window.title) {
this._windowTitle.text = this.window.title;
if (this._focusedDots) {
this._displayProperIndicator();
}
}
},
_setIconStyle: function(isFocused) {
let margin = this._dtpSettings.get_int('appicon-margin');
let inlineStyle = 'margin: 0 ' + margin + 'px;';
if(this._dtpSettings.get_boolean('focus-highlight') && tracker.focus_app == this.app && !this._isThemeProvidingIndicator()) {
let containerWidth = this._iconContainer.get_width() / St.ThemeContext.get_for_stage(global.stage).scale_factor;
if(this._dtpSettings.get_boolean('focus-highlight') &&
tracker.focus_app == this.app && !this.isLauncher &&
(!this.window || isFocused) && !this._isThemeProvidingIndicator()) {
let focusedDotStyle = this._dtpSettings.get_string('dot-style-focused');
let isWide = this._isWideDotStyle(focusedDotStyle);
let pos = this._dtpSettings.get_string('dot-position');
let highlightMargin = isWide ? this._dtpSettings.get_int('dot-size') : 0;
if(focusedDotStyle == DOT_STYLE.CILIORA || focusedDotStyle == DOT_STYLE.SEGMENTED)
if(!this.window) {
let containerWidth = this._iconContainer.get_width() / St.ThemeContext.get_for_stage(global.stage).scale_factor;
let backgroundSize = containerWidth + "px " +
(containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;";
if (focusedDotStyle == DOT_STYLE.CILIORA || focusedDotStyle == DOT_STYLE.SEGMENTED)
highlightMargin += 1;
inlineStyle += "background-image: url('" +
Me.path + "/img/highlight_" +
((this._nWindows > 1 && focusedDotStyle == DOT_STYLE.METRO) ? "stacked_" : "") +
"bg.svg'); background-position: 0 " +
(pos == DOT_POSITION.TOP ? highlightMargin : 0) +
"px; background-size: " +
containerWidth + "px " +
(containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;";
if (this._nWindows > 1 && focusedDotStyle == DOT_STYLE.METRO) {
inlineStyle += "background-image: url('" + Me.path + "/img/highlight_stacked_bg.svg');" +
"background-position: 0 " + (pos == DOT_POSITION.TOP ? highlightMargin : 0) + "px;" +
"background-size: " + backgroundSize;
}
}
inlineStyle += "background-color: " + cssHexTocssRgba(this._dtpSettings.get_string('focus-highlight-color'),
this._dtpSettings.get_int('focus-highlight-opacity') * 0.01);
}
// graphical glitches if i dont set this on a timeout
@@ -416,10 +523,22 @@ var taskbarAppIcon = new Lang.Class({
},
_displayProperIndicator: function (force) {
this._setIconStyle();
let isFocused = this._isFocusedWindow();
let containerWidth = this._iconContainer.get_width();
let isFocused = (tracker.focus_app == this.app);
this._setIconStyle(isFocused);
if(!this._isGroupApps) {
if (this.window && (this._dtpSettings.get_boolean('group-apps-underline-unfocused') || isFocused)) {
let dotPosition = this._dtpSettings.get_string('dot-position');
this._focusedDots.y_align = dotPosition == DOT_POSITION.TOP ? Clutter.ActorAlign.START : Clutter.ActorAlign.END;
this._focusedDots.background_color = this._getRunningIndicatorColor(isFocused);
this._focusedDots.show();
} else if (this._focusedDots.visible) {
this._focusedDots.hide();
}
} else {
let containerWidth = this.actor.get_children()[0].width;
let focusedDotStyle = this._dtpSettings.get_string('dot-style-focused');
let unfocusedDotStyle = this._dtpSettings.get_string('dot-style-unfocused');
let focusedIsWide = this._isWideDotStyle(focusedDotStyle);
@@ -430,6 +549,7 @@ var taskbarAppIcon = new Lang.Class({
let newUnfocusedDotsWidth = 0;
let newUnfocusedDotsOpacity = 0;
isFocused = (tracker.focus_app == this.app);
if(isFocused)
this.actor.add_style_class_name('focused');
@@ -461,13 +581,13 @@ var taskbarAppIcon = new Lang.Class({
(this._focusedDots.width != newUnfocusedDotsWidth || this._unfocusedDots.width != newFocusedDotsWidth))) {
this._animateDotDisplay(this._focusedDots, newFocusedDotsWidth, this._unfocusedDots, newUnfocusedDotsOpacity, force);
this._animateDotDisplay(this._unfocusedDots, newUnfocusedDotsWidth, this._focusedDots, newFocusedDotsOpacity, force);
}
else {
} else {
this._focusedDots.opacity = newFocusedDotsOpacity;
this._unfocusedDots.opacity = newUnfocusedDotsOpacity;
this._focusedDots.width = newFocusedDotsWidth;
this._unfocusedDots.width = newUnfocusedDotsWidth;
}
}
},
_animateDotDisplay: function (dots, newWidth, otherDots, newOtherOpacity, force) {
@@ -490,6 +610,20 @@ var taskbarAppIcon = new Lang.Class({
}
},
_isFocusedWindow: function() {
let focusedWindow = global.display.focus_window;
while (focusedWindow) {
if (focusedWindow == this.window) {
return true;
}
focusedWindow = focusedWindow.get_transient_for();
}
return false;
},
_isWideDotStyle: function(dotStyle) {
return dotStyle == DOT_STYLE.SEGMENTED ||
dotStyle == DOT_STYLE.CILIORA ||
@@ -549,16 +683,38 @@ var taskbarAppIcon = new Lang.Class({
&& getInterestingWindows(this.app, this._dtpSettings).length > 0
// We customize the action only when the application is already running
if (appIsRunning) {
if (appIsRunning && !this.isLauncher) {
if (this.window) {
//ungrouped applications behaviors
switch (buttonAction) {
case 'RAISE': case 'CYCLE': case 'CYCLE-MIN': case 'MINIMIZE':
if (!Main.overview._shown &&
(buttonAction == 'MINIMIZE' ||
(buttonAction == 'CYCLE-MIN' && this._isFocusedWindow()))) {
this.window.minimize();
} else {
Main.activateWindow(this.window);
}
break;
case "LAUNCH":
this._launchNewInstance();
break;
case "QUIT":
this.windows.delete(global.get_current_time());
break;
}
} else {
//grouped application behaviors
switch (buttonAction) {
case "RAISE":
activateAllWindows(this.app, this._dtpSettings);
break;
case "LAUNCH":
if(this._dtpSettings.get_boolean('animate-window-launch'))
this.animateLaunch();
this.app.open_new_window(-1);
this._launchNewInstance();
break;
case "MINIMIZE":
@@ -612,15 +768,22 @@ var taskbarAppIcon = new Lang.Class({
break;
}
}
}
else {
if(this._dtpSettings.get_boolean('animate-window-launch'))
this.animateLaunch();
this.app.open_new_window(-1);
this._launchNewInstance();
}
Main.overview.hide();
},
_launchNewInstance: function() {
if(this._dtpSettings.get_boolean('animate-window-launch')) {
this.animateLaunch();
}
this.app.open_new_window(-1);
},
_updateCounterClass: function() {
let maxN = 4;
this._nWindows = Math.min(getInterestingWindows(this.app, this._dtpSettings).length, maxN);
@@ -634,26 +797,39 @@ var taskbarAppIcon = new Lang.Class({
}
},
_drawRunningIndicator: function(area, type, isFocused) {
let bodyColor;
_getRunningIndicatorHeight: function() {
return this._dtpSettings.get_int('dot-size') * St.ThemeContext.get_for_stage(global.stage).scale_factor;
},
_getRunningIndicatorColor: function(isFocused) {
let color;
if(this._dtpSettings.get_boolean('dot-color-override')) {
let dotColorSettingPrefix = 'dot-color-';
if(!isFocused && this._dtpSettings.get_boolean('dot-color-unfocused-different'))
dotColorSettingPrefix = 'dot-color-unfocused-';
bodyColor = Clutter.color_from_string(this._dtpSettings.get_string(dotColorSettingPrefix + (this._nWindows > 0 ? this._nWindows : 1)))[1];
color = Clutter.color_from_string(this._dtpSettings.get_string(dotColorSettingPrefix + (this._nWindows > 0 ? this._nWindows : 1)))[1];
} else {
// Re-use the style - background color, and border width and color -
// of the default dot
let themeNode = this._dot.get_theme_node();
bodyColor = themeNode.get_background_color();
if(bodyColor.alpha == 0) // theme didn't provide one, use a default
bodyColor = new Clutter.Color({ red: 82, green: 148, blue: 226, alpha: 255 });
color = themeNode.get_background_color();
if(color.alpha == 0) // theme didn't provide one, use a default
color = new Clutter.Color({ red: 82, green: 148, blue: 226, alpha: 255 });
}
return color;
},
_drawRunningIndicator: function(area, type, isFocused) {
let bodyColor = this._getRunningIndicatorColor(isFocused);
let [width, height] = area.get_surface_size();
let cr = area.get_context();
let n = this._nWindows;
let size = this._dtpSettings.get_int('dot-size') * St.ThemeContext.get_for_stage(global.stage).scale_factor;
let size = this._getRunningIndicatorHeight();
let padding = 0; // distance from the margin
let yOffset = this._dtpSettings.get_string('dot-position') == DOT_POSITION.TOP ? 0 : (height - padding - size);
@@ -933,6 +1109,15 @@ function getInterestingWindows(app, settings) {
return windows;
}
function cssHexTocssRgba(cssHex, opacity) {
var bigint = parseInt(cssHex.slice(1), 16);
var r = (bigint >> 16) & 255;
var g = (bigint >> 8) & 255;
var b = bigint & 255;
return 'rgba(' + [r, g, b].join(',') + ',' + opacity + ')';
}
/**
* Extend AppIconMenu
*
@@ -1048,7 +1233,8 @@ var taskbarSecondaryMenu = new Lang.Class({
// quit menu
let app = this._source.app;
let count = getInterestingWindows(app, this._dtpSettings).length;
let window = this._source.window;
let count = window ? 1 : getInterestingWindows(app, this._dtpSettings).length;
if ( count > 0) {
this._appendSeparator();
let quitFromTaskbarMenuText = "";
@@ -1060,7 +1246,7 @@ var taskbarSecondaryMenu = new Lang.Class({
this._quitfromTaskbarMenuItem = this._appendMenuItem(quitFromTaskbarMenuText);
this._quitfromTaskbarMenuItem.connect('activate', Lang.bind(this, function() {
let app = this._source.app;
let windows = app.get_windows();
let windows = window ? [window] : app.get_windows();
for (let i = 0; i < windows.length; i++) {
this._closeWindowInstance(windows[i])
}

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1">
<rect width="1" height="1" fill="#eeeeee" opacity="0.25"/>
</svg>

Before

Width:  |  Height:  |  Size: 165 B

View File

@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 1">
<g fill="#eeeeee" opacity="0.25">
<rect width="45" height="1"/>
<rect x="45" width="1" height="1" opacity="0.2"/>
<rect x="46" width="2" height="1" opacity="0.6"/>
<g fill="#000000">
<rect x="45" width="1" height="1" opacity="0.6"/>
<rect x="46" width="2" height="1" opacity="0.4"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 237 B

View File

@@ -57,7 +57,7 @@ var dtpOverview = new Lang.Class({
// 1 static workspace only)
Main.overview._controls.dash.actor.set_width(1);
this._optionalWorkspaceIsolation();
this._isolation = this._optionalWorkspaceIsolation();
this._optionalHotKeys();
this._optionalNumberOverlay();
this._bindSettingsChanges();
@@ -75,6 +75,8 @@ var dtpOverview = new Lang.Class({
// Remove key bindings
this._disableHotKeys();
this._disableExtraShortcut();
this._isolation.disable.apply(this);
},
_bindSettingsChanges: function() {
@@ -142,6 +144,8 @@ var dtpOverview = new Lang.Class({
return Main.activateWindow(windows[0]);
return this.open_new_window(-1);
}
return { disable: disable };
},
// Hotkeys

View File

@@ -328,6 +328,14 @@ var dtpPanel = new Lang.Class({
this._dtpSettings.connect('changed::show-showdesktop-button', Lang.bind(this, function() {
this._displayShowDesktopButton(this._dtpSettings.get_boolean('show-showdesktop-button'));
}));
this._dtpSettings.connect('changed::group-apps', Lang.bind(this, function() {
this.taskbar.resetAppIcons();
}));
this._dtpSettings.connect('changed::group-apps-use-launchers', Lang.bind(this, function() {
this.taskbar.resetAppIcons();
}));
},
_allocate: function(actor, box, flags) {
@@ -611,7 +619,7 @@ var dtpPanel = new Lang.Class({
let panelBottom = panelTop + this.actor.get_height();
let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let isNearEnough = windows.some(Lang.bind(this, function(metaWindow) {
if (this._dtpPosition === 'TOP') {
if (this.hasOwnProperty('_dtpPosition') && this._dtpPosition === 'TOP') {
let verticalPosition = metaWindow.get_frame_rect().y;
return verticalPosition < panelBottom + 5 * scale;
} else {

View File

@@ -283,6 +283,13 @@ const Settings = new Lang.Class({
}
}));
this._builder.get_object('focus_highlight_color_colorbutton').connect('notify::color', Lang.bind(this, function(button) {
let rgba = button.get_rgba();
let css = rgba.to_string();
let hexString = cssHexString(css);
this._settings.set_string('focus-highlight-color', hexString);
}));
this._builder.get_object('dot_style_options_button').connect('clicked', Lang.bind(this, function() {
let dialog = new Gtk.Dialog({ title: _('Running Indicator Options'),
@@ -337,6 +344,17 @@ const Settings = new Lang.Class({
'active',
Gio.SettingsBindFlags.DEFAULT);
(function() {
let rgba = new Gdk.RGBA();
rgba.parse(this._settings.get_string('focus-highlight-color'));
this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba);
}).apply(this);
this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity'));
this._builder.get_object('focus_highlight_opacity_spinbutton').connect('value-changed', Lang.bind (this, function(widget) {
this._settings.set_int('focus-highlight-opacity', widget.get_value());
}));
this._builder.get_object('dot_size_spinbutton').set_value(this._settings.get_int('dot-size'));
this._builder.get_object('dot_size_spinbutton').connect('value-changed', Lang.bind (this, function(widget) {
this._settings.set_int('dot-size', widget.get_value());
@@ -348,9 +366,17 @@ const Settings = new Lang.Class({
this._settings.set_value('dot-color-override', this._settings.get_default_value('dot-color-override'));
this._settings.set_value('dot-color-unfocused-different', this._settings.get_default_value('dot-color-unfocused-different'));
this._settings.set_value('focus-highlight-color', this._settings.get_default_value('focus-highlight-color'));
let rgba = new Gdk.RGBA();
rgba.parse(this._settings.get_string('focus-highlight-color'));
this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba);
this._settings.set_value('focus-highlight-opacity', this._settings.get_default_value('focus-highlight-opacity'));
this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity'));
for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) {
this._settings.set_value('dot-color-' + i, this._settings.get_default_value('dot-color-' + i));
let rgba = new Gdk.RGBA();
rgba = new Gdk.RGBA();
rgba.parse(this._settings.get_string('dot-color-' + i));
this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba);
@@ -494,6 +520,73 @@ const Settings = new Lang.Class({
'active',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('group-apps',
this._builder.get_object('group_apps_switch'),
'active',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('group-apps-use-fixed-width',
this._builder.get_object('group_apps_use_fixed_width_switch'),
'active',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('group-apps-underline-unfocused',
this._builder.get_object('group_apps_underline_unfocused_switch'),
'active',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('group-apps-use-launchers',
this._builder.get_object('group_apps_use_launchers_switch'),
'active',
Gio.SettingsBindFlags.DEFAULT);
this._builder.get_object('show_group_apps_options_button').connect('clicked', Lang.bind(this, function() {
let dialog = new Gtk.Dialog({ title: _('Group applications options'),
transient_for: this.widget.get_toplevel(),
use_header_bar: true,
modal: true });
// GTK+ leaves positive values for application-defined response ids.
// Use +1 for the reset action
dialog.add_button(_('Reset to defaults'), 1);
let box = this._builder.get_object('box_group_apps_options');
dialog.get_content_area().add(box);
this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size'));
this._builder.get_object('group_apps_label_font_size_spinbutton').connect('value-changed', Lang.bind (this, function(widget) {
this._settings.set_int('group-apps-label-font-size', widget.get_value());
}));
this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width'));
this._builder.get_object('group_apps_label_max_width_spinbutton').connect('value-changed', Lang.bind (this, function(widget) {
this._settings.set_int('group-apps-label-max-width', widget.get_value());
}));
dialog.connect('response', Lang.bind(this, function(dialog, id) {
if (id == 1) {
// restore default settings
this._settings.set_value('group-apps-label-font-size', this._settings.get_default_value('group-apps-label-font-size'));
this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size'));
this._settings.set_value('group-apps-label-max-width', this._settings.get_default_value('group-apps-label-max-width'));
this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width'));
this._settings.set_value('group-apps-use-fixed-width', this._settings.get_default_value('group-apps-use-fixed-width'));
this._settings.set_value('group-apps-underline-unfocused', this._settings.get_default_value('group-apps-underline-unfocused'));
this._settings.set_value('group-apps-use-launchers', this._settings.get_default_value('group-apps-use-launchers'));
} else {
// remove the settings box so it doesn't get destroyed;
dialog.get_content_area().remove(box);
dialog.destroy();
}
return;
}));
dialog.show_all();
}));
this._builder.get_object('click_action_combo').set_active_id(this._settings.get_string('click-action'));
this._builder.get_object('click_action_combo').connect('changed', Lang.bind (this, function(widget) {
this._settings.set_string('click-action', widget.get_active_id());

View File

@@ -132,6 +132,16 @@
<summary>Highlight icon of focused application</summary>
<description>Whether to highlight the background of the currently focused application's icon</description>
</key>
<key type="s" name="focus-highlight-color">
<default>"#5A5A5A"</default>
<summary>Color of highlight of focused application</summary>
<description>Customize the color of the highlight of the focused application</description>
</key>
<key type="i" name="focus-highlight-opacity">
<default>50</default>
<summary>Opacity of highlight of focused application</summary>
<description>Customize the opacity of the highlight of the focused application</description>
</key>
<key name="location-clock" enum="org.gnome.shell.extensions.dash-to-panel.statusAreaPosition">
<default>'STATUSLEFT'</default>
<summary>Location of the clock</summary>
@@ -192,6 +202,36 @@
<summary>Provide workspace isolation</summary>
<description>Dash shows only windows from the current workspace</description>
</key>
<key type="b" name="group-apps">
<default>true</default>
<summary>Group applications</summary>
<description>Dash groups the application instances under the same icon</description>
</key>
<key type="i" name="group-apps-label-font-size">
<default>14</default>
<summary>Application title font size</summary>
<description>When the applications are ungrouped, this defines the application titles font size.</description>
</key>
<key type="i" name="group-apps-label-max-width">
<default>160</default>
<summary>Application title max width</summary>
<description>When the applications are ungrouped, this defines the application titles maximum width.</description>
</key>
<key type="b" name="group-apps-use-fixed-width">
<default>true</default>
<summary>Use a fixed width for the application titles</summary>
<description>The application titles all have the same width, even if their texts are shorter than the maximum width. The maximum width value is used as the fixed width.</description>
</key>
<key type="b" name="group-apps-underline-unfocused">
<default>true</default>
<summary>Display running indicators on unfocused applications</summary>
<description>When the applications are ungrouped, this defines if running applications should display an indicator.</description>
</key>
<key type="b" name="group-apps-use-launchers">
<default>false</default>
<summary>Use favorite icons as application launchers</summary>
<description>When the applications are ungrouped, this defines if running applications stay separate from the favorite icons.</description>
</key>
<key type="b" name="customize-click">
<default>true</default>
<summary>Customize click behaviour</summary>

View File

@@ -32,6 +32,20 @@
border: none;
}
#dashtopanelScrollview .app-well-app .overview-label {
padding-right: 8px;
}
#dashtopanelScrollview .app-well-app:hover .overview-icon,
#dashtopanelScrollview .app-well-app:focus .overview-icon {
background: none;
}
#dashtopanelScrollview .app-well-app:hover > :first-child,
#dashtopanelScrollview .app-well-app:focus > :first-child {
background-color: rgba(238, 238, 236, 0.1);
}
#dashtopanelScrollview .app-well-app-running-dot {
margin-bottom: 0;
}

View File

@@ -304,6 +304,7 @@ var taskbar = new Lang.Class({
destroy: function() {
this._signalsHandler.destroy();
this._signalsHandler = 0;
},
_bindSettingsChanges: function () {
@@ -439,10 +440,19 @@ var taskbar = new Lang.Class({
}
},
_createAppItem: function(app) {
let appIcon = new AppIcons.taskbarAppIcon(this._dtpSettings, app,
{ setSizeManually: true,
showLabel: false });
_createAppItem: function(app, window, isLauncher) {
let appIcon = new AppIcons.taskbarAppIcon(
this._dtpSettings,
{
app: app,
window: window,
isLauncher: isLauncher
},
{
setSizeManually: true,
showLabel: false
}
);
if (appIcon._draggable) {
appIcon._draggable.connect('drag-begin',
@@ -518,7 +528,9 @@ var taskbar = new Lang.Class({
_enableWindowPreview: function() {
let appIcons = this._getAppIcons();
appIcons.forEach(function (appIcon) {
appIcons.filter(appIcon => !appIcon.isLauncher)
.forEach(function (appIcon) {
appIcon.enableWindowPreview(appIcons);
});
},
@@ -683,144 +695,100 @@ var taskbar = new Lang.Class({
},
sortAppsCompareFunction: function(appA, appB) {
let windowA = getAppInterestingWindows(appA)[0];
let windowB = getAppInterestingWindows(appB)[0];
return windowA.get_stable_sequence() > windowB.get_stable_sequence();
return getAppStableSequence(appA) - getAppStableSequence(appB);
},
sortWindowsCompareFunction: function(windowA, windowB) {
return windowA.get_stable_sequence() - windowB.get_stable_sequence();
},
_redisplay: function () {
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
let running = this._appSystem.get_running().sort(this.sortAppsCompareFunction);
if (this._dtpSettings.get_boolean('isolate-workspaces')) {
// When using isolation, we filter out apps that have no windows in
// the current workspace
let settings = this._dtpSettings;
running = running.filter(function(_app) {
return AppIcons.getInterestingWindows(_app, settings).length != 0;
});
if (!this._signalsHandler) {
return;
}
let children = this._box.get_children().filter(function(actor) {
let groupApps = this._dtpSettings.get_boolean('group-apps');
let showFavorites = this._dtpSettings.get_boolean('show-favorites');
//get the currently displayed appIcons
let currentAppIcons = this._box.get_children().filter(function(actor) {
return actor.child &&
actor.child._delegate &&
actor.child._delegate.app;
actor.child._delegate.app &&
!actor.animatingOut;
});
// Apps currently in the taskbar
let oldApps = children.map(function(actor) {
return actor.child._delegate.app;
});
// Apps supposed to be in the taskbar
let newApps = [];
//get the user's favorite apps
let favoriteAppsMap = showFavorites ? AppFavorites.getAppFavorites().getFavoriteMap() : {};
let favoriteApps = Object.keys(favoriteAppsMap).map(appId => favoriteAppsMap[appId]);
// Adding favorites
if (this._dtpSettings.get_boolean('show-favorites')) {
for (let id in favorites)
newApps.push(favorites[id]);
}
//find the apps that should be in the taskbar: the favorites first, then add the running apps
// When using isolation, we filter out apps that have no windows in
// the current workspace (this check is done in AppIcons.getInterstingWindows)
let runningApps = this._getRunningApps().sort(this.sortAppsCompareFunction);
let expectedAppInfos;
// Adding running apps
for (let i = 0; i < running.length; i++) {
let app = running[i];
if (this._dtpSettings.get_boolean('show-favorites') && (app.get_id() in favorites))
continue;
newApps.push(app);
}
// Figure out the actual changes to the list of items; we iterate
// over both the list of items currently in the taskbar and the list
// of items expected there, and collect additions and removals.
// Moves are both an addition and a removal, where the order of
// the operations depends on whether we encounter the position
// where the item has been added first or the one from where it
// was removed.
// There is an assumption that only one item is moved at a given
// time; when moving several items at once, everything will still
// end up at the right position, but there might be additional
// additions/removals (e.g. it might remove all the launchers
// and add them back in the new order even if a smaller set of
// additions and removals is possible).
// If above assumptions turns out to be a problem, we might need
// to use a more sophisticated algorithm, e.g. Longest Common
// Subsequence as used by diff.
let addedItems = [];
let removedActors = [];
let newIndex = 0;
let oldIndex = 0;
while (newIndex < newApps.length || oldIndex < oldApps.length) {
// No change at oldIndex/newIndex
if (oldApps[oldIndex] == newApps[newIndex]) {
oldIndex++;
newIndex++;
continue;
}
// App removed at oldIndex
if (oldApps[oldIndex] &&
newApps.indexOf(oldApps[oldIndex]) == -1) {
removedActors.push(children[oldIndex]);
oldIndex++;
continue;
}
// App added at newIndex
if (newApps[newIndex] &&
oldApps.indexOf(newApps[newIndex]) == -1) {
addedItems.push({ app: newApps[newIndex],
item: this._createAppItem(newApps[newIndex]),
pos: newIndex });
newIndex++;
continue;
}
// App moved
let insertHere = newApps[newIndex + 1] &&
newApps[newIndex + 1] == oldApps[oldIndex];
let alreadyRemoved = removedActors.reduce(function(result, actor) {
let removedApp = actor.child._delegate.app;
return result || removedApp == newApps[newIndex];
}, false);
if (insertHere || alreadyRemoved) {
let newItem = this._createAppItem(newApps[newIndex]);
addedItems.push({ app: newApps[newIndex],
item: newItem,
pos: newIndex + removedActors.length });
newIndex++;
if (!groupApps && this._dtpSettings.get_boolean('group-apps-use-launchers')) {
expectedAppInfos = this._createAppInfos(favoriteApps, [], true)
.concat(this._createAppInfos(runningApps)
.filter(appInfo => appInfo.windows.length));
} else {
removedActors.push(children[oldIndex]);
oldIndex++;
}
}
for (let i = 0; i < addedItems.length; i++)
this._box.insert_child_at_index(addedItems[i].item,
addedItems[i].pos);
for (let i = 0; i < removedActors.length; i++) {
let item = removedActors[i];
item.animateOutAndDestroy();
}
this._adjustIconSize();
for (let i = 0; i < addedItems.length; i++){
// Emit a custom signal notifying that a new item has been added
this.emit('item-added', addedItems[i]);
expectedAppInfos = this._createAppInfos(favoriteApps.concat(runningApps.filter(app => favoriteApps.indexOf(app) < 0)))
.filter(appInfo => appInfo.windows.length || favoriteApps.indexOf(appInfo.app) >= 0);
}
// Skip animations on first run when adding the initial set
// of items, to avoid all items zooming in at once
let animate = this._shownInitially;
if (!this._shownInitially)
this._shownInitially = true;
for (let i = 0; i < addedItems.length; i++) {
addedItems[i].item.show(animate);
//remove the appIcons which are not in the expected apps list
for (let i = currentAppIcons.length - 1; i > -1; --i) {
let appIcon = currentAppIcons[i].child._delegate;
let appIndex = expectedAppInfos.findIndex(appInfo => appInfo.app == appIcon.app &&
appInfo.isLauncher == appIcon.isLauncher);
if (appIndex < 0 ||
(appIcon.window && (groupApps || expectedAppInfos[appIndex].windows.indexOf(appIcon.window) < 0)) ||
(!appIcon.window && !appIcon.isLauncher &&
!groupApps && expectedAppInfos[appIndex].windows.length)) {
currentAppIcons[i].animateOutAndDestroy();
currentAppIcons.splice(i, 1);
}
}
//if needed, reorder the existing appIcons and create the missing ones
let currentPosition = 0;
for (let i = 0, l = expectedAppInfos.length; i < l; ++i) {
let neededAppIcons = groupApps || !expectedAppInfos[i].windows.length ?
[{ app: expectedAppInfos[i].app, window: null, isLauncher: expectedAppInfos[i].isLauncher }] :
expectedAppInfos[i].windows.map(window => ({ app: expectedAppInfos[i].app, window: window, isLauncher: false }));
for (let j = 0, ll = neededAppIcons.length; j < ll; ++j) {
//check if the icon already exists
let matchingAppIconIndex = currentAppIcons.findIndex(appIcon => appIcon.child._delegate.app == neededAppIcons[j].app &&
appIcon.child._delegate.window == neededAppIcons[j].window);
if (matchingAppIconIndex > 0 && matchingAppIconIndex != currentPosition) {
//moved icon, reposition it
this._box.remove_child(currentAppIcons[matchingAppIconIndex]);
this._box.insert_child_at_index(currentAppIcons[matchingAppIconIndex], currentPosition);
} else if (matchingAppIconIndex < 0) {
//the icon doesn't exist yet, create a new one
let newAppIcon = this._createAppItem(neededAppIcons[j].app, neededAppIcons[j].window, neededAppIcons[j].isLauncher);
this._box.insert_child_at_index(newAppIcon, currentPosition);
currentAppIcons.splice(currentPosition, 0, newAppIcon);
// Emit a custom signal notifying that a new item has been added
this.emit('item-added', newAppIcon);
newAppIcon.show(animate);
}
++currentPosition;
}
}
this._adjustIconSize();
// Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
// Without it, StBoxLayout may use a stale size cache
@@ -836,6 +804,31 @@ var taskbar = new Lang.Class({
this._toggleWindowPreview();
},
_getRunningApps: function() {
let tracker = Shell.WindowTracker.get_default();
let windows = global.get_window_actors();
let apps = [];
for (let i = 0, l = windows.length; i < l; ++i) {
let app = tracker.get_window_app(windows[i].metaWindow);
if (app && apps.indexOf(app) < 0) {
apps.push(app);
}
}
return apps;
},
_createAppInfos: function(apps, defaultWindows, defaultIsLauncher) {
return apps.map(app => ({
app: app,
isLauncher: defaultIsLauncher || false,
windows: defaultWindows || AppIcons.getInterestingWindows(app, this._dtpSettings)
.sort(this.sortWindowsCompareFunction)
}));
},
// Reset the displayed apps icon to mantain the correct order
resetAppIcons : function() {
@@ -1195,6 +1188,14 @@ function getAppInterestingWindows(app, settings) {
return windows;
}
function getAppStableSequence(app) {
let windows = getAppInterestingWindows(app);
return windows.reduce((prevWindow, window) => {
return Math.min(prevWindow, window.get_stable_sequence());
}, Infinity);
}
/*
* This is a copy of the same function in utils.js, but also adjust horizontal scrolling
* and perform few further cheks on the current value to avoid changing the values when

View File

@@ -82,7 +82,7 @@ var thumbnailPreviewMenu = new Lang.Class({
this._boxPointer._arrowSide = side;
this._boxPointer._userArrowSide = side;
this._previewBox = new thumbnailPreviewList(this._app, this._dtpSettings);
this._previewBox = new thumbnailPreviewList(this._app, source.window, this._dtpSettings);
this.addMenuItem(this._previewBox);
this._peekMode = false;
@@ -820,8 +820,11 @@ var thumbnailPreview = new Lang.Class({
},
_onDestroy: function() {
if (this._titleNotifyId) {
this.window.disconnect(this._titleNotifyId);
this._titleNotifyId = 0;
}
if(this._resizeId) {
let mutterWindow = this.window.get_compositor_private();
if (mutterWindow) {
@@ -836,7 +839,7 @@ var thumbnailPreviewList = new Lang.Class({
Name: 'DashToPanel.ThumbnailPreviewList',
Extends: PopupMenu.PopupMenuSection,
_init: function(app, settings) {
_init: function(app, window, settings) {
this._dtpSettings = settings;
this.parent();
@@ -858,14 +861,15 @@ var thumbnailPreviewList = new Lang.Class({
this._shownInitially = false;
this.app = app;
this.window = window;
this._redisplayId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
this._scrollbarId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._showHideScrollbar));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._stateChangedId = this.app.connect('windows-changed',
Lang.bind(this,
this._queueRedisplay));
this._stateChangedId = this.window ? 0 :
this.app.connect('windows-changed', Lang.bind(this, this._queueRedisplay));
},
_needsScrollbar: function() {
@@ -953,8 +957,10 @@ var thumbnailPreviewList = new Lang.Class({
},
_onDestroy: function() {
if (this._stateChangedId) {
this.app.disconnect(this._stateChangedId);
this._stateChangedId = 0;
}
},
_createPreviewItem: function(window) {
@@ -986,7 +992,8 @@ var thumbnailPreviewList = new Lang.Class({
},
_redisplay: function () {
let windows = AppIcons.getInterestingWindows(this.app, this._dtpSettings).sort(this.sortWindowsCompareFunction);
let windows = this.window ? [this.window] :
AppIcons.getInterestingWindows(this.app, this._dtpSettings).sort(this.sortWindowsCompareFunction);
let children = this.box.get_children().filter(function(actor) {
return actor._delegate.window && actor._delegate.preview;
});
@@ -1004,13 +1011,6 @@ var thumbnailPreviewList = new Lang.Class({
let oldIndex = 0;
while (newIndex < newWin.length || oldIndex < oldWin.length) {
// No change at oldIndex/newIndex
if (oldWin[oldIndex] == newWin[newIndex]) {
oldIndex++;
newIndex++;
continue;
}
// Window removed at oldIndex
if (oldWin[oldIndex] &&
newWin.indexOf(oldWin[oldIndex]) == -1) {
@@ -1028,6 +1028,13 @@ var thumbnailPreviewList = new Lang.Class({
continue;
}
// No change at oldIndex/newIndex
if (oldWin[oldIndex] == newWin[newIndex]) {
oldIndex++;
newIndex++;
continue;
}
// Window moved
let insertHere = newWin[newIndex + 1] &&
newWin[newIndex + 1] == oldWin[oldIndex];