From d1158bd61bb91b37c60c78fdc598461956c64fd7 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel@debian.org>
Date: Mon, 24 Mar 2025 19:40:00 +0100
Subject: [PATCH] Adding multi-monitors-add-on version 25 [515dfd0].

Signed-off-by: Daniel Baumann <daniel@debian.org>
---
 multi-monitors-add-on/.project                |  11 +
 multi-monitors-add-on/LICENSE                 | 340 +++++++++
 multi-monitors-add-on/README.md               |  33 +
 .../convenience.js                            |  93 +++
 .../multi-monitors-add-on@spin83/extension.js | 289 ++++++++
 .../icons/multi-monitors-l-symbolic.svg       | 392 ++++++++++
 .../icons/multi-monitors-r-symbolic.svg       | 393 ++++++++++
 .../multi-monitors-add-on@spin83/indicator.js | 109 +++
 .../de/LC_MESSAGES/multi-monitors-add-on.mo   | Bin 0 -> 1722 bytes
 .../de/LC_MESSAGES/multi-monitors-add-on.po   |  95 +++
 .../es/LC_MESSAGES/multi-monitors-add-on.mo   | Bin 0 -> 1593 bytes
 .../es/LC_MESSAGES/multi-monitors-add-on.po   |  91 +++
 .../fr/LC_MESSAGES/multi-monitors-add-on.mo   | Bin 0 -> 1701 bytes
 .../fr/LC_MESSAGES/multi-monitors-add-on.po   |  94 +++
 .../it/LC_MESSAGES/multi-monitors-add-on.mo   | Bin 0 -> 1820 bytes
 .../it/LC_MESSAGES/multi-monitors-add-on.po   |  93 +++
 .../pl/LC_MESSAGES/multi-monitors-add-on.mo   | Bin 0 -> 1743 bytes
 .../pl/LC_MESSAGES/multi-monitors-add-on.po   |  94 +++
 .../LC_MESSAGES/multi-monitors-add-on.mo      | Bin 0 -> 1759 bytes
 .../LC_MESSAGES/multi-monitors-add-on.po      |  89 +++
 .../metadata.json                             |  10 +
 .../mmcalendar.js                             | 412 +++++++++++
 .../multi-monitors-add-on@spin83/mmlayout.js  | 251 +++++++
 .../mmoverview.js                             | 678 ++++++++++++++++++
 .../multi-monitors-add-on@spin83/mmpanel.js   | 520 ++++++++++++++
 .../multi-monitors-add-on.pot                 |  89 +++
 .../multi-monitors-add-on@spin83/prefs.js     | 289 ++++++++
 .../schemas/gschemas.compiled                 | Bin 0 -> 788 bytes
 ...tensions.multi-monitors-add-on.gschema.xml |  59 ++
 .../stylesheet.css                            |  29 +
 30 files changed, 4553 insertions(+)
 create mode 100644 multi-monitors-add-on/.project
 create mode 100644 multi-monitors-add-on/LICENSE
 create mode 100644 multi-monitors-add-on/README.md
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/convenience.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/extension.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-l-symbolic.svg
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-r-symbolic.svg
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/indicator.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/de/LC_MESSAGES/multi-monitors-add-on.mo
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/de/LC_MESSAGES/multi-monitors-add-on.po
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/es/LC_MESSAGES/multi-monitors-add-on.mo
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/es/LC_MESSAGES/multi-monitors-add-on.po
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/fr/LC_MESSAGES/multi-monitors-add-on.mo
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/fr/LC_MESSAGES/multi-monitors-add-on.po
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/it/LC_MESSAGES/multi-monitors-add-on.mo
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/it/LC_MESSAGES/multi-monitors-add-on.po
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pl/LC_MESSAGES/multi-monitors-add-on.mo
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pl/LC_MESSAGES/multi-monitors-add-on.po
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pt_BR/LC_MESSAGES/multi-monitors-add-on.mo
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pt_BR/LC_MESSAGES/multi-monitors-add-on.po
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/metadata.json
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/mmcalendar.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/mmlayout.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/mmoverview.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/mmpanel.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/multi-monitors-add-on.pot
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/prefs.js
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/schemas/gschemas.compiled
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/schemas/org.gnome.shell.extensions.multi-monitors-add-on.gschema.xml
 create mode 100644 multi-monitors-add-on/multi-monitors-add-on@spin83/stylesheet.css

diff --git a/multi-monitors-add-on/.project b/multi-monitors-add-on/.project
new file mode 100644
index 0000000..58f94f4
--- /dev/null
+++ b/multi-monitors-add-on/.project
@@ -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>
diff --git a/multi-monitors-add-on/LICENSE b/multi-monitors-add-on/LICENSE
new file mode 100644
index 0000000..d6a9326
--- /dev/null
+++ b/multi-monitors-add-on/LICENSE
@@ -0,0 +1,340 @@
+GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    {description}
+    Copyright (C) {year}  {fullname}
+
+    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, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  {signature of Ty Coon}, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+
diff --git a/multi-monitors-add-on/README.md b/multi-monitors-add-on/README.md
new file mode 100644
index 0000000..4aaa45a
--- /dev/null
+++ b/multi-monitors-add-on/README.md
@@ -0,0 +1,33 @@
+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.
+
+Versions
+========
+
+* Branch [master](https://github.com/realh/multi-monitors-add-on/tree/master) contains extension for GNOME 42
+* Branch [gnome-3-32_3-36](https://github.com/spin83/multi-monitors-add-on/tree/gnome-3-32_3-36) contains extension for GNOME 3.32, 3.34 and 3.36
+* Branch [gnome-3-24_3-30](https://github.com/spin83/multi-monitors-add-on/tree/gnome-3-24_3-30) contains extension for GNOME 3.24, 3.26, 3.28 and 3.30
+* Branch [gnome-3-20_3-22](https://github.com/spin83/multi-monitors-add-on/tree/gnome-3-20_3-22) contains extension for GNOME 3.20 and 3.22
+* Branch [gnome-3-16_3-18](https://github.com/spin83/multi-monitors-add-on/tree/gnome-3-16_3-18) contains extension for GNOME 3.16 and 3.18
+* Branch [gnome-3-14](https://github.com/spin83/multi-monitors-add-on/tree/gnome-3-14) contains extension for GNOME 3.14
+* Branch [gnome-3-10](https://github.com/spin83/multi-monitors-add-on/tree/gnome-3-10) contains extension for GNOME 3.10
+
+Installation from git
+=====================
+
+    git clone git://github.com/realh/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 LICENSE file for details.
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/convenience.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/convenience.js
new file mode 100644
index 0000000..bbc8608
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/convenience.js
@@ -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 });
+}
+								  
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/extension.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/extension.js
new file mode 100644
index 0000000..092d828
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/extension.js
@@ -0,0 +1,289 @@
+/*
+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 { Clutter, Gio } = imports.gi;
+
+const Main = imports.ui.main;
+var { ANIMATION_TIME } = imports.ui.overview;
+
+const Config = imports.misc.config;
+const GNOME_SHELL_VERSION = Config.PACKAGE_VERSION.split('.');
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const MultiMonitors = ExtensionUtils.getCurrentExtension();
+const Convenience = MultiMonitors.imports.convenience;
+
+const MMLayout = MultiMonitors.imports.mmlayout;
+const MMOverview = MultiMonitors.imports.mmoverview;
+const MMIndicator = MultiMonitors.imports.indicator;
+
+const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
+const MUTTER_SCHEMA = 'org.gnome.mutter';
+const WORKSPACES_ONLY_ON_PRIMARY_ID = 'workspaces-only-on-primary';
+
+const SHOW_INDICATOR_ID = 'show-indicator';
+const THUMBNAILS_SLIDER_POSITION_ID = 'thumbnails-slider-position';
+
+function copyClass (s, d) {
+//    global.log(s.name +" > "+ d.name);
+    if (!s) throw Error(`copyClass s undefined for d ${d.name}`)
+    let propertyNames = Reflect.ownKeys(s.prototype);
+    for (let pName of propertyNames.values()) {
+
+//        global.log(" ) "+pName.toString());
+        if (typeof pName === "symbol") continue;
+        if (d.prototype.hasOwnProperty(pName)) continue;
+        if (pName === "prototype") continue;
+        if (pName === "constructor") continue;
+//        global.log(pName);
+        let pDesc = Reflect.getOwnPropertyDescriptor(s.prototype, pName);
+//        global.log(typeof pDesc);
+        if (typeof pDesc !== 'object') continue;
+        Reflect.defineProperty(d.prototype, pName, pDesc);
+    }
+};
+
+function gnomeShellVersion() {
+    return GNOME_SHELL_VERSION;
+}
+
+class MultiMonitorsAddOn {
+
+    constructor() {
+        this._settings = Convenience.getSettings();
+        this._ov_settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
+        this._mu_settings = new Gio.Settings({ schema: MUTTER_SCHEMA });
+
+        this.mmIndicator = null;
+        Main.mmOverview = null;
+        Main.mmLayoutManager = null;
+
+        this._mmMonitors = 0;
+        this.syncWorkspacesActualGeometry = null;
+    }
+
+    _showIndicator() {
+		if(this._settings.get_boolean(SHOW_INDICATOR_ID)) {
+			if(!this.mmIndicator) {
+				this.mmIndicator = Main.panel.addToStatusArea('MultiMonitorsAddOn', new MMIndicator.MultiMonitorsIndicator());
+			}
+		}
+		else {
+			this._hideIndicator();
+		}
+    }
+
+    _hideIndicator() {
+		if(this.mmIndicator) {
+			this.mmIndicator.destroy();
+			this.mmIndicator = null;
+		}
+    }
+
+    _showThumbnailsSlider() {
+		if (this._settings.get_string(THUMBNAILS_SLIDER_POSITION_ID) === 'none') {
+			this._hideThumbnailsSlider();
+			return;
+		}
+
+		if(this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
+			this._ov_settings.set_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID, false);
+		if(this._mu_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
+			this._mu_settings.set_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID, false);
+
+		if (Main.mmOverview)
+			return;
+
+		Main.mmOverview = [];
+		for (let idx = 0; idx < Main.layoutManager.monitors.length; idx++) {
+			if (idx != Main.layoutManager.primaryIndex) {
+				Main.mmOverview[idx] = new MMOverview.MultiMonitorsOverview(idx);
+			}
+		}
+
+		this.syncWorkspacesActualGeometry = Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry;
+		Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry = function() {
+			if (this._inWindowFade)
+				return;
+
+			const primaryView = this._getPrimaryView();
+			if (primaryView) {
+				primaryView.ease({
+					...this._actualGeometry,
+					duration: Main.overview.animationInProgress ? ANIMATION_TIME : 0,
+					mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+				});
+			}
+
+			for (let idx = 0; idx < Main.mmOverview.length; idx++) {
+				if (!Main.mmOverview[idx])
+					continue;
+				if (!Main.mmOverview[idx]._overview)
+					continue;
+				const mmView = Main.mmOverview[idx]._overview._controls._workspacesViews;
+				if (!mmView)
+					continue;
+
+				const mmGeometry = Main.mmOverview[idx].getWorkspacesActualGeometry();
+				mmView.ease({
+					...mmGeometry,
+					duration: Main.overview.animationInProgress ? ANIMATION_TIME : 0,
+					mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+				});
+			}
+		}
+    }
+
+	_hideThumbnailsSlider() {
+        if (!Main.mmOverview)
+            return;
+
+        for (let idx = 0; idx < Main.mmOverview.length; idx++) {
+            if (Main.mmOverview[idx])
+                Main.mmOverview[idx].destroy();
+        }
+        Main.mmOverview = null;
+        Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry = this.syncWorkspacesActualGeometry;
+    }
+
+    _relayout() {
+		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._showThumbnailsSlider();
+		}
+    }
+
+    _switchOffThumbnails() {
+		if (this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID) || this._mu_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID)) {
+			this._settings.set_string(THUMBNAILS_SLIDER_POSITION_ID, 'none');
+		}
+    }
+
+    enable(version) {
+		global.log("Enable Multi Monitors Add-On ("+version+")...")
+		
+		if(Main.panel.statusArea.MultiMonitorsAddOn)
+			disable();
+		
+		this._mmMonitors = 0;
+
+		this._switchOffThumbnailsOvId = this._ov_settings.connect('changed::'+WORKSPACES_ONLY_ON_PRIMARY_ID,
+																	this._switchOffThumbnails.bind(this));
+		this._switchOffThumbnailsMuId = this._mu_settings.connect('changed::'+WORKSPACES_ONLY_ON_PRIMARY_ID,
+																	this._switchOffThumbnails.bind(this));
+
+		this._showIndicatorId = this._settings.connect('changed::'+SHOW_INDICATOR_ID, this._showIndicator.bind(this));
+		this._showIndicator();
+		
+		Main.mmLayoutManager = new MMLayout.MultiMonitorsLayoutManager();
+		this._showPanelId = this._settings.connect('changed::'+MMLayout.SHOW_PANEL_ID, Main.mmLayoutManager.showPanel.bind(Main.mmLayoutManager));
+		Main.mmLayoutManager.showPanel();
+		
+		this._thumbnailsSliderPositionId = this._settings.connect('changed::'+THUMBNAILS_SLIDER_POSITION_ID, this._showThumbnailsSlider.bind(this));
+		this._relayoutId = Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
+		this._relayout();
+    }
+
+    disable() {
+		Main.layoutManager.disconnect(this._relayoutId);
+		this._ov_settings.disconnect(this._switchOffThumbnailsOvId);
+		this._mu_settings.disconnect(this._switchOffThumbnailsMuId);
+		
+		this._settings.disconnect(this._showPanelId);
+		this._settings.disconnect(this._thumbnailsSliderPositionId);
+		this._settings.disconnect(this._showIndicatorId);
+
+		
+		this._hideIndicator();
+		
+		Main.mmLayoutManager.hidePanel();
+		Main.mmLayoutManager = null;
+		
+		this._hideThumbnailsSlider();
+		this._mmMonitors = 0;
+		
+		global.log("Disable Multi Monitors Add-On ...")
+    }
+}
+
+var multiMonitorsAddOn = null;
+var version = null;
+
+function init() {
+    Convenience.initTranslations();
+
+    // fix bug in panel: Destroy function many time added to this same indicator.
+    Main.panel._ensureIndicator = function(role) {
+        let indicator = this.statusArea[role];
+        if (indicator) {
+            indicator.container.show();
+            return null;
+        }
+        else {
+            let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
+            if (!constructor) {
+                // This icon is not implemented (this is a bug)
+                return null;
+            }
+            indicator = new constructor(this);
+            this.statusArea[role] = indicator;
+        }
+        return indicator;
+    };
+
+    const metaVersion = MultiMonitors.metadata['version'];
+    if (Number.isFinite(metaVersion)) {
+        version = 'v'+Math.trunc(metaVersion);
+        switch(Math.round((metaVersion%1)*10)) {
+           case 0:
+               break;
+            case 1:
+               version += '+bugfix';
+               break;
+            case 2:
+               version += '+develop';
+               break;
+           default:
+               version += '+modified';
+                break;
+        }
+    }
+    else
+        version = metaVersion;
+}
+
+function enable() {
+    if (multiMonitorsAddOn !== null)
+        return;
+
+    multiMonitorsAddOn = new MultiMonitorsAddOn();
+    multiMonitorsAddOn.enable(version);
+}
+
+function disable() {
+    if (multiMonitorsAddOn == null)
+        return;
+
+    multiMonitorsAddOn.disable();
+    multiMonitorsAddOn = null;
+}
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-l-symbolic.svg b/multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-l-symbolic.svg
new file mode 100644
index 0000000..6341c21
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-l-symbolic.svg
@@ -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>
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-r-symbolic.svg b/multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-r-symbolic.svg
new file mode 100644
index 0000000..6bf4651
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/icons/multi-monitors-r-symbolic.svg
@@ -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>
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/indicator.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/indicator.js
new file mode 100644
index 0000000..8b500ee
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/indicator.js
@@ -0,0 +1,109 @@
+/*
+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 { St, Gio, GLib, GObject } = imports.gi;
+
+const Util = imports.misc.util;
+const Main = imports.ui.main;
+const PanelMenu = imports.ui.panelMenu;
+
+const Gettext = imports.gettext.domain('multi-monitors-add-on');
+const _ = Gettext.gettext;
+const CE = imports.misc.extensionUtils.getCurrentExtension();
+const MultiMonitors = CE.imports.extension;
+const Convenience = CE.imports.convenience;
+const extensionPath = CE.path;
+
+var MultiMonitorsIndicator = (() => {
+	let MultiMonitorsIndicator = class MultiMonitorsIndicator extends PanelMenu.Button {
+		_init() {
+			super._init(0.0, "MultiMonitorsAddOn", false);
+
+			Convenience.initTranslations();
+
+			this.text = null;
+			this._mmStatusIcon = new St.BoxLayout({ style_class: 'multimonitor-status-indicators-box' });
+			this._mmStatusIcon.hide();
+			this.add_child(this._mmStatusIcon);
+			this._leftRightIcon = true;
+			this.menu.addAction(_("Preferences"), this._onPreferences.bind(this));
+			this._viewMonitorsId = Main.layoutManager.connect('monitors-changed', this._viewMonitors.bind(this));
+			this._viewMonitors();
+		}
+			
+		_onDestroy() {
+			Main.layoutManager.disconnect(this._viewMonitorsId);
+			super._onDestroy();
+		}
+
+	    _syncIndicatorsVisible() {
+	        this._mmStatusIcon.visible = this._mmStatusIcon.get_children().some(a => a.visible);
+	    }
+
+	    _icon_name (icon, iconName) {
+	    	icon.set_gicon(Gio.icon_new_for_string(extensionPath+"/icons/"+iconName+".svg"));
+	    }
+
+		_viewMonitors() {
+			let monitors = this._mmStatusIcon.get_children();
+		
+			let monitorChange = Main.layoutManager.monitors.length - monitors.length;
+			if(monitorChange>0){
+				global.log("Add Monitors ...");
+				for(let idx = 0; idx<monitorChange; idx++){
+					let icon;
+					icon = new St.Icon({style_class: 'system-status-icon multimonitor-status-icon'});
+					this._mmStatusIcon.add_child(icon);
+					icon.connect('notify::visible', this._syncIndicatorsVisible.bind(this));
+					
+					if (this._leftRightIcon)
+						this._icon_name(icon, 'multi-monitors-l-symbolic');
+					else
+						this._icon_name(icon, 'multi-monitors-r-symbolic');
+					this._leftRightIcon = !this._leftRightIcon;
+				}
+				this._syncIndicatorsVisible();
+			}
+			else if(monitorChange<0){
+				global.log("Remove Monitors ...");
+				monitorChange = -monitorChange;
+				
+				for(let idx = 0; idx<monitorChange; idx++){
+					let icon = this._mmStatusIcon.get_last_child();
+					this._mmStatusIcon.remove_child(icon);
+					icon.destroy();
+					this._leftRightIcon = !this._leftRightIcon;
+				}
+			}
+		}
+
+		_onPreferences() {
+			const uuid = "multi-monitors-add-on@spin83";
+			Gio.DBus.session.call(
+				'org.gnome.Shell.Extensions',
+				'/org/gnome/Shell/Extensions',
+				'org.gnome.Shell.Extensions',
+				'OpenExtensionPrefs',
+				new GLib.Variant('(ssa{sv})', [uuid, '', {}]),
+				null,
+				Gio.DBusCallFlags.NONE,
+				-1,
+				null);
+		}
+	};
+	return GObject.registerClass(MultiMonitorsIndicator);
+})();
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/de/LC_MESSAGES/multi-monitors-add-on.mo b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/de/LC_MESSAGES/multi-monitors-add-on.mo
new file mode 100644
index 0000000000000000000000000000000000000000..ce5795c05e08ff2e9fdfcb56f79a1c9e82b6a866
GIT binary patch
literal 1722
zcma)+&u<$=6vqcBKWcuc0xA&V@WhdJ)^^fL=~4=&m^3I>Ol?}krCRSkd#9b9v36$T
z5RM$UaP65(xN_pap`6Sgz+ZsG3GqLG#CN<-991cJl*wmj^5(todowS;zk2SWz<34o
zZOrd5U&H(xGmKkL32_bF0iOZC0p9?>1;d%|!HeLJ;EUj|;05qEFarMoFM$`H7UD8^
z9Smy)z5_l4gWb>IFR=X+yo>b@=W2idfQ0q=XN7nfd>4EZ+*+<b17FAb9{2(1!7JcT
zU<>?fxqj=pI_@5L1N&ct2q#{`3?t<70%ph&5*8!GJHPyf41pt}v0R5-;d(Ki55GI4
zmGflBq)evL#M{!**p}qW#JDlz!%~uE$}4LUO@%co*hHd}WnyP_#u^&hDfJV>TJ&nG
z;FAwx(W|sqwA^%rlXB09e#!99CS@lEtU2{74Pubn8Ff;x_7Rz#{HXFCA@FminA&_g
z?XjuWvi&&mJX8g*W&D`_lS&0SCrL-O=0ySiTjwyZijhf_c5<Lqh8jO9t$u0mqb_nM
zlXtjuxPq7-6N6&Xo}q1H3#LKNT2uGHvkAtH+dQ?UmpwO888V$XIkYk5-cMcJY)+KV
zt5KBNqUol}Y;87+a8dI3jwMPht!XOfDt3+jp1jTbDma#*d@*gb+E-<(EjKo4V<X;d
zU23&kt;TNRyc~w-qr-EG=~KKMpBVa*Ri=^c_51b4y~BFr!%1-vWqboC&7?{uEQg#F
zF>P~M;Mo6~$CPoSx6|vciqwu;jhoh>4v_NI6k0tW_~uk6%DhKuo|KOL`=1X#ky|Uf
z<%^eHliEy~NlaTK<r`nfZ8luix%4fg7pNUwjjrG?^->OORi=Eib{kXeS9FzO+C_UY
z?c;_+vpfi1*j%PeF(uV_!NbbUkNlxlY0l=jO>hP`p5}Ihy&0Do;H=hc#4TkGtMUBN
z1mCBeqI*yXJf>0TD%#}``M4ENcjEGXWw)HM@?2JC612ivYkZ&f3XN_yKgvVc&Vxla
zLMj_MKn=AY>-iBxFETkh3-qhOH3z31Gh>q>fGgO{AFX!?53MRBUXEYOKC1uM9A|h^
foil5*l2+Ghtq7u1j-bXZQ%52wx5L$~Cs6zgcODkO

literal 0
HcmV?d00001

diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/de/LC_MESSAGES/multi-monitors-add-on.po b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/de/LC_MESSAGES/multi-monitors-add-on.po
new file mode 100644
index 0000000..0691ac2
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/de/LC_MESSAGES/multi-monitors-add-on.po
@@ -0,0 +1,95 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Multi Monitors Add On Gnome Shell Extension\n"
+"Report-Msgid-Bugs-To: https://github.com/spin83/multi-monitors-add-on/"
+"issues\n"
+"POT-Creation-Date: 2019-10-04 04:44-0300\n"
+"PO-Revision-Date: 2015-01-23 22:30+0100\n"
+"Last-Translator: Jonatan Zeidler <jonatan_zeidler@gmx.de>\n"
+"Language-Team: German <jonatan_zeidler@gmx.de>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.4\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: indicator.js:46
+msgid "Preferences"
+msgstr "Einstellungen"
+
+#: indicator.js:115
+msgid "Multi Monitors Add-On"
+msgstr "Multimonitor-Erweiterung"
+
+#: mmoverview.js:642
+msgid "Overview"
+msgstr ""
+
+#. Translators: If there is no suitable word for "Activities"
+#. in your language, you can use the word for "Overview".
+#: mmpanel.js:333
+msgid "Activities"
+msgstr ""
+
+#: mmpanel.js:414
+msgid "Top Bar"
+msgstr ""
+
+#: prefs.js:62
+msgid "Show Multi Monitors indicator on Top Panel."
+msgstr "Multimonitor-Indikator in der oberen Leiste anzeigen"
+
+#: prefs.js:63
+msgid "Show Panel on additional monitors."
+msgstr "Leiste auf zusätzlichen Monitoren anzeigen"
+
+#: prefs.js:64
+msgid "Show Thumbnails-Slider on additional monitors."
+msgstr "Arbeitsflächenübersicht auf zusätzlichen Monitoren anzeigen"
+
+#: prefs.js:65
+msgid "Show Activities-Button on additional monitors."
+msgstr "Aktivitäten-Schaltfläche auf zusätzlichen Monitoren anzeigen"
+
+#: prefs.js:66
+msgid "Show AppMenu-Button on additional monitors."
+msgstr "Anwendungsmenü auf zusätzlichen Monitoren anzeigen"
+
+#: prefs.js:67
+msgid "Show DateTime-Button on additional monitors."
+msgstr "Datum-Zeit auf zusätzlichen Monitoren anzeigen."
+
+#: prefs.js:71
+msgid "Enable hot corners."
+msgstr ""
+
+#: prefs.js:77
+msgid "A list of indicators for transfer to additional monitors."
+msgstr ""
+"Eine Liste von Indikatoren, die auf die zusätzlichen Monitore verschoben "
+"werden sollen"
+
+#: prefs.js:124
+msgid "Select indicator"
+msgstr "Indikator auswählen"
+
+#: prefs.js:127
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: prefs.js:141
+msgid "Indicators on Top Panel"
+msgstr "Indikatoren in der oberen Leiste"
+
+#: prefs.js:170
+msgid "Monitor index:"
+msgstr "Monitorindex:"
+
+#~ msgid "Test"
+#~ msgstr "Test"
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/es/LC_MESSAGES/multi-monitors-add-on.mo b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/es/LC_MESSAGES/multi-monitors-add-on.mo
new file mode 100644
index 0000000000000000000000000000000000000000..0cd6a923b0ef28983066cced56d226fb11b17166
GIT binary patch
literal 1593
zcma)*J8x4l6vqveS9l2V5DSB0r1&O%L3=4x1GEs)(5Oi}BDuM4V&rRI*-j}l143e9
z=#0e1g2aZpmJh&+gpimJ-vJ^1zDb%=0qRwp-*s{x|8wl~_3Y3l!E+kx64pzsb67vI
z!gK!sAyZ%lJOn-iFM`j(;PV>10KNlHfFHp#;3qHwzk$QxnS+E}1E;~Tm*5p}6AX4A
zz(=tC4&KIoeu$8x;0rM1dj*ELZ^6sp7I+f;0-gtdfD_;^a0VPd+>PtN>)5{muY#Y!
zad7AeAxM|U0P<RnfuTl7$e&aAKHhsrSOOPP=<P$T2$erUCn-}Uou_7vN}b3i_r^N9
zW-RrVYquuwVkl1%>7~(J(bQ-eY$8%l5>grX7)=`{qcyIDBGs-{h$%K=Qtc=&Y41lz
z;mH;?sab*eLN|pYb)iJl4>XW^+dQG=rkCr;EF8Pt@g6Dg`Ky?&d6rd$?(EC<F887#
zQ?W1OJ^FV#73Ay`9d$M54fwy#M!S=)YA%&ybtMz@_+Mq!ta*&Suu8&KgmpNAnAXa7
z9+dCR(UrNSdS&rpVM%1hdRBEUnV_1MV+|A2w)dHfi^Z1o?ape{G-=UgQcsQ*({LE9
ze~t|8WJVXIa~<IdwMDih)@8`VLW^QLS{k{*N@J`vPDjV$iK*ezNU2m<;Lfu~xFRZC
znV6Q9(az8XZaJOi`6g1>M4956&$d#O8&u4|Rku34C0Il7G^X{8Yw6l_dSPK!$;jB&
zz$B)SRIOC!2Gx&5rNSMfz0k=2G=o4dHhd9Tq`pa;ZEl_Lx0W08Y;s`NyUJ`%H%%gS
zE2fjH(ih0G&Tl_Y3{6Du@+HO!N3&2ze*~nZynpfWAIF^J!yv*GY`@3e_9mh0EHo7g
zA$CuK-rh=uH8CkSao>%VdCJ}?AZWV1g=5JSW?^S8B<~GINViKL#>+vQrHVsMJ|hWF
z5Cn;pL9Fid?Uma1g0@sZPpFw^3PYdA-><vkbWNbq`^?rI7BnWL8z>vp8{+ia744MP
a|0Vo8@cN_m{dz(dQmG~P9gElhH{mx%Y~H~D

literal 0
HcmV?d00001

diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/es/LC_MESSAGES/multi-monitors-add-on.po b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/es/LC_MESSAGES/multi-monitors-add-on.po
new file mode 100644
index 0000000..6c51dca
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/es/LC_MESSAGES/multi-monitors-add-on.po
@@ -0,0 +1,91 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Alonso Lara <alonso.lara.plana@gmail.com>, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: https://github.com/spin83/multi-monitors-add-on/"
+"issues\n"
+"POT-Creation-Date: 2019-10-04 04:44-0300\n"
+"PO-Revision-Date: 2017-03-04 23:59+0100\n"
+"Last-Translator: Alonso Lara <alonso.lara.plana@gmail.com>\n"
+"Language-Team: Spanish <LL@li.org>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: indicator.js:46
+msgid "Preferences"
+msgstr "Preferencias"
+
+#: indicator.js:115
+msgid "Multi Monitors Add-On"
+msgstr "Accesorio de monitores múltiples"
+
+#: mmoverview.js:642
+msgid "Overview"
+msgstr ""
+
+#. Translators: If there is no suitable word for "Activities"
+#. in your language, you can use the word for "Overview".
+#: mmpanel.js:333
+msgid "Activities"
+msgstr ""
+
+#: mmpanel.js:414
+msgid "Top Bar"
+msgstr ""
+
+#: prefs.js:62
+msgid "Show Multi Monitors indicator on Top Panel."
+msgstr "Mostrar indicador de monitores múltiples en el panel."
+
+#: prefs.js:63
+msgid "Show Panel on additional monitors."
+msgstr "Mostrar el panel en monitores adicionales."
+
+#: prefs.js:64
+msgid "Show Thumbnails-Slider on additional monitors."
+msgstr "Mostrar las miniaturas en los monitores adicionales."
+
+#: prefs.js:65
+msgid "Show Activities-Button on additional monitors."
+msgstr "Mostrar las actividades en los monitores adicionales."
+
+#: prefs.js:66
+msgid "Show AppMenu-Button on additional monitors."
+msgstr "Mostrar el menú de aplicaciones en los monitores adicionales."
+
+#: prefs.js:67
+msgid "Show DateTime-Button on additional monitors."
+msgstr "Mostrar la fecha en los monitores adicionales."
+
+#: prefs.js:71
+msgid "Enable hot corners."
+msgstr ""
+
+#: prefs.js:77
+msgid "A list of indicators for transfer to additional monitors."
+msgstr "Un listado de indicadores para transferir a monitores adicionales."
+
+#: prefs.js:124
+msgid "Select indicator"
+msgstr "Seleccione indicador"
+
+#: prefs.js:127
+msgid "Add"
+msgstr "Añadir"
+
+#: prefs.js:141
+msgid "Indicators on Top Panel"
+msgstr "Indicadores en el panel"
+
+#: prefs.js:170
+msgid "Monitor index:"
+msgstr "Monitor número:"
+
+#~ msgid "Test"
+#~ msgstr "Prueba"
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/fr/LC_MESSAGES/multi-monitors-add-on.mo b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/fr/LC_MESSAGES/multi-monitors-add-on.mo
new file mode 100644
index 0000000000000000000000000000000000000000..2aefbb2353720dfbe132b19d731bc3a6b2bd41fe
GIT binary patch
literal 1701
zcmbW1zmF3~6vrn45^#QS3IduadP+la8UG@Ojs*$_?%<?Y=bTNF4vlx8?IF7}tDV{7
zs8ghgl!`j_HL0m+4yDdt5GfVn51>Gz$ai*aA0W7(j6C{ycHg}BeQ)ON-=7_SATU0~
z{2cRF%rlrTFvGa@o)DM8E$|rlGk6~S1q^$B2hW0kfFFU6!4>c?unGPHu7WG?3-J|r
z6%1<)ehEGRgWW^$H`qP_H?h8VT!;_BM_{n~6Fdz*1<!%c!B4=I6SbZ%z$;i^0yn?{
zyb3-9*T83Bh`aiM5Pk3m5aGnfm|=umPGW`}A)y+<|Ec+ZgcH~z8uN9?6)vk0bc!CO
z+Ig}Q(k9Wd^0sg^u?6`;88>14v80kjdu@$MDYHfgo2KX`iP$>aV-1aLP6K5)75&;O
z_~gAv^vl$1nm=@eopRfVLBa6PCT1swoO0|BHHhKN-lJaZ^)4c_li!ryBLseL6jPh$
zd7n-BPPR9c=aJ6%os3`8zpPY{vrM{KYpx1#w9e72%*ICP)X8D06V&)^X$=Z{7j=<a
ziTs`mha-sSH8ChAZ5z62Y{oR4ahlS`o@Wz`8#|oa!ppv!>I9iiogCSSX5Qy6YPF`?
z&&qK#wpq*N+N@t}W#ORY;*2FqEv;#3=Sp^s!M5DtT^$_DP`-$|?arF)bY=Gvb-U5U
z_G-J+Za2PF&dX7_K54j45q(#(@!HT0#Tnk3X{n|xN361l7R!hx#huNa<?DzV{jL7S
zVcMN$yK&tbWCrK=b42&N=UaKIw7Ej@Ocjp(wcDdjxqfIjzr%9F#5U1p8qxY#`^Jy*
zCL1nlbpy+|-PCEWHNVE2dMSstEMmT1yN#&!D{dRE`h_XEFuw&{qG57aFFVH5F3yTl
zc6GN@7LH?U5~T|~6}`K*^js|32L_a&T-ZXnGKN)2Nl7zR`e4F)OFyr)QssBqO9%Ut
zgZ)>!3Fm|)7d-`Q(VI+kJi{{t8bboE-MqyP_8mFMc&q3)?S;k+{YJe!Ps67J0sn`W
zaFygO$m63G;ES`Ae?g;~{BkQ)#i%k+G*$(iEh@O&6}}Behj=Lh_S^WU>admZRbANS
R3g0S9I2`pZ`u9J){R=u{1K|Jw

literal 0
HcmV?d00001

diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/fr/LC_MESSAGES/multi-monitors-add-on.po b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/fr/LC_MESSAGES/multi-monitors-add-on.po
new file mode 100644
index 0000000..3b207cc
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/fr/LC_MESSAGES/multi-monitors-add-on.po
@@ -0,0 +1,94 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Multi Monitors Add On Gnome Shell Extension\n"
+"Report-Msgid-Bugs-To: https://github.com/spin83/multi-monitors-add-on/"
+"issues\n"
+"POT-Creation-Date: 2019-10-04 04:44-0300\n"
+"PO-Revision-Date: 2015-12-26 22:30+0100\n"
+"Last-Translator: Quentin Daem\n"
+"Language-Team: Language: fr_FR\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.4\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: indicator.js:46
+msgid "Preferences"
+msgstr "Préférences"
+
+#: indicator.js:115
+msgid "Multi Monitors Add-On"
+msgstr "Multi Moniteurs Add-On"
+
+#: mmoverview.js:642
+msgid "Overview"
+msgstr ""
+
+#. Translators: If there is no suitable word for "Activities"
+#. in your language, you can use the word for "Overview".
+#: mmpanel.js:333
+msgid "Activities"
+msgstr ""
+
+#: mmpanel.js:414
+msgid "Top Bar"
+msgstr ""
+
+#: prefs.js:62
+msgid "Show Multi Monitors indicator on Top Panel."
+msgstr "Afficher l'icone Multi Moniteurs sur la barre du haut"
+
+#: prefs.js:63
+msgid "Show Panel on additional monitors."
+msgstr "Afficher Menu sur les moniteurs secondaires"
+
+#: prefs.js:64
+msgid "Show Thumbnails-Slider on additional monitors."
+msgstr ""
+"Afficher le dock listant les espaces de travail sur les moniteurs secondaires"
+
+#: prefs.js:65
+msgid "Show Activities-Button on additional monitors."
+msgstr "Afficher le bouton Activités sur les moniteurs secondaires"
+
+#: prefs.js:66
+msgid "Show AppMenu-Button on additional monitors."
+msgstr "Afficher le bouton du menu Applications sur les moniteurs secondaires"
+
+#: prefs.js:67
+msgid "Show DateTime-Button on additional monitors."
+msgstr "Afficher le bouton Date-Heure sur les moniteurs secondaires."
+
+#: prefs.js:71
+msgid "Enable hot corners."
+msgstr ""
+
+#: prefs.js:77
+msgid "A list of indicators for transfer to additional monitors."
+msgstr "Une liste d'indicateurs pour transfert vers les moniteurs secondaires "
+
+#: prefs.js:124
+msgid "Select indicator"
+msgstr "Selectionner indicateur"
+
+#: prefs.js:127
+msgid "Add"
+msgstr "Ajouter"
+
+#: prefs.js:141
+msgid "Indicators on Top Panel"
+msgstr "Indicateur dans le panneau du haut"
+
+#: prefs.js:170
+msgid "Monitor index:"
+msgstr "Index moniteur:"
+
+#~ msgid "Test"
+#~ msgstr "Test"
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/it/LC_MESSAGES/multi-monitors-add-on.mo b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/it/LC_MESSAGES/multi-monitors-add-on.mo
new file mode 100644
index 0000000000000000000000000000000000000000..14040b3852b62c9eddaa06edd085480c6fa62ac1
GIT binary patch
literal 1820
zcma)+zi%8x6vqb$zb=LV3W9>-fe=5G%-#<>lC$AQ&WDLk%IU1!#iAYWj`t>-omuV7
zUW_{$1RYKK6tuL66jbghs8Z3xe?Wo6cXsawBsOH^xsPY}&3oVXX5Rkx+PQlS<5kSJ
zFu%uq1M~7z_`&!Fyb68`w!jnc8Sob{*!>E=4E_PW4*m(g0A6^SvGd@Y;49#}U<6(P
zFM%m|8T@Xs{uz7+>)*j(w}BwfgV(?Z@HqhcSpRj7u@}KlpKbIE!MCxVf)~I!_#XK6
z;{6W`{sdmc^AoTKJ_HBg`R5qxf@5$C{0a>IegrqchhXr#0WpwK*8mdP1}0q8Bj^cQ
zL*9^A=NtCCgo*9-2=xsEY1H+q7x)P^sz;x+a-QrVDU+&1cw0I;v?cjc7<VY~k0p_&
z$}4Mxrra78Y$DcAyqe>&bgZAIY`ETT4NYx9d%{S~M$LxcULM74RB5kh@z4==^08s#
zxh&^O-er5GL`-QCc%4Ws6TjBQCNq1N)?xWh<vn8I?^J<}c~Oj{sh-I8GvVb_<?@M)
zA4z0Yy&z|mebi{KEAihtr?V<QFhXg^Ct9Vb`&nrP=R2ZAsq7uphYwS}FH48xiRlqh
zs4k5S-7q$nG?_`QY4^xW6O3E8WMNCsM=nz-GR_>I+L&hE7cOqMGv#O1L6q3M?FwbK
zH`{qQIler9j*@e0+RC{~y4K#9-;#3`9P?1dn0lS=Ro?CJUYELC@s-U>onEKYx+$FJ
z({QzPxN0%otP+8AaCwZP53cXq`~WXLq>nUSMDu2OJ<Cy<Am$TzFj*xs$){4}F%7-Y
zN|@!-n3P|c)Qiz@w7V`)H|n$o)}RKE@nr#>ULN^&p@lNnD4B`UN&oTf>F0cVZMWzI
zzH1T-omouV2MF^8zafn*n>_ZcM2}D}>P1_4(=7SKR%IdwjoX+SzwEXlTx~d`RIRVK
zq5`L`bm+X$c({lr^xm@N$jQW-RFn$6=j+}(xzGAprYe)6XVx7k35`dEFo3q?DmYel
zX(5*mV>YmPVGY7a615+AwY7{wojh3DF<f6;iX2~uRev7Kx;>A>M`4|UM7KN04_WNk
z(43N1QlUdFUH&tdedQ{g;qh_3t*EpUK~RbmP=Sj2MWGQogi>eucswjFp=ggG<&3C{
w9r}HRqKbbv4)&Z@zG#_U_@Kb%f0EHCYAKP3A}!{&3<q&)0np6QIa!_3-;h=rMgRZ+

literal 0
HcmV?d00001

diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/it/LC_MESSAGES/multi-monitors-add-on.po b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/it/LC_MESSAGES/multi-monitors-add-on.po
new file mode 100644
index 0000000..fd41a90
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/it/LC_MESSAGES/multi-monitors-add-on.po
@@ -0,0 +1,93 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Multi Monitors Add On Gnome Shell Extension\n"
+"Report-Msgid-Bugs-To: https://github.com/spin83/multi-monitors-add-on/"
+"issues\n"
+"POT-Creation-Date: 2019-10-04 04:44-0300\n"
+"PO-Revision-Date: 2019-10-21 14:53+0200\n"
+"Last-Translator: Luca Bandini (@Vombato) <luca.vombato@gmail.com>\n"
+"Language-Team: ItalianLanguage: it\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.2.4\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: indicator.js:46
+msgid "Preferences"
+msgstr "Preferenze"
+
+#: indicator.js:115
+msgid "Multi Monitors Add-On"
+msgstr "Componente aggiuntivo per più monitor"
+
+#: mmoverview.js:642
+msgid "Overview"
+msgstr "Panoramica"
+
+#. Translators: If there is no suitable word for "Activities"
+#. in your language, you can use the word for "Overview".
+#: mmpanel.js:333
+msgid "Activities"
+msgstr "Attività"
+
+#: mmpanel.js:414
+msgid "Top Bar"
+msgstr "Barra Superiore"
+
+#: prefs.js:62
+msgid "Show Multi Monitors indicator on Top Panel."
+msgstr "Mostra l'icona Multi Monitor sul pannello superiore."
+
+#: prefs.js:63
+msgid "Show Panel on additional monitors."
+msgstr "Mostra Menu su monitor secondari."
+
+#: prefs.js:64
+msgid "Show Thumbnails-Slider on additional monitors."
+msgstr "Visualizza le aree di lavoro sui monitor secondari."
+
+#: prefs.js:65
+msgid "Show Activities-Button on additional monitors."
+msgstr "Mostra il Bottone Attività sui monitor secondari."
+
+#: prefs.js:66
+msgid "Show AppMenu-Button on additional monitors."
+msgstr "Visualizza il pulsante del menu Applicazioni sui monitor secondari."
+
+#: prefs.js:67
+msgid "Show DateTime-Button on additional monitors."
+msgstr "Mostra il Bottone Data/Ora sui monitor secondari."
+
+#: prefs.js:71
+msgid "Enable hot corners."
+msgstr ""
+
+#: prefs.js:77
+msgid "A list of indicators for transfer to additional monitors."
+msgstr "Un elenco di indicatori per il trasferimento a monitor secondari."
+
+#: prefs.js:124
+msgid "Select indicator"
+msgstr "Seleziona indicatore"
+
+#: prefs.js:127
+msgid "Add"
+msgstr "Aggiungere"
+
+#: prefs.js:141
+msgid "Indicators on Top Panel"
+msgstr "Indicatore nel pannello superiore"
+
+#: prefs.js:170
+msgid "Monitor index:"
+msgstr "Indice monitor:"
+
+#~ msgid "Test"
+#~ msgstr "Test"
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pl/LC_MESSAGES/multi-monitors-add-on.mo b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pl/LC_MESSAGES/multi-monitors-add-on.mo
new file mode 100644
index 0000000000000000000000000000000000000000..84f0f8e7058fdec1b6b972022e44b20f3e946ea6
GIT binary patch
literal 1743
zcma)*&2Jnv7{(2Rucdse;s8Rg5LB&-cV{*M(oGi>niNIKs;g#8xFPS1Gvn;6JsNwu
z-BnMOD*gdLLKP<t+~EcX4kQQ8+&OTD69+i<@qVi%RYvRm*`D|H`}i6Ak5^W{Vt8Ie
zdjsuDwAawiJcd6!DR>D~;1l3?;H%*GppW|*d;$C&JPZB_J_r5>z67p3&R7*Z3tj}b
zz<0rXI{p@X3*+BFANLpdHF94^u?EIJtT6T@_%|4U|A23TZ)4K0e+Be)J75Jo1YZVA
z@B{FRDSrX|djEoJVErk^R>5S-dmzfPXVD;Gya$AipJ(v@^tA6i@LoNS1}O|_4?Sm=
zX1pfv58I?nSx4r8l#W#-oGC0Fn1Wm(v^|jM7!q-;oHANu)HhoBm@3<hW45hDH<Oea
zN0BMC^z%E5b&RHt$*C>0%vfuZ>FdZ_4c00%r)WB939IpInzajwno>v7vOSr}$SriS
zz0?e7Gji%C)JV%eE}cUO{Qg(qBs|YsQkSQS-4afAR9~Jd_yPTM_q?3>rmGXpV*?(o
zvy+znt`;h@d@oZmd_QSh?ZO<w7rqnoPhmJdOM@!cWo`<`TQ*TK<R_MQOoLMAa@(lY
z66MmeTa8S=W^<+2S8ILmKA(L|4*$5(HDzrnZKZvUUzazPUz&SQ8dML$_jy?7^-C14
zHR|tO48kC&><a66$DfnTpBu>76*?(JB6&xO{?fQXdG>jGx6;~aZ7)=Z)u3|4XeTw6
z8Rn?t<SkdrGokbbMX4yPbj=%`t9*SCH$9eoTSq2VI%&{)SGme({1b`uH__2H5(k#T
z>UuQ{EA6Z-M8>b0qHi0d^YPF&S2rNaziFP=&1Og+Q9yY8P8fXHtkb!3<L>3=n(v<X
z)4}C1pxd{{^FAiHfSeFH^$Qynwu@^dXkdHd_$RG;zy3I&*ic@Kq%E~N`X*9>w7^^}
zT+a;T>?RGXYzuRTZ2$Pq(cNeywUU&ZILVIg#wB{l!uL*vRwWfCDM|L=L0M({vs%h8
zoE+alO+D;W?yp<v@1gA3Ss8KCjk^Ka1BI%B?GL+37Nf-`FmrqlFJ0z0GK`e%ElFG2
z%`i&mg`yPF9?lbarg|be9E+W~aEd(GH6%sRNZ4}Oz>`zw-vD-v><ByZyL-?h+w&IA
Yb<XUAdsg;NS7;L2S6JPZ#iMfW1G>=+D*ylh

literal 0
HcmV?d00001

diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pl/LC_MESSAGES/multi-monitors-add-on.po b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pl/LC_MESSAGES/multi-monitors-add-on.po
new file mode 100644
index 0000000..80116d8
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pl/LC_MESSAGES/multi-monitors-add-on.po
@@ -0,0 +1,94 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://github.com/spin83/multi-monitors-add-on/"
+"issues\n"
+"POT-Creation-Date: 2019-10-04 04:44-0300\n"
+"PO-Revision-Date: 2016-12-29 14:25+0100\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: pl_PL\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.11\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+
+#: indicator.js:46
+msgid "Preferences"
+msgstr "Ustawienia"
+
+#: indicator.js:115
+msgid "Multi Monitors Add-On"
+msgstr "Multi Monitors Add-On"
+
+#: mmoverview.js:642
+msgid "Overview"
+msgstr ""
+
+#. Translators: If there is no suitable word for "Activities"
+#. in your language, you can use the word for "Overview".
+#: mmpanel.js:333
+msgid "Activities"
+msgstr ""
+
+#: mmpanel.js:414
+msgid "Top Bar"
+msgstr ""
+
+#: prefs.js:62
+msgid "Show Multi Monitors indicator on Top Panel."
+msgstr "Wyświetl wskaźnik rozszerzenia na głównym pasku."
+
+#: prefs.js:63
+msgid "Show Panel on additional monitors."
+msgstr "Wyświetl główny pasek na dodatkowych monitorach."
+
+#: prefs.js:64
+msgid "Show Thumbnails-Slider on additional monitors."
+msgstr "Wyświetl pasek miniatur na dodatkowych monitorach."
+
+#: prefs.js:65
+msgid "Show Activities-Button on additional monitors."
+msgstr "Wyświetl przycisk podglądu na dodatkowych monitorach."
+
+#: prefs.js:66
+msgid "Show AppMenu-Button on additional monitors."
+msgstr "Wyświetl przycisk aplikacji na dodatkowych monitorach."
+
+#: prefs.js:67
+msgid "Show DateTime-Button on additional monitors."
+msgstr "Wyświetl przycisk daty i czasu na dodatkowych monitorach."
+
+#: prefs.js:71
+msgid "Enable hot corners."
+msgstr "Włączenie podglądu po najechaniu rogu ekranu."
+
+#: prefs.js:77
+msgid "A list of indicators for transfer to additional monitors."
+msgstr "Lista wskaźników do przesunięcia na dodatkowe monitory."
+
+#: prefs.js:124
+msgid "Select indicator"
+msgstr "Wybierz wskaźnik"
+
+#: prefs.js:127
+msgid "Add"
+msgstr "Dodaj"
+
+#: prefs.js:141
+msgid "Indicators on Top Panel"
+msgstr "Wskaźniki na głównym panelu"
+
+#: prefs.js:170
+msgid "Monitor index:"
+msgstr "Indeks monitora:"
+
+#~ msgid "Test"
+#~ msgstr "Test"
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pt_BR/LC_MESSAGES/multi-monitors-add-on.mo b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pt_BR/LC_MESSAGES/multi-monitors-add-on.mo
new file mode 100644
index 0000000000000000000000000000000000000000..beae2e97077dd1afe2caa9cb4e477486dd07460d
GIT binary patch
literal 1759
zcma)+&u<$=6vwAfC@cXg3gQCjiBl1b>--QT+or-PNfZeyR_vl4kkG_Cwg=75tY*d`
z?SIe%H{c)W0f{?TkjNdbJ#pd>;1A%y_w711L}}BJXFof;@6G$ZxAXkx8<)Qq7_Vc#
zgZUli+n7t2aKV^>8=wK72Ooj_{zvdN@K^9H@OSVP@GtNx_&3-BFFhy3hhQ802>f!k
zeh9vg_0J&NJq9m>R}kbk_%4BWu>J!NUk0zeAjEs%yWlnO7RYgX;H%&Wd=pII8u$?0
z1b+cP0sjHl!L=8KxDJ+J2mArVPdvs2VZ}?BkRmcn*2CipCfo4f8gSkmlk>&4^T9Rb
zvDBcxvi5p($eNhQkI1;f3{~<W(#Qu&LAf~6xbdWl!X)FJvQ&C!*rp{qMIrVUKHky5
zSJYEZThVQ-cu#$ti|*7WL$imG;3@Z==mm}awHxXv`r7JYT4)gciT{Q=!(@&SSx31w
zO$j0JJ6B9&UR7P~rq5*inM!(KO8rd6XY|i2#d79Jw;IiL0iLdNFqxKzP8l0z-<kq7
zeo|Tk9TV#0zeaK7ULn8GA>upabVd;>O8bs>oi8=@C)!%tK2F-Padx09ACm0Gu_=)5
zILd*~DeLXa1AS!JL~=E9T4^tD$mO<duTuNtd~E|a?RNILib)RmG*~_zIUT5x(w26-
zLj;7<bSu=4Mx#&1tf1w?_%{69c&f%)4zwzB+6wA{u|_%SLCthL)e(-hy{yt#he7f|
zJa2=X@P6wc>+W^87Zq4;wX-|51gN`TL4MN5=|*LhaW`o=Q6cKId3UfQ*B5rPGcC8>
z&=<yyb6P(%DeKv3P*(2vP{y2GRWIY_%1vr+H?KRoP0Jr-_v9{84ow|)>lUetLaVLS
z6$rW~Pd`>a-M7$G=a-4QrK<Z(QK4styzoIss#H+(Rx_bl&w3266<U(}&eZ+Z+=p4$
zH5)h&AA`?8aa!qMd=Mw!a#w09{Ass7y#r5vazmqLJ;>3*LLxdjBF#XDKAk-BEWg7&
zS*QZ?ba@)#e_GFRD$$qhtSZZYGUmu%?Ct*(v`|Trrin+nE{f_G^0@|QTIHOAo#r?%
j<wX&OICsJ0;G+oEJWyx^POdc0sDz{R<lMNSRS^FIx;za<

literal 0
HcmV?d00001

diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pt_BR/LC_MESSAGES/multi-monitors-add-on.po b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pt_BR/LC_MESSAGES/multi-monitors-add-on.po
new file mode 100644
index 0000000..94c370c
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/locale/pt_BR/LC_MESSAGES/multi-monitors-add-on.po
@@ -0,0 +1,89 @@
+# Brazilian Portuguese translation for multi-monitors-add-on
+# Copyright (C) 2019 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the multi-monitors-add-on package.
+# Rafael Fontenelle <rafaelff@gnome.org>, 2019.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Multi Monitors Add On Gnome Shell Extension\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-01-23 22:29+0100\n"
+"PO-Revision-Date: 2019-10-03 06:49-0300\n"
+"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
+"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"X-Generator: Gtranslator 3.32.0\n"
+"X-Project-Style: gnome\n"
+
+#: prefs.js:61
+msgid "Show Multi Monitors indicator on Top Panel."
+msgstr "Mostrar o indicador do Multi Monitors no painel superior"
+
+#: prefs.js:62
+msgid "Show Panel on additional monitors."
+msgstr "Mostrar o painel em monitores adicionais"
+
+#: prefs.js:63
+msgid "Show Thumbnails-Slider on additional monitors."
+msgstr "Mostrar controle deslizante de miniaturas em monitores adicionais"
+
+#: prefs.js:64
+msgid "Show Activities-Button on additional monitors."
+msgstr "Mostrar botão de Atividades em monitores adicionais"
+
+#: prefs.js:65
+msgid "Show AppMenu-Button on additional monitors."
+msgstr "Mostrar botão de menu de aplicativos em monitores adicionais"
+
+#: prefs.js:67
+msgid "Show DateTime-Button on additional monitors."
+msgstr "Mostrar o botão de data e hora em monitores adicionais"
+
+#: prefs.js:75
+msgid "A list of indicators for transfer to additional monitors."
+msgstr "Uma lista de indicadores para transferir para monitores adicionais."
+
+#: prefs.js:71
+msgid "Enable hot corners."
+msgstr ""
+
+#: prefs.js:122
+msgid "Select indicator"
+msgstr "Selecionar indicador"
+
+#: prefs.js:125
+msgid "Add"
+msgstr "Adicionar"
+
+#: prefs.js:139
+msgid "Indicators on Top Panel"
+msgstr "Indicadores no painel superior"
+
+#: prefs.js:168
+msgid "Monitor index:"
+msgstr "Índice do monitor:"
+
+#: indicator.js:106
+msgid "Preferences"
+msgstr "Preferências"
+
+#: indicator.js:107
+msgid "Test"
+msgstr "Testar"
+
+#: indicator.js:129
+msgid "Multi Monitors Add-On"
+msgstr "Multi Monitors Add-On"
+
+#~ msgid "Overview"
+#~ msgstr "Panorama"
+
+#~ msgid "Activities"
+#~ msgstr "Atividades"
+
+#~ msgid "Top Bar"
+#~ msgstr "Barra superior"
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/metadata.json b/multi-monitors-add-on/multi-monitors-add-on@spin83/metadata.json
new file mode 100644
index 0000000..68b1295
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/metadata.json
@@ -0,0 +1,10 @@
+{
+    "shell-version": ["40", "41", "42", "43"],
+    "uuid": "multi-monitors-add-on@spin83",
+    "name": "Multi Monitors Add-On",
+    "settings-schema": "org.gnome.shell.extensions.multi-monitors-add-on",
+    "gettext-domain": "multi-monitors-add-on",
+    "description": "Add multiple monitors overview and panel for gnome-shell.",
+    "url": "https://github.com/spin83/multi-monitors-add-on.git",
+    "version": 25
+}
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/mmcalendar.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmcalendar.js
new file mode 100644
index 0000000..66237f4
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmcalendar.js
@@ -0,0 +1,412 @@
+/*
+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 Signals = imports.signals;
+
+const { St, Gio, Shell, Clutter, GnomeDesktop, Pango, GObject, GLib } = imports.gi;
+
+const Main = imports.ui.main;
+const PanelMenu = imports.ui.panelMenu;
+const MessageList = imports.ui.messageList;
+const DateMenu = imports.ui.dateMenu;
+const Calendar = imports.ui.calendar;
+const PopupMenu = imports.ui.popupMenu;
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const CE = ExtensionUtils.getCurrentExtension();
+const MultiMonitors = CE.imports.extension;
+const Convenience = CE.imports.convenience;
+
+// Calendar.DoNotDisturbSwitch is const, so not exported. Either
+// <https://gjs.guide/guides/gobject/subclassing.html#gtypename> is untrue, or
+// GObject.type_from_name() is broken, so we can't get its constructor via GI
+// either. Luckily it's a short class, so we can copy & paste.
+const MultiMonitorsDoNotDisturbSwitch = GObject.registerClass(
+class MultiMonitorsDoNotDisturbSwitch extends PopupMenu.Switch {
+    _init() {
+        this._settings = new Gio.Settings({
+            schema_id: 'org.gnome.desktop.notifications',
+        });
+
+        super._init(this._settings.get_boolean('show-banners'));
+
+        this._settings.bind('show-banners',
+            this, 'state',
+            Gio.SettingsBindFlags.INVERT_BOOLEAN);
+
+        this.connect('destroy', () => {
+            this._settings.run_dispose();
+            this._settings = null;
+        });
+    }
+});
+
+var MultiMonitorsCalendar = (() => {
+	let MultiMonitorsCalendar = class MultiMonitorsCalendar extends St.Widget {
+	    _init () {
+	        this._weekStart = Shell.util_get_week_start();
+	        this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
+	
+	        this._showWeekdateKeyId = this._settings.connect('changed::%s'.format(Calendar.SHOW_WEEKDATE_KEY), this._onSettingsChange.bind(this));
+	        this._useWeekdate = this._settings.get_boolean(Calendar.SHOW_WEEKDATE_KEY);
+	
+	        this._headerFormatWithoutYear = _('%OB');
+	        this._headerFormat = _('%OB %Y');
+	
+	        // Start off with the current date
+	        this._selectedDate = new Date();
+	
+	        this._shouldDateGrabFocus = false;
+	
+	        super._init({
+	            style_class: 'calendar',
+	            layout_manager: new Clutter.GridLayout(),
+	            reactive: true,
+	        });
+	
+	        this._buildHeader();
+			this.connect('destroy', this._onDestroy.bind(this));
+	    }
+	    
+	    _onDestroy() {
+	    	this._settings.disconnect(this._showWeekdateKeyId);
+	    }
+	};
+	MultiMonitors.copyClass(Calendar.Calendar, MultiMonitorsCalendar);
+	return GObject.registerClass({
+    	Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } },
+		}, MultiMonitorsCalendar);
+})();
+
+var MultiMonitorsEventsSection = (() => {
+    let MultiMonitorsEventsSection = class MultiMonitorsEventsSection extends St.Button {
+    _init() {
+        super._init({
+            style_class: 'events-button',
+            can_focus: true,
+            x_expand: true,
+            child: new St.BoxLayout({
+                style_class: 'events-box',
+                vertical: true,
+                x_expand: true,
+            }),
+        });
+
+        this._startDate = null;
+        this._endDate = null;
+
+        this._eventSource = null;
+        this._calendarApp = null;
+
+        this._title = new St.Label({
+            style_class: 'events-title',
+        });
+        this.child.add_child(this._title);
+
+        this._eventsList = new St.BoxLayout({
+            style_class: 'events-list',
+            vertical: true,
+            x_expand: true,
+        });
+        this.child.add_child(this._eventsList);
+
+        this._appSys = Shell.AppSystem.get_default();
+        this._appInstalledChangedId = this._appSys.connect('installed-changed',
+            this._appInstalledChanged.bind(this));
+        this._appInstalledChanged();
+
+        this.connect('destroy', this._onDestroy.bind(this));
+        this._appInstalledChanged();
+    }
+
+    _onDestroy() {
+        this._appSys.disconnect(this._appInstalledChangedId);
+    }};
+
+    MultiMonitors.copyClass(DateMenu.EventsSection, MultiMonitorsEventsSection);
+	return GObject.registerClass(MultiMonitorsEventsSection);
+})();
+
+var MultiMonitorsNotificationSection = (() => {
+    let MultiMonitorsNotificationSection = class MultiMonitorsNotificationSection extends MessageList.MessageListSection {
+    _init() {
+        super._init();
+
+        this._sources = new Map();
+        this._nUrgent = 0;
+
+        this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
+        Main.messageTray.getSources().forEach(source => {
+            this._sourceAdded(Main.messageTray, source);
+        });
+
+        this.connect('destroy', this._onDestroy.bind(this));
+    }
+
+    _onDestroy() {
+        Main.messageTray.disconnect(this._sourceAddedId);
+        let source, obj;
+        for ([source, obj] of this._sources.entries()) {
+            this._onSourceDestroy(source, obj);
+        }
+    }};
+
+    MultiMonitors.copyClass(Calendar.NotificationSection, MultiMonitorsNotificationSection);
+    return GObject.registerClass(MultiMonitorsNotificationSection);
+})();
+
+var MultiMonitorsCalendarMessageList = (() => {
+	let MultiMonitorsCalendarMessageList = class MultiMonitorsCalendarMessageList extends St.Widget {
+    _init() {
+        super._init({
+            style_class: 'message-list',
+            layout_manager: new Clutter.BinLayout(),
+            x_expand: true,
+            y_expand: true,
+        });
+
+        this._sessionModeUpdatedId = 0;
+
+        this._placeholder = new Calendar.Placeholder();
+        this.add_actor(this._placeholder);
+
+        let box = new St.BoxLayout({ vertical: true,
+                                     x_expand: true, y_expand: true });
+        this.add_actor(box);
+
+        this._scrollView = new St.ScrollView({
+            style_class: 'vfade',
+            overlay_scrollbars: true,
+            x_expand: true, y_expand: true,
+        });
+        this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
+        box.add_actor(this._scrollView);
+
+        let hbox = new St.BoxLayout({ style_class: 'message-list-controls' });
+        box.add_child(hbox);
+
+        const dndLabel = new St.Label({
+            text: _('Do Not Disturb'),
+            y_align: Clutter.ActorAlign.CENTER,
+        });
+        hbox.add_child(dndLabel);
+
+        this._dndSwitch = new MultiMonitorsDoNotDisturbSwitch();
+        this._dndButton = new St.Button({
+            can_focus: true,
+            toggle_mode: true,
+            child: this._dndSwitch,
+            label_actor: dndLabel,
+        });
+
+        this._dndSwitch.bind_property('state',
+                this._dndButton, 'checked',
+                GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE);
+
+        hbox.add_child(this._dndButton);
+
+        this._clearButton = new St.Button({
+            style_class: 'message-list-clear-button button',
+            label: _('Clear'),
+            can_focus: true,
+            x_expand: true,
+            x_align: Clutter.ActorAlign.END,
+        });
+        this._clearButton.connect('clicked', () => {
+            this._sectionList.get_children().forEach(s => s.clear());
+        });
+        hbox.add_actor(this._clearButton);
+
+        this._placeholder.bind_property('visible',
+            this._clearButton, 'visible',
+            GObject.BindingFlags.INVERT_BOOLEAN);
+
+        this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections',
+                                               vertical: true,
+                                               x_expand: true,
+                                               y_expand: true,
+                                               y_align: Clutter.ActorAlign.START });
+        this._sectionList.connect('actor-added', this._sync.bind(this));
+        this._sectionList.connect('actor-removed', this._sync.bind(this));
+        this._scrollView.add_actor(this._sectionList);
+
+        this._notificationSection = new MultiMonitorsNotificationSection();
+        this._addSection(this._notificationSection);
+
+        this._sessionModeUpdatedId = Main.sessionMode.connect('updated', this._sync.bind(this));
+        this.connect('destroy', this._onDestroy.bind(this));
+    }
+
+    _onDestroy() {
+        Main.sessionMode.disconnect(this._sessionModeUpdatedId);
+        this._sessionModeUpdatedId = 0;
+    }
+
+    _sync() {
+        if (this._sessionModeUpdatedId === 0) return;
+        Calendar.CalendarMessageList.prototype._sync.call(this);
+    }};
+
+    MultiMonitors.copyClass(Calendar.CalendarMessageList, MultiMonitorsCalendarMessageList);
+    return GObject.registerClass(MultiMonitorsCalendarMessageList);
+})();
+
+var MultiMonitorsMessagesIndicator  = (() => {
+    let MultiMonitorsMessagesIndicator = class MultiMonitorsMessagesIndicator extends St.Icon {
+    _init() {
+        super._init({
+            icon_size: 16,
+            visible: false,
+            y_expand: true,
+            y_align: Clutter.ActorAlign.CENTER,
+        });
+
+        this._sources = [];
+        this._count = 0;
+
+        this._settings = new Gio.Settings({
+            schema_id: 'org.gnome.desktop.notifications',
+        });
+        this._settings.connect('changed::show-banners', this._sync.bind(this));
+
+        this._sourceAddedId = Main.messageTray.connect('source-added', this._onSourceAdded.bind(this));
+        this._sourceRemovedId = Main.messageTray.connect('source-removed', this._onSourceRemoved.bind(this));
+        this._queueChangedId = Main.messageTray.connect('queue-changed', this._updateCount.bind(this));
+
+        let sources = Main.messageTray.getSources();
+        sources.forEach(source => this._onSourceAdded(null, source));
+
+        this._sync();
+
+        this.connect('destroy', () => {
+            this._settings.run_dispose();
+            this._settings = null;
+            Main.messageTray.disconnect(this._sourceAddedId);
+            Main.messageTray.disconnect(this._sourceRemovedId);
+            Main.messageTray.disconnect(this._queueChangedId);
+        });
+    }};
+
+    MultiMonitors.copyClass(DateMenu.MessagesIndicator, MultiMonitorsMessagesIndicator);
+    return GObject.registerClass(MultiMonitorsMessagesIndicator);
+})();
+
+var MultiMonitorsDateMenuButton  = (() => {
+    let MultiMonitorsDateMenuButton = class MultiMonitorsDateMenuButton extends PanelMenu.Button {
+    _init() {
+        let hbox;
+        let vbox;
+
+        super._init(0.5);
+
+        this._clockDisplay = new St.Label({ style_class: 'clock' });
+        this._clockDisplay.clutter_text.y_align = Clutter.ActorAlign.CENTER;
+        this._clockDisplay.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
+
+        this._indicator = new MultiMonitorsMessagesIndicator();
+
+        const indicatorPad = new St.Widget();
+        this._indicator.bind_property('visible',
+            indicatorPad, 'visible',
+            GObject.BindingFlags.SYNC_CREATE);
+        indicatorPad.add_constraint(new Clutter.BindConstraint({
+            source: this._indicator,
+            coordinate: Clutter.BindCoordinate.SIZE,
+        }));
+
+        let box = new St.BoxLayout({ style_class: 'clock-display-box' });
+        box.add_actor(indicatorPad);
+        box.add_actor(this._clockDisplay);
+        box.add_actor(this._indicator);
+
+        this.label_actor = this._clockDisplay;
+        this.add_actor(box);
+        this.add_style_class_name('clock-display');
+
+        let layout = new DateMenu.FreezableBinLayout();
+        let bin = new St.Widget({ layout_manager: layout });
+        // For some minimal compatibility with PopupMenuItem
+        bin._delegate = this;
+        this.menu.box.add_child(bin);
+
+        hbox = new St.BoxLayout({ name: 'calendarArea' });
+        bin.add_actor(hbox);
+
+        this._calendar = new MultiMonitorsCalendar();
+        this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
+            let date = DateMenu._gDateTimeToDate(datetime);
+            layout.frozen = !DateMenu._isToday(date);
+            this._eventsItem.setDate(date);
+        });
+        this._date = new DateMenu.TodayButton(this._calendar);
+
+        this.menu.connect('open-state-changed', (menu, isOpen) => {
+            // Whenever the menu is opened, select today
+            if (isOpen) {
+                let now = new Date();
+                this._calendar.setDate(now);
+                this._date.setDate(now);
+                this._eventsItem.setDate(now);
+            }
+        });
+
+        // Fill up the first column
+        this._messageList = new MultiMonitorsCalendarMessageList();
+        hbox.add_child(this._messageList);
+
+        // Fill up the second column
+        const boxLayout = new DateMenu.CalendarColumnLayout([this._calendar, this._date]);
+        vbox = new St.Widget({ style_class: 'datemenu-calendar-column',
+                               layout_manager: boxLayout });
+        boxLayout.hookup_style(vbox);
+        hbox.add(vbox);
+
+        vbox.add_actor(this._date);
+        vbox.add_actor(this._calendar);
+
+        this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
+                                                    x_expand: true,
+                                                    overlay_scrollbars: true });
+        this._displaysSection.set_policy(St.PolicyType.NEVER, St.PolicyType.EXTERNAL);
+        vbox.add_actor(this._displaysSection);
+
+        let displaysBox = new St.BoxLayout({ vertical: true,
+                                             x_expand: true,
+                                             style_class: 'datemenu-displays-box' });
+        this._displaysSection.add_actor(displaysBox);
+
+        this._eventsItem = new MultiMonitorsEventsSection();
+        displaysBox.add_child(this._eventsItem);
+
+        this._clock = new GnomeDesktop.WallClock();
+        this._clock.bind_property('clock', this._clockDisplay, 'text', GObject.BindingFlags.SYNC_CREATE);
+        this._clockNotifyTimezoneId = this._clock.connect('notify::timezone', this._updateTimeZone.bind(this));
+
+        this._sessionModeUpdatedId = Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
+        this._sessionUpdated();
+    }
+
+    _onDestroy() {
+        Main.sessionMode.disconnect(this._sessionModeUpdatedId);
+        this._clock.disconnect(this._clockNotifyTimezoneId);
+        super._onDestroy();
+    }};
+
+    MultiMonitors.copyClass(DateMenu.DateMenuButton, MultiMonitorsDateMenuButton);
+    return GObject.registerClass(MultiMonitorsDateMenuButton);
+})();
+
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/mmlayout.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmlayout.js
new file mode 100644
index 0000000..a354ec1
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmlayout.js
@@ -0,0 +1,251 @@
+/**
+ * New node file
+ */
+
+const { St, Meta } = imports.gi;
+
+const Main = imports.ui.main;
+const Panel = imports.ui.panel;
+const Layout = imports.ui.layout;
+
+const Config = imports.misc.config;
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const CE = ExtensionUtils.getCurrentExtension();
+const Convenience = CE.imports.convenience;
+const MultiMonitors = CE.imports.extension;
+const MMPanel = CE.imports.mmpanel;
+
+var SHOW_PANEL_ID = 'show-panel';
+var ENABLE_HOT_CORNERS = 'enable-hot-corners';
+
+const MultiMonitorsPanelBox = class MultiMonitorsPanelBox {
+    constructor(monitor) {
+        this.panelBox = new St.BoxLayout({ name: 'panelBox', vertical: true, clip_to_allocation: true });
+        Main.layoutManager.addChrome(this.panelBox, { affectsStruts: true, trackFullscreen: true });
+        this.panelBox.set_position(monitor.x, monitor.y);
+        this.panelBox.set_size(monitor.width, -1);
+        Main.uiGroup.set_child_below_sibling(this.panelBox, Main.layoutManager.panelBox);
+    }
+
+    destroy() {
+        this.panelBox.destroy();
+    }
+
+    updatePanel(monitor) {
+        this.panelBox.set_position(monitor.x, monitor.y);
+        this.panelBox.set_size(monitor.width, -1);
+    }
+};
+
+var MultiMonitorsLayoutManager = class MultiMonitorsLayoutManager {
+	constructor() {
+		this._settings = Convenience.getSettings();
+		this._desktopSettings = Convenience.getSettings("org.gnome.desktop.interface");
+
+		Main.mmPanel = [];
+	
+		this._monitorIds = [];
+		this.mmPanelBox = [];
+		this.mmappMenu = false;
+		
+		this._showAppMenuId = null;
+		this._monitorsChangedId = null;
+		
+		this.statusIndicatorsController = null;
+		this._layoutManager_updateHotCorners = null;
+		this._changedEnableHotCornersId = null;
+	}
+
+    showPanel() {
+        if (this._settings.get_boolean(SHOW_PANEL_ID)) {
+            if (!this._monitorsChangedId) {
+                this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', this._monitorsChanged.bind(this));
+                this._monitorsChanged();
+            }
+            if (!this._showAppMenuId) {
+                this._showAppMenuId = this._settings.connect('changed::'+MMPanel.SHOW_APP_MENU_ID, this._showAppMenu.bind(this));
+            }
+
+            if (!this.statusIndicatorsController) {
+                this.statusIndicatorsController = new MMPanel.StatusIndicatorsController();
+            }
+
+            if (!this._layoutManager_updateHotCorners) {
+                this._layoutManager_updateHotCorners = Main.layoutManager._updateHotCorners;
+
+                const _this = this;
+                Main.layoutManager._updateHotCorners = function() {
+                    this.hotCorners.forEach((corner) => {
+                        if (corner)
+                            corner.destroy();
+                    });
+                    this.hotCorners = [];
+
+                    if (!_this._desktopSettings.get_boolean(ENABLE_HOT_CORNERS)) {
+                        this.emit('hot-corners-changed');
+                        return;
+                    }
+
+                    let size = this.panelBox.height;
+
+                    for (let i = 0; i < this.monitors.length; i++) {
+                        let monitor = this.monitors[i];
+                        let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
+                        let cornerY = monitor.y;
+
+                        let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY);
+                        corner.setBarrierSize(size);
+                        this.hotCorners.push(corner);
+                    }
+
+                    this.emit('hot-corners-changed');
+                };
+
+                if (!this._changedEnableHotCornersId) {
+                    this._changedEnableHotCornersId = this._desktopSettings.connect('changed::'+ENABLE_HOT_CORNERS,
+                            Main.layoutManager._updateHotCorners.bind(Main.layoutManager));
+                }
+
+                Main.layoutManager._updateHotCorners();
+            }
+        }
+        else {
+            this.hidePanel();
+        }
+    }
+
+	hidePanel() {
+		if (this._changedEnableHotCornersId) {
+			global.settings.disconnect(this._changedEnableHotCornersId);
+			this._changedEnableHotCornersId = null;
+		}
+		
+		if (this._layoutManager_updateHotCorners) {
+			Main.layoutManager['_updateHotCorners'] = this._layoutManager_updateHotCorners;
+			this._layoutManager_updateHotCorners = null;
+			Main.layoutManager._updateHotCorners();
+		}
+			
+		if (this.statusIndicatorsController) {
+			this.statusIndicatorsController.destroy();
+			this.statusIndicatorsController = null;
+		}
+		
+		if (this._showAppMenuId) {
+			this._settings.disconnect(this._showAppMenuId);
+			this._showAppMenuId = null;
+		}
+		this._hideAppMenu();
+		
+		if (this._monitorsChangedId) {
+			Main.layoutManager.disconnect(this._monitorsChangedId);
+			this._monitorsChangedId = null;
+		}
+
+		let panels2remove = this._monitorIds.length;
+		for (let i = 0; i < panels2remove; i++) {
+			let monitorId = this._monitorIds.pop();
+			this._popPanel();
+			global.log("remove: "+monitorId);
+		}
+	}
+
+	_monitorsChanged () {
+		let monitorChange = Main.layoutManager.monitors.length - this._monitorIds.length -1;
+		if (monitorChange<0) {
+			for (let idx = 0; idx<-monitorChange; idx++) {
+				let monitorId = this._monitorIds.pop();
+				this._popPanel();
+				global.log("remove: "+monitorId);
+			}
+		}
+		
+		let j = 0;
+		let tIndicators = false;
+		for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
+			if (i!=Main.layoutManager.primaryIndex) {
+				let monitor = Main.layoutManager.monitors[i];
+				let monitorId = "i"+i+"x"+monitor.x+"y"+monitor.y+"w"+monitor.width+"h"+monitor.height;
+				if (monitorChange>0 && j==this._monitorIds.length) {
+					this._monitorIds.push(monitorId);
+					this._pushPanel(i, monitor);
+					global.log("new: "+monitorId);
+					tIndicators = true;
+				}
+				else if (this._monitorIds[j]>monitorId || this._monitorIds[j]<monitorId) {
+					let oldMonitorId = this._monitorIds[j];
+					this._monitorIds[j]=monitorId;
+					this.mmPanelBox[j].updatePanel(monitor);
+					global.log("update: "+oldMonitorId+">"+monitorId);
+				}
+				j++;
+			}
+		}
+		this._showAppMenu();
+		if (tIndicators && this.statusIndicatorsController) {
+			this.statusIndicatorsController.transferIndicators();
+		}
+	}
+
+	_pushPanel(i, monitor) {
+		let mmPanelBox = new MultiMonitorsPanelBox(monitor);
+		let panel = new MMPanel.MultiMonitorsPanel(i, mmPanelBox);
+		
+		Main.mmPanel.push(panel);
+		this.mmPanelBox.push(mmPanelBox);
+	}
+
+	_popPanel() {
+		let panel = Main.mmPanel.pop();
+		if (this.statusIndicatorsController) {
+			this.statusIndicatorsController.transferBack(panel);
+		}
+		let mmPanelBox = this.mmPanelBox.pop();
+		mmPanelBox.destroy();
+    }
+
+	_changeMainPanelAppMenuButton(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;
+        }
+        if (indicator._busyNotifyId) {
+        	indicator._targetApp.disconnect(indicator._busyNotifyId);
+        	indicator._busyNotifyId = 0;
+        }
+        if (indicator.menu._windowsChangedId) {
+        	indicator.menu._app.disconnect(indicator.menu._windowsChangedId);
+        	indicator.menu._windowsChangedId = 0;
+        }
+		indicator = new appMenuButton(panel);
+		panel.statusArea[role] = indicator;
+		let box = panel._leftBox;
+		panel._addToPanelBox(role, indicator, box.get_n_children()+1, box);
+	}
+
+	_showAppMenu() {
+		if (this._settings.get_boolean(MMPanel.SHOW_APP_MENU_ID) && Main.mmPanel.length>0) {
+			if (!this.mmappMenu) {
+				this._changeMainPanelAppMenuButton(MMPanel.MultiMonitorsAppMenuButton);
+				this.mmappMenu = true;
+			}
+		}
+		else {
+			this._hideAppMenu();
+		}
+	}
+
+	_hideAppMenu() {
+		if (this.mmappMenu) {
+			this._changeMainPanelAppMenuButton(Panel.AppMenuButton);
+			this.mmappMenu = false;
+			Main.panel._updatePanel()
+		}		
+	}
+};
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/mmoverview.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmoverview.js
new file mode 100644
index 0000000..b7555d2
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmoverview.js
@@ -0,0 +1,678 @@
+/*
+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 { Clutter, GObject, St, Shell, GLib, Gio, Meta } = imports.gi;
+
+const Main = imports.ui.main;
+const Params = imports.misc.params;
+const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
+const OverviewControls = imports.ui.overviewControls;
+const Overview = imports.ui.overview;
+const SearchController = imports.ui.searchController;
+const LayoutManager = imports.ui.layout;
+const Background = imports.ui.background;
+const WorkspacesView = imports.ui.workspacesView;
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const CE = ExtensionUtils.getCurrentExtension();
+const MultiMonitors = CE.imports.extension;
+const Convenience = CE.imports.convenience;
+
+const THUMBNAILS_SLIDER_POSITION_ID = 'thumbnails-slider-position';
+
+var MultiMonitorsWorkspaceThumbnail = (() => {
+    let MultiMonitorsWorkspaceThumbnail = class MultiMonitorsWorkspaceThumbnail extends St.Widget {
+    _init(metaWorkspace, monitorIndex) {
+        super._init({
+            clip_to_allocation: true,
+            style_class: 'workspace-thumbnail',
+        });
+        this._delegate = this;
+
+        this.metaWorkspace = metaWorkspace;
+        this.monitorIndex = monitorIndex;
+
+        this._removed = false;
+
+        this._contents = new Clutter.Actor();
+        this.add_child(this._contents);
+
+        this.connect('destroy', this._onDestroy.bind(this));
+
+        this._createBackground();
+
+        let workArea = Main.layoutManager.getWorkAreaForMonitor(this.monitorIndex);
+        this.setPorthole(workArea.x, workArea.y, workArea.width, workArea.height);
+
+        let windows = global.get_window_actors().filter(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',
+                                               this._updateMinimized.bind(this));
+            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',
+                                                         this._windowAdded.bind(this));
+        this._windowRemovedId = this.metaWorkspace.connect('window-removed',
+                                                           this._windowRemoved.bind(this));
+        this._windowEnteredMonitorId = global.display.connect('window-entered-monitor',
+                                                              this._windowEnteredMonitor.bind(this));
+        this._windowLeftMonitorId = global.display.connect('window-left-monitor',
+                                                           this._windowLeftMonitor.bind(this));
+
+        this.state = WorkspaceThumbnail.ThumbnailState.NORMAL;
+        this._slidePosition = 0; // Fully slid in
+        this._collapseFraction = 0; // Not collapsed
+    }
+
+    _createBackground() {
+        this._bgManager = new Background.BackgroundManager({ monitorIndex: this.monitorIndex,
+                                                             container: this._contents,
+                                                             vignette: false });
+    }};
+
+    MultiMonitors.copyClass(WorkspaceThumbnail.WorkspaceThumbnail, MultiMonitorsWorkspaceThumbnail);
+    return GObject.registerClass({
+        Properties: {
+            'collapse-fraction': GObject.ParamSpec.double(
+                'collapse-fraction', 'collapse-fraction', 'collapse-fraction',
+                GObject.ParamFlags.READWRITE,
+                0, 1, 0),
+            'slide-position': GObject.ParamSpec.double(
+                'slide-position', 'slide-position', 'slide-position',
+                GObject.ParamFlags.READWRITE,
+                0, 1, 0),
+        },
+    }, MultiMonitorsWorkspaceThumbnail);
+})();
+
+const MultiMonitorsThumbnailsBox = (() => {
+    let MultiMonitorsThumbnailsBox = class MultiMonitorsThumbnailsBox extends St.Widget {
+    _init(scrollAdjustment, monitorIndex) {
+
+        super._init({ reactive: true,
+                      style_class: 'workspace-thumbnails',
+                      request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
+
+        this._delegate = this;
+        this._monitorIndex = monitorIndex;
+
+        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.add_actor(indicator);
+
+        // The porthole is the part of the screen we're showing in the thumbnails
+        this._porthole = { width: global.stage.width, height: global.stage.height,
+                           x: global.stage.x, y: global.stage.y };
+
+        this._dropWorkspace = -1;
+        this._dropPlaceholderPos = -1;
+        this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
+        this.add_actor(this._dropPlaceholder);
+        this._spliceIndex = -1;
+
+        this._targetScale = 0;
+        this._scale = 0;
+        this._pendingScaleUpdate = false;
+        this._stateUpdateQueued = false;
+        this._animatingIndicator = false;
+
+        this._stateCounts = {};
+        for (let key in WorkspaceThumbnail.ThumbnailState)
+            this._stateCounts[WorkspaceThumbnail.ThumbnailState[key]] = 0;
+
+        this._thumbnails = [];
+
+        this._showingId = Main.overview.connect('showing',
+                              this._createThumbnails.bind(this));
+        this._hiddenId = Main.overview.connect('hidden',
+                              this._destroyThumbnails.bind(this));
+
+        this._itemDragBeginId = Main.overview.connect('item-drag-begin',
+                              this._onDragBegin.bind(this));
+        this._itemDragEndId = Main.overview.connect('item-drag-end',
+                              this._onDragEnd.bind(this));
+        this._itemDragCancelledId = Main.overview.connect('item-drag-cancelled',
+                              this._onDragCancelled.bind(this));
+        this._windowDragBeginId = Main.overview.connect('window-drag-begin',
+                              this._onDragBegin.bind(this));
+        this._windowDragEndId = Main.overview.connect('window-drag-end',
+                              this._onDragEnd.bind(this));
+        this._windowDragCancelledId = Main.overview.connect('window-drag-cancelled',
+                              this._onDragCancelled.bind(this));
+
+        this._settings = new Gio.Settings({ schema_id: WorkspaceThumbnail.MUTTER_SCHEMA });
+        this._changedDynamicWorkspacesId = this._settings.connect('changed::dynamic-workspaces',
+            this._updateSwitcherVisibility.bind(this));
+
+        this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', () => {
+            this._destroyThumbnails();
+            if (Main.overview.visible)
+                this._createThumbnails();
+        });
+
+        this._workareasChangedPortholeId = global.display.connect('workareas-changed',
+                               this._updatePorthole.bind(this));
+
+        this._switchWorkspaceNotifyId = 0;
+        this._nWorkspacesNotifyId = 0;
+        this._syncStackingId = 0;
+        this._workareasChangedId = 0;
+
+        this._scrollAdjustment = scrollAdjustment;
+
+        this._scrollAdjustmentNotifyValueId = this._scrollAdjustment.connect('notify::value', adj => {
+            let workspaceManager = global.workspace_manager;
+            let activeIndex = workspaceManager.get_active_workspace_index();
+
+            this._animatingIndicator = adj.value !== activeIndex;
+
+            if (!this._animatingIndicator)
+                this._queueUpdateStates();
+
+            this.queue_relayout();
+        });
+
+        this.connect('destroy', this._onDestroy.bind(this));
+    }
+
+    _onDestroy() {
+        this._destroyThumbnails();
+        this._scrollAdjustment.disconnect(this._scrollAdjustmentNotifyValueId);
+        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);
+        Main.layoutManager.disconnect(this._monitorsChangedId);
+        global.display.disconnect(this._workareasChangedPortholeId);
+    }
+
+    addThumbnails(start, count) {
+        let workspaceManager = global.workspace_manager;
+
+        for (let k = start; k < start + count; k++) {
+            let metaWorkspace = workspaceManager.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.add_actor(thumbnail);
+
+            if (start > 0 && this._spliceIndex == -1) {
+                // not the initial fill, and not splicing via DND
+                thumbnail.state = WorkspaceThumbnail.ThumbnailState.NEW;
+                thumbnail.slide_position = 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.set_child_above_sibling(this._indicator, null);
+
+        // Clear the splice index, we got the message
+        this._spliceIndex = -1;
+    }
+
+    _updatePorthole() {
+        this._porthole = Main.layoutManager.getWorkAreaForMonitor(this._monitorIndex);
+        this.queue_relayout();
+    }};
+
+    MultiMonitors.copyClass(WorkspaceThumbnail.ThumbnailsBox, MultiMonitorsThumbnailsBox);
+    return GObject.registerClass({
+        Properties: {
+            'indicator-y': GObject.ParamSpec.double(
+                'indicator-y', 'indicator-y', 'indicator-y',
+                GObject.ParamFlags.READWRITE,
+                0, Infinity, 0),
+            'scale': GObject.ParamSpec.double(
+                'scale', 'scale', 'scale',
+                GObject.ParamFlags.READWRITE,
+                0, Infinity, 0),
+        },
+    }, MultiMonitorsThumbnailsBox);
+})();
+
+/* This isn't compatible with GNOME 40 and i don't know how to fix it -- TH
+var MultiMonitorsSlidingControl = (() => {
+    let MultiMonitorsSlidingControl = class MultiMonitorsSlidingControl extends St.Widget {
+    _init(params) {
+        params = Params.parse(params, { slideDirection: OverviewControls.SlideDirection.LEFT });
+
+        this.layout = new OverviewControls.SlideLayout();
+        this.layout.slideDirection = params.slideDirection;
+        super._init({
+            layout_manager: this.layout,
+            style_class: 'overview-controls',
+            clip_to_allocation: true,
+        });
+
+        this._visible = true;
+        this._inDrag = false;
+
+        this.connect('destroy', this._onDestroy.bind(this));
+        this._hidingId = Main.overview.connect('hiding', this._onOverviewHiding.bind(this));
+
+        this._itemDragBeginId = Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this));
+        this._itemDragEndId = Main.overview.connect('item-drag-end', this._onDragEnd.bind(this));
+        this._itemDragCancelledId = Main.overview.connect('item-drag-cancelled', this._onDragEnd.bind(this));
+
+        this._windowDragBeginId = Main.overview.connect('window-drag-begin', this._onWindowDragBegin.bind(this));
+        this._windowDragCancelledId = Main.overview.connect('window-drag-cancelled', this._onWindowDragEnd.bind(this));
+        this._windowDragEndId = Main.overview.connect('window-drag-end', this._onWindowDragEnd.bind(this));
+    }
+
+    _onDestroy() {
+        Main.overview.disconnect(this._hidingId);
+
+        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);
+    }};
+
+    MultiMonitors.copyClass(OverviewControls.SlidingControl, MultiMonitorsSlidingControl);
+    return GObject.registerClass(MultiMonitorsSlidingControl);
+})();
+
+var MultiMonitorsThumbnailsSlider = (() => {
+    let MultiMonitorsThumbnailsSlider = class MultiMonitorsThumbnailsSlider extends MultiMonitorsSlidingControl {
+    _init(thumbnailsBox) {
+        super._init({ slideDirection: OverviewControls.SlideDirection.RIGHT });
+
+        this._thumbnailsBox = thumbnailsBox;
+
+        this.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
+        this.reactive = true;
+        this.track_hover = true;
+        this.add_actor(this._thumbnailsBox);
+
+        this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', this._updateSlide.bind(this));
+        this._activeWorkspaceChangedId = global.workspace_manager.connect('active-workspace-changed',
+                                         this._updateSlide.bind(this));
+        this._notifyNWorkspacesId = global.workspace_manager.connect('notify::n-workspaces',
+                                         this._updateSlide.bind(this));
+        this.connect('notify::hover', this._updateSlide.bind(this));
+        this._thumbnailsBox.bind_property('visible', this, 'visible', GObject.BindingFlags.SYNC_CREATE);
+    }
+
+    _onDestroy() {
+        global.workspace_manager.disconnect(this._activeWorkspaceChangedId);
+        global.workspace_manager.disconnect(this._notifyNWorkspacesId);
+        Main.layoutManager.disconnect(this._monitorsChangedId);
+        super._onDestroy();
+    }};
+
+    MultiMonitors.copyClass(OverviewControls.ThumbnailsSlider, MultiMonitorsThumbnailsSlider);
+    return GObject.registerClass(MultiMonitorsThumbnailsSlider);
+})();
+*/
+
+var MultiMonitorsControlsManager = GObject.registerClass(
+class MultiMonitorsControlsManager extends St.Widget {
+    _init(index) {
+        this._monitorIndex = index;
+        this._workspacesViews = null;
+        this._spacer_height = 0;
+        this._fixGeometry = 0;
+        this._visible = false;
+
+        let layout
+        if (OverviewControls.ControlsManagerLayout) {
+            layout = new OverviewControls.ControlsManagerLayout();
+        } else {
+            layout = new OverviewControls.ControlsLayout();
+        }
+        super._init({
+            layout_manager: layout,
+            x_expand: true,
+            y_expand: true,
+            clip_to_allocation: true,
+        });
+
+        this._workspaceAdjustment = Main.overview._overview._controls._workspaceAdjustment;
+
+        this._thumbnailsBox =
+            new MultiMonitorsThumbnailsBox(this._workspaceAdjustment, this._monitorIndex);
+        //this._thumbnailsSlider = new MultiMonitorsThumbnailsSlider(this._thumbnailsBox);
+
+        this._searchController = new St.Widget({ visible: false, x_expand: true, y_expand: true, clip_to_allocation: true });
+        this._pageChangedId = Main.overview.searchController.connect('page-changed', this._setVisibility.bind(this));
+        this._pageEmptyId = Main.overview.searchController.connect('page-empty', this._onPageEmpty.bind(this));
+
+        this._group = new St.BoxLayout({ name: 'mm-overview-group-'+index,
+                                         x_expand: true, y_expand: true });
+        this.add_actor(this._group);
+
+        this._group.add_child(this._searchController);
+        //this._group.add_actor(this._thumbnailsSlider);
+
+        this._settings = Convenience.getSettings();
+
+        this._monitorsChanged();
+        //this._thumbnailsSlider.slideOut();
+        this._thumbnailsBox._updatePorthole();
+
+        this.connect('notify::allocation', this._updateSpacerVisibility.bind(this));
+        this.connect('destroy', this._onDestroy.bind(this));
+        //this._thumbnailsSelectSideId = this._settings.connect('changed::'+THUMBNAILS_SLIDER_POSITION_ID,
+        //                                                this._thumbnailsSelectSide.bind(this));
+        this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', this._monitorsChanged.bind(this));
+    }
+
+    _onDestroy() {
+        Main.overview.searchController.disconnect(this._pageChangedId);
+        Main.overview.searchController.disconnect(this._pageEmptyId);
+        this._settings.disconnect(this._thumbnailsSelectSideId);
+        Main.layoutManager.disconnect(this._monitorsChangedId);
+    }
+
+    _monitorsChanged() {
+        this._primaryMonitorOnTheLeft = Main.layoutManager.monitors[this._monitorIndex].x > Main.layoutManager.primaryMonitor.x;
+        this._thumbnailsSelectSide();
+    }
+
+    /*
+    _thumbnailsSelectSide() {
+        let thumbnailsSlider;
+        thumbnailsSlider = this._thumbnailsSlider;
+
+        let sett = this._settings.get_string(THUMBNAILS_SLIDER_POSITION_ID);
+        let onLeftSide = sett === 'left' || (sett === 'auto' && this._primaryMonitorOnTheLeft);
+
+        if (onLeftSide) {
+            let first = this._group.get_first_child();
+            if (first != thumbnailsSlider) {
+                this._thumbnailsSlider.layout.slideDirection = OverviewControls.SlideDirection.LEFT;
+                this._thumbnailsBox.remove_style_class_name('workspace-thumbnails');
+                this._thumbnailsBox.set_style_class_name('workspace-thumbnails workspace-thumbnails-left');
+                this._group.set_child_below_sibling(thumbnailsSlider, first)
+            }
+        }
+        else {
+            let last = this._group.get_last_child();
+            if (last != thumbnailsSlider) {
+                this._thumbnailsSlider.layout.slideDirection = OverviewControls.SlideDirection.RIGHT;
+                this._thumbnailsBox.remove_style_class_name('workspace-thumbnails workspace-thumbnails-left');
+                this._thumbnailsBox.set_style_class_name('workspace-thumbnails');
+                this._group.set_child_above_sibling(thumbnailsSlider, last);
+            }
+        }
+        this._fixGeometry = 3;
+    }
+    */
+
+    _updateSpacerVisibility() {
+        if (Main.layoutManager.monitors.length<this._monitorIndex)
+            return;
+
+        let top_spacer_height = Main.layoutManager.primaryMonitor.height;
+
+        let panelGhost_height = 0;
+        if (Main.mmOverview[this._monitorIndex]._overview._panelGhost)
+            panelGhost_height = Main.mmOverview[this._monitorIndex]._overview._panelGhost.get_height();
+
+        let allocation = Main.overview._overview._controls.allocation;
+        let primaryControl_height = allocation.get_height();
+        let bottom_spacer_height = Main.layoutManager.primaryMonitor.height - allocation.y2;
+
+        top_spacer_height -= primaryControl_height + panelGhost_height + bottom_spacer_height;
+        top_spacer_height = Math.round(top_spacer_height);
+
+        let spacer = Main.mmOverview[this._monitorIndex]._overview._spacer;
+        if (spacer.get_height()!=top_spacer_height) {
+            this._spacer_height = top_spacer_height;
+            spacer.set_height(top_spacer_height);
+        }
+    }
+
+    getWorkspacesActualGeometry() {
+        let geometry;
+        if (this._visible) {
+            const [x, y] = this._searchController.get_transformed_position();
+            const width = this._searchController.allocation.get_width();
+            const height = this._searchController.allocation.get_height();
+            geometry = { x, y, width, height };
+        }
+        else {
+            let [x, y] = this.get_transformed_position();
+            const width = this.allocation.get_width();
+            let height = this.allocation.get_height();
+            y -= this._spacer_height;
+            height += this._spacer_height;
+            geometry = { x, y, width, height };
+        }
+        if (isNaN(geometry.x))
+            return null;
+        //global.log("actualG+ i: "+this._monitorIndex+" x: "+geometry.x+" y: "+geometry.y+" width: "+geometry.width+" height: "+geometry.height);
+        return geometry;
+    }
+
+    _setVisibility() {
+        // 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.searchController.getActivePage();
+        let thumbnailsVisible = activePage == SearchController.ViewPage.WINDOWS;
+
+        let opacity = null;
+        if (thumbnailsVisible) {
+            opacity = 255;
+            if (this._fixGeometry===1)
+                this._fixGeometry = 0;
+        }
+        else {
+            opacity = 0;
+            this._fixGeometry = 1;
+        }
+
+        if (!this._workspacesViews)
+            return;
+
+        this._workspacesViews.ease({
+            opacity: opacity,
+            duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        });
+    }
+
+    _onPageEmpty() {
+        //this._thumbnailsSlider.pageEmpty();
+    }
+    
+    show() {
+        this._searchController.visible = true;
+        this._workspacesViews = Main.overview.searchController._workspacesDisplay._workspacesViews[this._monitorIndex];
+        this._visible = true;
+        const geometry = this.getWorkspacesActualGeometry();
+
+        if (!geometry) {
+            this._fixGeometry = 0;
+            return;
+        }
+
+        /*
+        if (this._fixGeometry) {
+            const width = this._thumbnailsSlider.get_width();
+            if (this._fixGeometry===2) {
+                geometry.width = geometry.width-width;
+                if (this._thumbnailsSlider.layout.slideDirection === OverviewControls.SlideDirection.LEFT)
+                    geometry.x = geometry.x + width;
+            }
+            else if (this._fixGeometry===3) {
+                if (this._thumbnailsSlider.layout.slideDirection === OverviewControls.SlideDirection.LEFT)
+                    geometry.x = geometry.x + width;
+                else
+                    geometry.x = geometry.x - width;
+            }
+            this._fixGeometry = 0;
+        }
+        */
+
+        this._workspacesViews.ease({
+            ...geometry,
+            duration: Main.overview.animationInProgress ? Overview.ANIMATION_TIME : 0,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        });
+    }
+
+    hide() {
+        this._visible = false;
+        this._workspacesViews.opacity = 255;
+        if (this._fixGeometry===1)
+            this._fixGeometry = 2;
+        const geometry = this.getWorkspacesActualGeometry();
+        this._workspacesViews.ease({
+            ...geometry,
+            duration: Main.overview.animationInProgress ? Overview.ANIMATION_TIME : 0,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._searchController.visible = false;
+            },
+        });
+        this._workspacesViews = null;
+    }
+});
+
+var MultiMonitorsOverviewActor = GObject.registerClass(
+class MultiMonitorsOverviewActor extends St.BoxLayout {
+    _init(index) {
+        this._monitorIndex = index;
+        super._init({
+            name: 'mm-overview-'+index,
+            /* Translators: This is the main view to select
+                activities. See also note for "Activities" string. */
+            accessible_name: _("MMOverview@"+index),
+            vertical: true,
+        });
+
+        this.add_constraint(new LayoutManager.MonitorConstraint({ index: this._monitorIndex }));
+
+        this._panelGhost = null;
+        if (Main.mmPanel) {
+            for (let idx in Main.mmPanel) {
+                if (Main.mmPanel[idx].monitorIndex !== this._monitorIndex) 
+                    continue
+                // Add a clone of the panel to the overview so spacing and such is
+                // automatic
+                this._panelGhost = new St.Bin({
+                    child: new Clutter.Clone({ source: Main.mmPanel[idx] }),
+                    reactive: false,
+                    opacity: 0,
+                });
+                this.add_actor(this._panelGhost);
+                break;
+            }
+        }
+
+        this._spacer = new St.Widget();
+        this.add_actor(this._spacer);
+
+        this._controls = new MultiMonitorsControlsManager(this._monitorIndex);
+
+        // Add our same-line elements after the search entry
+        this.add_child(this._controls);
+    }
+});
+
+
+var MultiMonitorsOverview = class MultiMonitorsOverview {
+    constructor(index) {
+        this.monitorIndex = index;
+
+        this._initCalled = true;
+        this._overview = new MultiMonitorsOverviewActor(this.monitorIndex);
+        this._overview._delegate = this;
+        this._overview.connect('destroy', this._onDestroy.bind(this));
+        Main.layoutManager.overviewGroup.add_child(this._overview);
+
+        this._showingId = Main.overview.connect('showing', this._show.bind(this));
+        this._hidingId = Main.overview.connect('hiding', this._hide.bind(this));
+    }
+
+    getWorkspacesActualGeometry() {
+        return this._overview._controls.getWorkspacesActualGeometry();
+    }
+
+    _onDestroy() {
+        Main.overview.disconnect(this._showingId);
+        Main.overview.disconnect(this._hidingId);
+
+        Main.layoutManager.overviewGroup.remove_child(this._overview);
+        this._overview._delegate = null;
+    }
+
+    _show() {
+        this._overview._controls.show();
+    }
+
+    _hide() {
+        this._overview._controls.hide();
+    }
+
+    destroy() {
+        this._overview.destroy();
+    }
+
+    addAction(action) {
+        this._overview.add_action(action);
+    }
+
+    removeAction(action) {
+        if (action.get_actor())
+            this._overview.remove_action(action);
+    }
+};
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/mmpanel.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmpanel.js
new file mode 100644
index 0000000..a381f15
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/mmpanel.js
@@ -0,0 +1,520 @@
+/*
+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 { St, Shell, Meta, Atk, Clutter, GObject } = imports.gi;
+
+const Main = imports.ui.main;
+const Panel = imports.ui.panel;
+const PopupMenu = imports.ui.popupMenu;
+const PanelMenu = imports.ui.panelMenu;
+const CtrlAltTab = imports.ui.ctrlAltTab;
+const ExtensionSystem = imports.ui.extensionSystem;
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const CE = ExtensionUtils.getCurrentExtension();
+const MultiMonitors = CE.imports.extension;
+const Convenience = CE.imports.convenience;
+const MMCalendar = CE.imports.mmcalendar;
+
+const SHOW_ACTIVITIES_ID = 'show-activities';
+var SHOW_APP_MENU_ID = 'show-app-menu';
+const SHOW_DATE_TIME_ID = 'show-date-time';
+const AVAILABLE_INDICATORS_ID = 'available-indicators';
+const TRANSFER_INDICATORS_ID = 'transfer-indicators';
+
+var StatusIndicatorsController = class StatusIndicatorsController  {
+    constructor() {
+        this._transfered_indicators = [];
+        this._settings = Convenience.getSettings();
+
+        this._updatedSessionId = Main.sessionMode.connect('updated', this._updateSessionIndicators.bind(this));
+        this._updateSessionIndicators();
+        this._extensionStateChangedId = Main.extensionManager.connect('extension-state-changed', 
+                                            this._extensionStateChanged.bind(this));
+
+        this._transferIndicatorsId = this._settings.connect('changed::'+TRANSFER_INDICATORS_ID,
+                                                                        this.transferIndicators.bind(this));
+    }
+
+    destroy() {
+        this._settings.disconnect(this._transferIndicatorsId);
+        Main.extensionManager.disconnect(this._extensionStateChangedId);
+        Main.sessionMode.disconnect(this._updatedSessionId);
+        this._settings.set_strv(AVAILABLE_INDICATORS_ID, []);
+        this._transferBack(this._transfered_indicators);
+    }
+
+	transferBack(panel) {
+		let transfer_back = this._transfered_indicators.filter((element) => {
+			return element.monitor==panel.monitorIndex;
+		});
+		
+		this._transferBack(transfer_back, panel);
+	}
+
+	transferIndicators() {
+		let boxs = ['_leftBox', '_centerBox', '_rightBox'];
+    	let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
+    	let show_app_menu = this._settings.get_value(SHOW_APP_MENU_ID);
+    	
+    	let transfer_back = this._transfered_indicators.filter((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];
+				let panel = this._findPanel(monitor);
+				boxs.forEach((box) => {
+					if(Main.panel[box].contains(indicator.container) && panel) {
+						global.log('a '+box+ " > " + iname + " : "+ monitor);
+						this._transfered_indicators.push({iname:iname, box:box, monitor:monitor});
+						Main.panel[box].remove_child(indicator.container);
+						if (show_app_menu && box === '_leftBox')
+							panel[box].insert_child_at_index(indicator.container, 1);
+						else
+							panel[box].insert_child_at_index(indicator.container, 0);
+					}
+				});
+			}
+		}
+	}
+
+	_findPanel(monitor) {
+		for (let i = 0; i < Main.mmPanel.length; i++) {
+			if (Main.mmPanel[i].monitorIndex == monitor) {
+				return Main.mmPanel[i];
+			}
+		}
+		return null;
+	}
+
+	_transferBack(transfer_back, panel) {
+    	transfer_back.forEach((element) => {
+    		this._transfered_indicators.splice(this._transfered_indicators.indexOf(element));
+			if(Main.panel.statusArea[element.iname]) {
+				let indicator = Main.panel.statusArea[element.iname];
+				if(!panel) {
+					panel = this._findPanel(element.monitor);
+				}
+				if(panel[element.box].contains(indicator.container)) {
+		    		global.log("r "+element.box+ " > " + element.iname + " : "+ element.monitor);
+		    		panel[element.box].remove_child(indicator.container);
+		    		if (element.box === '_leftBox')
+		    			Main.panel[element.box].insert_child_at_index(indicator.container, 1);
+		    		else
+		    			Main.panel[element.box].insert_child_at_index(indicator.container, 0);
+				}
+			}
+		});
+	}
+
+	_extensionStateChanged() {
+		this._findAvailableIndicators();
+        this.transferIndicators();
+	}
+
+	_updateSessionIndicators() {
+        let session_indicators = [];
+        session_indicators.push('MultiMonitorsAddOn');
+        let sessionPanel = Main.sessionMode.panel;
+        for (let sessionBox in sessionPanel){
+        	sessionPanel[sessionBox].forEach((sesionIndicator) => {
+        		session_indicators.push(sesionIndicator);
+            });
+        }
+        this._session_indicators = session_indicators;
+		this._available_indicators = [];
+		
+        this._findAvailableIndicators();
+        this.transferIndicators();
+	}
+
+    _findAvailableIndicators() {
+		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);
+		}
+	}
+};
+
+var MultiMonitorsAppMenuButton  = (() => {
+	let MultiMonitorsAppMenuButton = class MultiMonitorsAppMenuButton extends PanelMenu.Button {
+	    _init(panel) {
+	    	if (panel.monitorIndex==undefined)
+	    		this._monitorIndex = Main.layoutManager.primaryIndex;
+	    	else	
+	    		this._monitorIndex = panel.monitorIndex;
+	    	this._actionOnWorkspaceGroupNotifyId = 0;
+	    	this._targetAppGroup = null;
+	    	this._lastFocusedWindow = null;
+	    	Panel.AppMenuButton.prototype._init.call(this, panel);
+
+	    	this._windowEnteredMonitorId = global.display.connect('window-entered-monitor',
+			                					this._windowEnteredMonitor.bind(this));
+			this._windowLeftMonitorId = global.display.connect('window-left-monitor',
+			                					this._windowLeftMonitor.bind(this));
+	    }
+	    
+	    _windowEnteredMonitor (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 (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() {
+	    	
+	        if (this._actionOnWorkspaceGroupNotifyId) {
+	            this._targetAppGroup.disconnect(this._actionOnWorkspaceGroupNotifyId);
+	            this._actionOnWorkspaceGroupNotifyId = 0;
+	            this._targetAppGroup = null;
+	        }
+	        let groupWindow = false;
+	        let groupFocus = false;
+	
+	        let workspaceManager = global.workspace_manager;
+	        let workspace = workspaceManager.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', 
+	    																				this._sync.bind(this));
+	//    				 	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 windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, 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;
+	    }
+	    
+	    _sync() {
+	    	if (!this._switchWorkspaceNotifyId)
+	    		return;
+	    	Panel.AppMenuButton.prototype._sync.call(this);
+	    }
+	    
+	    _onDestroy() {
+	    	if (this._actionGroupNotifyId) {
+	            this._targetApp.disconnect(this._actionGroupNotifyId);
+	            this._actionGroupNotifyId = 0;
+	        }
+
+	        global.display.disconnect(this._windowEnteredMonitorId);
+	        global.display.disconnect(this._windowLeftMonitorId);
+	        
+            if (this._busyNotifyId) {
+                this._targetApp.disconnect(this._busyNotifyId);
+                this._busyNotifyId = 0;
+            }
+            
+            if (this.menu._windowsChangedId) {
+                this.menu._app.disconnect(this.menu._windowsChangedId);
+                this.menu._windowsChangedId = 0;
+            }
+            Panel.AppMenuButton.prototype._onDestroy.call(this);
+		}
+	};
+	MultiMonitors.copyClass(Panel.AppMenuButton, MultiMonitorsAppMenuButton);
+	return GObject.registerClass({Signals: {'changed': {}},}, MultiMonitorsAppMenuButton);
+})();
+
+var MultiMonitorsActivitiesButton = (() => {
+    let MultiMonitorsActivitiesButton = class MultiMonitorsActivitiesButton extends PanelMenu.Button {
+    _init() {
+            super._init(0.0, null, true);
+            this.accessible_role = Atk.Role.TOGGLE_BUTTON;
+
+            this.name = 'mmPanelActivities';
+
+            /* Translators: If there is no suitable word for "Activities"
+               in your language, you can use the word for "Overview". */
+            this._label = new St.Label({ text: _("Activities"),
+                                         y_align: Clutter.ActorAlign.CENTER });
+            this.add_actor(this._label);
+
+            this.label_actor = this._label;
+
+            this._showingId = Main.overview.connect('showing', () => {
+                this.add_style_pseudo_class('overview');
+                this.add_accessible_state (Atk.StateType.CHECKED);
+            });
+            this._hidingId = Main.overview.connect('hiding', () => {
+                this.remove_style_pseudo_class('overview');
+                this.remove_accessible_state (Atk.StateType.CHECKED);
+            });
+            
+            this._xdndTimeOut = 0;
+        }
+
+        _onDestroy() {
+            Main.overview.disconnect(this._showingId);
+            Main.overview.disconnect(this._hidingId);
+            super._onDestroy();
+        }
+    }
+    MultiMonitors.copyClass(Panel.ActivitiesButton, MultiMonitorsActivitiesButton);
+    return GObject.registerClass(MultiMonitorsActivitiesButton);
+})();
+
+const MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS = {
+    'activities': MultiMonitorsActivitiesButton,
+    'appMenu': MultiMonitorsAppMenuButton,
+    'dateMenu': MMCalendar.MultiMonitorsDateMenuButton,
+};
+
+var MultiMonitorsPanel = (() => {
+    let MultiMonitorsPanel = class MultiMonitorsPanel extends St.Widget {
+    _init(monitorIndex, mmPanelBox) {
+        super._init({ name: 'panel',
+                      reactive: true });
+
+        this.monitorIndex = monitorIndex;
+
+        this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
+
+        this._sessionStyle = null;
+
+        this.statusArea = {};
+
+        this.menuManager = new PopupMenu.PopupMenuManager(this);
+
+        this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
+        this.add_child(this._leftBox);
+        this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
+        this.add_child(this._centerBox);
+        this._rightBox = new St.BoxLayout({ name: 'panelRight' });
+        this.add_child(this._rightBox);
+
+        this._showingId = Main.overview.connect('showing', () => {
+            this.add_style_pseudo_class('overview');
+        });
+        this._hidingId = Main.overview.connect('hiding', () => {
+            this.remove_style_pseudo_class('overview');
+        });
+
+        mmPanelBox.panelBox.add(this);
+        Main.ctrlAltTabManager.addGroup(this, _("Top Bar"), 'focus-top-bar-symbolic',
+                                        { sortGroup: CtrlAltTab.SortGroup.TOP });
+
+        this._updatedId = Main.sessionMode.connect('updated', this._updatePanel.bind(this));
+
+        this._workareasChangedId = global.display.connect('workareas-changed', () => this.queue_relayout());
+        this._updatePanel();
+
+        this._settings = Convenience.getSettings();
+        this._showActivitiesId = this._settings.connect('changed::'+SHOW_ACTIVITIES_ID,
+                                                            this._showActivities.bind(this));
+        this._showActivities();
+
+        this._showAppMenuId = this._settings.connect('changed::'+SHOW_APP_MENU_ID,
+                                                            this._showAppMenu.bind(this));
+        this._showAppMenu();
+
+        this._showDateTimeId = this._settings.connect('changed::'+SHOW_DATE_TIME_ID,
+                                                            this._showDateTime.bind(this));
+        this._showDateTime();
+
+        this.connect('destroy', this._onDestroy.bind(this));
+    }
+
+    _onDestroy() {
+        global.display.disconnect(this._workareasChangedId);
+        Main.overview.disconnect(this._showingId);
+        Main.overview.disconnect(this._hidingId);
+
+        this._settings.disconnect(this._showActivitiesId);
+        this._settings.disconnect(this._showAppMenuId);
+        this._settings.disconnect(this._showDateTimeId);
+
+        Main.ctrlAltTabManager.removeGroup(this);
+        Main.sessionMode.disconnect(this._updatedId);
+    }
+
+    _showActivities() {
+        let name = 'activities';
+        if (this._settings.get_boolean(SHOW_ACTIVITIES_ID)) {
+            if (this.statusArea[name])
+                this.statusArea[name].visible = true;
+        }
+        else {
+            if (this.statusArea[name])
+                this.statusArea[name].visible = false;
+        }
+    }
+
+    _showDateTime() {
+        let name = 'dateMenu';
+        if (this._settings.get_boolean(SHOW_DATE_TIME_ID)) {
+            if (this.statusArea[name])
+                this.statusArea[name].visible = true;
+        }
+        else {
+            if (this.statusArea[name])
+                this.statusArea[name].visible = false;
+        }
+    }
+
+    _showAppMenu() {
+        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();
+                delete this.statusArea[name];
+            }
+        }
+    }
+
+    vfunc_get_preferred_width(forHeight) {
+        if (Main.layoutManager.monitors.length>this.monitorIndex)
+            return [0, Main.layoutManager.monitors[this.monitorIndex].width];
+        
+        return [0,  0];
+    }
+
+    _hideIndicators() {
+        for (let role in MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS) {
+            let indicator = this.statusArea[role];
+            if (!indicator)
+                continue;
+            indicator.container.hide();
+        }
+    }
+
+    _ensureIndicator(role) {
+        let indicator = this.statusArea[role];
+        if (indicator) {
+            indicator.container.show();
+            return null;
+        }
+        else {
+            let constructor = MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS[role];
+            if (!constructor) {
+                // This icon is not implemented (this is a bug)
+                return null;
+            }
+            indicator = new constructor(this);
+            this.statusArea[role] = indicator;
+        }
+        return indicator;
+    }
+
+    _getDraggableWindowForPosition(stageX) {
+        let workspaceManager = global.workspace_manager;
+        const windows = workspaceManager.get_active_workspace().list_windows();
+        const allWindowsByStacking =
+            global.display.sort_windows_by_stacking(windows).reverse();
+
+        return allWindowsByStacking.find(metaWindow => {
+            let rect = metaWindow.get_frame_rect();
+            return metaWindow.get_monitor() == this.monitorIndex &&
+                   metaWindow.showing_on_its_workspace() &&
+                   metaWindow.get_window_type() != Meta.WindowType.DESKTOP &&
+                   metaWindow.maximized_vertically &&
+                   stageX > rect.x && stageX < rect.x + rect.width;
+        });
+    }};
+
+    MultiMonitors.copyClass(Panel.Panel, MultiMonitorsPanel);
+    return GObject.registerClass(MultiMonitorsPanel);
+})();
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/multi-monitors-add-on.pot b/multi-monitors-add-on/multi-monitors-add-on@spin83/multi-monitors-add-on.pot
new file mode 100644
index 0000000..6b18906
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/multi-monitors-add-on.pot
@@ -0,0 +1,89 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the multi-monitors-add-on package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: multi-monitors-add-on\n"
+"Report-Msgid-Bugs-To: https://github.com/spin83/multi-monitors-add-on/"
+"issues\n"
+"POT-Creation-Date: 2019-10-04 04:44-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: indicator.js:46
+msgid "Preferences"
+msgstr ""
+
+#: indicator.js:115
+msgid "Multi Monitors Add-On"
+msgstr ""
+
+#: mmoverview.js:642
+msgid "Overview"
+msgstr ""
+
+#. Translators: If there is no suitable word for "Activities"
+#. in your language, you can use the word for "Overview".
+#: mmpanel.js:333
+msgid "Activities"
+msgstr ""
+
+#: mmpanel.js:414
+msgid "Top Bar"
+msgstr ""
+
+#: prefs.js:62
+msgid "Show Multi Monitors indicator on Top Panel."
+msgstr ""
+
+#: prefs.js:63
+msgid "Show Panel on additional monitors."
+msgstr ""
+
+#: prefs.js:64
+msgid "Show Thumbnails-Slider on additional monitors."
+msgstr ""
+
+#: prefs.js:65
+msgid "Show Activities-Button on additional monitors."
+msgstr ""
+
+#: prefs.js:66
+msgid "Show AppMenu-Button on additional monitors."
+msgstr ""
+
+#: prefs.js:67
+msgid "Show DateTime-Button on additional monitors."
+msgstr ""
+
+#: prefs.js:68
+msgid "Show Thumbnails-Slider on left side of additional monitors."
+msgstr ""
+
+#: prefs.js:77
+msgid "A list of indicators for transfer to additional monitors."
+msgstr ""
+
+#: prefs.js:124
+msgid "Select indicator"
+msgstr ""
+
+#: prefs.js:127
+msgid "Add"
+msgstr ""
+
+#: prefs.js:141
+msgid "Indicators on Top Panel"
+msgstr ""
+
+#: prefs.js:170
+msgid "Monitor index:"
+msgstr ""
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/prefs.js b/multi-monitors-add-on/multi-monitors-add-on@spin83/prefs.js
new file mode 100644
index 0000000..d1ba7ea
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/prefs.js
@@ -0,0 +1,289 @@
+/*
+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('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_ACTIVITIES_ID = 'show-activities';
+const SHOW_APP_MENU_ID = 'show-app-menu';
+const SHOW_DATE_TIME_ID = 'show-date-time';
+const THUMBNAILS_SLIDER_POSITION_ID = 'thumbnails-slider-position';
+const AVAILABLE_INDICATORS_ID = 'available-indicators';
+const TRANSFER_INDICATORS_ID = 'transfer-indicators';
+const ENABLE_HOT_CORNERS = 'enable-hot-corners';
+
+const Columns = {
+    INDICATOR_NAME: 0,
+    MONITOR_NUMBER: 1
+};
+
+
+var MultiMonitorsPrefsWidget = GObject.registerClass(
+class MultiMonitorsPrefsWidget extends Gtk.Grid {
+    _init() {
+        super._init({
+            margin_top: 6, margin_end: 6, margin_bottom: 6, margin_start: 6
+        });
+
+        this._numRows = 0;
+
+        this.set_orientation(Gtk.Orientation.VERTICAL);
+
+        this._settings = Convenience.getSettings();
+        this._desktopSettings = Convenience.getSettings("org.gnome.desktop.interface");
+
+        this._display = Gdk.Display.get_default();
+        this._monitors = this._display.get_monitors()
+
+        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 Activities-Button on additional monitors.'), SHOW_ACTIVITIES_ID);
+        this._addBooleanSwitch(_('Show AppMenu-Button on additional monitors.'), SHOW_APP_MENU_ID);
+        this._addBooleanSwitch(_('Show DateTime-Button on additional monitors.'), SHOW_DATE_TIME_ID);
+        this._addComboBoxSwitch(_('Show Thumbnails-Slider on additional monitors.'), THUMBNAILS_SLIDER_POSITION_ID, {
+            none: _('No'),
+            right: _('On the right'),
+            left: _('On the left'),
+            auto: _('Auto')
+        });
+        this._addSettingsBooleanSwitch(_('Enable hot corners.'), this._desktopSettings, ENABLE_HOT_CORNERS);
+
+        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);
+
+        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.Box({orientation: Gtk.Orientation.HORIZONTAL});
+        toolbar.get_style_context().add_class("inline-toolbar");
+
+        this._settings.connect('changed::'+TRANSFER_INDICATORS_ID, Lang.bind(this, this._updateIndicators));
+        this._updateIndicators();
+
+        let addTButton = new Gtk.Button({ icon_name: "list-add" });
+        addTButton.connect('clicked', Lang.bind(this, this._addIndicator));
+        toolbar.append(addTButton);
+
+        let removeTButton = new Gtk.Button({ icon_name: "list-remove" });
+        removeTButton.connect('clicked', Lang.bind(this, this._removeIndicator));
+        toolbar.append(removeTButton);
+        
+        this.add(toolbar);
+    }
+
+    add(child) {
+        this.attach(child, 0, this._numRows++, 1, 1);
+    }
+
+    _updateIndicators() {
+    	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() {
+	
+    	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_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 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 = () => {
+        	let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).unpack();
+    		dialog._store.clear();
+    		this._settings.get_strv(AVAILABLE_INDICATORS_ID).forEach((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,
+        													availableIndicators);
+        let transferIndicatorsId = this._settings.connect('changed::'+TRANSFER_INDICATORS_ID,
+															availableIndicators);
+        
+        availableIndicators.apply(this);
+    	grid.attach(dialog._treeView, 0, 0, 2, 1);
+    	
+		let gHBox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL,
+                margin_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 10,
+                spacing: 20, hexpand: true});
+		let gLabel = new Gtk.Label({label: _('Monitor index:'), halign: Gtk.Align.START});
+		gHBox.append(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.append(spinButton);
+		
+		let monitorsChanged = () => {
+			let n_monitors = this._monitors.get_n_items() -1;
+			dialog._adjustment.set_upper(n_monitors)
+			dialog._adjustment.set_value(n_monitors);
+		};
+		
+		let monitorsChangedId = this._monitors.connect('items-changed', monitorsChanged);
+
+		monitorsChanged.apply(this);
+		grid.append(gHBox);
+    	
+    	dialog.get_content_area().append(grid);
+
+    	dialog.connect('response', (dialog, id) => {
+    		this._monitors.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();
+		});
+    }
+    
+    _removeIndicator() {
+        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));
+        	}
+        }
+    }
+
+	_addComboBoxSwitch(label, schema_id, options) {
+		this._addSettingsComboBoxSwitch(label, this._settings, schema_id, options)
+	}
+
+	_addSettingsComboBoxSwitch(label, settings, schema_id, options) {
+		let gHBox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL,
+                margin_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 10,
+                spacing: 20, hexpand: true});
+		let gLabel = new Gtk.Label({label: _(label), halign: Gtk.Align.START});
+		gHBox.append(gLabel);
+
+		let gCBox = new Gtk.ComboBoxText({halign: Gtk.Align.END});
+		Object.entries(options).forEach(function(entry) {
+			const [key, val] = entry;
+			gCBox.append(key, val);
+		});
+		gHBox.append(gCBox);
+
+		this.add(gHBox);
+
+		settings.bind(schema_id, gCBox, 'active-id', Gio.SettingsBindFlags.DEFAULT);
+	}
+
+    _addBooleanSwitch(label, schema_id) {
+        this._addSettingsBooleanSwitch(label, this._settings, schema_id);
+    }
+
+    _addSettingsBooleanSwitch(label, settings, schema_id) {
+        let gHBox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL,
+                margin_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 10,
+                spacing: 20, hexpand: true});
+        let gLabel = new Gtk.Label({label: _(label), halign: Gtk.Align.START});
+        gHBox.append(gLabel);
+        let gSwitch = new Gtk.Switch({halign: Gtk.Align.END});
+        gHBox.append(gSwitch);
+        this.add(gHBox);
+
+        settings.bind(schema_id, gSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
+    }
+});
+
+function init() {
+    Convenience.initTranslations();
+}
+
+function buildPrefsWidget() {
+    let widget = new MultiMonitorsPrefsWidget();
+
+    return widget;
+}
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/schemas/gschemas.compiled b/multi-monitors-add-on/multi-monitors-add-on@spin83/schemas/gschemas.compiled
new file mode 100644
index 0000000000000000000000000000000000000000..5a9e94565242d0ad6ef361456e66623083e8ff76
GIT binary patch
literal 788
zcmZuvze^lJ6dsdYVhox<6eMM;y<&F#8!U{45G%3FyW8=0V0UKOnLU4@ogg8k3^sv)
zjfLi4h^1v9AU1(CAywcItS{f2y^9tOeEWU#&6}C`=Ixs`sx%odMq?hl-stGT$eRFP
zF1%i2=CuW}EDpgZFj{j$3^Ar3!VoLs1$Y*)RWI%tTd3G&D$irJ<&|;T8W$IJ?zJqe
z(cV^0QkqI@usNFIBSwSo9-{?4#w0Yyjql|g_+I7<p!@w>j~&*tqAz}de*<6V-mkFF
z`W1XWd<i(;+keLSvu?p(1s?#>$DIMkvwjZ$2>cm1cGvhedJ6stW@o^k;>RNUtY5-E
z2VVexXWpK&&w2*_75FFcY5B`L_E}HEAAoOw!PSR^ebyX5iMQmpMcU#K!1X@?o&x+P
z2osM1>XXi?lPjrBs=LHb3mb)yYx}G&ItBqwx?HEKlBIRpqZ@*1Z#k^XAB>@~MuCE^
zbT9KGovRJ}B#qx}8n#5_qHU_%?YJbLh5ZQ{pM=IIq4CLW<CA+Ek7}LE?53oy*L@_V
zLf#W1>a>Gjl2JM8$J|$B+y>IWQ)5KCPVY6LDS0KmE>OVjekw~@C{u^@?)d-D2n!*;
H2@(GQ?GU!l

literal 0
HcmV?d00001

diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/schemas/org.gnome.shell.extensions.multi-monitors-add-on.gschema.xml b/multi-monitors-add-on/multi-monitors-add-on@spin83/schemas/org.gnome.shell.extensions.multi-monitors-add-on.gschema.xml
new file mode 100644
index 0000000..4a42a23
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/schemas/org.gnome.shell.extensions.multi-monitors-add-on.gschema.xml
@@ -0,0 +1,59 @@
+<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-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="show-date-time" type="b">
+      <default>true</default>
+      <summary>Show DateTime-Button on additional monitors.</summary>
+      <description>Change visibility of DateTime-Button on additional monitors.</description>
+    </key>
+
+    <key name="thumbnails-slider-position" type="s">
+      <choices>
+        <choice value='none'/>
+        <choice value='right'/>
+        <choice value='left'/>
+        <choice value='auto'/>
+      </choices>
+      <default>'auto'</default>
+      <summary>Show Thumbnails-Slider on additional monitors.</summary>
+      <description>Select position of Thumbnails-Slider 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>
\ No newline at end of file
diff --git a/multi-monitors-add-on/multi-monitors-add-on@spin83/stylesheet.css b/multi-monitors-add-on/multi-monitors-add-on@spin83/stylesheet.css
new file mode 100644
index 0000000..b1d20c5
--- /dev/null
+++ b/multi-monitors-add-on/multi-monitors-add-on@spin83/stylesheet.css
@@ -0,0 +1,29 @@
+
+.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;
+}
+
+.multimonitor-status-indicators-box {
+    spacing: 0px;
+}
+
+.multimonitor-status-icon {
+    padding: 0 2px;
+}
+
+.workspace-thumbnails-left {
+  border-radius: 0 9px 9px 0; 
+}
+
+.workspace-thumbnails-left:rtl {
+    border-radius: 9px 0 0 9px; 
+}