mirror of
https://github.com/BreizhHardware/multi-monitors-add-on.git
synced 2026-01-18 16:47:26 +01:00
Multi Monitors Add-On
This commit is contained in:
11
.project
Normal file
11
.project
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>multi-monitors-add-on</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
22
README.md
22
README.md
@@ -1,2 +1,22 @@
|
||||
multi-monitors-add-on
|
||||
Multi Monitors Add-On
|
||||
=====================
|
||||
|
||||
Extension inspired by https://github.com/darkxst/multiple-monitor-panels
|
||||
and rewritten from scratch for gnome-shell version 3.10.4. Adds panels
|
||||
and thumbnails for additional monitors. Settings changes are applied
|
||||
in dynamic fashion, no restart needed.
|
||||
|
||||
Installation from git
|
||||
=====================
|
||||
|
||||
git clone git://github.com/spin83/multi-monitors-add-on.git
|
||||
cd multi-monitors-add-on
|
||||
cp -r multi-monitors-add-on@spin83 ~/.local/share/gnome-shell/extensions
|
||||
|
||||
Restart the shell and then enable the extension.
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Multi Monitors Add-On extension is distributed under the terms of the
|
||||
GNU General Public License, version 2 or later. See the COPYING file for details.
|
||||
93
multi-monitors-add-on@spin83/convenience.js
Normal file
93
multi-monitors-add-on@spin83/convenience.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011-2012, Giovanni Campagna <scampa.giovanni@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the GNOME nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
const Gettext = imports.gettext;
|
||||
const Gio = imports.gi.Gio;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
/**
|
||||
* initTranslations:
|
||||
* @domain: (optional): the gettext domain to use
|
||||
*
|
||||
* Initialize Gettext to load translations from extensionsdir/locale.
|
||||
* If @domain is not provided, it will be taken from metadata['gettext-domain']
|
||||
*/
|
||||
function initTranslations(domain) {
|
||||
let extension = ExtensionUtils.getCurrentExtension();
|
||||
|
||||
domain = domain || extension.metadata['gettext-domain'];
|
||||
|
||||
// check if this extension was built with "make zip-file", and thus
|
||||
// has the locale files in a subfolder
|
||||
// otherwise assume that extension has been installed in the
|
||||
// same prefix as gnome-shell
|
||||
let localeDir = extension.dir.get_child('locale');
|
||||
if (localeDir.query_exists(null))
|
||||
Gettext.bindtextdomain(domain, localeDir.get_path());
|
||||
else
|
||||
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* getSettings:
|
||||
* @schema: (optional): the GSettings schema id
|
||||
*
|
||||
* Builds and return a GSettings schema for @schema, using schema files
|
||||
* in extensionsdir/schemas. If @schema is not provided, it is taken from
|
||||
* metadata['settings-schema'].
|
||||
*/
|
||||
function getSettings(schema) {
|
||||
let extension = ExtensionUtils.getCurrentExtension();
|
||||
|
||||
schema = schema || extension.metadata['settings-schema'];
|
||||
|
||||
const GioSSS = Gio.SettingsSchemaSource;
|
||||
|
||||
// check if this extension was built with "make zip-file", and thus
|
||||
// has the schema files in a subfolder
|
||||
// otherwise assume that extension has been installed in the
|
||||
// same prefix as gnome-shell (and therefore schemas are available
|
||||
// in the standard folders)
|
||||
let schemaDir = extension.dir.get_child('schemas');
|
||||
let schemaSource;
|
||||
if (schemaDir.query_exists(null))
|
||||
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
|
||||
GioSSS.get_default(),
|
||||
false);
|
||||
else
|
||||
schemaSource = GioSSS.get_default();
|
||||
|
||||
let schemaObj = schemaSource.lookup(schema, true);
|
||||
if (!schemaObj)
|
||||
throw new Error('Schema ' + schema + ' could not be found for extension '
|
||||
+ extension.metadata.uuid + '. Please check your installation.');
|
||||
|
||||
return new Gio.Settings({ settings_schema: schemaObj });
|
||||
}
|
||||
|
||||
262
multi-monitors-add-on@spin83/extension.js
Normal file
262
multi-monitors-add-on@spin83/extension.js
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
Copyright (C) 2014 spin83
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, visit https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const St = imports.gi.St;
|
||||
const Gio = imports.gi.Gio;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Panel = imports.ui.panel;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const MultiMonitors = ExtensionUtils.getCurrentExtension();
|
||||
const Convenience = MultiMonitors.imports.convenience;
|
||||
const MMPanel = MultiMonitors.imports.mmpanel;
|
||||
const MMOverview = MultiMonitors.imports.mmoverview;
|
||||
const MMIndicator = MultiMonitors.imports.indicator;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
const WORKSPACES_ONLY_ON_PRIMARY_ID = 'workspaces-only-on-primary';
|
||||
|
||||
const SHOW_INDICATOR_ID = 'show-indicator';
|
||||
const SHOW_PANEL_ID = 'show-panel';
|
||||
const SHOW_THUMBNAILS_SLIDER_ID = 'show-thumbnails-slider';
|
||||
const SHOW_ACTIVITIES_ID = 'show-activities';
|
||||
const SHOW_APP_MENU_ID = 'show-app-menu';
|
||||
const THUMBNAILS_ON_LEFT_SIDE_ID = 'thumbnails-on-left-side';
|
||||
|
||||
const MultiMonitorsAddOn = new Lang.Class({
|
||||
Name: 'MultiMonitorsAddOn',
|
||||
|
||||
_init: function() {
|
||||
this._settings = Convenience.getSettings();
|
||||
|
||||
this._ov_settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
|
||||
|
||||
this.mmIndicator = null;
|
||||
Main.mmOverview = null;
|
||||
Main.mmPanel = null;
|
||||
this.panelBox = null;
|
||||
this.mmappMenu = false;
|
||||
|
||||
this._mmMonitors = 0;
|
||||
},
|
||||
|
||||
_changeMainPanelAppMenuButton: function(appMenuButton) {
|
||||
let role = "appMenu";
|
||||
let panel = Main.panel;
|
||||
let indicator = panel.statusArea[role];
|
||||
panel.menuManager.removeMenu(indicator.menu);
|
||||
indicator.destroy();
|
||||
if (indicator._actionGroupNotifyId) {
|
||||
indicator._targetApp.disconnect(indicator._actionGroupNotifyId);
|
||||
indicator._actionGroupNotifyId = 0;
|
||||
}
|
||||
indicator = new appMenuButton(panel);
|
||||
panel.statusArea[role] = indicator;
|
||||
let box = panel._leftBox;
|
||||
panel._addToPanelBox(role, indicator, box.get_n_children()+1, box);
|
||||
},
|
||||
|
||||
_showIndicator: function() {
|
||||
if(this._settings.get_boolean(SHOW_INDICATOR_ID)) {
|
||||
if(!this.mmIndicator) {
|
||||
this.mmIndicator = Main.panel.addToStatusArea('MultiMonitorsAddOn', new MMIndicator.MultiMonitorsIndicator());
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._hideIndicator();
|
||||
}
|
||||
},
|
||||
|
||||
_hideIndicator: function() {
|
||||
if(this.mmIndicator) {
|
||||
this.mmIndicator.destroy();
|
||||
this.mmIndicator = null;
|
||||
}
|
||||
},
|
||||
|
||||
_showPanel: function() {
|
||||
if(this._settings.get_boolean(SHOW_PANEL_ID)){
|
||||
Main.mmPanel = [];
|
||||
this.panelBox = [];
|
||||
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
|
||||
let monitor = Main.layoutManager.monitors[i];
|
||||
if(i != Main.layoutManager.primaryIndex) {
|
||||
let panel = new MMPanel.MultiMonitorsPanel(i);
|
||||
this.panelBox[i] = new St.BoxLayout({ name: 'panelBox'+i, vertical: true });
|
||||
Main.layoutManager.addChrome(this.panelBox[i], { affectsStruts: true, trackFullscreen: true });
|
||||
this.panelBox[i].set_position(monitor.x, monitor.y);
|
||||
// this.panelBox.connect('allocation-changed', Lang.bind(this, this._panelBoxChanged));
|
||||
this.panelBox[i].add(panel.actor);
|
||||
|
||||
Main.mmPanel[i] = panel;
|
||||
}
|
||||
}
|
||||
|
||||
this.statusIndicatorsController = new MMPanel.StatusIndicatorsController();
|
||||
|
||||
this._showAppMenuId = this._settings.connect('changed::'+SHOW_APP_MENU_ID, Lang.bind(this, this._showAppMenu));
|
||||
this._showAppMenu();
|
||||
|
||||
|
||||
if(Main.mmOverview){
|
||||
for (let i = 0; i < Main.mmOverview.length; i++) {
|
||||
if(Main.mmOverview[i])
|
||||
Main.mmOverview[i].addPanelGhost();
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
this._hidePanel();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_showAppMenu: function(){
|
||||
if(this._settings.get_boolean(SHOW_APP_MENU_ID)){
|
||||
this._changeMainPanelAppMenuButton(MMPanel.MultiMonitorsAppMenuButton);
|
||||
this.mmappMenu = true;
|
||||
}
|
||||
else{
|
||||
if(this.mmappMenu){
|
||||
this._changeMainPanelAppMenuButton(Panel.AppMenuButton);
|
||||
this.mmappMenu = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_hidePanel: function() {
|
||||
if(Main.mmPanel){
|
||||
this._settings.disconnect(this._showAppMenuId);
|
||||
|
||||
|
||||
this.statusIndicatorsController.destroy();
|
||||
this.statusIndicatorsController = null;
|
||||
|
||||
for (let i = 0; i < Main.mmPanel.length; i++) {
|
||||
if(Main.mmPanel[i])
|
||||
this.panelBox[i].destroy();
|
||||
}
|
||||
|
||||
Main.mmPanel = null;
|
||||
this.panelBox = null;
|
||||
|
||||
if(this.mmappMenu){
|
||||
this._changeMainPanelAppMenuButton(Panel.AppMenuButton);
|
||||
this.mmappMenu = false;
|
||||
}
|
||||
|
||||
if(Main.mmOverview){
|
||||
for (let i = 0; i < Main.mmOverview.length; i++) {
|
||||
if(Main.mmOverview[i])
|
||||
Main.mmOverview[i].removePanelGhost();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_showThumbnailsSlider: function() {
|
||||
if(this._settings.get_boolean(SHOW_THUMBNAILS_SLIDER_ID)){
|
||||
|
||||
if(this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
|
||||
this._ov_settings.set_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID, false);
|
||||
|
||||
Main.mmOverview = [];
|
||||
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
|
||||
let monitor = Main.layoutManager.monitors[i];
|
||||
if(i != Main.layoutManager.primaryIndex) {
|
||||
Main.mmOverview[i] = new MMOverview.MultiMonitorsOverview(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
this._hideThumbnailsSlider();
|
||||
}
|
||||
},
|
||||
|
||||
_hideThumbnailsSlider: function() {
|
||||
if(Main.mmOverview){
|
||||
for (let i = 0; i < Main.mmOverview.length; i++) {
|
||||
if(Main.mmOverview[i])
|
||||
Main.mmOverview[i].destroy();
|
||||
}
|
||||
|
||||
Main.mmOverview = null;
|
||||
}
|
||||
},
|
||||
|
||||
_relayout: function() {
|
||||
|
||||
if(this._mmMonitors!=Main.layoutManager.monitors.length){
|
||||
this._mmMonitors = Main.layoutManager.monitors.length;
|
||||
global.log("pi:"+Main.layoutManager.primaryIndex);
|
||||
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
|
||||
let monitor = Main.layoutManager.monitors[i];
|
||||
global.log("i:"+i+" x:"+monitor.x+" y:"+monitor.y+" w:"+monitor.width+" h:"+monitor.height);
|
||||
}
|
||||
this._hideThumbnailsSlider();
|
||||
this._hidePanel();
|
||||
this._showPanel();
|
||||
this._showThumbnailsSlider();
|
||||
}
|
||||
},
|
||||
|
||||
_switchOffThumbnails: function() {
|
||||
if(this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
|
||||
this._settings.set_boolean(SHOW_THUMBNAILS_SLIDER_ID, false);
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
global.log("Enable Multi Monitors Add-On ...")
|
||||
|
||||
this._switchOffThumbnailsId = this._ov_settings.connect('changed::'+WORKSPACES_ONLY_ON_PRIMARY_ID,
|
||||
Lang.bind(this, this._switchOffThumbnails));
|
||||
|
||||
this._showIndicator();
|
||||
|
||||
this._relayoutId = Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout));
|
||||
|
||||
this._showIndicatorId = this._settings.connect('changed::'+SHOW_INDICATOR_ID, Lang.bind(this, this._showIndicator));
|
||||
this._showPanelId = this._settings.connect('changed::'+SHOW_PANEL_ID, Lang.bind(this, this._showPanel));
|
||||
this._showThumbnailsSliderId = this._settings.connect('changed::'+SHOW_THUMBNAILS_SLIDER_ID, Lang.bind(this, this._showThumbnailsSlider));
|
||||
|
||||
this._relayout();
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
Main.layoutManager.disconnect(this._relayoutId);
|
||||
|
||||
this._settings.disconnect(this._showPanelId);
|
||||
this._settings.disconnect(this._showThumbnailsSliderId);
|
||||
|
||||
this._hideThumbnailsSlider();
|
||||
this._hidePanel();
|
||||
this._mmMonitors = 0;
|
||||
|
||||
this._hideIndicator();
|
||||
|
||||
this._ov_settings.disconnect(this._switchOffThumbnailsId);
|
||||
}
|
||||
});
|
||||
|
||||
function init(extensionMeta) {
|
||||
let theme = imports.gi.Gtk.IconTheme.get_default();
|
||||
theme.append_search_path(extensionMeta.path + "/icons");
|
||||
return new MultiMonitorsAddOn();
|
||||
}
|
||||
392
multi-monitors-add-on@spin83/icons/multi-monitors-l-symbolic.svg
Normal file
392
multi-monitors-add-on@spin83/icons/multi-monitors-l-symbolic.svg
Normal file
@@ -0,0 +1,392 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="multi-monitor-symbolic.svg"
|
||||
height="16"
|
||||
id="svg7384"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
version="1.1"
|
||||
width="16">
|
||||
<metadata
|
||||
id="metadata90">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Gnome Symbolic Icon Theme</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
inkscape:bbox-paths="false"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
inkscape:current-layer="layer11"
|
||||
inkscape:cx="3.128503"
|
||||
inkscape:cy="7.3630629"
|
||||
gridtolerance="10"
|
||||
inkscape:guide-bbox="true"
|
||||
guidetolerance="10"
|
||||
id="namedview88"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:object-paths="false"
|
||||
objecttolerance="10"
|
||||
pagecolor="#555753"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
showborder="false"
|
||||
showgrid="true"
|
||||
showguides="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-midpoints="false"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:window-height="1014"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:zoom="32">
|
||||
<inkscape:grid
|
||||
empspacing="2"
|
||||
enabled="true"
|
||||
id="grid4866"
|
||||
originx="-42.000009px"
|
||||
originy="412px"
|
||||
snapvisiblegridlinesonly="true"
|
||||
spacingx="1px"
|
||||
spacingy="1px"
|
||||
type="xygrid"
|
||||
visible="true" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="3.4692426,9.4354561"
|
||||
id="guide4029" />
|
||||
</sodipodi:namedview>
|
||||
<title
|
||||
id="title9167">Gnome Symbolic Icon Theme</title>
|
||||
<defs
|
||||
id="defs7386">
|
||||
<linearGradient
|
||||
id="linearGradient5351"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#00a600;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5353" />
|
||||
</linearGradient>
|
||||
<marker
|
||||
inkscape:stockid="EmptyTriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="EmptyTriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4013"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.2,0,0,0.2,-0.6,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Legs"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Legs"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g4046"
|
||||
transform="scale(-0.7,-0.7)">
|
||||
<g
|
||||
id="g4048"
|
||||
transform="matrix(0,-1,-1,0,20.70862,21.31391)">
|
||||
<path
|
||||
id="path4050"
|
||||
d="m 21.22125,20.67536 c -6.910151,4.721157 -2.454525,6.606844 -5.841071,13.443235"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4052"
|
||||
d="m 21.39811,20.54812 c -1.360509,8.347524 3.536072,8.76994 4.505041,13.824958"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
id="path4054"
|
||||
d="m -14.09007,-6.7318716 -0.922168,4.043383 3.962751,-1.22307 -3.040583,-2.820313 z"
|
||||
style="fill:#030300;fill-rule:evenodd;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4056"
|
||||
d="m -15.215679,4.5567534 1.874127,3.699613 2.266874,-3.472855 -4.141001,-0.226758 z"
|
||||
style="fill:#030300;fill-rule:evenodd;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Torso"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Torso"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g4059"
|
||||
transform="scale(0.7,0.7)">
|
||||
<path
|
||||
id="path4061"
|
||||
d="m -4.7792281,-3.239542 c 2.350374,0.3659393 5.30026732,1.9375477 5.03715532,3.62748546 C -0.00518779,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 -6.9134221,1.8857769 -8.521035,0.75201414 -8.257922,-0.93792336 -7.994809,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.239542 z"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.25"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4063"
|
||||
d="M 4.4598789,0.08866574 C -2.5564571,-4.378332 5.2248769,-3.9061806 -0.84829578,-8.7197331"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4065"
|
||||
d="M 4.9298719,0.05752074 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
id="rect4067"
|
||||
transform="matrix(0.527536,-0.849533,0.887668,0.460484,0,0)"
|
||||
y="-1.7408575"
|
||||
x="-10.391706"
|
||||
height="2.7608147"
|
||||
width="2.6366582"
|
||||
style="fill-rule:evenodd;stroke-width:1pt" />
|
||||
<rect
|
||||
id="rect4069"
|
||||
transform="matrix(0.671205,-0.741272,0.790802,0.612072,0,0)"
|
||||
y="-7.9629307"
|
||||
x="4.9587269"
|
||||
height="2.8614161"
|
||||
width="2.7327356"
|
||||
style="fill-rule:evenodd;stroke-width:1pt" />
|
||||
<path
|
||||
id="path4071"
|
||||
transform="matrix(0,-1.109517,1.109517,0,25.96648,19.71619)"
|
||||
d="m 16.779951,-28.685045 a 0.60731727,0.60731727 0 1 0 -1.214634,0 0.60731727,0.60731727 0 1 0 1.214634,0 z"
|
||||
style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4073"
|
||||
transform="matrix(0,-1.109517,1.109517,0,26.8245,16.99126)"
|
||||
d="m 16.779951,-28.685045 a 0.60731727,0.60731727 0 1 0 -1.214634,0 0.60731727,0.60731727 0 1 0 1.214634,0 z"
|
||||
style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="EmptyDiamondLstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="EmptyDiamondLstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3962"
|
||||
d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.8,0,0,0.8,5.6,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DiamondSend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="DiamondSend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3950"
|
||||
d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.2,0,0,0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3856"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Tail"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Tail"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g3883"
|
||||
transform="scale(-1.2,-1.2)">
|
||||
<path
|
||||
id="path3885"
|
||||
d="M -3.8048674,-3.9585227 0.54352094,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3887"
|
||||
d="M -1.2866832,-3.9585227 3.0617053,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3889"
|
||||
d="M 1.3053582,-3.9585227 5.6537466,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3891"
|
||||
d="M -3.8048674,4.1775838 0.54352094,0.21974226"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3893"
|
||||
d="M -1.2866832,4.1775838 3.0617053,0.21974226"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3895"
|
||||
d="M 1.3053582,4.1775838 5.6537466,0.21974226"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Sstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3877"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotL"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="DotL"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3908"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.8,0,0,0.8,5.92,0.8)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer9"
|
||||
inkscape:label="status"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer10"
|
||||
inkscape:label="devices"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer11"
|
||||
inkscape:label="apps"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)">
|
||||
<g
|
||||
id="g3040">
|
||||
<path
|
||||
id="path3795-3"
|
||||
d="m 283.60374,629.58458 0,12.86095 14.78834,-1.16918 0,-10.5226 -14.78834,-1.16917 z m 0.73172,0.65766 13.28639,1.05957 0,9.46303 -13.32491,1.02303 0.0385,-11.54563 z"
|
||||
style="fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:#bebebe;stroke-width:1.20035386;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3839-5"
|
||||
d="m 290.99791,641.86094 -2e-5,2.33836"
|
||||
style="fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:#bebebe;stroke-width:3.60105371;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3841-2"
|
||||
d="m 295.34001,643.66019 -8.13359,0.64305"
|
||||
style="fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:#bebebe;stroke-width:1.32038927;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;display:inline" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="on"
|
||||
style="display:inline" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="off"
|
||||
style="display:inline" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer13"
|
||||
inkscape:label="places"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer14"
|
||||
inkscape:label="mimetypes"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer15"
|
||||
inkscape:label="emblems"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="g71291"
|
||||
inkscape:label="emotes"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="g4953"
|
||||
inkscape:label="categories"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer12"
|
||||
inkscape:label="actions"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
393
multi-monitors-add-on@spin83/icons/multi-monitors-r-symbolic.svg
Normal file
393
multi-monitors-add-on@spin83/icons/multi-monitors-r-symbolic.svg
Normal file
@@ -0,0 +1,393 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="multi-monitor-l-symbolic.svg"
|
||||
height="16"
|
||||
id="svg7384"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
version="1.1"
|
||||
width="16">
|
||||
<metadata
|
||||
id="metadata90">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Gnome Symbolic Icon Theme</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
inkscape:bbox-paths="false"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
inkscape:current-layer="layer11"
|
||||
inkscape:cx="3.191003"
|
||||
inkscape:cy="7.3005629"
|
||||
gridtolerance="10"
|
||||
inkscape:guide-bbox="true"
|
||||
guidetolerance="10"
|
||||
id="namedview88"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:object-paths="false"
|
||||
objecttolerance="10"
|
||||
pagecolor="#555753"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
showborder="false"
|
||||
showgrid="true"
|
||||
showguides="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-midpoints="false"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:window-height="958"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="27"
|
||||
inkscape:zoom="32">
|
||||
<inkscape:grid
|
||||
empspacing="2"
|
||||
enabled="true"
|
||||
id="grid4866"
|
||||
originx="-42.000009px"
|
||||
originy="412px"
|
||||
snapvisiblegridlinesonly="true"
|
||||
spacingx="1px"
|
||||
spacingy="1px"
|
||||
type="xygrid"
|
||||
visible="true" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="3.4692426,9.4354561"
|
||||
id="guide4029" />
|
||||
</sodipodi:namedview>
|
||||
<title
|
||||
id="title9167">Gnome Symbolic Icon Theme</title>
|
||||
<defs
|
||||
id="defs7386">
|
||||
<linearGradient
|
||||
id="linearGradient5351"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#00a600;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5353" />
|
||||
</linearGradient>
|
||||
<marker
|
||||
inkscape:stockid="EmptyTriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="EmptyTriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4013"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.2,0,0,0.2,-0.6,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Legs"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Legs"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g4046"
|
||||
transform="scale(-0.7,-0.7)">
|
||||
<g
|
||||
id="g4048"
|
||||
transform="matrix(0,-1,-1,0,20.70862,21.31391)">
|
||||
<path
|
||||
id="path4050"
|
||||
d="m 21.22125,20.67536 c -6.910151,4.721157 -2.454525,6.606844 -5.841071,13.443235"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4052"
|
||||
d="m 21.39811,20.54812 c -1.360509,8.347524 3.536072,8.76994 4.505041,13.824958"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
id="path4054"
|
||||
d="m -14.09007,-6.7318716 -0.922168,4.043383 3.962751,-1.22307 -3.040583,-2.820313 z"
|
||||
style="fill:#030300;fill-rule:evenodd;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4056"
|
||||
d="m -15.215679,4.5567534 1.874127,3.699613 2.266874,-3.472855 -4.141001,-0.226758 z"
|
||||
style="fill:#030300;fill-rule:evenodd;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Torso"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Torso"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g4059"
|
||||
transform="scale(0.7,0.7)">
|
||||
<path
|
||||
id="path4061"
|
||||
d="m -4.7792281,-3.239542 c 2.350374,0.3659393 5.30026732,1.9375477 5.03715532,3.62748546 C -0.00518779,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 -6.9134221,1.8857769 -8.521035,0.75201414 -8.257922,-0.93792336 -7.994809,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.239542 z"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.25"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4063"
|
||||
d="M 4.4598789,0.08866574 C -2.5564571,-4.378332 5.2248769,-3.9061806 -0.84829578,-8.7197331"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4065"
|
||||
d="M 4.9298719,0.05752074 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
|
||||
style="fill:none;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
id="rect4067"
|
||||
transform="matrix(0.527536,-0.849533,0.887668,0.460484,0,0)"
|
||||
y="-1.7408575"
|
||||
x="-10.391706"
|
||||
height="2.7608147"
|
||||
width="2.6366582"
|
||||
style="fill-rule:evenodd;stroke-width:1pt" />
|
||||
<rect
|
||||
id="rect4069"
|
||||
transform="matrix(0.671205,-0.741272,0.790802,0.612072,0,0)"
|
||||
y="-7.9629307"
|
||||
x="4.9587269"
|
||||
height="2.8614161"
|
||||
width="2.7327356"
|
||||
style="fill-rule:evenodd;stroke-width:1pt" />
|
||||
<path
|
||||
id="path4071"
|
||||
transform="matrix(0,-1.109517,1.109517,0,25.96648,19.71619)"
|
||||
d="m 16.779951,-28.685045 a 0.60731727,0.60731727 0 1 0 -1.214634,0 0.60731727,0.60731727 0 1 0 1.214634,0 z"
|
||||
style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4073"
|
||||
transform="matrix(0,-1.109517,1.109517,0,26.8245,16.99126)"
|
||||
d="m 16.779951,-28.685045 a 0.60731727,0.60731727 0 1 0 -1.214634,0 0.60731727,0.60731727 0 1 0 1.214634,0 z"
|
||||
style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="EmptyDiamondLstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="EmptyDiamondLstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3962"
|
||||
d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.8,0,0,0.8,5.6,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DiamondSend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="DiamondSend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3950"
|
||||
d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.2,0,0,0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3856"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Tail"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Tail"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g3883"
|
||||
transform="scale(-1.2,-1.2)">
|
||||
<path
|
||||
id="path3885"
|
||||
d="M -3.8048674,-3.9585227 0.54352094,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3887"
|
||||
d="M -1.2866832,-3.9585227 3.0617053,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3889"
|
||||
d="M 1.3053582,-3.9585227 5.6537466,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3891"
|
||||
d="M -3.8048674,4.1775838 0.54352094,0.21974226"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3893"
|
||||
d="M -1.2866832,4.1775838 3.0617053,0.21974226"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3895"
|
||||
d="M 1.3053582,4.1775838 5.6537466,0.21974226"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Sstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3877"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotL"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="DotL"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3908"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.8,0,0,0.8,5.92,0.8)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer9"
|
||||
inkscape:label="status"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer10"
|
||||
inkscape:label="devices"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer11"
|
||||
inkscape:label="apps"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)">
|
||||
<g
|
||||
id="g3040"
|
||||
transform="matrix(-1,0,0,1,581.99582,0)">
|
||||
<path
|
||||
id="path3795-3"
|
||||
d="m 283.60374,629.58458 0,12.86095 14.78834,-1.16918 0,-10.5226 -14.78834,-1.16917 z m 0.73172,0.65766 13.28639,1.05957 0,9.46303 -13.32491,1.02303 0.0385,-11.54563 z"
|
||||
style="fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:#bebebe;stroke-width:1.20035386;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3839-5"
|
||||
d="m 290.99791,641.86094 -2e-5,2.33836"
|
||||
style="fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:#bebebe;stroke-width:3.60105371;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3841-2"
|
||||
d="m 295.34001,643.66019 -8.13359,0.64305"
|
||||
style="fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:#bebebe;stroke-width:1.32038927;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;display:inline" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="on"
|
||||
style="display:inline" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="off"
|
||||
style="display:inline" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer13"
|
||||
inkscape:label="places"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer14"
|
||||
inkscape:label="mimetypes"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer15"
|
||||
inkscape:label="emblems"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="g71291"
|
||||
inkscape:label="emotes"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="g4953"
|
||||
inkscape:label="categories"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer12"
|
||||
inkscape:label="actions"
|
||||
style="display:inline"
|
||||
transform="translate(-283.00021,-629)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
132
multi-monitors-add-on@spin83/indicator.js
Normal file
132
multi-monitors-add-on@spin83/indicator.js
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (C) 2014 spin83
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, visit https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const MultiMonitorsStatusIcon = new Lang.Class({
|
||||
Name: 'MultiMonitorsStatusIcon',
|
||||
Extends: St.BoxLayout,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ style_class: 'panel-status-menu-box' });
|
||||
|
||||
this._leftRightIcon = true;
|
||||
this._viewMonitorsId = Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._viewMonitors));
|
||||
this.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._viewMonitors();
|
||||
},
|
||||
|
||||
_onDestroy: function(actor) {
|
||||
Main.layoutManager.disconnect(this._viewMonitorsId);
|
||||
},
|
||||
|
||||
_viewMonitors: function() {
|
||||
let monitors = this.get_children();
|
||||
|
||||
let monitorChange = Main.layoutManager.monitors.length - monitors.length;
|
||||
if(monitorChange>0){
|
||||
for(let idx = 0; idx<monitorChange; idx++){
|
||||
if(this._leftRightIcon){
|
||||
this.add_child(new St.Icon({
|
||||
icon_name: 'multi-monitors-l-symbolic',
|
||||
style_class: 'system-status-icon'
|
||||
}));
|
||||
}
|
||||
else{
|
||||
this.add_child(new St.Icon({
|
||||
icon_name: 'multi-monitors-r-symbolic',
|
||||
style_class: 'system-status-icon'
|
||||
}));
|
||||
}
|
||||
this._leftRightIcon = !this._leftRightIcon;
|
||||
}
|
||||
}
|
||||
else if(monitorChange<0){
|
||||
monitorChange = -monitorChange;
|
||||
|
||||
for(let idx = 0; idx<monitorChange; idx++){
|
||||
this.remove_child(this.get_last_child());
|
||||
this._leftRightIcon = !this._leftRightIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const MultiMonitorsIndicator = new Lang.Class({
|
||||
Name: 'MultiMonitorsIndicator',
|
||||
Extends: PanelMenu.Button,
|
||||
|
||||
_init: function() {
|
||||
this.parent(0.0, "MultiMonitorsAddOn");
|
||||
|
||||
this.text = null;
|
||||
|
||||
this._mmStatusIcon = new MultiMonitorsStatusIcon();
|
||||
this.actor.add_child(this._mmStatusIcon);
|
||||
|
||||
this.menu.addAction('Preferences', Lang.bind(this, this._onPreferences));
|
||||
this.menu.addAction('Test', Lang.bind(this, this._onTest));
|
||||
|
||||
},
|
||||
|
||||
_onPreferences: function()
|
||||
{
|
||||
Util.spawn(["gnome-shell-extension-prefs", "multi-monitors-add-on@spin83"]);
|
||||
},
|
||||
|
||||
_onTest: function()
|
||||
{
|
||||
global.log('Multi Monitors Add-On');
|
||||
this._showHello();
|
||||
},
|
||||
|
||||
_hideHello: function() {
|
||||
Main.uiGroup.remove_actor(this.text);
|
||||
this.text = null;
|
||||
},
|
||||
|
||||
_showHello: function() {
|
||||
if (!this.text) {
|
||||
this.text = new St.Label({ style_class: 'helloworld-label', text: "Multi Monitors Add-On" });
|
||||
Main.uiGroup.add_actor(this.text);
|
||||
}
|
||||
|
||||
this.text.opacity = 255;
|
||||
|
||||
let monitor = Main.layoutManager.primaryMonitor;
|
||||
|
||||
this.text.set_position(Math.floor(monitor.width / 2 - this.text.width / 2),
|
||||
Math.floor(monitor.height / 2 - this.text.height / 2));
|
||||
|
||||
Tweener.addTween(this.text,
|
||||
{ opacity: 0,
|
||||
time: 4,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, this._hideHello) });
|
||||
|
||||
},
|
||||
});
|
||||
8
multi-monitors-add-on@spin83/metadata.json
Normal file
8
multi-monitors-add-on@spin83/metadata.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"shell-version": ["3.10.4"],
|
||||
"uuid": "multi-monitors-add-on@spin83",
|
||||
"name": "Multi Monitors Add-On",
|
||||
"settings-schema": "org.gnome.shell.extensions.multi-monitors-add-on",
|
||||
"gettext-domain": "gnome-shell-extensions-multi-monitors-add-on",
|
||||
"description": "Add multiple monitors overview and panel for gnome-shell."
|
||||
}
|
||||
662
multi-monitors-add-on@spin83/mmoverview.js
Normal file
662
multi-monitors-add-on@spin83/mmoverview.js
Normal file
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
Copyright (C) 2014 spin83
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, visit https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GObject = imports.gi.GObject;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Meta = imports.gi.Meta;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Params = imports.misc.params;
|
||||
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
const OverviewControls = imports.ui.overviewControls;
|
||||
const Overview = imports.ui.overview;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
const LayoutManager = imports.ui.layout;
|
||||
const Background = imports.ui.background;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const MultiMonitors = ExtensionUtils.getCurrentExtension();
|
||||
const Convenience = MultiMonitors.imports.convenience;
|
||||
|
||||
const THUMBNAILS_ON_LEFT_SIDE_ID = 'thumbnails-on-left-side';
|
||||
|
||||
const MultiMonitorsWorkspaceThumbnail = new Lang.Class({
|
||||
Name: 'MultiMonitorsWorkspaceThumbnail',
|
||||
Extends: WorkspaceThumbnail.WorkspaceThumbnail,
|
||||
|
||||
_init : function(metaWorkspace, monitorIndex) {
|
||||
this.metaWorkspace = metaWorkspace;
|
||||
this.monitorIndex = monitorIndex;
|
||||
|
||||
this._removed = false;
|
||||
|
||||
this.actor = new St.Widget({ clip_to_allocation: true,
|
||||
style_class: 'workspace-thumbnail' });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this._contents = new Clutter.Actor();
|
||||
this.actor.add_child(this._contents);
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
// this._createBackground();
|
||||
this._bgManager = new Background.BackgroundManager({ monitorIndex: this.monitorIndex,
|
||||
container: this._contents,
|
||||
effects: Meta.BackgroundEffects.NONE });
|
||||
|
||||
let monitor = Main.layoutManager.monitors[this.monitorIndex];
|
||||
this.setPorthole(monitor.x, monitor.y, monitor.width, monitor.height);
|
||||
|
||||
let windows = global.get_window_actors().filter(Lang.bind(this, function(actor) {
|
||||
let win = actor.meta_window;
|
||||
return win.located_on_workspace(metaWorkspace);
|
||||
}));
|
||||
|
||||
// Create clones for windows that should be visible in the Overview
|
||||
this._windows = [];
|
||||
this._allWindows = [];
|
||||
this._minimizedChangedIds = [];
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let minimizedChangedId =
|
||||
windows[i].meta_window.connect('notify::minimized',
|
||||
Lang.bind(this,
|
||||
this._updateMinimized));
|
||||
this._allWindows.push(windows[i].meta_window);
|
||||
this._minimizedChangedIds.push(minimizedChangedId);
|
||||
|
||||
if (this._isMyWindow(windows[i]) && this._isOverviewWindow(windows[i])) {
|
||||
this._addWindowClone(windows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Track window changes
|
||||
this._windowAddedId = this.metaWorkspace.connect('window-added',
|
||||
Lang.bind(this, this._windowAdded));
|
||||
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
|
||||
Lang.bind(this, this._windowRemoved));
|
||||
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
|
||||
Lang.bind(this, this._windowEnteredMonitor));
|
||||
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
|
||||
Lang.bind(this, this._windowLeftMonitor));
|
||||
|
||||
this.state = WorkspaceThumbnail.ThumbnailState.NORMAL;
|
||||
this._slidePosition = 0; // Fully slid in
|
||||
this._collapseFraction = 0; // Not collapsed
|
||||
}
|
||||
});
|
||||
|
||||
const MultiMonitorsThumbnailsBox = new Lang.Class({
|
||||
Name: 'MultiMonitorsThumbnailsBox',
|
||||
Extends: WorkspaceThumbnail.ThumbnailsBox,
|
||||
|
||||
_init: function(monitorIndex) {
|
||||
this._monitorIndex = monitorIndex;
|
||||
|
||||
this.actor = new Shell.GenericContainer({ reactive: true,
|
||||
style_class: 'workspace-thumbnails',
|
||||
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
this.actor._delegate = this;
|
||||
|
||||
let indicator = new St.Bin({ style_class: 'workspace-thumbnail-indicator' });
|
||||
|
||||
// We don't want the indicator to affect drag-and-drop
|
||||
Shell.util_set_hidden_from_pick(indicator, true);
|
||||
|
||||
this._indicator = indicator;
|
||||
this.actor.add_actor(indicator);
|
||||
|
||||
this._dropWorkspace = -1;
|
||||
this._dropPlaceholderPos = -1;
|
||||
this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
|
||||
this.actor.add_actor(this._dropPlaceholder);
|
||||
this._spliceIndex = -1;
|
||||
|
||||
this._targetScale = 0;
|
||||
this._scale = 0;
|
||||
this._pendingScaleUpdate = false;
|
||||
this._stateUpdateQueued = false;
|
||||
this._animatingIndicator = false;
|
||||
this._indicatorY = 0; // only used when _animatingIndicator is true
|
||||
|
||||
this._stateCounts = {};
|
||||
for (let key in WorkspaceThumbnail.ThumbnailState)
|
||||
this._stateCounts[WorkspaceThumbnail.ThumbnailState[key]] = 0;
|
||||
|
||||
this._thumbnails = [];
|
||||
|
||||
this.actor.connect('button-press-event', function() { return true; });
|
||||
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
|
||||
|
||||
this._showingId = Main.overview.connect('showing', Lang.bind(this, this._createThumbnails));
|
||||
this._hiddenId = Main.overview.connect('hidden', Lang.bind(this, this._destroyThumbnails));
|
||||
|
||||
this._itemDragBeginId = Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
this._itemDragEndId = Main.overview.connect('item-drag-end', Lang.bind(this, this._onDragEnd));
|
||||
this._itemDragCancelledId = Main.overview.connect('item-drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
||||
this._windowDragBeginId = Main.overview.connect('window-drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
this._windowDragEndId = Main.overview.connect('window-drag-end', Lang.bind(this, this._onDragEnd));
|
||||
this._windowDragCancelledId = Main.overview.connect('window-drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
||||
|
||||
this._settings = new Gio.Settings({ schema: WorkspaceThumbnail.OVERRIDE_SCHEMA });
|
||||
this._changedDynamicWorkspacesId = this._settings.connect('changed::dynamic-workspaces',
|
||||
Lang.bind(this, this._updateSwitcherVisibility));
|
||||
},
|
||||
|
||||
_onDestroy: function(actor) {
|
||||
this._destroyThumbnails();
|
||||
|
||||
Main.overview.disconnect(this._showingId);
|
||||
Main.overview.disconnect(this._hiddenId);
|
||||
|
||||
Main.overview.disconnect(this._itemDragBeginId);
|
||||
Main.overview.disconnect(this._itemDragEndId);
|
||||
Main.overview.disconnect(this._itemDragCancelledId);
|
||||
Main.overview.disconnect(this._windowDragBeginId);
|
||||
Main.overview.disconnect(this._windowDragEndId);
|
||||
Main.overview.disconnect(this._windowDragCancelledId);
|
||||
|
||||
this._settings.disconnect(this._changedDynamicWorkspacesId);
|
||||
//TODO drag end ??
|
||||
|
||||
Tweener.removeTweens(actor);
|
||||
|
||||
this.actor._delegate = null;
|
||||
},
|
||||
|
||||
_createThumbnails: function() {
|
||||
this._switchWorkspaceNotifyId =
|
||||
global.window_manager.connect('switch-workspace',
|
||||
Lang.bind(this, this._activeWorkspaceChanged));
|
||||
this._nWorkspacesNotifyId =
|
||||
global.screen.connect('notify::n-workspaces',
|
||||
Lang.bind(this, this._workspacesChanged));
|
||||
this._syncStackingId =
|
||||
Main.overview.connect('windows-restacked',
|
||||
Lang.bind(this, this._syncStacking));
|
||||
|
||||
this._targetScale = 0;
|
||||
this._scale = 0;
|
||||
this._pendingScaleUpdate = false;
|
||||
this._stateUpdateQueued = false;
|
||||
|
||||
this._stateCounts = {};
|
||||
for (let key in WorkspaceThumbnail.ThumbnailState)
|
||||
this._stateCounts[WorkspaceThumbnail.ThumbnailState[key]] = 0;
|
||||
|
||||
// The "porthole" is the portion of the screen that we show in the workspaces
|
||||
this._porthole = Main.layoutManager.getWorkAreaForMonitor(this._monitorIndex);
|
||||
|
||||
this.addThumbnails(0, global.screen.n_workspaces);
|
||||
|
||||
this._updateSwitcherVisibility();
|
||||
},
|
||||
|
||||
addThumbnails: function(start, count) {
|
||||
for (let k = start; k < start + count; k++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(k);
|
||||
|
||||
let thumbnail = new MultiMonitorsWorkspaceThumbnail(metaWorkspace, this._monitorIndex);
|
||||
|
||||
thumbnail.setPorthole(this._porthole.x, this._porthole.y,
|
||||
this._porthole.width, this._porthole.height);
|
||||
this._thumbnails.push(thumbnail);
|
||||
this.actor.add_actor(thumbnail.actor);
|
||||
|
||||
if (start > 0 && this._spliceIndex == -1) {
|
||||
// not the initial fill, and not splicing via DND
|
||||
thumbnail.state = WorkspaceThumbnail.ThumbnailState.NEW;
|
||||
thumbnail.slidePosition = 1; // start slid out
|
||||
this._haveNewThumbnails = true;
|
||||
} else {
|
||||
thumbnail.state = WorkspaceThumbnail.ThumbnailState.NORMAL;
|
||||
}
|
||||
|
||||
this._stateCounts[thumbnail.state]++;
|
||||
}
|
||||
|
||||
this._queueUpdateStates();
|
||||
|
||||
// The thumbnails indicator actually needs to be on top of the thumbnails
|
||||
this._indicator.raise_top();
|
||||
|
||||
// Clear the splice index, we got the message
|
||||
this._spliceIndex = -1;
|
||||
}
|
||||
});
|
||||
|
||||
const MultiMonitorsSlidingControl = new Lang.Class({
|
||||
Name: 'MultiMonitorsSlidingControl',
|
||||
Extends: OverviewControls.SlidingControl,
|
||||
|
||||
_init: function(params) {
|
||||
params = Params.parse(params, { slideDirection: OverviewControls.SlideDirection.LEFT });
|
||||
|
||||
this.visible = true;
|
||||
this.inDrag = false;
|
||||
|
||||
this.layout = new OverviewControls.SlideLayout();
|
||||
this.layout.slideDirection = params.slideDirection;
|
||||
this.actor = new St.Widget({ layout_manager: this.layout,
|
||||
style_class: 'overview-controls',
|
||||
clip_to_allocation: true });
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._showingId = Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing));
|
||||
|
||||
this._itemDragBeginId = Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
this._itemDragEndId = Main.overview.connect('item-drag-end', Lang.bind(this, this._onDragEnd));
|
||||
this._itemDragCancelledId = Main.overview.connect('item-drag-cancelled', Lang.bind(this, this._onDragEnd));
|
||||
|
||||
this._windowDragBeginId = Main.overview.connect('window-drag-begin', Lang.bind(this, this._onWindowDragBegin));
|
||||
this._windowDragCancelledId = Main.overview.connect('window-drag-cancelled', Lang.bind(this, this._onWindowDragEnd));
|
||||
this._windowDragEndId = Main.overview.connect('window-drag-end', Lang.bind(this, this._onWindowDragEnd));
|
||||
},
|
||||
|
||||
_onDestroy: function(actor) {
|
||||
Main.overview.disconnect(this._showingId);
|
||||
|
||||
Main.overview.disconnect(this._itemDragBeginId);
|
||||
Main.overview.disconnect(this._itemDragEndId);
|
||||
Main.overview.disconnect(this._itemDragCancelledId);
|
||||
|
||||
Main.overview.disconnect(this._windowDragBeginId);
|
||||
Main.overview.disconnect(this._windowDragCancelledId);
|
||||
Main.overview.disconnect(this._windowDragEndId);
|
||||
|
||||
Tweener.removeTweens(actor);
|
||||
},
|
||||
});
|
||||
|
||||
const MultiMonitorsThumbnailsSlider = new Lang.Class({
|
||||
Name: 'MultiMonitorsThumbnailsSlider',
|
||||
Extends: MultiMonitorsSlidingControl,
|
||||
|
||||
_init: function(thumbnailsBox) {
|
||||
this.parent({ slideDirection: OverviewControls.SlideDirection.RIGHT });
|
||||
|
||||
this._thumbnailsBox = thumbnailsBox;
|
||||
|
||||
this.actor.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
|
||||
this.actor.reactive = true;
|
||||
this.actor.track_hover = true;
|
||||
this.actor.add_actor(this._thumbnailsBox.actor);
|
||||
|
||||
this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.updateSlide));
|
||||
this._hidingId = Main.overview.connect('hiding', Lang.bind(this, this.slideOut));
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this.updateSlide));
|
||||
this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
Main.layoutManager.disconnect(this._monitorsChangedId);
|
||||
Main.overview.disconnect(this._hidingId);
|
||||
this.parent();
|
||||
},
|
||||
|
||||
_getAlwaysZoomOut: function() {
|
||||
// Always show the pager when hover, during a drag, or if workspaces are
|
||||
// actually used, e.g. there are windows on more than one
|
||||
let alwaysZoomOut = this.actor.hover || this.inDrag || !Meta.prefs_get_dynamic_workspaces() || global.screen.n_workspaces > 2;
|
||||
|
||||
if (!alwaysZoomOut) {
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let primary = Main.layoutManager.primaryMonitor;
|
||||
|
||||
/* Look for any monitor to the right of the primary, if there is
|
||||
* one, we always keep zoom out, otherwise its hard to reach
|
||||
* the thumbnail area without passing into the next monitor. */
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].x >= primary.x + primary.width) {
|
||||
alwaysZoomOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alwaysZoomOut;
|
||||
},
|
||||
|
||||
_onOverviewShowing: function() {
|
||||
this.visible = true;
|
||||
this.layout.slideX = this.getSlide();
|
||||
this.actor.translation_x = this._getTranslation();
|
||||
this.slideIn();
|
||||
},
|
||||
|
||||
getNonExpandedWidth: function() {
|
||||
let child = this.actor.get_first_child();
|
||||
return child.get_theme_node().get_length('visible-width');
|
||||
},
|
||||
|
||||
getSlide: function() {
|
||||
if (!this.visible)
|
||||
return 0;
|
||||
|
||||
let alwaysZoomOut = this._getAlwaysZoomOut();
|
||||
if (alwaysZoomOut)
|
||||
return 1;
|
||||
|
||||
let child = this.actor.get_first_child();
|
||||
let preferredHeight = child.get_preferred_height(-1)[1];
|
||||
let expandedWidth = child.get_preferred_width(preferredHeight)[1];
|
||||
|
||||
return this.getNonExpandedWidth() / expandedWidth;
|
||||
},
|
||||
|
||||
getVisibleWidth: function() {
|
||||
let alwaysZoomOut = this._getAlwaysZoomOut();
|
||||
if (alwaysZoomOut)
|
||||
return this.parent();
|
||||
else
|
||||
return this.getNonExpandedWidth();
|
||||
}
|
||||
});
|
||||
|
||||
const MultiMonitorsControlsManager = new Lang.Class({
|
||||
Name: 'MultiMonitorsControlsManager',
|
||||
|
||||
_init: function(index) {
|
||||
this._monitorIndex = index;
|
||||
this._workspacesViews = null;
|
||||
|
||||
this._thumbnailsBox = new MultiMonitorsThumbnailsBox(this._monitorIndex);
|
||||
this._thumbnailsSlider = new MultiMonitorsThumbnailsSlider(this._thumbnailsBox);
|
||||
|
||||
let layout = new OverviewControls.ControlsLayout();
|
||||
this.actor = new St.Widget({ layout_manager: layout,
|
||||
reactive: true,
|
||||
x_expand: true, y_expand: true,
|
||||
clip_to_allocation: true });
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
|
||||
this._group = new St.BoxLayout({ name: 'mm-overview-group',
|
||||
x_expand: true, y_expand: true });
|
||||
this.actor.add_actor(this._group);
|
||||
|
||||
this._viewActor = new St.Widget({ clip_to_allocation: true });
|
||||
|
||||
this._group.add(this._viewActor, { x_fill: true,
|
||||
expand: true });
|
||||
|
||||
this._group.add_actor(this._thumbnailsSlider.actor);
|
||||
|
||||
layout.connect('allocation-changed', Lang.bind(this, this._updateWorkspacesGeometry));
|
||||
|
||||
this._settings = Convenience.getSettings();
|
||||
this._thumbnailsOnLeftSideId = this._settings.connect('changed::'+THUMBNAILS_ON_LEFT_SIDE_ID,
|
||||
Lang.bind(this, this._thumbnailsOnLeftSide));
|
||||
this._thumbnailsOnLeftSide();
|
||||
|
||||
this._pageChangedId = Main.overview.viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility));
|
||||
this._pageEmptyId = Main.overview.viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty));
|
||||
|
||||
//
|
||||
// Main.overview.connect('item-drag-begin', Lang.bind(this,
|
||||
// function() {
|
||||
// let activePage = this.viewSelector.getActivePage();
|
||||
// if (activePage != ViewSelector.ViewPage.WINDOWS)
|
||||
// this.viewSelector.fadeHalf();
|
||||
// }));
|
||||
// Main.overview.connect('item-drag-end', Lang.bind(this,
|
||||
// function() {
|
||||
// this.viewSelector.fadeIn();
|
||||
// }));
|
||||
// Main.overview.connect('item-drag-cancelled', Lang.bind(this,
|
||||
// function() {
|
||||
// this.viewSelector.fadeIn();
|
||||
// }));
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
Main.overview.viewSelector.disconnect(this._pageChangedId);
|
||||
Main.overview.viewSelector.disconnect(this._pageEmptyId);
|
||||
this._settings.disconnect(this._thumbnailsOnLeftSideId);
|
||||
},
|
||||
|
||||
_thumbnailsOnLeftSide: function() {
|
||||
if(this._settings.get_boolean(THUMBNAILS_ON_LEFT_SIDE_ID)){
|
||||
let first = this._group.get_first_child();
|
||||
if(first != this._thumbnailsSlider.actor){
|
||||
this._thumbnailsSlider.layout.slideDirection = OverviewControls.SlideDirection.LEFT;
|
||||
this._thumbnailsBox.actor.remove_style_class_name('workspace-thumbnails');
|
||||
this._thumbnailsBox.actor.set_style_class_name('workspace-thumbnails-left');
|
||||
this._group.set_child_below_sibling(this._thumbnailsSlider.actor, first)
|
||||
}
|
||||
}
|
||||
else{
|
||||
let last = this._group.get_last_child();
|
||||
if(last != this._thumbnailsSlider.actor){
|
||||
this._thumbnailsSlider.layout.slideDirection = OverviewControls.SlideDirection.RIGHT;
|
||||
this._thumbnailsBox.actor.remove_style_class_name('workspace-thumbnails-left');
|
||||
this._thumbnailsBox.actor.set_style_class_name('workspace-thumbnails');
|
||||
this._group.set_child_above_sibling(this._thumbnailsSlider.actor, last);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_updateWorkspacesGeometry: function() {
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
let [width, height] = this.actor.get_transformed_size();
|
||||
let geometry = { x: x, y: y, width: width, height: height };
|
||||
|
||||
let spacing = this.actor.get_theme_node().get_length('spacing');
|
||||
|
||||
let thumbnailsWidth = this._thumbnailsSlider.getVisibleWidth() + spacing;
|
||||
|
||||
geometry.width -= thumbnailsWidth;
|
||||
|
||||
if(this._settings.get_boolean(THUMBNAILS_ON_LEFT_SIDE_ID)){
|
||||
geometry.x += thumbnailsWidth;
|
||||
}
|
||||
|
||||
// let [x, y] = this._viewActor.get_transformed_position();
|
||||
// let width = this._viewActor.allocation.x2 - this._viewActor.allocation.x1;
|
||||
// let height = this._viewActor.allocation.y2 - this._viewActor.allocation.y1;
|
||||
// let geometry = { x: x, y: y, width: width, height: height };
|
||||
|
||||
this.setWorkspacesFullGeometry(geometry);
|
||||
},
|
||||
|
||||
_setVisibility: function() {
|
||||
// Ignore the case when we're leaving the overview, since
|
||||
// actors will be made visible again when entering the overview
|
||||
// next time, and animating them while doing so is just
|
||||
// unnecessary noise
|
||||
if (!Main.overview.visible ||
|
||||
(Main.overview.animationInProgress && !Main.overview.visibleTarget))
|
||||
return;
|
||||
|
||||
let activePage = Main.overview.viewSelector.getActivePage();
|
||||
|
||||
let thumbnailsVisible = (activePage == ViewSelector.ViewPage.WINDOWS);
|
||||
|
||||
let opacity = null;
|
||||
if (thumbnailsVisible){
|
||||
this._thumbnailsSlider.slideIn();
|
||||
|
||||
opacity = 255;
|
||||
}
|
||||
else{
|
||||
this._thumbnailsSlider.slideOut();
|
||||
|
||||
opacity = 0;
|
||||
}
|
||||
|
||||
if(!this._workspacesViews)
|
||||
return;
|
||||
|
||||
this._workspacesViews.actor.visible = opacity != 0;
|
||||
Tweener.addTween(this._workspacesViews.actor,
|
||||
{ opacity: opacity,
|
||||
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
_onPageEmpty: function() {
|
||||
this._thumbnailsSlider.pageEmpty();
|
||||
},
|
||||
show: function() {
|
||||
this._workspacesViews = Main.overview.viewSelector._workspacesDisplay._workspacesViews[this._monitorIndex];
|
||||
},
|
||||
zoomFromOverview: function() {
|
||||
|
||||
// this._workspacesViews.hide();
|
||||
|
||||
// this._workspacesDisplay.zoomFromOverview();
|
||||
//
|
||||
// if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
||||
// Main.overview.fadeInDesktop();
|
||||
},
|
||||
setWorkspacesFullGeometry: function(geom) {
|
||||
if(!this._workspacesViews)
|
||||
return;
|
||||
|
||||
|
||||
this._workspacesViews.setActualGeometry(geom);
|
||||
},
|
||||
hide: function() {
|
||||
if(!this._workspacesViews.actor.visible){
|
||||
this._workspacesViews.actor.opacity = 255;
|
||||
this._workspacesViews.actor.visible = true;
|
||||
}
|
||||
this._workspacesViews = null;
|
||||
}
|
||||
});
|
||||
|
||||
const MultiMonitorsOverview = new Lang.Class({
|
||||
Name: 'MultiMonitorsOverview',
|
||||
|
||||
_init: function(index) {
|
||||
this.monitorIndex = index;
|
||||
this._settings = Convenience.getSettings();
|
||||
|
||||
let monitor = Main.layoutManager.monitors[this.monitorIndex];
|
||||
|
||||
let layout = new Clutter.BinLayout();
|
||||
this._stack = new Clutter.Actor({ layout_manager: layout });
|
||||
this._stack.add_constraint(new LayoutManager.MonitorConstraint({ index: this.monitorIndex }));
|
||||
this._stack.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
Main.layoutManager.overviewGroup.add_child(this._stack);
|
||||
|
||||
|
||||
this._overview = new St.BoxLayout({ name: 'overview'+this.monitorIndex,
|
||||
accessible_name: _("Overview"+this.monitorIndex),
|
||||
reactive: true,
|
||||
vertical: true,
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
this._overview._delegate = this;
|
||||
this._stack.add_actor(this._overview);
|
||||
|
||||
if(Main.mmPanel && Main.mmPanel[this.monitorIndex]){
|
||||
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.mmPanel[this.monitorIndex].actor }),
|
||||
reactive: false, opacity: 0 });
|
||||
this._overview.add_actor(this._panelGhost);
|
||||
}
|
||||
else
|
||||
this._panelGhost = null;
|
||||
|
||||
|
||||
this._overview.add_actor(new St.Widget({style_class: 'multimonitor-spacer'}));
|
||||
|
||||
this._controls = new MultiMonitorsControlsManager(this.monitorIndex);
|
||||
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
|
||||
|
||||
this._showingId = Main.overview.connect('showing', Lang.bind(this, this._show));
|
||||
this._hidingId = Main.overview.connect('hiding', Lang.bind(this, this._hide));
|
||||
},
|
||||
|
||||
_onDestroy: function(actor) {
|
||||
Main.overview.disconnect(this._showingId);
|
||||
Main.overview.disconnect(this._hidingId);
|
||||
|
||||
Tweener.removeTweens(actor);
|
||||
|
||||
Main.layoutManager.overviewGroup.remove_child(this._stack);
|
||||
|
||||
this._overview._delegate = null;
|
||||
},
|
||||
|
||||
addPanelGhost: function() {
|
||||
if(!this._panelGhost) {
|
||||
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.mmPanel[this.monitorIndex].actor }),
|
||||
reactive: false, opacity: 0 });
|
||||
this._overview.add_actor(this._panelGhost);
|
||||
this._overview.set_child_at_index(this._panelGhost, 0);
|
||||
}
|
||||
},
|
||||
|
||||
removePanelGhost: function() {
|
||||
if(this._panelGhost) {
|
||||
this._overview.remove_actor(this._panelGhost);
|
||||
this._panelGhost.destroy();
|
||||
this._panelGhost = null;
|
||||
}
|
||||
},
|
||||
|
||||
_show: function() {
|
||||
this._controls.show();
|
||||
|
||||
this._stack.opacity = 0;
|
||||
Tweener.addTween(this._stack,
|
||||
{ opacity: 255,
|
||||
transition: 'easeOutQuad',
|
||||
time: Overview.ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this, this._showDone),
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
_showDone: function() {
|
||||
},
|
||||
|
||||
_hide: function() {
|
||||
this._controls.zoomFromOverview();
|
||||
|
||||
Tweener.addTween(this._stack,
|
||||
{ opacity: 0,
|
||||
transition: 'easeOutQuad',
|
||||
time: Overview.ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this, this._hideDone),
|
||||
onCompleteScope: this
|
||||
});
|
||||
},
|
||||
|
||||
_hideDone: function() {
|
||||
this._controls.hide();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._stack.destroy();
|
||||
}
|
||||
|
||||
});
|
||||
413
multi-monitors-add-on@spin83/mmpanel.js
Normal file
413
multi-monitors-add-on@spin83/mmpanel.js
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
Copyright (C) 2014 spin83
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, visit https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Meta = imports.gi.Meta;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Panel = imports.ui.panel;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
const ExtensionSystem = imports.ui.extensionSystem;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const MultiMonitors = ExtensionUtils.getCurrentExtension();
|
||||
const Convenience = MultiMonitors.imports.convenience;
|
||||
|
||||
const SHOW_ACTIVITIES_ID = 'show-activities';
|
||||
const SHOW_APP_MENU_ID = 'show-app-menu';
|
||||
const AVAILABLE_INDICATORS_ID = 'available-indicators';
|
||||
const TRANSFER_INDICATORS_ID = 'transfer-indicators';
|
||||
|
||||
const StatusIndicatorsController = new Lang.Class({
|
||||
Name: 'StatusIndicatorController',
|
||||
|
||||
_init: function() {
|
||||
this._transfered_indicators = []; //{iname:, box:, monitor:}
|
||||
this._settings = Convenience.getSettings();
|
||||
|
||||
this._updatedSessionId = Main.sessionMode.connect('updated', Lang.bind(this, this._updateSessionIndicators));
|
||||
this._updateSessionIndicators();
|
||||
this._extensionStateChangedId = ExtensionSystem.connect('extension-state-changed',
|
||||
Lang.bind(this, this._extensionStateChanged));
|
||||
|
||||
this._transferIndicatorsId = this._settings.connect('changed::'+TRANSFER_INDICATORS_ID,
|
||||
Lang.bind(this, this._transferIndicators));
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._settings.disconnect(this._transferIndicatorsId);
|
||||
ExtensionSystem.disconnect(this._extensionStateChangedId);
|
||||
Main.sessionMode.disconnect(this._updatedSessionId);
|
||||
this._settings.set_strv(AVAILABLE_INDICATORS_ID, []);
|
||||
this._transferBack(this._transfered_indicators);
|
||||
},
|
||||
|
||||
_transferIndicators: function() {
|
||||
let boxs = ['_leftBox', '_centerBox', '_rightBox'];
|
||||
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
|
||||
|
||||
let transfer_back = this._transfered_indicators.filter(function(element) {
|
||||
return !transfers.hasOwnProperty(element.iname);
|
||||
});
|
||||
|
||||
this._transferBack(transfer_back);
|
||||
|
||||
for(let iname in transfers) {
|
||||
if(transfers.hasOwnProperty(iname) && Main.panel.statusArea[iname]) {
|
||||
let monitor = transfers[iname];
|
||||
let indicator = Main.panel.statusArea[iname];
|
||||
boxs.forEach(Lang.bind(this, function(box) {
|
||||
if(Main.panel[box].contains(indicator.container) && Main.mmPanel[monitor]) {
|
||||
global.log('a '+box+ " > " + iname + " : "+ monitor);
|
||||
this._transfered_indicators.push({iname:iname, box:box, monitor:monitor});
|
||||
Main.panel[box].remove_child(indicator.container);
|
||||
Main.mmPanel[monitor][box].insert_child_at_index(indicator.container, 0);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_transferBack: function(transfer_back) {
|
||||
transfer_back.forEach(Lang.bind(this, function(element) {
|
||||
this._transfered_indicators.slice(this._transfered_indicators.indexOf(element));
|
||||
if(Main.panel.statusArea[element.iname]) {
|
||||
let indicator = Main.panel.statusArea[element.iname];
|
||||
if(Main.mmPanel[element.monitor][element.box].contains(indicator.container)) {
|
||||
global.log("r "+element.box+ " > " + element.iname + " : "+ element.monitor);
|
||||
Main.mmPanel[element.monitor][element.box].remove_child(indicator.container);
|
||||
Main.panel[element.box].insert_child_at_index(indicator.container, 0);
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_extensionStateChanged: function() {
|
||||
this._findAvailableIndicators();
|
||||
this._transferIndicators();
|
||||
},
|
||||
|
||||
_updateSessionIndicators: function() {
|
||||
let session_indicators = [];
|
||||
session_indicators.push('MultiMonitorsAddOn');
|
||||
let sessionPanel = Main.sessionMode.panel;
|
||||
for (let sessionBox in sessionPanel){
|
||||
sessionPanel[sessionBox].forEach(function(sesionIndicator){
|
||||
session_indicators.push(sesionIndicator);
|
||||
});
|
||||
}
|
||||
this._session_indicators = session_indicators;
|
||||
this._available_indicators = [];
|
||||
|
||||
this._findAvailableIndicators();
|
||||
this._transferIndicators();
|
||||
},
|
||||
|
||||
_findAvailableIndicators: function() {
|
||||
let available_indicators = [];
|
||||
let statusArea = Main.panel.statusArea;
|
||||
for(let indicator in statusArea) {
|
||||
if(statusArea.hasOwnProperty(indicator) && this._session_indicators.indexOf(indicator)<0){
|
||||
available_indicators.push(indicator);
|
||||
}
|
||||
}
|
||||
if(available_indicators.length!=this._available_indicators.length) {
|
||||
this._available_indicators = available_indicators;
|
||||
// global.log(this._available_indicators);
|
||||
this._settings.set_strv(AVAILABLE_INDICATORS_ID, this._available_indicators);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const MultiMonitorsAppMenuButton = new Lang.Class({
|
||||
Name: 'MultiMonitorsAppMenuButton',
|
||||
Extends: Panel.AppMenuButton,
|
||||
|
||||
_init: function(panel){
|
||||
if(!panel.monitorIndex)
|
||||
this._monitorIndex = Main.layoutManager.primaryIndex;
|
||||
else
|
||||
this._monitorIndex = panel.monitorIndex;
|
||||
this._actionOnWorkspaceGroupNotifyId = 0;
|
||||
this._targetAppGroup = null;
|
||||
this._lastFocusedWindow = null;
|
||||
this.parent(panel);
|
||||
|
||||
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
|
||||
Lang.bind(this, this._windowEnteredMonitor));
|
||||
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
|
||||
Lang.bind(this, this._windowLeftMonitor));
|
||||
},
|
||||
|
||||
_windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) {
|
||||
if (monitorIndex == this._monitorIndex) {
|
||||
switch(metaWin.get_window_type()){
|
||||
case Meta.WindowType.NORMAL:
|
||||
case Meta.WindowType.DIALOG:
|
||||
case Meta.WindowType.MODAL_DIALOG:
|
||||
case Meta.WindowType.SPLASHSCREEN:
|
||||
this._sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) {
|
||||
if (monitorIndex == this._monitorIndex) {
|
||||
switch(metaWin.get_window_type()){
|
||||
case Meta.WindowType.NORMAL:
|
||||
case Meta.WindowType.DIALOG:
|
||||
case Meta.WindowType.MODAL_DIALOG:
|
||||
case Meta.WindowType.SPLASHSCREEN:
|
||||
this._sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_findTargetApp: function() {
|
||||
|
||||
if (this._actionOnWorkspaceGroupNotifyId) {
|
||||
this._targetAppGroup.disconnect(this._actionOnWorkspaceGroupNotifyId);
|
||||
this._actionOnWorkspaceGroupNotifyId = 0;
|
||||
this._targetAppGroup = null;
|
||||
}
|
||||
let groupWindow = false;
|
||||
let groupFocus = false;
|
||||
|
||||
let workspace = global.screen.get_active_workspace();
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
let focusedApp = tracker.focus_app;
|
||||
if (focusedApp && focusedApp.is_on_workspace(workspace)){
|
||||
let windows = focusedApp.get_windows();
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let win = windows[i];
|
||||
if(win.located_on_workspace(workspace)){
|
||||
if(win.get_monitor() == this._monitorIndex){
|
||||
if(win.has_focus()){
|
||||
this._lastFocusedWindow = win;
|
||||
// global.log(this._monitorIndex+": focus :"+win.get_title()+" : "+win.has_focus());
|
||||
return focusedApp;
|
||||
}
|
||||
else
|
||||
groupWindow = true;
|
||||
}
|
||||
else{
|
||||
if(win.has_focus())
|
||||
groupFocus = true;
|
||||
}
|
||||
if(groupFocus && groupWindow){
|
||||
if(focusedApp != this._targetApp){
|
||||
this._targetAppGroup = focusedApp;
|
||||
this._actionOnWorkspaceGroupNotifyId = this._targetAppGroup.connect('notify::action-group',
|
||||
Lang.bind(this, this._sync));
|
||||
// global.log(this._monitorIndex+": gConnect :"+win.get_title()+" : "+win.has_focus());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._startingApps.length; i++)
|
||||
if (this._startingApps[i].is_on_workspace(workspace)){
|
||||
// global.log(this._monitorIndex+": newAppFocus");
|
||||
return this._startingApps[i];
|
||||
}
|
||||
|
||||
if (this._lastFocusedWindow && this._lastFocusedWindow.located_on_workspace(workspace) &&
|
||||
this._lastFocusedWindow.get_monitor() == this._monitorIndex){
|
||||
// global.log(this._monitorIndex+": lastFocus :"+this._lastFocusedWindow.get_title());
|
||||
return tracker.get_window_app(this._lastFocusedWindow);
|
||||
}
|
||||
|
||||
let screen = global.screen;
|
||||
let windows = screen.get_display().get_tab_list(Meta.TabList.NORMAL_ALL, screen, workspace);
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if(windows[i].get_monitor() == this._monitorIndex){
|
||||
this._lastFocusedWindow = windows[i];
|
||||
// global.log(this._monitorIndex+": appFind :"+windows[i].get_title());
|
||||
return tracker.get_window_app(windows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
destroy: function() {
|
||||
this.parent();
|
||||
|
||||
if (this._actionGroupNotifyId) {
|
||||
this._targetApp.disconnect(this._actionGroupNotifyId);
|
||||
this._actionGroupNotifyId = 0;
|
||||
}
|
||||
|
||||
global.screen.disconnect(this._windowEnteredMonitorId);
|
||||
global.screen.disconnect(this._windowLeftMonitorId);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS = {
|
||||
'activities': Panel.ActivitiesButton,
|
||||
// 'aggregateMenu': Panel.AggregateMenu,
|
||||
'appMenu': MultiMonitorsAppMenuButton,
|
||||
// 'dateMenu': imports.ui.dateMenu.DateMenuButton,
|
||||
// 'a11y': imports.ui.status.accessibility.ATIndicator,
|
||||
// 'a11yGreeter': imports.ui.status.accessibility.ATGreeterIndicator,
|
||||
// 'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
|
||||
};
|
||||
|
||||
const MultiMonitorsPanel = new Lang.Class({
|
||||
Name: 'MultiMonitorsPanel',
|
||||
Extends: Panel.Panel,
|
||||
|
||||
_init : function(monitorIndex) {
|
||||
this.monitorIndex = monitorIndex;
|
||||
this.actor = new Shell.GenericContainer({ name: 'panel', reactive: true });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this._sessionStyle = null;
|
||||
|
||||
this.statusArea = {};
|
||||
|
||||
this.menuManager = new PopupMenu.PopupMenuManager(this, { keybindingMode: Shell.KeyBindingMode.TOPBAR_POPUP });
|
||||
|
||||
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
|
||||
this.actor.add_actor(this._leftBox);
|
||||
this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
|
||||
this.actor.add_actor(this._centerBox);
|
||||
this._rightBox = new St.BoxLayout({ name: 'panelRight' });
|
||||
this.actor.add_actor(this._rightBox);
|
||||
|
||||
this._leftCorner = new Panel.PanelCorner(St.Side.LEFT);
|
||||
this.actor.add_actor(this._leftCorner.actor);
|
||||
|
||||
this._rightCorner = new Panel.PanelCorner(St.Side.RIGHT);
|
||||
this.actor.add_actor(this._rightCorner.actor);
|
||||
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._showingId = Main.overview.connect('showing', Lang.bind(this, function () {
|
||||
this.actor.add_style_pseudo_class('overview');
|
||||
}));
|
||||
this._hidingId = Main.overview.connect('hiding', Lang.bind(this, function () {
|
||||
this.actor.remove_style_pseudo_class('overview');
|
||||
}));
|
||||
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar "+this.monitorIndex), 'emblem-system-symbolic',
|
||||
{ sortGroup: CtrlAltTab.SortGroup.TOP });
|
||||
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._updatePanel));
|
||||
this._updatePanel();
|
||||
|
||||
this._settings = Convenience.getSettings();
|
||||
this._showActivitiesId = this._settings.connect('changed::'+SHOW_ACTIVITIES_ID,
|
||||
Lang.bind(this, this._showActivities));
|
||||
this._showActivities();
|
||||
|
||||
this._showAppMenuId = this._settings.connect('changed::'+SHOW_APP_MENU_ID,
|
||||
Lang.bind(this, this._showAppMenu));
|
||||
this._showAppMenu();
|
||||
},
|
||||
|
||||
_onDestroy: function(actor) {
|
||||
Main.overview.disconnect(this._showingId);
|
||||
Main.overview.disconnect(this._hidingId);
|
||||
this._settings.disconnect(this._showActivitiesId);
|
||||
|
||||
// Tweener.removeTweens(actor);
|
||||
|
||||
Main.ctrlAltTabManager.removeGroup(this.actor);
|
||||
|
||||
for(let name in this.statusArea){
|
||||
if(this.statusArea.hasOwnProperty(name))
|
||||
this.statusArea[name].destroy();
|
||||
}
|
||||
|
||||
this.actor._delegate = null;
|
||||
},
|
||||
|
||||
_showActivities: function() {
|
||||
let name = 'activities';
|
||||
if(this._settings.get_boolean(SHOW_ACTIVITIES_ID)){
|
||||
if(this.statusArea[name])
|
||||
this.statusArea[name].actor.visible = true;
|
||||
}
|
||||
else{
|
||||
if(this.statusArea[name])
|
||||
this.statusArea[name].actor.visible = false;
|
||||
}
|
||||
},
|
||||
|
||||
_showAppMenu: function() {
|
||||
let name = 'appMenu';
|
||||
if(this._settings.get_boolean(SHOW_APP_MENU_ID)){
|
||||
if(!this.statusArea[name]){
|
||||
let indicator = new MultiMonitorsAppMenuButton(this);
|
||||
this.statusArea[name] = indicator;
|
||||
let box = this._leftBox;
|
||||
this._addToPanelBox(name, indicator, box.get_n_children()+1, box);
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
if(this.statusArea[name]){
|
||||
let indicator = this.statusArea[name];
|
||||
this.menuManager.removeMenu(indicator.menu);
|
||||
indicator.destroy();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
alloc.min_size = -1;
|
||||
alloc.natural_size = Main.layoutManager.monitors[this.monitorIndex].width;
|
||||
},
|
||||
|
||||
_hideIndicators: function() {
|
||||
for (let role in MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS) {
|
||||
let indicator = this.statusArea[role];
|
||||
if (!indicator)
|
||||
continue;
|
||||
if (indicator.menu)
|
||||
indicator.menu.close();
|
||||
indicator.container.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_ensureIndicator: function(role) {
|
||||
let indicator = this.statusArea[role];
|
||||
if (!indicator) {
|
||||
let constructor = MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS[role];
|
||||
if (!constructor) {
|
||||
return null;
|
||||
}
|
||||
indicator = new constructor(this);
|
||||
this.statusArea[role] = indicator;
|
||||
}
|
||||
return indicator;
|
||||
}
|
||||
});
|
||||
247
multi-monitors-add-on@spin83/prefs.js
Normal file
247
multi-monitors-add-on@spin83/prefs.js
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
Copyright (C) 2014 spin83
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, visit https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions-multi-monitors-add-on');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const MultiMonitors = ExtensionUtils.getCurrentExtension();
|
||||
const Convenience = MultiMonitors.imports.convenience;
|
||||
|
||||
const SHOW_INDICATOR_ID = 'show-indicator';
|
||||
const SHOW_PANEL_ID = 'show-panel';
|
||||
const SHOW_THUMBNAILS_SLIDER_ID = 'show-thumbnails-slider';
|
||||
const SHOW_ACTIVITIES_ID = 'show-activities';
|
||||
const SHOW_APP_MENU_ID = 'show-app-menu';
|
||||
const THUMBNAILS_ON_LEFT_SIDE_ID = 'thumbnails-on-left-side';
|
||||
const AVAILABLE_INDICATORS_ID = 'available-indicators';
|
||||
const TRANSFER_INDICATORS_ID = 'transfer-indicators';
|
||||
|
||||
const Columns = {
|
||||
INDICATOR_NAME: 0,
|
||||
MONITOR_NUMBER: 1
|
||||
};
|
||||
|
||||
|
||||
const MultiMonitorsPrefsWidget = new GObject.Class({
|
||||
Name: 'MultiMonitorsPrefsWidget',
|
||||
Extends: Gtk.Grid,
|
||||
|
||||
_init: function(params) {
|
||||
this.parent(params);
|
||||
|
||||
this.set_orientation(Gtk.Orientation.VERTICAL);
|
||||
|
||||
this._settings = Convenience.getSettings();
|
||||
|
||||
this._screen = Gdk.Screen.get_default();
|
||||
|
||||
this._addBooleanSwitch(_('Show Multi Monitors indicator on Top Panel.'), SHOW_INDICATOR_ID);
|
||||
this._addBooleanSwitch(_('Show Panel on additional monitors.'), SHOW_PANEL_ID);
|
||||
this._addBooleanSwitch(_('Show Thumbnails-Slider on additional monitors.'), SHOW_THUMBNAILS_SLIDER_ID);
|
||||
this._addBooleanSwitch(_('Show Activities-Button on additional monitors.'), SHOW_ACTIVITIES_ID);
|
||||
this._addBooleanSwitch(_('Show AppMenu-Button on additional monitors.'), SHOW_APP_MENU_ID);
|
||||
this._addBooleanSwitch(_('Show Thumbnails-Slider on left side of additional monitors.'), THUMBNAILS_ON_LEFT_SIDE_ID);
|
||||
|
||||
this._store = new Gtk.ListStore();
|
||||
this._store.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT]);
|
||||
|
||||
this._treeView = new Gtk.TreeView({ model: this._store, hexpand: true, vexpand: true });
|
||||
this._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
|
||||
|
||||
let appColumn = new Gtk.TreeViewColumn({ expand: true, sort_column_id: Columns.INDICATOR_NAME,
|
||||
title: _("A list of indicators for transfer to additional monitors.") });
|
||||
|
||||
let nameRenderer = new Gtk.CellRendererText;
|
||||
appColumn.pack_start(nameRenderer, true);
|
||||
appColumn.add_attribute(nameRenderer, "text", Columns.INDICATOR_NAME);
|
||||
|
||||
let nameRenderer = new Gtk.CellRendererText;
|
||||
appColumn.pack_start(nameRenderer, true);
|
||||
appColumn.add_attribute(nameRenderer, "text", Columns.MONITOR_NUMBER);
|
||||
|
||||
this._treeView.append_column(appColumn);
|
||||
this.add(this._treeView);
|
||||
|
||||
let toolbar = new Gtk.Toolbar();
|
||||
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
|
||||
|
||||
this._settings.connect('changed::'+TRANSFER_INDICATORS_ID, Lang.bind(this, this._updateIndicators));
|
||||
this._updateIndicators();
|
||||
|
||||
let addTButton = new Gtk.ToolButton({ stock_id: Gtk.STOCK_ADD });
|
||||
addTButton.connect('clicked', Lang.bind(this, this._addIndicator));
|
||||
toolbar.add(addTButton);
|
||||
|
||||
let removeTButton = new Gtk.ToolButton({ stock_id: Gtk.STOCK_REMOVE });
|
||||
removeTButton.connect('clicked', Lang.bind(this, this._removeIndicator));
|
||||
toolbar.add(removeTButton);
|
||||
|
||||
this.add(toolbar);
|
||||
|
||||
},
|
||||
|
||||
_updateIndicators: function() {
|
||||
this._store.clear();
|
||||
|
||||
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
|
||||
|
||||
for(let indicator in transfers) {
|
||||
if(transfers.hasOwnProperty(indicator)){
|
||||
let monitor = transfers[indicator];
|
||||
let iter = this._store.append();
|
||||
this._store.set(iter, [Columns.INDICATOR_NAME, Columns.MONITOR_NUMBER], [indicator, monitor]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_addIndicator: function() {
|
||||
|
||||
let dialog = new Gtk.Dialog({ title: _("Select indicator"),
|
||||
transient_for: this.get_toplevel(), modal: true });
|
||||
dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
|
||||
dialog.add_button(_("Add"), Gtk.ResponseType.OK);
|
||||
dialog.set_default_response(Gtk.ResponseType.OK);
|
||||
|
||||
let grid = new Gtk.Grid({ column_spacing: 10, row_spacing: 15, margin: 10 });
|
||||
|
||||
grid.set_orientation(Gtk.Orientation.VERTICAL);
|
||||
|
||||
dialog._store = new Gtk.ListStore();
|
||||
dialog._store.set_column_types([GObject.TYPE_STRING]);
|
||||
|
||||
dialog._treeView = new Gtk.TreeView({ model: dialog._store, hexpand: true, vexpand: true });
|
||||
dialog._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
|
||||
|
||||
let appColumn = new Gtk.TreeViewColumn({ expand: true, sort_column_id: Columns.INDICATOR_NAME,
|
||||
title: _("Indicators on Top Panel") });
|
||||
|
||||
let nameRenderer = new Gtk.CellRendererText;
|
||||
appColumn.pack_start(nameRenderer, true);
|
||||
appColumn.add_attribute(nameRenderer, "text", Columns.INDICATOR_NAME);
|
||||
|
||||
dialog._treeView.append_column(appColumn);
|
||||
|
||||
let availableIndicators = function() {
|
||||
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).unpack();
|
||||
dialog._store.clear();
|
||||
this._settings.get_strv(AVAILABLE_INDICATORS_ID).forEach(function(indicator){
|
||||
if(!transfers.hasOwnProperty(indicator)){
|
||||
let iter = dialog._store.append();
|
||||
dialog._store.set(iter, [Columns.INDICATOR_NAME], [indicator]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let availableIndicatorsId = this._settings.connect('changed::'+AVAILABLE_INDICATORS_ID,
|
||||
Lang.bind(this, availableIndicators));
|
||||
let transferIndicatorsId = this._settings.connect('changed::'+TRANSFER_INDICATORS_ID,
|
||||
Lang.bind(this, availableIndicators));
|
||||
|
||||
availableIndicators.apply(this);
|
||||
// grid.attach(dialog._treeView, 0, 0, 2, 1);
|
||||
grid.add(dialog._treeView);
|
||||
|
||||
let gHBox = new Gtk.HBox({margin: 10, spacing: 20, hexpand: true});
|
||||
let gLabel = new Gtk.Label({label: _('Monitor index:'), halign: Gtk.Align.START});
|
||||
gHBox.add(gLabel);
|
||||
dialog._adjustment = new Gtk.Adjustment({lower: 0.0, upper: 0.0, step_increment:1.0});
|
||||
let spinButton = new Gtk.SpinButton({halign: Gtk.Align.END, adjustment: dialog._adjustment, numeric: 1});
|
||||
gHBox.add(spinButton);
|
||||
|
||||
let monitorsChanged = function() {
|
||||
let n_monitors = this._screen.get_n_monitors() -1;
|
||||
dialog._adjustment.set_upper(n_monitors)
|
||||
dialog._adjustment.set_value(n_monitors);
|
||||
};
|
||||
|
||||
let monitorsChangedId = this._screen.connect('monitors-changed', Lang.bind(this, monitorsChanged));
|
||||
|
||||
monitorsChanged.apply(this);
|
||||
grid.add(gHBox);
|
||||
|
||||
dialog.get_content_area().add(grid);
|
||||
|
||||
dialog.connect('response', Lang.bind(this, function(dialog, id) {
|
||||
this._screen.disconnect(monitorsChangedId);
|
||||
this._settings.disconnect(availableIndicatorsId);
|
||||
this._settings.disconnect(transferIndicatorsId);
|
||||
if (id != Gtk.ResponseType.OK) {
|
||||
dialog.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
let [any, model, iter] = dialog._treeView.get_selection().get_selected();
|
||||
if (any) {
|
||||
let indicator = model.get_value(iter, Columns.INDICATOR_NAME);
|
||||
|
||||
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
|
||||
if(!transfers.hasOwnProperty(indicator)){
|
||||
transfers[indicator] = dialog._adjustment.get_value();
|
||||
this._settings.set_value(TRANSFER_INDICATORS_ID, new GLib.Variant('a{si}', transfers));
|
||||
}
|
||||
}
|
||||
|
||||
dialog.destroy();
|
||||
}));
|
||||
|
||||
dialog.show_all();
|
||||
},
|
||||
|
||||
_removeIndicator: function() {
|
||||
let [any, model, iter] = this._treeView.get_selection().get_selected();
|
||||
if (any) {
|
||||
let indicator = model.get_value(iter, Columns.INDICATOR_NAME);
|
||||
|
||||
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
|
||||
if(transfers.hasOwnProperty(indicator)){
|
||||
delete transfers[indicator];
|
||||
this._settings.set_value(TRANSFER_INDICATORS_ID, new GLib.Variant('a{si}', transfers));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_addBooleanSwitch: function(label, schema_id) {
|
||||
let gHBox = new Gtk.HBox({margin: 10, spacing: 20, hexpand: true});
|
||||
let gLabel = new Gtk.Label({label: _(label), halign: Gtk.Align.START});
|
||||
gHBox.add(gLabel);
|
||||
let gSwitch = new Gtk.Switch({halign: Gtk.Align.END});
|
||||
gHBox.add(gSwitch);
|
||||
this.add(gHBox);
|
||||
|
||||
this._settings.bind(schema_id, gSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
|
||||
}
|
||||
});
|
||||
|
||||
function init() {
|
||||
Convenience.initTranslations();
|
||||
}
|
||||
|
||||
function buildPrefsWidget() {
|
||||
let widget = new MultiMonitorsPrefsWidget();
|
||||
widget.show_all();
|
||||
|
||||
return widget;
|
||||
}
|
||||
BIN
multi-monitors-add-on@spin83/schemas/gschemas.compiled
Normal file
BIN
multi-monitors-add-on@spin83/schemas/gschemas.compiled
Normal file
Binary file not shown.
@@ -0,0 +1,53 @@
|
||||
<schemalist gettext-domain="gnome-shell-extensions">
|
||||
<schema id="org.gnome.shell.extensions.multi-monitors-add-on" path="/org/gnome/shell/extensions/multi-monitors-add-on/">
|
||||
|
||||
<key name="show-indicator" type="b">
|
||||
<default>true</default>
|
||||
<summary>Show Multi Monitors indicator on Top Panel.</summary>
|
||||
<description>Add or remove Multi Monitors indicator from Top Panel.</description>
|
||||
</key>
|
||||
|
||||
<key name="show-panel" type="b">
|
||||
<default>true</default>
|
||||
<summary>Show Panel on additional monitors.</summary>
|
||||
<description>Add or remove Panel from additional monitors.</description>
|
||||
</key>
|
||||
|
||||
<key name="show-thumbnails-slider" type="b">
|
||||
<default>true</default>
|
||||
<summary>Show Thumbnails-Slider on additional monitors.</summary>
|
||||
<description>Add or remove Thumbnails-Slider from additional monitors.</description>
|
||||
</key>
|
||||
|
||||
<key name="show-activities" type="b">
|
||||
<default>true</default>
|
||||
<summary>Show Activities-Button on additional monitors.</summary>
|
||||
<description>Change visibility of Activities-Button on additional monitors.</description>
|
||||
</key>
|
||||
|
||||
<key name="show-app-menu" type="b">
|
||||
<default>true</default>
|
||||
<summary>Show AppMenu-Button on additional monitors.</summary>
|
||||
<description>Change visibility of AppMenu-Button on additional monitors.</description>
|
||||
</key>
|
||||
|
||||
<key name="thumbnails-on-left-side" type="b">
|
||||
<default>true</default>
|
||||
<summary>Show Thumbnails-Slider on left side of additional monitors.</summary>
|
||||
<description>Toggle position of Thumbnails-Slider from right to left on additional monitors.</description>
|
||||
</key>
|
||||
|
||||
<key name="available-indicators" type="as">
|
||||
<default>[]</default>
|
||||
<summary>A list of available indicators.</summary>
|
||||
<description>A list of indicators that are available for transfer. For internal use only.</description>
|
||||
</key>
|
||||
|
||||
<key name="transfer-indicators" type="a{si}">
|
||||
<default>{}</default>
|
||||
<summary>A list of indicators for transfer.</summary>
|
||||
<description>A list of indicators selected for transfer to additional Panel.</description>
|
||||
</key>
|
||||
|
||||
</schema>
|
||||
</schemalist>
|
||||
39
multi-monitors-add-on@spin83/stylesheet.css
Normal file
39
multi-monitors-add-on@spin83/stylesheet.css
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
.helloworld-label {
|
||||
font-size: 72px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
border-radius: 5px;
|
||||
padding: .5em;
|
||||
}
|
||||
|
||||
.multimonitor-spacer {
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
.panel-status-menu-box {
|
||||
spacing: 0px;
|
||||
}
|
||||
|
||||
.system-status-icon {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.workspace-thumbnails-left {
|
||||
spacing: 11px;
|
||||
visible-width: 32px; /* Amount visible before hovering */
|
||||
border: 1px solid rgba(128, 128, 128, 0.4);
|
||||
border-left: 0px;
|
||||
border-radius: 0px 9px 9px 0px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
padding: 11px 11px 11px 7px;
|
||||
|
||||
}
|
||||
|
||||
.workspace-thumbnails-left:rtl {
|
||||
border-left: 1px;
|
||||
border-right: 0px;
|
||||
border-radius: 9px 0px 0px 9px;
|
||||
padding: 11px 7px 11px 11px;
|
||||
}
|
||||
Reference in New Issue
Block a user