Compare commits

..

5 Commits

Author SHA1 Message Date
Simon McVittie
1a41467649 3.29.3+really3.28.1-1 2018-07-27 23:48:06 +01:00
Simon McVittie
27c4995ce9 Hard-code compatible Shell versions for this branch
${gnome:Version} doesn't understand the +really workaround.
2018-07-27 23:46:52 +01:00
Simon McVittie
d483f00cce Set Rules-Requires-Root to no 2018-07-27 23:20:57 +01:00
Simon McVittie
e7c333b1a1 Bump Standards-Version to 4.1.5 2018-07-27 23:20:52 +01:00
Simon McVittie
1ffd854eb1 Revert unintended upload of 3.29.3 to unstable
d/gbp.conf: Use debian/unstable and upstream/3.28.x branches
2018-07-27 23:20:47 +01:00
142 changed files with 10312 additions and 11549 deletions

View File

@@ -1,3 +0,0 @@
extends:
- ./lint/eslintrc-gjs.yml
- ./lint/eslintrc-shell.yml

222
NEWS
View File

@@ -1,225 +1,3 @@
3.35.91
=======
Contributors:
Florian Müllner
Translators:
Zander Brown [en_GB]
3.35.90
=======
* Adjust to gnome-shell changes [Florian; !100, !101, !102]
* Force single-line window titles in window list [Florian; #202]
* Misc. bug fixes and cleanup [Florian; !104, !105]
Contributors:
Florian Müllner
Translators:
sicklylife [ja], Umarzuki Bin Mochlis Moktar [ms]
3.35.3
======
Translators:
Fran Dieguez [gl]
3.35.2
======
* Adjust to gnome-shell changes [Marco, Florian; !89, !95, !96]
* window-list, workspace-indicator: Exclude DESKTOP windows from previews
[Florian; !93]
* screenshot-window-sizer: Fix cycling through all valid sizes [Willy; !97]
Contributors:
Marco Trevisan (Treviño), Florian Müllner, Willy Stadnick
3.34.1
======
* Adjust to gnome-settings-daemon plugin removals [Xiaoguang; !94]
Contributors:
Florian Müllner, Xiaoguang Wang
Translators:
Nathan Follens [nl], Dušan Kazik [sk], Ask Hjorth Larsen [da],
Yi-Jyun Pan [zh_TW]
3.34.0
======
Translators:
Rafael Fontenelle [pt_BR], Efstathios Iosifidis [el], Milo Casagrande [it],
Sabri Ünal [tr]
3.33.92
=======
Translators:
Марко Костић [sr], Tim Sabsch [de], Rūdolfs Mazurs [lv], Matej Urbančič [sl],
Balázs Úr [hu], Claude Paroz [fr], Fran Dieguez [gl], Changwoo Ryu [ko],
Ryuta Fujii [ja], Fabio Tomat [fur], Goran Vidović [hr]
3.33.91
=======
* Misc. bug fixes and cleanups [Florian; !88, !90, !91, !92]
Contributors:
Florian Müllner
Translators:
Asier Sarasua Garmendia [eu], Anders Jonsson [sv], Marek Černocký [cs],
Kukuh Syafaat [id], Jiri Grönroos [fi], Florentina Mușat [ro],
Aurimas Černius [lt], Daniel Mustieles [es], Piotr Drąg [pl], Jordi Mas [ca],
Danial Behzadi [fa]
3.33.90
=======
* window-list: Support showing windows from all workspaces [Florian; #154]
* Misc. bug fixes and cleanups [Florian; !86, !87]
Contributors:
Florian Müllner
Translators:
Jor Teron [mjw]
3.33.4
======
* Make GNOME Classic more classic:
- Disable GNOME 3 overview [Florian; !69]
- Add window picker button to window list [Florian; !73, !80]
- Style improvements and fixes [Jakub; #169, !82]
- Support horizontal workspace layout in window list [Florian; !70]
- Add draggable previews to window list workspace switcher [Florian; !74]
- Arrange workspaces horizontally [Florian; !72]
* workspace-indicator: Support horizontal workspace layout [Florian; !71]
* workspace-indicator: Add draggable previews [Florian; !77]
* Misc. bug fixes and cleanups [Florian; !75, !76, !79, !78, #168, !84]
Contributors:
Florian Müllner, Jakub Steiner, Jor Teron
Translators:
Jor Teron [mjw]
3.33.3
======
* Misc. bug fixes [Florian, Marco; !67, !68]
Contributors:
Florian Müllner, Marco Trevisan (Treviño)
3.33.2
======
* Misc. bug fixes and cleanups [Florian; !66]
Contributors:
Florian Müllner
3.33.1
======
* Misc. bug fixes [Florian; !64]
Contributors:
Florian Müllner
3.32.1
======
* Fix windowsNavigator extension after ES6 port [Florian; #143]
* screenshot-window-sizer: Add phone screenshot sizes [Adrien; !65]
* Misc. bug fixes and cleanups [Fabian; !62]
Contributors:
Florian Müllner, Adrien Plazas, Fabian P. Schmidt
3.32.0
======
Contributors:
Florian Müllner
Translations:
Victor Ibragimov [tg], Kristjan SCHMIDT [eo], Mart Raudsepp [et]
3.31.92
=======
* Misc. bug fixes and cleanups [Florian; !57, !58, !59, !60]
Contributors:
Florian Müllner
3.31.91
=======
* apps-menu: Remove outdated legacy-tray handling [Florian; !53]
* user-theme: Allow using XDG user data dir [Tomasz; !55]
* Misc. bug fixes and cleanups [Florian; !52, !54, !56]
Contributors:
Tomasz Gąsior, Florian Müllner
Translators:
Matej Urbančič [sl], Gun Chleoc [gd]
3.31.90
=======
* Misc. bug fixes and cleanups [Florian; !49, !50, !51]
Contributors:
Florian Müllner
Translators:
Ryuta Fujii [ja], Charles Monzat [fr], Pieter Schalk Schoeman [af]
3.31.2
======
* Remove obsolete alternate-tab extension [Florian; #786496]
* Adjust to gnome-shell changes [Florian; #113]
Contributors:
Florian Müllner
3.30.1
======
* apps-menu: Fix height on HiDPI systems [Florian; #102]
* window-list: Only switch between windows on active workspace when scrolling
[Florian; #78]
Contributors:
Florian Müllner
3.30.0
======
* Bump version
3.29.91
=======
* Misc. bug fixes [Florian; #90]
Contributors:
Florian Müllner
3.29.90
=======
* Misc. bug fixes [Florian; #786496]
Contributors:
Florian Müllner
3.29.3
======
* Adjust to global.screen removal [Jonas; #759538]
Contributors:
Jonas Ådahl, Florian Müllner
3.29.2
======
* Misc. bug fixes [Florian; #69]
Contributors:
Florian Müllner
3.28.1
======
* Misc. bug fixes [Xiaoguang, Florian; #59, #62]

View File

@@ -15,11 +15,9 @@ Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
## Extensions
* alternate-tab (**OBSOLETE**)
* alternate-tab
Lets you use classic Alt+Tab (window-based instead of app-based) in GNOME Shell.
This extension is obsolete since GNOME 3.30, see [this blogpost][alternatetab-post]
for further details.
* apps-menu
@@ -36,6 +34,10 @@ GSettings key.
Shows a status menu for rapid unmount and power off of external storage devices
(i.e. pendrives)
* example
A minimal example illustrating how to write extensions.
* launch-new-instance
Changes application icons to always launch a new instance when activated.
@@ -80,4 +82,3 @@ file for details.
[shell-page]: https://wiki.gnome.org/Projects/GnomeShell
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues
[license]: COPYING
[alternatetab-post]: https://blogs.gnome.org/fmuellner/2018/10/11/the-future-of-alternatetab-and-why-you-need-not-worry/

View File

@@ -1,9 +0,0 @@
[org.gnome.mutter:GNOME-Classic]
dynamic-workspaces=false
[org.gnome.desktop.wm.preferences:GNOME-Classic]
button-layout='appmenu:minimize,maximize,close'
[org.gnome.desktop.wm.keybindings:GNOME-Classic]
switch-applications=[]
switch-windows=['<Super>Tab','<Alt>Tab']

View File

@@ -1,9 +1,8 @@
{
"parentMode": "user",
"stylesheetName": "gnome-classic.css",
"hasOverview": false,
"enabledExtensions": [@CLASSIC_EXTENSIONS@],
"panel": { "left": ["appMenu"],
"panel": { "left": ["activities", "appMenu"],
"center": [],
"right": ["a11y", "keyboard", "dateMenu", "aggregateMenu"]
}

View File

@@ -4,7 +4,6 @@ $variant: 'light';
@import "gnome-shell-sass/_colors"; //use gtk colors
@import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common";
@import "gnome-shell-sass/_widgets";
/* Overrides */
@@ -33,20 +32,18 @@ $variant: 'light';
font-weight: normal;
color: $fg_color;
text-shadow: none;
&:hover {
color: lighten($fg_color,10%);
text-shadow: none;
& .system-status-icon { icon-shadow: none; }
}
&:active, &:overview, &:focus, &:checked {
// Trick due to St limitations. It needs a background to draw
// a box-shadow
background-color: $selected_bg_color;
color: $selected_fg_color;
background-color: $selected_bg_color !important;
color: $selected_fg_color !important;
box-shadow: none;
& > .system-status-icon { icon-shadow: none; }
}
&:hover {
text-shadow: none;
& .system-status-icon { icon-shadow: none; }
}
.app-menu-icon { width: 0; height: 0; margin: 0; } // shell's display:none; :D
.system-status-icon {
@@ -63,9 +60,9 @@ $variant: 'light';
&.lock-screen,
&.unlock-screen,
&.login-screen {
background-color: transparentize($bg_color, 0.5);
background-gradient-start: transparentize($bg_color, 0.5);
background-gradient-end: transparentize($bg_color, 0.5);
background-color: transparentize($_bubble_bg_color, 0.5);
background-gradient-start: transparentize($_bubble_bg_color, 0.5);
background-gradient-end: transparentize($_bubble_bg_color, 0.5);
border-bottom: none;
.panel-button { color: $osd_fg_color; }
}
@@ -94,3 +91,15 @@ $variant: 'light';
background-image: url("calendar-today.svg");
}
.message-list-clear-button.button {
color: $fg_color
}
.notification-banner {
background-color: $bg_color !important;
color: $fg_color;
.notification-button {
background-color: darken($bg_color,5%);
&:hover, &focus { background-color: darken($bg_color,2%); }
}
}

View File

@@ -1,3 +1,3 @@
[GNOME Session]
Name=GNOME Classic
RequiredComponents=org.gnome.Shell;org.gnome.SettingsDaemon.A11ySettings;org.gnome.SettingsDaemon.Color;org.gnome.SettingsDaemon.Datetime;org.gnome.SettingsDaemon.Housekeeping;org.gnome.SettingsDaemon.Keyboard;org.gnome.SettingsDaemon.MediaKeys;org.gnome.SettingsDaemon.Power;org.gnome.SettingsDaemon.PrintNotifications;org.gnome.SettingsDaemon.Rfkill;org.gnome.SettingsDaemon.ScreensaverProxy;org.gnome.SettingsDaemon.Sharing;org.gnome.SettingsDaemon.Smartcard;org.gnome.SettingsDaemon.Sound;org.gnome.SettingsDaemon.Wacom;org.gnome.SettingsDaemon.XSettings;
RequiredComponents=org.gnome.Shell;org.gnome.SettingsDaemon.A11ySettings;org.gnome.SettingsDaemon.Clipboard;org.gnome.SettingsDaemon.Color;org.gnome.SettingsDaemon.Datetime;org.gnome.SettingsDaemon.Housekeeping;org.gnome.SettingsDaemon.Keyboard;org.gnome.SettingsDaemon.MediaKeys;org.gnome.SettingsDaemon.Mouse;org.gnome.SettingsDaemon.Power;org.gnome.SettingsDaemon.PrintNotifications;org.gnome.SettingsDaemon.Rfkill;org.gnome.SettingsDaemon.ScreensaverProxy;org.gnome.SettingsDaemon.Sharing;org.gnome.SettingsDaemon.Smartcard;org.gnome.SettingsDaemon.Sound;org.gnome.SettingsDaemon.Wacom;org.gnome.SettingsDaemon.XSettings;

View File

@@ -0,0 +1,6 @@
--- Generating the css file ---
You need sass to generate the css file.
To generate them run from a command line in the project directory:
sass --sourcemap=none --update ./

View File

@@ -0,0 +1,7 @@
GNOME Shell Sass is a project intended to allow the sharing of the theme sources in sass between gnome-shell and other projects like gnome-shell-extensions.
License
=======
GNOME Shell Sass is distributed under the terms of the GNU General Public License,
version 2 or later. See the COPYING file for details.

View File

@@ -1,16 +0,0 @@
# GNOME Shell Sass
GNOME Shell Sass is a project intended to allow the sharing of the
theme sources in sass between gnome-shell and other projects like
gnome-shell-extensions.
Any changes should be done in the [GNOME Shell subtree][shell-subtree]
and not the stand-alone [gnome-shell-sass repository][sass-repo]. They
will then be synchronized periodically before releases.
## License
GNOME Shell Sass is distributed under the terms of the GNU General Public
License, version 2 or later. See the [COPYING][license] file for details.
[shell-subtree]: https://gitlab.gnome.org/GNOME/gnome-shell/tree/master/data/theme/gnome-shell-sass
[sass-repo]: https://gitlab.gnome.org/GNOME/gnome-shell-sass
[license]: COPYING

View File

@@ -1,38 +1,39 @@
// When color definition differs for dark and light variant,
// it gets @if ed depending on $variant
$base_color: if($variant == 'light', #fff, lighten(desaturate(#241f31, 20%), 2%));
$bg_color: if($variant == 'light', #f6f5f4, darken(desaturate(#3d3846, 100%), 4%));
$fg_color: if($variant == 'light', #2e3436, #eeeeec);
$selected_fg_color: #fff;
$selected_bg_color: if($variant == 'light', #3584e4, darken(#3584e4, 10%));
$selected_borders_color: if($variant== 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%));
$borders_color: if($variant == 'light', darken($bg_color, 18%), darken($bg_color, 8%));
$borders_edge: if($variant == 'light', rgba(255,255,255,0.8), transparentize($fg_color, 0.93));
$link_color: if($variant == 'light', darken($selected_bg_color, 10%), lighten($selected_bg_color, 20%));
$link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), lighten($selected_bg_color, 10%));
$base_color: if($variant =='light', #ffffff, #292929);
$bg_color: if($variant =='light', #ededed, #393f3f);
$fg_color: if($variant =='light', #2e3436, #eeeeec);
$selected_fg_color: #ffffff;
$selected_bg_color: if($variant == 'light', #4a90d9, darken(#4a90d9,20%));
$selected_borders_color: if($variant=='light', darken($selected_bg_color, 30%),
darken($selected_bg_color, 20%));
$borders_color: if($variant =='light', darken($bg_color,30%), darken($bg_color,12%));
$borders_edge: if($variant =='light', white, transparentize($fg_color, 0.9));
$link_color: if($variant == 'light', darken($selected_bg_color,10%),
lighten($selected_bg_color,20%));
$link_visited_color: if($variant == 'light', darken($selected_bg_color,20%),
lighten($selected_bg_color,10%));
$top_hilight: $borders_edge;
$warning_color: #f57900;
$error_color: #ff8080;
$success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%));
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%));
$error_color: #cc0000;
$success_color: if($variant =='light', #73d216, darken(#73d216,10%));
$destructive_color: if($variant =='light', #ef2929, darken(#ef2929,10%));
$osd_fg_color: #eeeeec;
$osd_text_color: white;
$osd_bg_color: transparentize(darken(desaturate(#3d3846, 100%), 12%),0.04);
$osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5);
$osd_insensitive_fg_color: mix($osd_fg_color, opacify($osd_bg_color, 1), 50%);
$osd_bg_color: #2e3436;
$osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.84);
$osd_outer_borders_color: transparentize(white, 0.9);
$shadow_color: if($variant == 'light', rgba(0,0,0,0.1), rgba(0,0,0,0.2));
$tooltip_borders_color: $osd_outer_borders_color;
//insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
$insensitive_bg_color: mix($bg_color, $base_color, 60%);
$insensitive_borders_color: mix($borders_color, $base_color, 60%);
$insensitive_borders_color: $borders_color;
//colors for the backdrop state, derived from the main colors.
$backdrop_base_color: if($variant =='light', darken($base_color,1%), lighten($base_color,1%));

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
// generic drawing of more complex things
@function draw_widget_edge($c:$borders_edge) {
@function _widget_edge($c:$borders_edge) {
// outer highlight "used" on most widgets
@return 0 1px $c;
}
@@ -13,7 +13,7 @@
//font-size: ($size / $base) * 1rem;
}
@mixin draw_shadows($shadow1, $shadow2:none, $shadow3:none, $shadow4:none) {
@mixin _shadows($shadow1, $shadow2:none, $shadow3:none, $shadow4:none) {
//
// Helper function to stack up to 4 box-shadows;
//
@@ -31,22 +31,25 @@
//
// $t: entry type
// $fc: focus color
// $edge: set to none to not draw the bottom edge or specify a color to not use the default one
// $edge: set to none to not draw the bottom edge or specify a color to not
// use the default one
//
// possible $t values:
// normal, focus, insensitive
//
$_inner_shadows: inset 0 2px 4px transparentize(black, 0.6);
@if $t==normal {
background-color: $base_color;
border-color: $borders_color;
@include _shadows($_inner_shadows);
}
@if $t==focus {
@include _shadows($_inner_shadows);
border-color: if($fc==$selected_bg_color,
$selected_borders_color,
darken($fc,35%));
box-shadow: inset 0 0 0 1px $fc;
$selected_borders_color,
darken($fc,35%));
}
@if $t==hover { }
@if $t==insensitive {
@@ -58,39 +61,36 @@
// buttons
@function draw_border_color ($c) {
//
// colored buttons want the border form the base color
//
@return if($variant == 'light', darken($c, 18%), darken($c, 4%));
}
@function _border_color ($c) { @return darken($c,25%); } // colored buttons want
// the border form the
// base color
@function draw_text_shadow_color ($tc:$fg_color, $bg:$bg_color) {
@function _text_shadow_color ($tc:$fg_color, $bg:$bg_color) {
//
// calculate the color of text shadows
//
// $tc is the text color
// $bg is the background color
//
$lbg: lightness($bg)/100%;
@if lightness($tc)<50% { @return rgba(255,255,255,$lbg/($lbg*1.3)); }
@else { @return rgba(0,0,0,1-$lbg*0.8); }
$_lbg: lightness($bg)/100%;
@if lightness($tc)<50% { @return transparentize(white,1-$_lbg/($_lbg*1.3)); }
@else { @return transparentize(black,$_lbg*0.8); }
}
@function draw_button_hilight_color($c) {
@function _button_hilight_color($c) {
//
// calculate the right top hilight color for buttons
//
// $c: base color;
//
@if lightness($c)>90% { @return white; }
@else if lightness($c)>80% { @return rgba(255,255,255, 0.7); }
@else if lightness($c)>50% { @return rgba(255,255,255, 0.5); }
@else if lightness($c)>40% { @return rgba(255,255,255, 0.3); }
@else { @return rgba(255,255,255, 0.1); }
@else if lightness($c)>80% { @return transparentize(white, 0.3); }
@else if lightness($c)>50% { @return transparentize(white, 0.5); }
@else if lightness($c)>40% { @return transparentize(white, 0.7); }
@else { @return transparentize(white, 0.9); }
}
@mixin draw_button_text_shadow ($tc:$fg_color, $bg:$bg_color) {
@mixin _button_text_shadow ($tc:$fg_color, $bg:$bg_color) {
//
// helper function for the text emboss effect
//
@@ -99,19 +99,19 @@
// TODO: this functions needs a way to deal with special cases
//
$shadow: draw_text_shadow_color($tc, $bg);
$_shadow: _text_shadow_color($tc, $bg);
@if lightness($tc)<50% {
text-shadow: 0 1px $shadow;
icon-shadow: 0 1px $shadow;
text-shadow: 0 1px $_shadow;
icon-shadow: 0 1px $_shadow;
}
@else {
text-shadow: 0 -1px $shadow;
icon-shadow: 0 -1px $shadow;
text-shadow: 0 -1px $_shadow;
icon-shadow: 0 -1px $_shadow;
}
}
@mixin button($t, $c:$bg_color, $tc:$fg_color, $edge: $borders_edge, $shadow: $shadow_color) {
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
//
// Button drawing function
//
@@ -120,8 +120,6 @@
// $tc: optional text color for colored* types
// $edge: set to none to not draw the bottom edge or specify a color to not
// use the default one
// $shadow: set to none to not draw the drop shadow or specify a color to not
// use the default one
//
// possible $t values:
// normal, hover, active, insensitive, insensitive-active,
@@ -129,103 +127,95 @@
// osd, osd-hover, osd-active, osd-insensitive, osd-backdrop, undecorated
//
$hilight_color: draw_button_hilight_color($c);
$button_edge: if($edge == none, none, draw_widget_edge($edge));
$blank_edge: if($edge == none, none, draw_widget_edge(transparentize($edge,1)));
$button_shadow: if($shadow == none, none, 0 1px 1px 0 $shadow);
$_hilight_color: _button_hilight_color($c);
$_button_edge: if($edge == none, none, _widget_edge($edge));
$_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
// normal button
@if $t==normal {
color: $tc;
background-color: lighten($c, 3%);
border-color: draw_border_color($c);
@include draw_shadows($button_shadow);
// box-shadow: 0 1px 1px 0 rgba(0,0,0,0.1);
text-shadow: 0 1px $text_shadow_color;
icon-shadow: 0 1px $text_shadow_color;
}
//
// normal button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
// focused button
color: $osd_fg_color;
background-color: $_bg;
border-color: $osd_borders_color;
box-shadow: inset 0 1px lighten($osd_bg_color,10%);
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
}
@if $t==focus {
color: $tc;
text-shadow: 0 1px $text_shadow_color;
icon-shadow: 0 1px $text_shadow_color;
box-shadow: inset 0 0 0 2px transparentize($selected_bg_color, 0.7);
//border-color: $selected_bg_color;
//
// focused button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
color: $osd_fg_color;
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
box-shadow: inset 0px 0px 0px 1px $selected_bg_color;
}
// hover button
@else if $t==hover {
color: $tc;
background-color: lighten($c, if($variant == 'light', 8%, 5%));
border-color: if($variant == 'light', draw_border_color(lighten($c, 7%)), draw_border_color($c));
@include draw_shadows($button_shadow);
text-shadow: 0 1px $text_shadow_color;
icon-shadow: 0 1px $text_shadow_color;
}
//
// active osd button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,10%));
// active button
color: white;
border-color: $osd_borders_color;
background-color: $_bg;
box-shadow: inset 0 1px lighten($osd_bg_color,20%);
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
}
@else if $t==active {
color: $tc;
background-color: darken($c,3%);
border-color: draw_border_color(if($variant == 'light', $c, darken($c,7%)));
//
// active osd button
//
$_bg: if($c!=$bg_color, $c, $osd_borders_color);
color: white;
border-color: $osd_borders_color;
background-color: darken($_bg,5%);
// This should be none, but it's creating some issues with borders, so to
// workaround it for now, use inset wich goes through a different code path.
// see https://bugzilla.gnome.org/show_bug.cgi?id=752934
box-shadow: inset 0 0 black;
text-shadow: none;
icon-shadow: none;
box-shadow: none;
}
// insensitive button
@else if $t==insensitive {
//
// insensitive osd button
//
$_bg: transparentize(mix($insensitive_fg_color,$osd_bg_color,20%),0.3);
color: $insensitive_fg_color;
border-color: $insensitive_borders_color;
background-color: $insensitive_bg_color;
border-color: $osd_borders_color;
background-color: $_bg;
box-shadow: none;
text-shadow: none;
icon-shadow: none;
}
// reset
@else if $t==undecorated {
//
// reset
//
border-color: transparent;
background-color: transparent;
background-image: none;
@include draw_shadows(inset 0 1px rgba(255,255,255,0),$blank_edge);
@include _shadows(inset 0 1px transparentize(white,1),
$_blank_edge);
text-shadow: none;
icon-shadow: none;
}
}
// overview icons
@mixin overview-icon($color) {
.overview-icon {
@extend %icon_tile;
color: $color;
}
&:hover,
&:selected {
.overview-icon {
background-color: transparentize($color, .9);
}
}
&:focus {
.overview-icon {
background-color: transparentize($color, .7);
// border-color: $selected_bg_color;
}
}
&:drop {
.overview-icon {
background-color: transparentize($selected_bg_color, .15);
}
}
&:active,
&:checked {
.overview-icon {
background-color: transparentize(darken($osd_bg_color, 10%), .5);
}
}
}

View File

@@ -22,10 +22,10 @@ $destructive_color: darken(#ef2929,10%);
$osd_fg_color: #eeeeec;
$osd_bg_color: #2e3436;
$osd_borders_color: rgba(0,0,0, 0.7);
$osd_outer_borders_color: rgba(255,255,255, 0.1);
$osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9);
$shadow_color: rgba(0,0,0, 0.1);
$tooltip_borders_color: $osd_outer_borders_color;
//insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);

View File

@@ -1,51 +0,0 @@
//
// Shell widgets stylesheets are placed in separate .scss files
// in 'widgets' and imported into the main stylesheet in this file.
// To create or update a widget for the shell modify the list below.
//
/* WIDGETS */
// Primary widgets
@import 'widgets/base';
@import 'widgets/entries';
@import 'widgets/buttons';
@import 'widgets/check-box';
@import 'widgets/switches';
@import 'widgets/slider';
@import 'widgets/scrollbars';
// Popovers
@import 'widgets/popovers';
@import 'widgets/calendar';
@import 'widgets/message-list';
@import 'widgets/ibus-popup';
// Notifications
@import 'widgets/notifications';
@import 'widgets/hotplug';
// Dialogs
@import 'widgets/dialogs';
@import 'widgets/network-dialog';
// OSDs
@import 'widgets/osd';
@import 'widgets/switcher-popup';
@import 'widgets/workspace-switcher';
// Panel
@import 'widgets/panel';
@import 'widgets/corner-ripple';
// Overview
@import 'widgets/overview';
@import 'widgets/window-picker';
@import 'widgets/search-entry';
@import 'widgets/search-results';
@import 'widgets/app-grid';
@import 'widgets/dash';
@import 'widgets/workspace-thumbnails';
// A11y / misc
@import 'widgets/a11y';
@import 'widgets/misc';
@import 'widgets/tiled-previews';
@import 'widgets/keyboard';
@import 'widgets/looking-glass';
// Lock / login screens
@import 'widgets/login-dialog';
@import 'widgets/screen-shield';

View File

@@ -1,24 +0,0 @@
// Pointer location
.ripple-pointer-location {
width: $ripple_size;
height: $ripple_size;
border-radius: $ripple_size * 0.5; // radius equals the size of the box to give us the curve
background-color: lighten(transparentize($selected_bg_color, 0.7), 30%);
box-shadow: 0 0 2px 2px lighten($selected_bg_color, 20%);
}
// Pointer accessibility notifications
.pie-timer {
width: 60px;
height: 60px;
-pie-border-width: 3px;
-pie-border-color: $selected_bg_color;
-pie-background-color: lighten(transparentize($selected_bg_color, 0.7), 40%);
}
// Screen zoom/Magnifier
.magnifier-zoom-region {
border: 2px solid $selected_bg_color;
&.full-screen { border-width: 0; }
}

View File

@@ -1,186 +0,0 @@
/* App Grid */
$app_icon_size: 96px;
$app_icon_padding: 24px;
// app icons
.icon-grid {
-shell-grid-horizontal-item-size: $app_icon_size + $app_icon_padding * 2;
-shell-grid-vertical-item-size: $app_icon_size + $app_icon_padding * 2;
spacing: $base_spacing * 6;
.overview-icon {
icon-size: $app_icon_size;
}
}
//.app-display { spacing: 20px; }
/* App Icons */
$app_grid_fg_color: #fff;
// Icon tiles in the app grid
.app-well-app,
%app-well-app {
@include overview-icon($app_grid_fg_color);
.overview-icon.overview-icon-with-label {
padding: 10px 8px 5px 8px;
> StBoxLayout {
spacing: $base_spacing;
}
}
}
/* App Folders */
.app-folder {
.overview-icon {
}
}
// expanded folder
.app-folder-dialog {
border-radius: $modal_radius * 1.5;
border: 1px solid $osd_outer_borders_color;
spacing: 12px;
background-color: transparentize(darken($osd_bg_color,10%), 0.05);
& .folder-name-container {
padding: 24px 36px 0;
spacing: 12px;
& .folder-name-label,
& .folder-name-entry {
font-size: 18pt;
font-weight: bold;
}
& .folder-name-entry { width: 300px }
/* FIXME: this is to keep the label in sync with the entry */
& .folder-name-label { padding: 5px 7px }
& .edit-folder-button {
@extend %button;
padding: 0;
width: 36px;
height: 36px;
border-radius: 18px;
& > StIcon { icon-size: 16px }
}
}
& StButton#vhandle,
& StButton#vhandle:hover,
& StButton#vhandle:active { background-color: transparent; }
}
.app-folder-dialog-container {
padding: 12px;
width: 800px;
height: 600px;
}
.app-folder-icon {
padding: $base_padding;
spacing-rows: $base_spacing;
spacing-columns: $base_spacing;
}
// Running app indicator (also shown in dash)
.app-well-app-running-dot {
height: 5px;
width: 5px;
border-radius:5px;
background-color: $osd_fg_color;
margin-bottom: 1px;
}
// Rename popup for app folders
.rename-folder-popup {
.rename-folder-popup-item {
spacing: $base_spacing;
&:ltr, &:rtl { padding: 0 $base_padding * 2; }
}
}
// right-click app menu
.app-menu,
.app-well-menu {
max-width: 27.25em;
}
// App Grid pagination indicators
.page-indicator {
padding: 15px 20px;
.page-indicator-icon {
width: 10px;
height: 10px;
border-radius: 10px; // the same as height&width
background-color: white;
}
}
// Some hacks I don't even know
.all-apps,
.frequent-apps > StBoxLayout {
// horizontal padding to make sure scrollbars or dash don't overlap content
padding: 0px 88px 10px 88px;
}
// Label when no frequent apps
.no-frequent-applications-label { @extend %status_text; }
// shutdown and other actions in the grid
.system-action-icon {
background-color: rgba(0,0,0,0.8);
color: #fff;
border-radius: 99px;
icon-size: $app_icon_size * 0.5;
}
/* Frequent | All toggle */
// container
.app-view-controls {
padding-bottom: 32px;
}
// buttons
.app-view-control {
padding: 4px 32px;
margin: 0 4px;
&, &:hover, &:checked {
@include button(undecorated);
color: darken($osd_fg_color, 25%);
}
&:hover {
color: $osd_fg_color;
box-shadow: inset 0 -2px darken($osd_fg_color, 25%);
}
&:active {
box-shadow: inset 0 -2px $osd_fg_color;
}
&:checked {
color: $osd_fg_color;
box-shadow: inset 0 -2px $selected_bg_color;
}
&:first-child {
border-right-width: 0;
border-radius: 0;
}
&:last-child {
border-radius: 0;
}
}

View File

@@ -1,18 +0,0 @@
// Links
.shell-link {
color: $link_color;
&:hover {
color: lighten($link_color, 10%);
}
}
// Outline for low res icons
.lowres-icon {
icon-shadow: 0 1px 2px rgba(black, 0.3);
}
// Dropshadow for large icons
.icon-dropshadow {
icon-shadow: 0 1px 2px rgba(black, 0.4);
}

View File

@@ -1,5 +0,0 @@
/* Buttons */
.button {
@extend %button; // that's it
}

View File

@@ -1,255 +0,0 @@
/* Date/Time Menu */
.clock-display-box { spacing: $base_spacing; }
// overall menu
#calendarArea {
padding:0;
}
// Calendar menu side column
.datemenu-calendar-column {
spacing: $base_spacing;
border: 0 solid $bubble_borders_color;
padding: 0 $base_padding * 2;
&:ltr {margin-right: $base_margin * 2; border-left-width: 1px; }
&:rtl {margin-left: $base_margin * 2; border-right-width: 1px; }
.datemenu-displays-section {
}
.datemenu-displays-box {
spacing: $base_spacing;
}
}
.events-section-title {
@include notification_bubble($flat: true);
color: desaturate(darken($fg_color,40%), 10%);
font-weight: bold;
padding: .4em;
}
/* today button (the date) */
.datemenu-today-button {
@include notification_bubble($flat: true);
padding: $base_padding * 1.5;
// weekday label
.day-label {
@include fontsize($base_font_size+1);
font-weight: bold;
}
// date label
.date-label {
@include fontsize($base_font_size+7);
font-weight: 1000;
}
}
/* Calendar */
.calendar {
@include notification_bubble;
padding: $base_padding;
// month
.calendar-month-label {
color: lighten($fg_color,5%);
font-weight: bold;
padding: 8px 0;
&:focus {}
}
// prev/next month icons
.calendar-change-month-back StIcon,
.calendar-change-month-forward StIcon {
icon-size: $base_icon_size;
}
.pager-button {
background-color: transparent;
height: 32px;
width: 32px;
border-radius: $base_border_radius;
&:hover, &:focus { background-color: lighten($hover_bg_color, 5%); }
&:active { background-color: $active_bg_color; }
}
$calendar_day_size: 32px;
.calendar-day-base {
@include fontsize($base_font_size - 3);
text-align: center;
width: $calendar_day_size;
height: $calendar_day_size;
padding: 0;
margin: 2px;
border-radius: $calendar_day_size * 0.5 + 2px;
border: 1px solid transparent; //avoid jumparound due to today
font-feature-settings: "tnum";
&:hover, &:focus { background-color: $hover_bg_color; }
&:active,&:selected {
color: lighten($fg_color,10%);
background-color: darken($bg_color,5%);
}
// day of week heading
&.calendar-day-heading {
color: lighten($fg_color,10%);
margin-top: 1em;
@include fontsize($base_font_size - 4);
}
}
.calendar-day { //border collapse hack - see calendar.js
border-width: 0;
}
.calendar-day-top {
border-top-width: 1px;
}
.calendar-day-left {
border-left-width: 1px;
}
.calendar-work-day {}
.calendar-nonwork-day {
color: $insensitive_fg_color;
}
// Today
.calendar-today {
font-weight: bold;
border: 1px solid transparent;
background-color: $selected_bg_color;
color: $selected_fg_color;
&:hover,&:focus {
background-color:lighten($selected_bg_color, 3%);
color: $selected_fg_color;
}
&:active,&:selected {
background-color: $selected_bg_color;
color: $selected_fg_color;
&:hover,&:focus {
background-color:lighten($selected_bg_color, 3%);
color: $selected_fg_color;
}
}
}
.calendar-day-with-events {
color: lighten($fg_color,10%);
font-weight: bold;
background-image: url("resource:///org/gnome/shell/theme/calendar-today.svg");
}
.calendar-other-month-day {
color: transparentize($fg_color ,0.5);
}
.calendar-week-number {
@include fontsize($base_font_size - 4);
font-weight: bold;
height: 1.8em;
width: 2.3em;
border-radius: 2px;
padding: 0.5em 0 0;
margin: 6px;
background-color: darken($bg_color, 2%);
color: lighten($fg_color, 5%);
}
}
/* World clocks */
.world-clocks-button {
@include notification_bubble;
padding: $base_padding * 2;
.world-clocks-grid {
spacing-rows: $base_spacing;
spacing-columns: $base_spacing * 2;
}
// title
.world-clocks-header {
color: desaturate(darken($fg_color,40%), 10%);
font-weight: bold;
}
// city label
.world-clocks-city {
color: $fg_color;
@include fontsize($base_font_size);
font-weight: normal;
}
// timezone time
.world-clocks-time {
font-weight: bold;
color: $fg_color;
font-feature-settings: "lnum";
@include fontsize($base_font_size);
text-align: right;
}
// timezone offset label
.world-clocks-timezone {
color: darken($fg_color,20%);
font-feature-settings: "tnum";
@include fontsize($base_font_size - 1);
}
}
/* Weather */
.weather-button {
@include notification_bubble;
padding: $base_padding * 2;
.weather-box {
spacing: $base_spacing + $base_margin;
}
.weather-header-box {
spacing: $base_spacing;
}
.weather-header {
color: desaturate(darken($fg_color,40%), 10%);
font-weight: bold;
&.location {
font-weight: normal;
@include fontsize($base_font_size - 1);
}
}
.weather-grid {
spacing-rows: $base_spacing;
spacing-columns: $base_spacing * 2;
}
.weather-forecast-time {
color: darken($fg_color,30%);
font-feature-settings: "tnum";
@include fontsize($base_font_size - 2);
font-weight: normal;
padding-top: 0.2em;
padding-bottom: 0.4em;
}
.weather-forecast-icon {
icon-size: $base_icon_size * 2;
}
.weather-forecast-temp {
font-weight: bold;
}
}

View File

@@ -1,18 +0,0 @@
/* Check Boxes */
// these are equal to the size of the SVG assets
$check_height: 22px;
$check_width: 24px;
.check-box {
StBoxLayout { spacing: .8em; }
StBin {
width: $check_width;
height: $check_height;
background-image: url("resource:///org/gnome/shell/theme/checkbox-off.svg");
}
&:focus StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox-off-focused.svg"); }
&:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox.svg"); }
&:focus:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox-focused.svg"); }
}

View File

@@ -1,15 +0,0 @@
/* Activities Ripple */
$ripple_size: 50px;
.ripple-box {
background-color: lighten(transparentize($selected_bg_color, 0.7), 40%);
box-shadow: 0 0 2px 2px lighten($selected_bg_color, 20%);
// plus + 2px for the border (box-shadow)
width: $ripple_size + 2px;
height: $ripple_size + 2px;
border-radius: 0 0 $ripple_size + 2px 0; // radius equals the size of the box to give us the curve
// just a simple change to the border radius position
&:rtl { border-radius: 0 0 0 $ripple_size + 2px; }
}

View File

@@ -1,61 +0,0 @@
/* Dash */
$dash_placeholder_size: 32px;
$dash_spacing: $base_padding + 4px;
$dash_border_radius: $modal_radius * 1.5;
#dash {
@extend %overview_panel;
@include fontsize($base_font_size - 2);
padding: ($dash_spacing / 2) 0;
border-radius: 0 $dash_border_radius $dash_border_radius 0;
border-left-width: 0;
&:rtl {
border-radius: $dash_border_radius 0 0 $dash_border_radius;
border-right-width: 0;
}
.placeholder {
// background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
background-image:none;
background-size: contain;
height: $dash_placeholder_size;
}
.empty-dash-drop-target {
width: $dash_placeholder_size;
height: $dash_placeholder_size;
}
}
// Dash Items
.dash-item-container > StWidget {
padding: ($dash_spacing / 2) $dash_spacing;
}
// OSD Tooltip
.dash-label {
background-color: transparentize($osd_bg_color,0.05);
border-radius: $base_border_radius + 2px;
border:none;
box-shadow:0 0 0 1px $osd_outer_borders_color;
color: $osd_fg_color;
padding: $base_padding $base_padding + 2px;
text-align: center;
-x-offset: $base_margin * 2; // distance from the dash edge
}
// Show apps button
.show-apps {
@include overview-icon($osd_fg_color);
&:focus,
&:checked {
.overview-icon {
background-color: darken($osd_bg_color,10%);
color: $fg_color;
}
}
}

View File

@@ -1,168 +0,0 @@
/* Modal Dialogs */
.headline {
@include fontsize($base_font_size + 1);
}
.modal-dialog {
border-radius: $modal_radius;
@extend %bubble_panel;
.modal-dialog-content-box {
margin: 32px 40px;
spacing: 32px;
max-width: 28em;
}
.modal-dialog-linked-button {
@extend %bubble_button;
}
}
/* End Session Dialog */
.end-session-dialog {
width: 30em;
.end-session-dialog-battery-warning,
.dialog-list-title {
color: $warning_color;
}
}
/* Message Dialog */
.message-dialog-content {
spacing: 18px;
.message-dialog-title {
text-align: center;
font-size: 18pt;
font-weight: 800;
&.leightweight {
font-size: 13pt;
font-weight: 800;
}
}
.message-dialog-description { text-align: center; }
}
/* Dialog List */
.dialog-list {
spacing: 18px;
.dialog-list-title {
text-align: center;
font-weight: bold;
}
.dialog-list-scrollview { max-height: 200px; }
.dialog-list-box {
spacing: 1em;
.dialog-list-item {
spacing: 1em;
.dialog-list-item-title { font-weight: bold; }
.dialog-list-item-description {
color: darken($fg_color,5%);
@include fontsize($base_font_size - 1);
}
}
}
}
/* Run Dialog */
.run-dialog {
.modal-dialog-content-box {
margin-top: 24px;
margin-bottom: 14px;
}
.run-dialog-entry { width: 20em; }
.run-dialog-description {
@include fontsize($base_font_size - 1);
text-align: center;
color: darken($fg_color, 20%);
}
}
/* Password or Authentication Dialog */
.prompt-dialog {
width: 28em;
.modal-dialog-content-box {
margin-bottom: 24px;
}
}
.prompt-dialog-password-grid {
spacing-rows: 8px;
spacing-columns: 4px;
.prompt-dialog-password-entry {
width: auto;
// 4px (spacing) + 16px (spinner-width)
&:ltr { margin-left: 20px; }
&:rtl { margin-right: 20px; }
}
}
.prompt-dialog-password-layout {
spacing: 8px;
}
.prompt-dialog-password-entry {
width: 20em;
}
.prompt-dialog-error-label,
.prompt-dialog-info-label,
.prompt-dialog-null-label {
text-align: center;
@include fontsize($base_font_size - 1);
}
.prompt-dialog-error-label {
color: $warning_color;
}
/* Polkit Dialog */
.polkit-dialog-user-layout {
text-align: center;
spacing: 8px;
margin-bottom: 6px;
.polkit-dialog-user-icon {
border-radius: 99px;
background-size: contain;
}
.polkit-dialog-user-root-label { color: $warning_color; }
}
/* Audio selection dialog */
.audio-device-selection-dialog {
.modal-dialog-content-box { margin-bottom: 28px; }
.audio-selection-box { spacing: 20px; }
}
.audio-selection-device {
border: 1px solid $bubble_borders_color;
border-radius: 12px;
&:hover,&:focus { background-color: $hover_bg_color; }
&:active {
background-color: $selected_bg_color;
color: $selected_fg_color;
}
}
.audio-selection-device-box {
padding: 20px;
spacing: 20px;
}
.audio-selection-device-icon {
icon-size: $base_icon_size * 4;
}

View File

@@ -1,27 +0,0 @@
/* Entries */
StEntry {
border-radius: $base_border_radius;
padding: 8px;
border-width: 1px;
color: $fg_color;
@include entry(normal);
//&:hover { @include entry(hover);}
&:focus { @include entry(focus);}
&:insensitive { @include entry(insensitive);}
selection-background-color: $selected_bg_color;
selected-color: $selected_fg_color;
StIcon.capslock-warning {
icon-size: 16px;
warning-color: $warning_color;
padding: 0 4px;
}
StIcon.peek-password {
icon-size: $base_icon_size;
padding: 0 4px;
}
StLabel.hint-text {
margin-left: 2px;
color: transparentize($fg_color, 0.3);
}
}

View File

@@ -1,10 +0,0 @@
// hotplug
.hotplug-notification-item {
@extend %bubble_button;
}
.hotplug-notification-item-icon {
icon-size: 24px;
padding: 0 4px;
}

View File

@@ -1,35 +0,0 @@
// IBus Candidate Popup
.candidate-popup-boxpointer {
@extend .popup-menu-boxpointer;
}
.candidate-popup-content {
padding: 0.5em;
spacing: 0.3em;
}
.candidate-index {
padding: 0 0.5em 0 0;
color: darken($fg_color,10%);
}
.candidate-box {
padding: 0.3em 0.5em 0.3em 0.5em;
border-radius: $base_border_radius;
&:selected,&:hover { background-color: $selected_bg_color; color: $selected_fg_color; }
}
.candidate-page-button-box {
height: 2em;
.vertical & { padding-top: 0.5em; }
.horizontal & { padding-left: 0.5em; }
}
.candidate-page-button {
padding: 4px;
}
.candidate-page-button-previous { border-radius: $base_border_radius 0px 0px $base_border_radius; border-right-width: 0; }
.candidate-page-button-next { border-radius: 0px $base_border_radius $base_border_radius 0px; }
.candidate-page-button-icon { icon-size: 1em; }

View File

@@ -1,124 +0,0 @@
/* On-screen Keyboard */
$key_size: 1.2em;
$key_border_radius: $base_border_radius + 3px;
$key_bg_color: $bg_color;
// $default_key_bg_color: darken($key_bg_color, 4%);
$default_key_bg_color: if($variant=='light', darken($osd_bg_color, 11%), lighten($osd_bg_color, 2%));
// draw keys using button function
#keyboard {
background-color: transparentize(if($variant=='light', darken($bg_color, 5%), darken($bg_color, 8%)), 0.1);
box-shadow: inset 0 1px 0 0 $osd_outer_borders_color;
.page-indicator {
padding: $base_padding;
.page-indicator-icon {
width: 8px;
height: 8px;
}
}
}
// the container for individual keys
.key-container {
padding: $base_margin;
spacing: $base_margin;
}
// the keys
.keyboard-key {
@include button(normal, $c:$key_bg_color);
&:focus { @include button(focus);}
&:hover, &:checked { @include button(hover, $c: $key_bg_color);}
&:active { @include button(active, $c: $key_bg_color); }
@include fontsize($base_font_size + 5);
min-height: $key_size;
min-width: $key_size;
border-width: 1px;
border-style: solid;
border-radius: $key_border_radius;
&:grayed { //FIXMEy
background-color: darken($bg_color, 3%);
color: $osd_fg_color;
border-color: $osd_borders_color;
}
// non-character keys
&.default-key {
// size of the icon asset
background-size: 24px;
@include button(normal, $c:$default_key_bg_color);
&:hover, &:checked {@include button(hover, $c: $default_key_bg_color);}
&:active { @include button(active, $c: $default_key_bg_color);}
}
// enter key is suggested-action
&.enter-key {
background-image: url("resource:///org/gnome/shell/theme/key-enter.svg");
@include button(normal, $c:$selected_bg_color, $tc:$selected_fg_color);
&:hover, &:checked { @include button(hover, $c: lighten($selected_bg_color, 3%));}
&:active {@include button(active, $c: darken($selected_bg_color, 2%));}
}
// key assets
&.shift-key-lowercase {background-image: url("resource:///org/gnome/shell/theme/key-shift.svg");}
&.shift-key-uppercase {background-image: url("resource:///org/gnome/shell/theme/key-shift-uppercase.svg");}
&.shift-key-uppercase:latched {background-image: url("resource:///org/gnome/shell/theme/key-shift-latched-uppercase.svg");}
&.hide-key {background-image: url("resource:///org/gnome/shell/theme/key-hide.svg");}
&.layout-key {background-image: url("resource:///org/gnome/shell/theme/key-layout.svg");}
}
// long press on a key popup
.keyboard-subkeys {
color: $osd_fg_color;
-arrow-border-radius: $modal_radius;
-arrow-background-color: $osd_bg_color;
-arrow-border-width: 1px;
-arrow-border-color: lighten($osd_bg_color, 9%);
-arrow-base: 20px;
-arrow-rise: 10px;
-boxpointer-gap: $base_spacing;
.keyboard-key {
@include button(normal, $c:$key_bg_color);
&:focus { @include button(focus);}
&:hover, &:checked { @include button(hover, $c: $key_bg_color);}
&:active { @include button(active, $c: $key_bg_color); }
border-radius:$base_border_radius;
}
}
// emoji
.emoji-page {
.keyboard-key {
background-color: transparent;
border: none;
color: initial;
}
}
.emoji-panel {
.keyboard-key:latched {
border-color: lighten($selected_bg_color, 5%);
background-color: $selected_bg_color;
}
}
// suggestions
.word-suggestions {
@include fontsize($base_font_size + 3);
spacing: 12px;
min-height: 20pt;
}

View File

@@ -1,171 +0,0 @@
/* Login Dialog */
.login-dialog-banner-view {
padding-top: 24px;
max-width: 23em;
}
.login-dialog {
//reset
border: none;
background-color: transparent;
$_gdm_bg: lighten(#2e3436, 19%);
StEntry {
@if $variant=='dark' {
$_gdm_entry_bg: transparentize(lighten(desaturate(#241f31, 20%), 2%), 0.5);
background-color: $_gdm_entry_bg;
color: $osd_fg_color;
}
}
.modal-dialog-button-box { spacing: 3px; }
.modal-dialog-button {
padding: 4px 18px;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
background-color: $_gdm_bg;
border-color: $_gdm_bg;
color: $fg_color;
$_hover_c: lighten($_gdm_bg, 5%);
&:hover, &:focus {
background-color: $_hover_c;
border-color: $_hover_c;
}
&:active {
$_active_c: darken($_gdm_bg, 5%);
box-shadow: none;
background-color: $_active_c;
border-color: $_active_c;
}
&:insensitive {
@include button(insensitive);
border-color: darken($_gdm_bg, 5%);
background-color: darken($_gdm_bg, 5%);
color: transparentize($fg_color, 0.3);
}
&:default {
@include button(normal, $c:$selected_bg_color, $tc:$selected_fg_color);
border-color: $selected_bg_color;
&:hover, &:focus {
@include button(hover,$c:$selected_bg_color, $tc:$selected_fg_color);
$_def_hover_c: lighten($selected_bg_color, 5%);
background-color: $_def_hover_c;
border-color: $_def_hover_c;
}
&:active {
@include button(active,$c:$selected_bg_color, $tc:$selected_fg_color);
$_def_active_c: darken($selected_bg_color, 5%);
background-color: $_def_active_c;
border-color: $_def_active_c;
}
&:insensitive {
@include button(insensitive);
border-color: darken($selected_bg_color, 10%);
background-color: darken($selected_bg_color, 10%);
color: transparentize($selected_fg_color, 0.3);
}
}
}
.cancel-button,
.switch-user-button,
.login-dialog-session-list-button {
padding: 0;
border-radius: 99px;
width: $base_icon_size * 2;
height: $base_icon_size * 2;
border-color: transparentize($bg_color,0.7);
background-color: transparentize($bg_color,0.7);
StIcon { icon-size: $base_icon_size; }
}
.caps-lock-warning-label,
.login-dialog-message-warning {
color: $osd_fg_color;
}
}
.login-dialog-logo-bin { padding: 24px 0px; }
.login-dialog-banner { color: darken($osd_fg_color,10%); }
.login-dialog-button-box { width: 23em; spacing: 5px; }
.login-dialog-message { text-align: center; }
.login-dialog-message-hint { padding-top: 0; padding-bottom: 20px; }
.login-dialog-user-selection-box { padding: 100px 0px; }
.login-dialog-not-listed-label {
padding-left: 2px;
.login-dialog-not-listed-button:focus &,
.login-dialog-not-listed-button:hover & {
color: $osd_fg_color;
}
}
.login-dialog-not-listed-label {
@include fontsize($base_font_size - 1);
font-weight: bold;
color: darken($osd_fg_color,30%);
padding-top: 1em;
}
.login-dialog-user-list-view { -st-vfade-offset: 1em; }
.login-dialog-user-list {
spacing: 12px;
width: 23em;
&:expanded .login-dialog-user-list-item:selected { background-color: $selected_bg_color; color: $selected_fg_color; }
&:expanded .login-dialog-user-list-item:logged-in { border-right: 2px solid $selected_bg_color; }
}
.login-dialog-user-list-item {
border-radius: $base_border_radius + 4px;
padding: 6px;
color: darken($osd_fg_color,30%);
&:ltr .user-widget { padding-right: 1em; }
&:rtl .user-widget { padding-left: 1em; }
.login-dialog-timed-login-indicator {
height: 2px;
margin-top: 6px;
background-color: $osd_fg_color;
}
&:focus .login-dialog-timed-login-indicator { background-color: $selected_fg_color; }
}
.user-widget-label {
color: $osd_fg_color;
}
.user-widget.horizontal .user-widget-label {
@include fontsize($base_font_size + 2);
font-weight: bold;
text-align: left;
padding-left: 15px;
&:ltr { padding-left: 14px; }
&:rtl { padding-right: 14px; }
}
.user-widget.vertical .user-widget-label {
@include fontsize($base_font_size + 5);
text-align: center;
font-weight: normal;
padding-top: 16px;
}
.login-dialog-prompt-layout {
padding-top: 24px;
padding-bottom: 12px;
spacing: $base_spacing * 2;
width: 23em;
}
.login-dialog-prompt-entry {
width: 17.89em;
height: 1.5em;
}
.login-dialog-prompt-label {
color: darken($osd_fg_color, 20%);
@include fontsize($base_font_size + 1);
padding-top: 1em;
}

View File

@@ -1,97 +0,0 @@
/* Looking Glass */
// Dialog
#LookingGlassDialog {
background-color: $osd_bg_color;
spacing: $base_spacing;
padding: 4px;
border: 2px solid transparentize($osd_fg_color, 0.8);
border-top-width:0;
border-radius: 0 0 $base_border_radius $base_border_radius;
& > #Toolbar {
border: none;
border-radius: $base_border_radius;
background-color: darken($osd_bg_color, 10%);
}
.labels { spacing: $base_spacing; }
.notebook-tab {
-natural-hpadding: $base_padding * 2;
-minimum-hpadding: 6px;
font-weight: bold;
color: $fg_color;
transition-duration: 100ms;
padding-left: .3em;
padding-right: .3em;
&:hover {
color: white;
text-shadow: black 0px 2px 2px;
}
&:selected {
border-bottom-width: 2px;
border-color: lighten($selected_bg_color,5%);
color: white;
text-shadow: black 0px 2px 2px;
}
}
StBoxLayout#EvalBox { padding: 4px; spacing: $base_spacing; }
StBoxLayout#ResultsArea { spacing: $base_spacing; }
}
.lg-dialog {
StEntry {
selection-background-color: #bbbbbb;
selected-color: $osd_bg_color;
}
.shell-link {
color: #999999;
&:hover { color: #dddddd; }
}
}
.lg-completions-text {
font-size: .9em;
font-style: italic;
}
.lg-obj-inspector-title {
spacing: $base_spacing;
}
.lg-obj-inspector-button {
border: 1px solid gray;
padding: 4px;
border-radius: $base_border_radius;
&:hover { border: 1px solid #ffffff; }
}
// Extensions
#lookingGlassExtensions { padding: 4px; }
.lg-extensions-list {
padding: 4px;
spacing: 6px;
}
.lg-extension {
border: 1px solid $osd_borders_color;
border-radius: $base_border_radius;
padding: 4px;
}
.lg-extension-name {
font-weight: bold;
}
.lg-extension-meta {
spacing: 6px;
}
// Inspector
#LookingGlassPropertyInspector {
background: $osd_bg_color;
border: 1px solid $osd_borders_color;
border-radius: $base_border_radius;
padding: 6px;
}

View File

@@ -1,134 +0,0 @@
/* Message List */
// a.k.a. notifications in the menu
// main list
.message-list {
width: 31.5em;
padding: 0 $base_padding * 2;
.message-list-placeholder { spacing: 12px; }
}
.message-list-sections {
spacing: $base_spacing;
margin: 0 $base_margin * 4; // to account for scrollbar
}
.message-list-section,
.message-list-section-list {
spacing: $base_spacing;
}
// do-not-disturb + clear button
.message-list-controls {
margin: ($base_margin * 2) ($base_margin * 4) 0;
// NOTE: remove the padding if notification_bubble could remove margin for drop shadow
padding: $base_margin;
spacing: $base_spacing;
}
// message bubbles
.message {
@include notification_bubble;
// icon container
.message-icon-bin {
padding: ($base_padding * 3) 0 ($base_padding * 3) ($base_padding * 2);
&:rtl {
padding: ($base_padding * 3) ($base_padding * 2) ($base_padding * 3) 0;
}
// icon size and color
> StIcon {
icon-size: $base_icon_size*2; // 32px
-st-icon-style: symbolic;
}
// fallback
> .fallback-app-icon {
width: $base_icon_size;
height: $base_icon_size;
}
}
// content
.message-content {
padding: $base_padding + $base_margin * 2;
spacing: 4px;
}
// title
.message-title {
font-weight: bold;
}
// secondary container in title box
.message-secondary-bin {
padding: 0 $base_margin * 2;
// notification time stamp
> .event-time {
color: transparentize($fg_color, 0.5);
@include fontsize($base_font_size - 2);
text-align: right;
/* HACK: the label should be baseline-aligned with a 1em label, fake this with some bottom padding */
padding-bottom: 0.13em;
}
}
// close button
.message-close-button {
color: lighten($fg_color, 15%);
&:hover { color: if($variant=='light', lighten($fg_color, 30%), darken($fg_color, 10%)); }
&:active { color: if($variant=='light', lighten($fg_color, 40%), darken($fg_color, 20%)); }
}
// body
.message-body {
color: darken($fg_color, 10%);
}
}
// URLs in messages
.url-highlighter {
link-color: $link_color;
}
/* Media Controls */
.message-media-control {
padding: $base_padding * 2 $base_padding * 4;
color: darken($fg_color, 15%);
// uses $hover_bg_color since the media controls are in a notification_bubble
&:hover {
background-color: lighten($hover_bg_color, 5%);
color: $fg_color;
}
&:active {
background-color: darken($hover_bg_color, 2%);
color: $fg_color;
}
&:insensitive { color: darken($fg_color,40%); }
// fix border-radius for last button
&:last-child:ltr { border-radius: 0 $base_border_radius+2 $base_border_radius+2 0; }
&:last-child:rtl { border-radius: $base_border_radius+2 0 0 $base_border_radius+2; }
}
// album-art
.media-message-cover-icon {
icon-size: $base_icon_size*2 !important; // 48px
border-radius: $base_border_radius;
// when there is no artwork
&.fallback {
color: darken($fg_color, 17%);
background-color: $bg_color;
border: 1px solid transparent;
border-radius: $base_border_radius;
icon-size: $base_icon_size * 2 !important;
}
}

View File

@@ -1,45 +0,0 @@
// Rubberband for select-area screenshots
.select-area-rubberband {
background-color: transparentize($selected_bg_color,0.7);
border: 1px solid $selected_bg_color;
}
// User icon
.user-icon {
background-size: contain;
color: $osd_fg_color;
border-radius: 99px;
&:hover {
color: lighten($osd_fg_color,30%);
}
& StIcon {
background-color: transparentize($osd_fg_color,0.95);
padding: 18px 20px 22px 20px;
width: 88px; height: 88px;
border-radius: 99px;
}
}
.user-widget.vertical .user-icon {
icon-size: 128px;
}
.user-widget.horizontal .user-icon {
icon-size: 64px;
}
.lightbox { background-color: black; }
.flashspot { background-color: white; }
// Hidden
.hidden { color: rgba(0,0,0,0);}
// Caps-lock warning
.caps-lock-warning-label {
text-align: center;
padding-bottom: 8px;
@include fontsize($base_font_size - 1);
color: $warning_color;
}

View File

@@ -1,56 +0,0 @@
/* Network Dialogs */
.nm-dialog {
max-height: 34em;
min-height: 31em;
min-width: 32em;
}
.nm-dialog-content {
spacing: 20px;
padding: 24px;
}
.nm-dialog-airplane-box { spacing: 12px; }
.nm-dialog-airplane-headline {
font-weight: bold;
text-align: center;
}
.nm-dialog-airplane-text { color: $fg_color; }
// header
.nm-dialog-header {
font-weight: bold;
}
.nm-dialog-header-icon {
icon-size: $base_icon_size * 2;
}
.nm-dialog-header-hbox { spacing: 10px; }
// list of networks
.nm-dialog-scroll-view {
border: 1px solid $borders_color;
padding:0;
background-color: darken($bg_color, 3%);
}
// list item
.nm-dialog-item {
@include fontsize($base_font_size);
border-bottom: 1px solid $borders_color;
padding: $base_padding * 2;
spacing: 0px;
&:selected {
background-color: $selected_bg_color;
color: $selected_fg_color;
}
}
// icons in list
.nm-dialog-icon { icon-size: $base_icon_size; }
.nm-dialog-icons { spacing: $base_spacing * 2; }
// no networks
.no-networks-label { color: $insensitive_fg_color; }
.no-networks-box { spacing: $base_padding; }

View File

@@ -1,57 +0,0 @@
/* Notifications & Mesage Tray */
$notification_banner_height: 64px;
$notification_banner_width: 34em;
// Banner notifications
.notification-banner {
min-height: $notification_banner_height;
width: $notification_banner_width;
.notification-actions {
spacing: 0;
}
.notification-button {
@extend %bubble_button;
}
}
// counter
.summary-source-counter {
font-size: $base_font_size - 1pt;
font-weight: bold;
height: 1.6em;
width: 1.6em;
-shell-counter-overlap-x: 3px;
-shell-counter-overlap-y: 3px;
background-color: $selected_bg_color;
color: $selected_fg_color;
border: 2px solid $fg_color;
box-shadow: 0 2px 2px rgba(0,0,0,0.5);
border-radius: 0.9em; // should be 0.8 but whatever; wish I could do 50%;
}
// chat bubbles
.chat-body { spacing: 5px; }
.chat-response { margin: 5px; }
.chat-log-message { color: darken($fg_color,10%); }
.chat-new-group { padding-top: 1em; }
.chat-received {
padding-left: 4px;
&:rtl { padding-left: 0px; padding-right: 4px; }
}
.chat-sent {
padding-left: 18pt;
color: lighten($fg_color, 15%);
&:rtl { padding-left: 0; padding-right: 18pt; }
}
.chat-meta-message {
padding-left: 4px;
@include fontsize($base_font_size - 2);
font-weight: bold;
color: lighten($fg_color,18%);
&:rtl { padding-left: 0; padding-right: 4px; }
}

View File

@@ -1,45 +0,0 @@
/* OSD */
$osd_levelbar_height:8px;
.osd-window {
@extend %osd_panel;
text-align: center;
font-weight: bold;
spacing: $base_spacing * 2; // 12px
margin: $base_margin * 8; // 32px
min-width: 64px;
min-height: 64px;
StIcon {
icon-size:$base_icon_size * 6;
}
.osd-monitor-label { font-size: 3em; }
.level {
height: $osd_levelbar_height;
-barlevel-height: $osd_levelbar_height;
-barlevel-background-color: transparentize($osd_fg_color, if($variant=='light', 0.7, 0.9));
-barlevel-active-background-color: $osd_fg_color;
-barlevel-overdrive-color: $destructive_color;
-barlevel-overdrive-separator-width: 3px;
}
}
/* Pad OSD */
.pad-osd-window {
padding: 32px;
background-color: transparentize(#000, 0.2);
.pad-osd-title-box { spacing: 12px; }
.pad-osd-title-menu-box { spacing: 6px; }
}
.combo-box-label {
width: 15em;
}
.resize-popup {
@extend %osd_panel;
}

View File

@@ -1,10 +0,0 @@
/* OVERVIEW */
#overview {
spacing: 24px;
background-color: transparent;
}
.overview-controls {
padding-bottom: 32px;
}

View File

@@ -1,104 +0,0 @@
/* Top Bar */
// a.k.a. the panel
$panel_corner_radius: $base_border_radius+1;
$panel_bg_color: #000;
$panel_fg_color: #ccc;
$panel_height: 1.86em;
#panel {
background-color: $panel_bg_color;
font-weight: bold;
height: $panel_height;
font-feature-settings: "tnum";
// transparent panel on lock & login screens
&.unlock-screen,
&.login-screen {
background-color: transparent;
.panel-corner {
-panel-corner-radius: 0;
-panel-corner-background-color: transparent;
-panel-corner-border-color: transparent;
}
}
// spacing between activities, app menu and such
#panelLeft, #panelCenter {
spacing: $base_spacing;
}
// the rounded outset corners
.panel-corner {
-panel-corner-radius: $panel_corner_radius;
-panel-corner-background-color: $panel_bg_color;
-panel-corner-border-width: 2px;
-panel-corner-border-color: transparent;
&:active, &:overview, &:focus {
-panel-corner-border-color: lighten($selected_bg_color,5%);
}
}
// panel menus
.panel-button {
font-weight: bold;
color: $panel_fg_color;
-natural-hpadding: $base_padding * 2;
-minimum-hpadding: $base_padding;
&:hover {
color: lighten($panel_fg_color, 20%);
}
&:active, &:overview, &:focus, &:checked {
// Trick due to St limitations. It needs a background to draw a box-shadow
background-color: rgba(0, 0, 0, 0.01);
box-shadow: inset 0 -2px 0 0 lighten($selected_bg_color,5%);
color: lighten($panel_fg_color, 20%);
}
// status area icons
.system-status-icon {
icon-size: $base_icon_size;
padding: $base_padding - 1px;
}
// app menu icon
.app-menu-icon {
margin-left: $base_margin;
margin-right: $base_margin;
-st-icon-style: symbolic;
// dimensions of the icon are hardcoded
}
// lock & login screen styles
.unlock-screen &,
.login-screen & {
color: lighten($fg_color, 10%);
&:focus, &:hover, &:active { color: lighten($fg_color, 10%); }
}
}
.panel-status-indicators-box,
.panel-status-menu-box {
spacing: 2px;
}
// spacing between power icon and (optional) percentage label
.power-status.panel-status-indicators-box {
spacing: 0;
}
// indicator for active
.screencast-indicator,
.remote-access-indicator { color: $warning_color; }
}
// App Menu
#appMenu {
spacing: $base_spacing;
.label-shadow { color: transparent; }
}

View File

@@ -1,129 +0,0 @@
/* Popovers/Menus */
$popover_arrow_height: 12px;
//.the popover itself
.popup-menu-boxpointer {
-arrow-border-radius: $base_border_radius+4;
-arrow-background-color: $bg_color;
-arrow-border-width: 1px;
-arrow-border-color: $borders_color;
-arrow-base: $popover_arrow_height * 2;
-arrow-rise: $popover_arrow_height;
-arrow-box-shadow: 0 1px 3px rgba(0,0,0,0.5); // dreaming bugzilla #689995
}
// container of the popover menu
.popup-menu {
min-width: 15em;
color: $fg_color;
//.popup-status-menu-item { font-weight: normal; color: pink; } //dunno what that is
&.panel-menu {
-boxpointer-gap: $base_margin; // distance from the panel
margin-bottom: 1.75em;
}
}
.popup-menu-content {
padding: $base_padding * 2 + $base_margin 0;
}
// menu items
.popup-menu-item {
spacing: $base_padding;
padding: $base_padding;
&:ltr { padding-right:1.75em; padding-left: 0; }
&:rtl { padding-right: 0; padding-left:1.75em; }
&:checked {
background-color: lighten($bg_color, 2%);
box-shadow: none;
}
&.selected {
background-color: transparentize(white, if($variant=='light', 0.2, 0.9));
color: $fg_color;
}
&:active {
background-color: $selected_bg_color;
color: $selected_fg_color;
}
&:insensitive { color: transparentize($fg_color,0.5);}
}
// all icons and other graphical elements
.popup-inactive-menu-item {
color: $fg_color;
&:insensitive { color: transparentize($fg_color,0.5); }
}
// symbolic icons in popover
.popup-menu-arrow,
.popup-menu-icon { icon-size: $base_icon_size; }
// popover submenus
.popup-sub-menu {
background-color: darken($bg_color, 3%);
box-shadow: none;
border-top: 1px solid transparentize($borders_color, 0.2);
border-bottom: 1px solid transparentize($borders_color, 0.2);
}
// container for radio and check boxes
.popup-menu-ornament {
text-align: right;
width: 1.2em;
}
// separator
.popup-separator-menu-item {
padding: 0;
.popup-separator-menu-item-separator {
//-margin-horizontal: 24px;
height: 1px; //not really the whole box
margin: 6px 64px;
background-color: lighten($borders_color, 2%);
.popup-sub-menu & { //submenu separators
margin: 0 64px 0 32px;
@if $variant == 'dark' {
background-color: lighten($bg_color,10%);
}
}
}
}
// desktop background menu
.background-menu {
-boxpointer-gap: $base_margin;
-arrow-rise: 0px; // hide the beak on the menu
}
// system status menu
.aggregate-menu {
min-width: 21em;
// lock screen, shutdown, etc. buttons
.popup-menu-icon {
padding:0;
margin: 0 $base_margin;
-st-icon-style: symbolic;
}
.popup-sub-menu .popup-menu-item > :first-child {
// account for icons in submenus with padding
&:ltr {
padding-left: $base_padding + $base_margin * 2;
margin-left: $base_icon_size;
}
&:rtl {
padding-right: $base_padding + $base_margin * 2; ;
margin-right: $base_icon_size;
}
}
}

View File

@@ -1,78 +0,0 @@
/* Screen Shield */
.unlock-dialog-clock {
color: white;
font-weight: 300;
text-align: center;
spacing: 24px;
padding-bottom: 2.5em;
}
.unlock-dialog-clock-time {
font-size: 64pt;
padding-top: 42px;
font-feature-settings: "tnum";
}
.unlock-dialog-clock-date {
font-size: 16pt;
font-weight: normal;
}
.unlock-dialog-clock-hint {
font-weight: normal;
padding-top: 48px;
}
.unlock-dialog-notifications-container {
margin: 12px 0;
spacing: 6px;
width: 23em;
background-color: transparent;
.summary-notification-stack-scrollview {
padding-top: 0;
padding-bottom: 0;
}
.notification,
.unlock-dialog-notification-source {
padding: 12px 6px;
border: none;
background-color: transparentize($osd_bg_color,0.7);
color: $osd_fg_color;
border-radius: $modal_radius;
&.critical { background-color: transparentize($osd_bg_color,0.1) }
}
}
.unlock-dialog-notification-label {
padding: 0px 0px 0px 12px;
}
.unlock-dialog-notification-count-text {
weight: bold;
padding: 0 6px;
color: $osd_bg_color;
background-color: transparentize($osd_fg_color, 0.7);
border-radius: 99px;
margin-right: 12px;
}
.screen-shield-background { //just the shadow, really
background: black;
box-shadow: 0px 2px 4px rgba(0,0,0,0.6);
}
#lockDialogGroup {
background-color: lighten(#2e3436, 8%);
}
#unlockDialogNotifications {
StButton#vhandle, StButton#hhandle {
background-color: transparentize($bg_color,0.7);
&:hover, &:focus { background-color: transparentize($bg_color,0.5); }
&:active { background-color: transparentize($selected_bg_color,0.5); }
}
}

View File

@@ -1,29 +0,0 @@
/* Scrollbars */
StScrollView {
&.vfade { -st-vfade-offset: 68px; }
&.hfade { -st-hfade-offset: 68px; }
}
StScrollBar {
padding: 0;
StScrollView & {
min-width: 14px;
min-height: 14px;
}
StBin#trough {
border-radius: 0;
background-color: transparent;
}
StButton#vhandle, StButton#hhandle {
border-radius: 8px;
background-color: mix($fg_color, $bg_color, 60%);
//border: 3px solid transparent; //would be nice to margin or at least to transparent
margin: 3px;
&:hover { background-color: mix($fg_color, $bg_color, 80%); }
&:active { background-color: $selected_bg_color; }
}
}

View File

@@ -1,35 +0,0 @@
// Search entry
$search_entry_width: 320px;
$search_entry_height: 36px;
%search_entry,
.search-entry {
width: $search_entry_width;
padding: $base_padding+1 $base_padding+3;
border-radius: $search_entry_height * 0.5; // half the height
color: transparentize($fg_color,0.3);
background-color: $bg_color;
border-color: $borders_color;
&:hover {
background-color: $hover_bg_color;
border-color: $hover_borders_color;
color: $hover_fg_color;
}
&:focus {
padding: $base_padding $base_padding+2; // 1px less to account for wider border
border-width: 2px;
border-style: solid;
border-color: $selected_bg_color;
color: $fg_color;
box-shadow: inset 0 1px 2px 1px rgba(0,0,0,0.2);
}
.search-entry-icon {
icon-size: $base_icon_size;
padding: 0 4px;
color: inherit;
}
}

View File

@@ -1,104 +0,0 @@
/* Search */
// search overview container
#searchResultsContent {
max-width: 1024px;
spacing: $base_margin * 2;
}
// search results sections "the boxes"
.search-section {
// This should be equal to #searchResultsContent spacing
spacing: $base_margin * 2;
// separator
.search-section-separator {
// height: 1px;
// background-color: $osd_outer_borders_color;
height: 0;
background-color: transparent;
}
}
// content
.search-section-content {
background-color: transparentize(lighten($osd_bg_color, 5%), 0.2);
border-radius: $modal_radius+3;
border: 1px solid $osd_outer_borders_color;
box-shadow: 0 2px 4px 0 $shadow_color;
text-shadow: 0 1px if($variant == 'light', rgba(255,255,255,0.2), rgba(0,0,0,0.2));
color: $osd_fg_color;
padding: $base_padding * 3;
// This is the space between the provider icon and the results container
spacing: $base_margin * 2;
}
%search-section-content-item {
@extend %icon_tile;
&:focus,
&:hover,
&:selected {
background-color: transparentize($osd_fg_color, .9);
transition-duration: 200ms;
}
&:active,
&:checked {
background-color: transparentize(darken($osd_bg_color, 10%), .1);
}
}
// "no results" text
.search-statustext {
@extend %status_text;
}
// Search results with icons
.grid-search-result {
@extend %app-well-app;
}
// search result provider
.search-provider-icon {
@extend %search-section-content-item;
// content
.list-search-provider-content {
spacing: $base_spacing * 2;
// provider labels
.list-search-provider-details {
width: 120px;
margin-top: 0;
color: darken($osd_fg_color, 8%);
// font-weight: bold;
}
}
}
// search results list
.list-search-results {
spacing: $base_spacing;
}
// search result listitem
.list-search-result {
@extend %search-section-content-item;
// content
.list-search-result-content {
spacing: $base_padding;
}
// list item title (with leading icon)
.list-search-result-title {
spacing: $base_spacing * 2;
// font-weight: bold;
}
// list item description
.list-search-result-description {
color: darken($osd_fg_color, 30%);
}
}

View File

@@ -1,27 +0,0 @@
/* Slider */
$slider_size: 15px;
.slider {
height: $slider_size;
// slider trough
-barlevel-height: 3px; // has to be an odd number
-barlevel-background-color: $borders_color; //background of the trough
-barlevel-border-width: 1px;
-barlevel-border-color: $borders_color; // trough border color
// fill style
-barlevel-active-background-color: $selected_bg_color; //active trough fill
-barlevel-active-border-color: if($variant == 'light', darken($selected_bg_color, 4%), lighten($selected_bg_color, 2%)); //active trough border
// overfill style (red in this case)
-barlevel-overdrive-color: $destructive_color;
-barlevel-overdrive-border-color: if($variant == 'light', darken($destructive_color, 4%), lighten($destructive_color, 2%)); //trough border when red;
-barlevel-overdrive-separator-width:1px;
// slider hander
-slider-handle-radius: $slider_size * 0.5; // half the size of the size
-slider-handle-border-width: 1px;
-slider-handle-border-color: if($variant == 'light', $borders_color, $fg_color);
color: if($variant == 'light', lighten($bg_color, 10%), $fg_color);
&:hover { color: $hover_bg_color; }
&:active { color: $active_bg_color; }
}

View File

@@ -1,67 +0,0 @@
/* App Switcher */
.switcher-popup {
padding: 8px;
spacing: $base_spacing * 4;
}
// switcher onscreen panel
.switcher-list {
@extend %osd_panel;
.item-box {
padding: 8px;
border-radius: $base_border_radius + 1px;
border: 1px solid transparent;
&:outlined {
border: 1px solid darken($borders_color,5%);
background-color: transparentize($osd_fg_color, 0.9);
box-shadow: inset 0 2px 2px 0 rgba(0,0,0,0.4);
}
&:selected {
background-color: transparentize($osd_fg_color, 0.9);
color: $osd_fg_color;
}
}
// window thumbnails
.thumbnail-box {
padding: 2px;
spacing: $base_spacing;
}
.thumbnail {
width: 256px;
}
.separator {
width: 1px;
background: $borders_color;
}
.switcher-list-item-container {
spacing: $base_spacing * 2;
}
}
.switcher-arrow {
border-color: rgba(0,0,0,0);
color: transparentize($fg_color,0.2);
&:highlighted {
color: $fg_color;
}
}
// Input Source Switcher
.input-source-switcher-symbol {
font-size: 34pt;
width: 96px;
height: 96px;
}
// Window cycler highlight
.cycler-highlight {
border: 5px solid $selected_bg_color;
}

View File

@@ -1,16 +0,0 @@
/* Switches */
// these are equal to the size of the SVG assets
$switch_height: 22px;
$switch_width: 46px;
.toggle-switch {
color: $fg_color;
height: $switch_height;
width: $switch_width;
background-size: contain;
background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-off.svg"),url("resource:///org/gnome/shell/theme/toggle-off-dark.svg"));
&:checked {
background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-on.svg"),url("resource:///org/gnome/shell/theme/toggle-on-dark.svg"));
}
}

View File

@@ -1,19 +0,0 @@
/* Tiled window previews */
$tile_corner_radius: $base_border_radius + 1px;
.tile-preview {
background-color: transparentize($selected_bg_color,0.5);
border: 1px solid $selected_bg_color;
}
.tile-preview-left.on-primary {
border-radius: $tile_corner_radius 0 0 0;
}
.tile-preview-right.on-primary {
border-radius: 0 $tile_corner_radius 0 0;
}
.tile-preview-left.tile-preview-right.on-primary {
border-radius: $tile_corner_radius $tile_corner_radius 0 0;
}

View File

@@ -1,66 +0,0 @@
/* Window Picker */
$window_picker_spacing: $base_spacing * 2; // 16px
$window_picker_padding: $base_padding * 2; // 16px
$window_thumbnail_border_color:transparentize($selected_fg_color, 0.65);
$window_close_button_size: 24px;
$window_close_button_padding: 3px;
// Window picker
.window-picker {
// Space between window thumbnails
-horizontal-spacing: $window_picker_spacing;
-vertical-spacing: $window_picker_spacing;
// Padding for container around window thumbnails
padding: $window_picker_padding;
&.external-monitor { padding: $window_picker_padding; }
}
// Borders on window thumbnails
.window-clone-border {
border-width: 6px;
border-style: solid;
border-color: $window_thumbnail_border_color;
border-radius: $base_border_radius + 2;
// For window decorations with round corners we can't match
// the exact shape when the window is scaled. So apply a shadow
// to fix that case
box-shadow: inset 0 0 0 1px transparentize($borders_color, 0.8);
}
// Window titles
.window-caption {
color: $osd_fg_color;
background-color: $osd_bg_color;
border:1px solid $osd_outer_borders_color;
border-radius: $base_border_radius + 1;
padding: $base_padding $base_padding * 2;
font-weight: bold;
@include fontsize($base_font_size + 1);
}
// Close button
.window-close {
background-color: $selected_bg_color;
color: $selected_fg_color;
border: none;
border-radius: $window_close_button_size * 0.5 + $window_close_button_padding * 2;
padding: $window_close_button_padding;
height: $window_close_button_size;
width: $window_close_button_size;
box-shadow: -1px 1px 5px 0px rgba(0,0,0,0.5);
-shell-close-overlap: $window_close_button_size * 0.5;
&:hover {
background-color: lighten($selected_bg_color, 5%);
}
&:active {
background-color: darken($selected_bg_color, 5%);
}
}

View File

@@ -1,36 +0,0 @@
/* Workspace Switcher */
.workspace-switcher-group {
padding: $base_padding * 2;
}
.workspace-switcher-container {
@extend %osd_panel;
}
.workspace-switcher {
background: transparent;
border: none;
border-radius: 0;
padding: 0;
spacing: $base_spacing * 2;
}
.ws-switcher-box {
// background: transparent;
background: transparent;
height: 50px;
background-size: 32px;
border: 1px solid transparentize($osd_fg_color,0.9);
border-radius: $base_border_radius + 3px;
}
// active workspace in the switcher
.ws-switcher-active-up,
.ws-switcher-active-down,
.ws-switcher-active-left,
.ws-switcher-active-right {
background-color: $selected_bg_color;
border: 1px solid if($variant=='light', darken($selected_bg_color, 8%), lighten($selected_bg_color, 5%));
border-radius: $base_border_radius + 3px;
color: $selected_fg_color;
}

View File

@@ -1,32 +0,0 @@
/* Workspace pager */
// thumbnails in overview
.workspace-thumbnails {
@extend %overview_panel;
visible-width: 32px; //amount visible before hover
spacing: $base_spacing;
padding: $base_padding;
border-radius: $modal_radius 0 0 $modal_radius;
border-right-width: 0;
&:rtl {
border-radius: 0 $modal_radius $modal_radius 0;
border-left-width: 0;
}
// drag and drop indicator
.placeholder {
background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
background-size: contain;
height: 24px;
}
}
// selected indicator
.workspace-thumbnail-indicator {
border: 3px solid $selected_bg_color;
border-radius: 3px;
padding: 0px;
// background-color: transparentize($selected_bg_color, 0.9);
}

View File

@@ -59,5 +59,5 @@ custom_target(style + '.css',
install_data(theme_data, install_dir: themedir)
classic_override = '00_org.gnome.shell.extensions.classic.gschema.override'
install_data(classic_override, install_dir: schemadir)
classic_schema = 'org.gnome.shell.extensions.classic-overrides.gschema.xml'
install_data(classic_schema, install_dir: schemadir)

View File

@@ -0,0 +1,46 @@
<schemalist>
<schema id="org.gnome.shell.extensions.classic-overrides"
path="/org/gnome/shell/extensions/classic-overrides/"
gettext-domain="gnome-shell-extensions">
<key name="attach-modal-dialogs" type="b">
<default>true</default>
<summary>Attach modal dialog to the parent window</summary>
<description>
This key overrides the key in org.gnome.mutter when running
GNOME Shell.
</description>
</key>
<key name="button-layout" type="s">
<default>"appmenu:minimize,maximize,close"</default>
<summary>Arrangement of buttons on the titlebar</summary>
<description>
This key overrides the key in org.gnome.desktop.wm.preferences when running GNOME Shell.
</description>
</key>
<key name="edge-tiling" type="b">
<default>true</default>
<summary>Enable edge tiling when dropping windows on screen edges</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
<key name="workspaces-only-on-primary" type="b">
<default>true</default>
<summary>Workspaces only on primary monitor</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
<key name="focus-change-on-pointer-rest" type="b">
<default>true</default>
<summary>Delay focus changes in mouse mode until the pointer stops moving</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
</schema>
</schemalist>

147
debian/changelog vendored
View File

@@ -1,149 +1,14 @@
gnome-shell-extensions (3.35.91-1) experimental; urgency=medium
* New upstream release
- Fixes and adjustments to latest gnome-shell
-- Marco Trevisan (Treviño) <marco@ubuntu.com> Mon, 24 Feb 2020 18:29:29 +0000
gnome-shell-extensions (3.34.2-1) unstable; urgency=medium
* New upstream release
* debian/control.in: Bump Standards-Version to 4.4.1 (no further changes)
-- Laurent Bigonville <bigon@debian.org> Mon, 30 Dec 2019 00:51:13 +0100
gnome-shell-extensions (3.34.1-2) unstable; urgency=high
* New upstream release
- Fix GNOME Classic session's compatibility with gnome-setting-daemon 3.34
-- Jeremy Bicha <jbicha@debian.org> Tue, 08 Oct 2019 22:49:14 -0400
gnome-shell-extensions (3.34.0-2) unstable; urgency=medium
* Team upload.
* Upload to unstable.
-- Andreas Henriksson <andreas@fatal.se> Mon, 30 Sep 2019 17:27:38 +0200
gnome-shell-extensions (3.34.0-1) experimental; urgency=medium
* New upstream translation release
-- Iain Lane <laney@debian.org> Tue, 10 Sep 2019 10:59:31 +0100
gnome-shell-extensions (3.33.92-1) experimental; urgency=medium
* New upstream bugfix / translation releases
-- Iain Lane <laney@debian.org> Thu, 05 Sep 2019 18:22:14 +0100
gnome-shell-extensions (3.33.90-1) experimental; urgency=medium
[ Marco Trevisan (Treviño) ]
* New upstream release
+ window-list: Support showing windows from all workspaces
+ Make GNOME Classic more classic:
- Disable GNOME 3 overview
- Add window picker button to window list
- Style improvements and fixes
- Support horizontal workspace layout in window list
- Add draggable previews to window list workspace switcher
- Arrange workspaces horizontally
+ workspace-indicator: Support horizontal workspace layout
+ workspace-indicator: Add draggable previews
+ Fix windowsNavigator extension after ES6 port
+ screenshot-window-sizer: Add phone screenshot sizes
[ Iain Lane ]
* rules: Build all extensions via the upstream build system. We don't need
to hardcode the list to build, as the build system provides a way to build
'all' extensions.
* rules: Build with --fail-missing
* compat, control, rules: Move to compat 12 and specifying via build-deps
-- Iain Lane <laney@debian.org> Tue, 13 Aug 2019 11:59:22 +0100
gnome-shell-extensions (3.32.0-1) experimental; urgency=medium
* New upstream release
-- Iain Lane <laney@debian.org> Tue, 12 Mar 2019 16:34:14 +0000
gnome-shell-extensions (3.31.92-1) experimental; urgency=medium
* New upstream release
-- Iain Lane <laney@debian.org> Wed, 06 Mar 2019 15:40:48 +0000
gnome-shell-extensions (3.31.90-1) experimental; urgency=medium
* New upstream release
+ Misc. bug fixes and cleanups
+ Remove obsolete alternate-tab extension
+ Adjust to gnome-shell changes
* debian/watch: Watch for unstable releases
* rules: alternate-tab is dropped; stop trying to enable it
-- Iain Lane <laney@debian.org> Thu, 21 Feb 2019 10:33:12 +0000
gnome-shell-extensions (3.30.1-1) unstable; urgency=medium
gnome-shell-extensions (3.29.3+really3.28.1-1) unstable; urgency=medium
* Team upload
* New upstream release
* Bump Standards-Version to 4.2.1
* d/p/gnome-session-classic-wrapper-script.patch:
Re-word to avoid a Lintian warning
-- Simon McVittie <smcv@debian.org> Fri, 02 Nov 2018 09:26:47 +0000
gnome-shell-extensions (3.30.0-1) unstable; urgency=medium
* New upstream release
* Release to unstable
-- Jeremy Bicha <jbicha@debian.org> Wed, 05 Sep 2018 12:34:40 -0400
gnome-shell-extensions (3.29.91-1) experimental; urgency=medium
* Team upload
* New upstream development release
* Bump Standards-Version to 4.2.0
* Sort dependency lists (wrap-and-sort -a)
* d/copyright: Remove unnecessary sentence fragment
* d/p/series: Remove commented-out line
-- Simon McVittie <smcv@debian.org> Mon, 20 Aug 2018 20:27:57 +0100
gnome-shell-extensions (3.29.90-1) experimental; urgency=medium
* Team upload
* New upstream development release
-- Simon McVittie <smcv@debian.org> Thu, 02 Aug 2018 10:46:44 +0100
gnome-shell-extensions (3.29.3+really3.29.3-1) experimental; urgency=medium
* Team upload
* d/watch: Watch for development versions
* Re-upload to experimental with a higher version than
3.29.3+really3.28.1-1, which reverted the incorrect upload of the
previous version to unstable
-- Simon McVittie <smcv@debian.org> Fri, 27 Jul 2018 23:56:10 +0100
gnome-shell-extensions (3.29.3-1) unstable; urgency=medium
* Team upload
[ Arnaud Rebillout ]
* New upstream release
[ Simon McVittie ]
* Revert unintended upload of 3.29.3 to unstable
* d/gbp.conf: Use debian/unstable and upstream/3.28.x branches
* Bump Standards-Version to 4.1.5
* Set Rules-Requires-Root to no
* Hard-code compatible Shell versions for this branch since
${gnome:Version} doesn't understand the +really workaround
-- Simon McVittie <smcv@debian.org> Fri, 27 Jul 2018 09:37:34 +0100
-- Simon McVittie <smcv@debian.org> Fri, 27 Jul 2018 23:47:37 +0100
gnome-shell-extensions (3.28.1-1) unstable; urgency=medium

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
11

20
debian/control vendored
View File

@@ -6,32 +6,32 @@ Source: gnome-shell-extensions
Section: gnome
Priority: optional
Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
Uploaders: Iain Lane <laney@debian.org>, Jeremy Bicha <jbicha@debian.org>, Laurent Bigonville <bigon@debian.org>
Build-Depends: debhelper-compat (= 12),
dh-sequence-gnome,
Uploaders: Jeremy Bicha <jbicha@debian.org>, Michael Biebl <biebl@debian.org>
Build-Depends: debhelper (>= 11.1.3),
gnome-pkg-tools,
meson (>= 0.44.0),
sassc
Rules-Requires-Root: no
Standards-Version: 4.4.1
Standards-Version: 4.1.5
Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-shell-extensions
Vcs-Git: https://salsa.debian.org/gnome-team/gnome-shell-extensions.git
Homepage: https://wiki.gnome.org/Projects/GnomeShell/Extensions
Package: gnome-shell-extensions
Architecture: all
Depends: gir1.2-atk-1.0,
Depends: ${misc:Depends},
gnome-shell (>= 3.28),
gnome-shell (<< 3.29),
gir1.2-atk-1.0,
gir1.2-clutter-1.0,
gir1.2-gdkpixbuf-2.0,
gir1.2-glib-2.0,
gir1.2-gmenu-3.0,
gir1.2-gtk-3.0,
gir1.2-pango-1.0,
gnome-session-bin (>= 3.8),
gnome-settings-daemon (>= 3.24),
gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gvfs (>= 1.16.0),
${misc:Depends}
gnome-session-bin (>= 3.8),
gnome-settings-daemon (>= 3.24)
Recommends: gnome-tweaks
Replaces: gnome-shell-common (<< 3.18)
Breaks: gnome-shell-common (<< 3.18)

18
debian/control.in vendored
View File

@@ -3,31 +3,31 @@ Section: gnome
Priority: optional
Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
Uploaders: @GNOME_TEAM@
Build-Depends: debhelper-compat (= 12),
dh-sequence-gnome,
Build-Depends: debhelper (>= 11.1.3),
gnome-pkg-tools,
meson (>= 0.44.0),
sassc
Rules-Requires-Root: no
Standards-Version: 4.4.1
Standards-Version: 4.1.5
Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-shell-extensions
Vcs-Git: https://salsa.debian.org/gnome-team/gnome-shell-extensions.git
Homepage: https://wiki.gnome.org/Projects/GnomeShell/Extensions
Package: gnome-shell-extensions
Architecture: all
Depends: gir1.2-atk-1.0,
Depends: ${misc:Depends},
gnome-shell (>= 3.28),
gnome-shell (<< 3.29),
gir1.2-atk-1.0,
gir1.2-clutter-1.0,
gir1.2-gdkpixbuf-2.0,
gir1.2-glib-2.0,
gir1.2-gmenu-3.0,
gir1.2-gtk-3.0,
gir1.2-pango-1.0,
gnome-session-bin (>= 3.8),
gnome-settings-daemon (>= 3.24),
gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gvfs (>= 1.16.0),
${misc:Depends}
gnome-session-bin (>= 3.8),
gnome-settings-daemon (>= 3.24)
Recommends: gnome-tweaks
Replaces: gnome-shell-common (<< 3.18)
Breaks: gnome-shell-common (<< 3.18)

3
debian/copyright vendored
View File

@@ -24,5 +24,8 @@ License: GPL-2+
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, see
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".

13
debian/gbp.conf vendored
View File

@@ -1,14 +1,5 @@
[DEFAULT]
pristine-tar = True
debian-branch = debian/master
upstream-branch = upstream/latest
debian-branch = debian/unstable
upstream-branch = upstream/3.28.x
upstream-vcs-tag = %(version)s
[buildpackage]
sign-tags = True
[import-orig]
postimport = dch -v%(version)s New upstream release; git add debian/changelog; debcommit
[pq]
patch-numbers = False

View File

@@ -2,7 +2,7 @@ From: Michael Biebl <biebl@debian.org>
Date: Tue, 30 Jan 2018 09:04:03 +0000
Subject: Use a wrapper script to start GNOME classic session
Xsession currently doesn't allow passing more then one argument, as it
Xsession currently doesn't allow to pass more then one argument, as it
otherwise fails with
Xsession: unable to launch "gnome-session --session classic" X session ---
"gnome-session --session classic" not found; falling back to default session.

View File

@@ -1 +1,2 @@
#dont-require-nautilus-classic.patch
gnome-session-classic-wrapper-script.patch

15
debian/rules vendored
View File

@@ -1,12 +1,17 @@
#!/usr/bin/make -f
%:
dh $@
EXTENSIONS_ENABLED='alternate-tab, apps-menu, places-menu, \
launch-new-instance, window-list, \
drive-menu, screenshot-window-sizer, \
windowsNavigator, workspace-indicator, \
auto-move-windows, native-window-placement, user-theme'
override_dh_missing:
dh_missing --fail-missing
EXTENSIONS_DISABLED='example'
%:
dh $@ --with gnome
override_dh_auto_configure:
dh_auto_configure -- \
-Dextension_set=all \
-Denable_extensions=$(EXTENSIONS_ENABLED) \
-Dclassic_mode=true

2
debian/watch vendored
View File

@@ -1,3 +1,3 @@
version=4
https://download.gnome.org/sources/@PACKAGE@/([\d\.]+)/ \
https://download.gnome.org/sources/@PACKAGE@/([\d\.]+[02468])/ \
@PACKAGE@@ANY_VERSION@\.tar\.xz

View File

@@ -22,7 +22,6 @@ for f in $extensiondir/*; do
schema=$schemadir/org.gnome.shell.extensions.$name.gschema.xml
cp $srcdir/NEWS $srcdir/COPYING $f
cp -r $localedir $f
if [ -f $schema ]; then
mkdir $f/schemas

View File

@@ -0,0 +1,62 @@
/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const AltTab = imports.ui.altTab;
const Main = imports.ui.main;
const WindowManager = imports.ui.windowManager;
let injections = {};
function init(metadata) {
}
function setKeybinding(name, func) {
Main.wm.setCustomKeybindingHandler(name, Shell.ActionMode.NORMAL, func);
}
function enable() {
injections['_keyPressHandler'] = AltTab.WindowSwitcherPopup.prototype._keyPressHandler;
AltTab.WindowSwitcherPopup.prototype._keyPressHandler = function(keysym, action) {
switch(action) {
case Meta.KeyBindingAction.SWITCH_APPLICATIONS:
action = Meta.KeyBindingAction.SWITCH_WINDOWS;
break;
case Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD:
action = Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD;
break;
}
return injections['_keyPressHandler'].call(this, keysym, action);
};
Main.wm._forcedWindowSwitcher = function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.WindowSwitcherPopup();
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
tabPopup.destroy();
};
setKeybinding('switch-applications',
Main.wm._forcedWindowSwitcher.bind(Main.wm));
setKeybinding('switch-applications-backward',
Main.wm._forcedWindowSwitcher.bind(Main.wm));
}
function disable() {
var prop;
setKeybinding('switch-applications',
Main.wm._startSwitcher.bind(Main.wm));
setKeybinding('switch-applications-backward',
Main.wm._startSwitcher.bind(Main.wm));
for (prop in injections)
AltTab.WindowSwitcherPopup.prototype[prop] = injections[prop];
delete Main.wm._forcedWindowSwitcher;
}

View File

@@ -3,3 +3,5 @@ extension_data += configure_file(
output: metadata_name,
configuration: metadata_conf
)
extension_sources += files('prefs.js')

View File

@@ -0,0 +1,11 @@
{
"extension-id": "@extension_id@",
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "AlternateTab",
"description": "Substitute Alt-Tab with a window based switcher that does not group by application.\nThis extension is part of Classic Mode and is officially supported by GNOME. Please do not report bugs using the form below, use GNOME's GitLab instance instead.",
"original-authors": [ "jw@bargsten.org", "thomas.bouffon@gmail.com" ],
"shell-version": [ "@shell_current@" ],
"url": "@url@"
}

View File

@@ -0,0 +1,81 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const GObject = imports.gi.GObject;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = e => e;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const SETTINGS_APP_ICON_MODE = 'app-icon-mode';
const SETTINGS_CURRENT_WORKSPACE_ONLY = 'current-workspace-only';
const MODES = {
'thumbnail-only': N_("Thumbnail only"),
'app-icon-only': N_("Application icon only"),
'both': N_("Thumbnail and application icon"),
};
const AltTabSettingsWidget = GObject.registerClass(
class AltTabSettingsWidget extends Gtk.Grid {
_init(params) {
super._init(params);
this.margin = 24;
this.row_spacing = 6;
this.orientation = Gtk.Orientation.VERTICAL;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
let presentLabel = '<b>' + _("Present windows as") + '</b>';
this.add(new Gtk.Label({ label: presentLabel, use_markup: true,
halign: Gtk.Align.START }));
let align = new Gtk.Alignment({ left_padding: 12 });
this.add(align);
let grid = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
row_spacing: 6,
column_spacing: 6 });
align.add(grid);
let radio = null;
let currentMode = this._settings.get_string(SETTINGS_APP_ICON_MODE);
for (let mode in MODES) {
// copy the mode variable because it has function scope, not block scope
// so cannot be used in a closure
let modeCapture = mode;
let name = Gettext.gettext(MODES[mode]);
radio = new Gtk.RadioButton({ group: radio, label: name, valign: Gtk.Align.START });
radio.connect('toggled', widget => {
if (widget.active)
this._settings.set_string(SETTINGS_APP_ICON_MODE, modeCapture);
});
grid.add(radio);
if (mode == currentMode)
radio.active = true;
}
let check = new Gtk.CheckButton({ label: _("Show only windows in the current workspace"),
margin_top: 6 });
this._settings.bind(SETTINGS_CURRENT_WORKSPACE_ONLY, check, 'active', Gio.SettingsBindFlags.DEFAULT);
this.add(check);
}
});
function init() {
Convenience.initTranslations();
}
function buildPrefsWidget() {
let widget = new AltTabSettingsWidget();
widget.show_all();
return widget;
}

View File

@@ -1,20 +1,28 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported init enable disable */
const {
Atk, Clutter, Gio, GLib, GMenu, GObject, Gtk, Meta, Shell, St,
} = imports.gi;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const DND = imports.ui.dnd;
const ExtensionUtils = imports.misc.extensionUtils;
const GMenu = imports.gi.GMenu;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Clutter = imports.gi.Clutter;
const Main = imports.ui.main;
const Meta = imports.gi.Meta;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Gtk = imports.gi.Gtk;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Signals = imports.signals;
const Pango = imports.gi.Pango;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const appSys = Shell.AppSystem.get_default();
const APPLICATION_ICON_SIZE = 32;
@@ -22,53 +30,65 @@ const HORIZ_FACTOR = 5;
const MENU_HEIGHT_OFFSET = 132;
const NAVIGATION_REGION_OVERSHOOT = 50;
Gio._promisify(Gio._LocalFilePrototype, 'query_info_async', 'query_info_finish');
Gio._promisify(Gio._LocalFilePrototype, 'set_attributes_async', 'set_attributes_finish');
class ActivitiesMenuItem extends PopupMenu.PopupBaseMenuItem {
constructor(button) {
super();
this._button = button;
this.actor.add_child(new St.Label({ text: _("Activities Overview") }));
}
activate(event) {
this._button.menu.toggle();
Main.overview.toggle();
super.activate(event);
}
};
var ApplicationMenuItem = GObject.registerClass(
class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(button, app) {
super._init();
constructor(button, app) {
super();
this._app = app;
this._button = button;
this._iconBin = new St.Bin();
this.add_child(this._iconBin);
this.actor.add_child(this._iconBin);
let appLabel = new St.Label({
text: app.get_name(),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
this.add_child(appLabel);
this.label_actor = appLabel;
let appLabel = new St.Label({ text: app.get_name(), y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this.actor.add_child(appLabel);
this.actor.label_actor = appLabel;
let textureCache = St.TextureCache.get_default();
let iconThemeChangedId = textureCache.connect('icon-theme-changed',
this._updateIcon.bind(this));
this.connect('destroy', () => {
this._updateIcon.bind(this));
this.actor.connect('destroy', () => {
textureCache.disconnect(iconThemeChangedId);
});
this._updateIcon();
this._delegate = this;
let draggable = DND.makeDraggable(this);
this.actor._delegate = this;
let draggable = DND.makeDraggable(this.actor);
let maybeStartDrag = draggable._maybeStartDrag;
draggable._maybeStartDrag = event => {
draggable._maybeStartDrag = (event) => {
if (this._dragEnabled)
return maybeStartDrag.call(draggable, event);
return false;
};
draggable.connect('drag-begin', () => {
Shell.util_set_hidden_from_pick(Main.legacyTray.actor, true);
});
draggable.connect('drag-end', () => {
Shell.util_set_hidden_from_pick(Main.legacyTray.actor, false);
});
}
activate(event) {
this._app.open_new_window(-1);
this._button.selectCategory(null);
this._button.selectCategory(null, null);
this._button.menu.toggle();
super.activate(event);
Main.overview.hide();
}
setActive(active, params) {
@@ -77,8 +97,8 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
super.setActive(active, params);
}
setDragEnabled(enabled) {
this._dragEnabled = enabled;
setDragEnabled(enable) {
this._dragEnabled = enable;
}
getDragActor() {
@@ -90,16 +110,13 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
}
_updateIcon() {
let icon = this.getDragActor();
icon.style_class = 'icon-dropshadow';
this._iconBin.set_child(icon);
this._iconBin.set_child(this.getDragActor());
}
});
};
var CategoryMenuItem = GObject.registerClass(
class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(button, category) {
super._init();
constructor(button, category) {
super();
this._category = category;
this._button = button;
@@ -110,23 +127,22 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
if (this._category)
name = this._category.get_name();
else
name = _('Favorites');
name = _("Favorites");
this.add_child(new St.Label({ text: name }));
this.connect('motion-event', this._onMotionEvent.bind(this));
this.connect('notify::active', this._onActiveChanged.bind(this));
this.actor.add_child(new St.Label({ text: name }));
this.actor.connect('motion-event', this._onMotionEvent.bind(this));
}
activate(event) {
this._button.selectCategory(this._category);
this._button.selectCategory(this._category, this);
this._button.scrollToCatButton(this);
super.activate(event);
}
_isNavigatingSubmenu([x, y]) {
let [posX, posY] = this.get_transformed_position();
let [posX, posY] = this.actor.get_transformed_position();
if (this._oldX === -1) {
if (this._oldX == -1) {
this._oldX = x;
this._oldY = y;
return true;
@@ -139,11 +155,11 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
this._oldY = y;
// If it lies outside the x-coordinates then it is definitely outside.
if (posX > x || posX + this.width < x)
if (posX > x || posX + this.actor.width < x)
return false;
// If it lies inside the menu item then it is definitely inside.
if (posY <= y && posY + this.height >= y)
if (posY <= y && posY + this.actor.height >= y)
return true;
// We want the keep-up triangle only if the movement is more
@@ -164,38 +180,37 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
// only check for triangle ABC.
if (posY > y) {
let offset = posY - y;
y = posY + this.height + offset;
y = posY + this.actor.height + offset;
}
// Ensure that A is (0, 0).
x -= posX;
y -= posY + this.height;
y -= posY + this.actor.height;
// Check which side of line AB the point P lies on by taking the
// cross-product of AB and AP. See:
// http://stackoverflow.com/questions/3461453/determine-which-side-of-a-line-a-point-lies
if (this.width * y - NAVIGATION_REGION_OVERSHOOT * x <= 0)
return true;
if (((this.actor.width * y) - (NAVIGATION_REGION_OVERSHOOT * x)) <= 0)
return true;
return false;
}
_onMotionEvent(actor, event) {
let device = event.get_device();
if (!device.get_grabbed_actor()) {
if (!Clutter.get_pointer_grab()) {
this._oldX = -1;
this._oldY = -1;
device.grab(this);
Clutter.grab_pointer(this.actor);
}
this.hover = true;
this.actor.hover = true;
if (this._isNavigatingSubmenu(event.get_coords()))
return true;
this._oldX = -1;
this._oldY = -1;
this.hover = false;
device.ungrab();
this.actor.hover = false;
Clutter.ungrab_pointer();
let source = event.get_source();
if (source instanceof St.Widget)
@@ -204,14 +219,14 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
return false;
}
_onActiveChanged() {
if (!this.active)
return;
this._button.selectCategory(this._category);
this._button.scrollToCatButton(this);
setActive(active, params) {
if (active) {
this._button.selectCategory(this._category, this);
this._button.scrollToCatButton(this);
}
super.setActive(active, params);
}
});
};
class ApplicationsMenu extends PopupMenu.PopupMenu {
constructor(sourceActor, arrowAlignment, arrowSide, button) {
@@ -223,12 +238,31 @@ class ApplicationsMenu extends PopupMenu.PopupMenu {
return false;
}
open(animate) {
this._button.hotCorner.setBarrierSize(0);
if (this._button.hotCorner.actor) // fallback corner
this._button.hotCorner.actor.hide();
super.open(animate);
}
close(animate) {
let size = Main.layoutManager.panelBox.height;
this._button.hotCorner.setBarrierSize(size);
if (this._button.hotCorner.actor) // fallback corner
this._button.hotCorner.actor.show();
super.close(animate);
}
toggle() {
if (this.isOpen)
this._button.selectCategory(null);
if (this.isOpen) {
this._button.selectCategory(null, null);
} else {
if (Main.overview.visible)
Main.overview.hide();
}
super.toggle();
}
}
};
class DesktopTarget {
constructor() {
@@ -237,7 +271,7 @@ class DesktopTarget {
this._windowAddedId =
global.window_group.connect('actor-added',
this._onWindowAdded.bind(this));
this._onWindowAdded.bind(this));
global.get_window_actors().forEach(a => {
this._onWindowAdded(a.get_parent(), a);
@@ -245,14 +279,14 @@ class DesktopTarget {
}
get hasDesktop() {
return this._desktop !== null;
return this._desktop != null;
}
_onWindowAdded(group, actor) {
if (!(actor instanceof Meta.WindowActor))
return;
if (actor.meta_window.get_window_type() === Meta.WindowType.DESKTOP)
if (actor.meta_window.get_window_type() == Meta.WindowType.DESKTOP)
this._setDesktop(actor);
}
@@ -281,32 +315,48 @@ class DesktopTarget {
return source._app.app_info;
}
async _markTrusted(file) {
_touchFile(file) {
let queryFlags = Gio.FileQueryInfoFlags.NONE;
let ioPriority = GLib.PRIORITY_DEFAULT;
let info = new Gio.FileInfo();
info.set_attribute_uint64(Gio.FILE_ATTRIBUTE_TIME_ACCESS,
GLib.get_real_time());
file.set_attributes_async (info, queryFlags, ioPriority, null,
(o, res) => {
try {
o.set_attributes_finish(res);
} catch(e) {
log('Failed to update access time: ' + e.message);
}
});
}
_markTrusted(file) {
let modeAttr = Gio.FILE_ATTRIBUTE_UNIX_MODE;
let trustedAttr = 'metadata::trusted';
let queryFlags = Gio.FileQueryInfoFlags.NONE;
let ioPriority = GLib.PRIORITY_DEFAULT;
try {
let info = await file.query_info_async(modeAttr, queryFlags, ioPriority, null);
file.query_info_async(modeAttr, queryFlags, ioPriority, null,
(o, res) => {
try {
let info = o.query_info_finish(res);
let mode = info.get_attribute_uint32(modeAttr) | 0o100;
let mode = info.get_attribute_uint32(modeAttr) | 0o100;
info.set_attribute_uint32(modeAttr, mode);
info.set_attribute_string(trustedAttr, 'yes');
await file.set_attributes_async(info, queryFlags, ioPriority, null);
info.set_attribute_uint32(modeAttr, mode);
info.set_attribute_string(trustedAttr, 'yes');
file.set_attributes_async (info, queryFlags, ioPriority, null,
(o, res) => {
o.set_attributes_finish(res);
// Hack: force nautilus to reload file info
info = new Gio.FileInfo();
info.set_attribute_uint64(
Gio.FILE_ATTRIBUTE_TIME_ACCESS, GLib.get_real_time());
try {
await file.set_attributes_async(info, queryFlags, ioPriority, null);
} catch (e) {
log(`Failed to update access time: ${e.message}`);
}
} catch (e) {
log(`Failed to mark file as trusted: ${e.message}`);
}
// Hack: force nautilus to reload file info
this._touchFile(file);
});
} catch(e) {
log('Failed to mark file as trusted: ' + e.message);
}
});
}
destroy() {
@@ -317,7 +367,7 @@ class DesktopTarget {
this._setDesktop(null);
}
handleDragOver(source, _actor, _x, _y, _time) {
handleDragOver(source, actor, x, y, time) {
let appInfo = this._getSourceAppInfo(source);
if (!appInfo)
return DND.DragMotionResult.CONTINUE;
@@ -325,7 +375,7 @@ class DesktopTarget {
return DND.DragMotionResult.COPY_DROP;
}
acceptDrop(source, _actor, _x, _y, _time) {
acceptDrop(source, actor, x, y, time) {
let appInfo = this._getSourceAppInfo(source);
if (!appInfo)
return false;
@@ -341,50 +391,50 @@ class DesktopTarget {
// copy_async() isn't introspectable :-(
src.copy(dst, Gio.FileCopyFlags.OVERWRITE, null, null);
this._markTrusted(dst);
} catch (e) {
log(`Failed to copy to desktop: ${e.message}`);
} catch(e) {
log('Failed to copy to desktop: ' + e.message);
}
return true;
}
}
};
Signals.addSignalMethods(DesktopTarget.prototype);
let ApplicationsButton = GObject.registerClass(
class ApplicationsButton extends PanelMenu.Button {
_init() {
super._init(1.0, null, false);
constructor() {
super(1.0, null, false);
this.setMenu(new ApplicationsMenu(this, 1.0, St.Side.TOP, this));
this.setMenu(new ApplicationsMenu(this.actor, 1.0, St.Side.TOP, this));
Main.panel.menuManager.addMenu(this.menu);
// At this moment applications menu is not keyboard navigable at
// all (so not accessible), so it doesn't make sense to set as
// role ATK_ROLE_MENU like other elements of the panel.
this.accessible_role = Atk.Role.LABEL;
this.actor.accessible_role = Atk.Role.LABEL;
let hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
this._label = new St.Label({
text: _('Applications'),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
this._label = new St.Label({ text: _("Applications"),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
hbox.add_child(this._label);
hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.add_actor(hbox);
this.name = 'panelApplications';
this.label_actor = this._label;
this.actor.add_actor(hbox);
this.actor.name = 'panelApplications';
this.actor.label_actor = this._label;
this.actor.connect('captured-event', this._onCapturedEvent.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._showingId = Main.overview.connect('showing', () => {
this.add_accessible_state(Atk.StateType.CHECKED);
this.actor.add_accessible_state (Atk.StateType.CHECKED);
});
this._hidingId = Main.overview.connect('hiding', () => {
this.remove_accessible_state(Atk.StateType.CHECKED);
this.actor.remove_accessible_state (Atk.StateType.CHECKED);
});
Main.layoutManager.connect('startup-complete',
this._setKeybinding.bind(this));
this._setKeybinding.bind(this));
this._setKeybinding();
this._desktopTarget = new DesktopTarget();
@@ -399,14 +449,14 @@ class ApplicationsButton extends PanelMenu.Button {
this._tree = new GMenu.Tree({ menu_basename: 'applications.menu' });
this._treeChangedId = this._tree.connect('changed',
this._onTreeChanged.bind(this));
this._onTreeChanged.bind(this));
this._applicationsButtons = new Map();
this.reloadFlag = false;
this._createLayout();
this._display();
this._installedChangedId = appSys.connect('installed-changed',
this._onTreeChanged.bind(this));
this._onTreeChanged.bind(this));
}
_onTreeChanged() {
@@ -418,18 +468,18 @@ class ApplicationsButton extends PanelMenu.Button {
}
}
get hotCorner() {
return Main.layoutManager.hotCorners[Main.layoutManager.primaryIndex];
}
_createVertSeparator() {
let separator = new St.DrawingArea({
style_class: 'calendar-vertical-separator',
pseudo_class: 'highlighted',
});
let separator = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
pseudo_class: 'highlighted' });
separator.connect('repaint', this._onVertSepRepaint.bind(this));
return separator;
}
_onDestroy() {
super._onDestroy();
Main.overview.disconnect(this._showingId);
Main.overview.disconnect(this._hidingId);
appSys.disconnect(this._installedChangedId);
@@ -437,19 +487,28 @@ class ApplicationsButton extends PanelMenu.Button {
this._tree = null;
Main.wm.setCustomKeybindingHandler('panel-main-menu',
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
Main.sessionMode.hasOverview
? Main.overview.toggle.bind(Main.overview)
: null);
Shell.ActionMode.NORMAL |
Shell.ActionMode.OVERVIEW,
Main.sessionMode.hasOverview ?
Main.overview.toggle.bind(Main.overview) :
null);
this._desktopTarget.destroy();
}
_onCapturedEvent(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
if (!Main.overview.shouldToggleByCornerOrButton())
return true;
}
return false;
}
_onMenuKeyPress(actor, event) {
let symbol = event.get_key_symbol();
if (symbol === Clutter.KEY_Left || symbol === Clutter.KEY_Right) {
let direction = symbol === Clutter.KEY_Left
? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
let direction = symbol == Clutter.KEY_Left ? Gtk.DirectionType.LEFT
: Gtk.DirectionType.RIGHT;
if (this.menu.actor.navigate_focus(global.stage.key_focus, direction, false))
return true;
}
@@ -462,7 +521,7 @@ class ApplicationsButton extends PanelMenu.Button {
let [width, height] = area.get_surface_size();
let stippleColor = themeNode.get_color('-stipple-color');
let stippleWidth = themeNode.get_length('-stipple-width');
let x = Math.floor(width / 2) + 0.5;
let x = Math.floor(width/2) + 0.5;
cr.moveTo(x, 0);
cr.lineTo(x, height);
Clutter.cairo_set_source_color(cr, stippleColor);
@@ -472,20 +531,21 @@ class ApplicationsButton extends PanelMenu.Button {
}
_onOpenStateChanged(menu, open) {
if (open) {
if (this.reloadFlag) {
this._redisplay();
this.reloadFlag = false;
}
this.mainBox.show();
}
super._onOpenStateChanged(menu, open);
if (open) {
if (this.reloadFlag) {
this._redisplay();
this.reloadFlag = false;
}
this.mainBox.show();
}
super._onOpenStateChanged(menu, open);
}
_setKeybinding() {
Main.wm.setCustomKeybindingHandler('panel-main-menu',
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
() => this.menu.toggle());
Shell.ActionMode.NORMAL |
Shell.ActionMode.OVERVIEW,
() => { this.menu.toggle(); });
}
_redisplay() {
@@ -497,13 +557,13 @@ class ApplicationsButton extends PanelMenu.Button {
_loadCategory(categoryId, dir) {
let iter = dir.iter();
let nextType;
while ((nextType = iter.next()) !== GMenu.TreeItemType.INVALID) {
if (nextType === GMenu.TreeItemType.ENTRY) {
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
if (nextType == GMenu.TreeItemType.ENTRY) {
let entry = iter.get_entry();
let id;
try {
id = entry.get_desktop_file_id(); // catch non-UTF8 filenames
} catch (e) {
} catch(e) {
continue;
}
let app = appSys.lookup_app(id);
@@ -511,9 +571,9 @@ class ApplicationsButton extends PanelMenu.Button {
app = new Shell.App({ app_info: entry.get_app_info() });
if (app.get_app_info().should_show())
this.applicationsByCategory[categoryId].push(app);
} else if (nextType === GMenu.TreeItemType.SEPARATOR) {
} else if (nextType == GMenu.TreeItemType.SEPARATOR) {
this.applicationsByCategory[categoryId].push('separator');
} else if (nextType === GMenu.TreeItemType.DIRECTORY) {
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
let subdir = iter.get_directory();
if (!subdir.get_is_nodisplay())
this._loadCategory(categoryId, subdir);
@@ -526,13 +586,13 @@ class ApplicationsButton extends PanelMenu.Button {
let appsScrollBoxAlloc = this.applicationsScrollBox.get_allocation_box();
let currentScrollValue = appsScrollBoxAdj.get_value();
let boxHeight = appsScrollBoxAlloc.y2 - appsScrollBoxAlloc.y1;
let buttonAlloc = button.get_allocation_box();
let buttonAlloc = button.actor.get_allocation_box();
let newScrollValue = currentScrollValue;
if (currentScrollValue > buttonAlloc.y1 - 10)
newScrollValue = buttonAlloc.y1 - 10;
if (boxHeight + currentScrollValue < buttonAlloc.y2 + 10)
newScrollValue = buttonAlloc.y2 - boxHeight + 10;
if (newScrollValue !== currentScrollValue)
if (newScrollValue != currentScrollValue)
appsScrollBoxAdj.set_value(newScrollValue);
}
@@ -541,13 +601,13 @@ class ApplicationsButton extends PanelMenu.Button {
let catsScrollBoxAlloc = this.categoriesScrollBox.get_allocation_box();
let currentScrollValue = catsScrollBoxAdj.get_value();
let boxHeight = catsScrollBoxAlloc.y2 - catsScrollBoxAlloc.y1;
let buttonAlloc = button.get_allocation_box();
let buttonAlloc = button.actor.get_allocation_box();
let newScrollValue = currentScrollValue;
if (currentScrollValue > buttonAlloc.y1 - 10)
newScrollValue = buttonAlloc.y1 - 10;
if (boxHeight + currentScrollValue < buttonAlloc.y2 + 10)
newScrollValue = buttonAlloc.y2 - boxHeight + 10;
if (newScrollValue !== currentScrollValue)
if (newScrollValue != currentScrollValue)
catsScrollBoxAdj.set_value(newScrollValue);
}
@@ -556,10 +616,9 @@ class ApplicationsButton extends PanelMenu.Button {
this.menu.addMenuItem(section);
this.mainBox = new St.BoxLayout({ vertical: false });
this.leftBox = new St.BoxLayout({ vertical: true });
this.applicationsScrollBox = new St.ScrollView({
style_class: 'apps-menu vfade',
x_expand: true,
});
this.applicationsScrollBox = new St.ScrollView({ x_fill: true, y_fill: false,
y_align: St.Align.START,
style_class: 'apps-menu vfade' });
this.applicationsScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
let vscroll = this.applicationsScrollBox.get_vscroll_bar();
vscroll.connect('scroll-start', () => {
@@ -568,14 +627,21 @@ class ApplicationsButton extends PanelMenu.Button {
vscroll.connect('scroll-stop', () => {
this.menu.passEvents = false;
});
this.categoriesScrollBox = new St.ScrollView({
style_class: 'vfade',
});
this.categoriesScrollBox = new St.ScrollView({ x_fill: true, y_fill: false,
y_align: St.Align.START,
style_class: 'vfade' });
this.categoriesScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
vscroll = this.categoriesScrollBox.get_vscroll_bar();
vscroll.connect('scroll-start', () => (this.menu.passEvents = true));
vscroll.connect('scroll-stop', () => (this.menu.passEvents = false));
this.leftBox.add_child(this.categoriesScrollBox);
vscroll.connect('scroll-start', () => { this.menu.passEvents = true; });
vscroll.connect('scroll-stop', () => { this.menu.passEvents = false; });
this.leftBox.add(this.categoriesScrollBox, { expand: true,
x_fill: true, y_fill: true,
y_align: St.Align.START });
let activities = new ActivitiesMenuItem(this);
this.leftBox.add(activities.actor, { expand: false,
x_fill: true, y_fill: false,
y_align: St.Align.START });
this.applicationsBox = new St.BoxLayout({ vertical: true });
this.applicationsScrollBox.add_actor(this.applicationsBox);
@@ -583,52 +649,47 @@ class ApplicationsButton extends PanelMenu.Button {
this.categoriesScrollBox.add_actor(this.categoriesBox);
this.mainBox.add(this.leftBox);
this.mainBox.add_child(this._createVertSeparator());
this.mainBox.add_child(this.applicationsScrollBox);
this.mainBox.add(this._createVertSeparator(), { expand: false, x_fill: false, y_fill: true});
this.mainBox.add(this.applicationsScrollBox, { expand: true, x_fill: true, y_fill: true });
section.actor.add_actor(this.mainBox);
}
_display() {
this._applicationsButtons.clear();
this.mainBox.style = 'width: 35em;';
this.mainBox.style=('width: 35em;');
this.mainBox.hide();
// Load categories
//Load categories
this.applicationsByCategory = {};
this._tree.load_sync();
let root = this._tree.get_root_directory();
let categoryMenuItem = new CategoryMenuItem(this, null);
this.categoriesBox.add_actor(categoryMenuItem);
this.categoriesBox.add_actor(categoryMenuItem.actor);
let iter = root.iter();
let nextType;
while ((nextType = iter.next()) !== GMenu.TreeItemType.INVALID) {
if (nextType !== GMenu.TreeItemType.DIRECTORY)
continue;
let dir = iter.get_directory();
if (dir.get_is_nodisplay())
continue;
let categoryId = dir.get_menu_id();
this.applicationsByCategory[categoryId] = [];
this._loadCategory(categoryId, dir);
if (this.applicationsByCategory[categoryId].length > 0) {
categoryMenuItem = new CategoryMenuItem(this, dir);
this.categoriesBox.add_actor(categoryMenuItem);
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
if (nextType == GMenu.TreeItemType.DIRECTORY) {
let dir = iter.get_directory();
if (!dir.get_is_nodisplay()) {
let categoryId = dir.get_menu_id();
this.applicationsByCategory[categoryId] = [];
this._loadCategory(categoryId, dir);
if (this.applicationsByCategory[categoryId].length > 0) {
let categoryMenuItem = new CategoryMenuItem(this, dir);
this.categoriesBox.add_actor(categoryMenuItem.actor);
}
}
}
}
// Load applications
//Load applications
this._displayButtons(this._listApplications(null));
let themeContext = St.ThemeContext.get_for_stage(global.stage);
let scaleFactor = themeContext.scale_factor;
let categoriesHeight = this.categoriesBox.height / scaleFactor;
let height = Math.round(categoriesHeight) + MENU_HEIGHT_OFFSET;
this.mainBox.style += `height: ${height}px`;
let height = this.categoriesBox.height + MENU_HEIGHT_OFFSET + 'px';
this.mainBox.style+=('height: ' + height);
}
selectCategory(dir) {
selectCategory(dir, categoryMenuItem) {
this.applicationsBox.get_children().forEach(c => {
if (c._delegate instanceof PopupMenu.PopupSeparatorMenuItem)
c._delegate.destroy();
@@ -643,51 +704,64 @@ class ApplicationsButton extends PanelMenu.Button {
}
_displayButtons(apps) {
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
let item;
if (app instanceof Shell.App)
item = this._applicationsButtons.get(app);
else
item = new PopupMenu.PopupSeparatorMenuItem();
if (!item) {
item = new ApplicationMenuItem(this, app);
item.setDragEnabled(this._desktopTarget.hasDesktop);
this._applicationsButtons.set(app, item);
if (apps) {
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
let item;
if (app instanceof Shell.App)
item = this._applicationsButtons.get(app);
else
item = new PopupMenu.PopupSeparatorMenuItem();
if (!item) {
item = new ApplicationMenuItem(this, app);
item.setDragEnabled(this._desktopTarget.hasDesktop);
this._applicationsButtons.set(app, item);
}
if (!item.actor.get_parent())
this.applicationsBox.add_actor(item.actor);
}
if (!item.get_parent())
this.applicationsBox.add_actor(item);
}
}
}
_listApplications(categoryMenuId) {
_listApplications(category_menu_id) {
let applist;
if (categoryMenuId) {
applist = this.applicationsByCategory[categoryMenuId];
if (category_menu_id) {
applist = this.applicationsByCategory[category_menu_id];
} else {
applist = global.settings.get_strv('favorite-apps')
.map(id => appSys.lookup_app(id))
.filter(app => app);
applist = new Array();
let favorites = global.settings.get_strv('favorite-apps');
for (let i = 0; i < favorites.length; i++) {
let app = appSys.lookup_app(favorites[i]);
if (app)
applist.push(app);
}
}
return applist;
}
});
destroy() {
super.destroy();
}
};
let appsMenuButton;
let activitiesButton;
function enable() {
activitiesButton = Main.panel.statusArea['activities'];
activitiesButton.container.hide();
appsMenuButton = new ApplicationsButton();
let index = Main.sessionMode.panel.left.indexOf('activities') + 1;
Main.panel.addToStatusArea('apps-menu', appsMenuButton, index, 'left');
Main.panel.addToStatusArea('apps-menu', appsMenuButton, 1, 'left');
}
function disable() {
Main.panel.menuManager.removeMenu(appsMenuButton.menu);
appsMenuButton.destroy();
activitiesButton.container.show();
}
function init() {
ExtensionUtils.initTranslations();
function init(metadata) {
Convenience.initTranslations();
}

View File

@@ -1,22 +1,24 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Start apps on custom workspaces
/* exported init enable disable */
const { Shell } = imports.gi;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
class WindowMover {
constructor() {
this._settings = ExtensionUtils.getSettings();
this._settings = Convenience.getSettings();
this._appSystem = Shell.AppSystem.get_default();
this._appConfigs = new Map();
this._appData = new Map();
this._appsChangedId =
this._appSystem.connect('installed-changed',
this._updateAppData.bind(this));
this._updateAppData.bind(this));
this._settings.connect('changed', this._updateAppConfigs.bind(this));
this._updateAppConfigs();
@@ -44,15 +46,15 @@ class WindowMover {
});
let addedApps = ids.map(id => this._appSystem.lookup_app(id)).filter(
app => app && !this._appData.has(app)
app => app != null && !this._appData.has(app)
);
addedApps.forEach(app => {
let data = {
windowsChangedId: app.connect('windows-changed',
this._appWindowsChanged.bind(this)),
this._appWindowsChanged.bind(this)),
moveWindowsId: 0,
windows: app.get_windows(),
};
windows: app.get_windows()
}
this._appData.set(app, data);
});
}
@@ -77,10 +79,9 @@ class WindowMover {
return;
// ensure we have the required number of workspaces
let workspaceManager = global.workspace_manager;
for (let i = workspaceManager.n_workspaces; i <= workspaceNum; i++) {
for (let i = global.screen.n_workspaces; i <= workspaceNum; i++) {
window.change_workspace_by_index(i - 1, false);
workspaceManager.append_new_workspace(false, 0);
global.screen.append_new_workspace(false, 0);
}
window.change_workspace_by_index(workspaceNum, false);
@@ -95,7 +96,7 @@ class WindowMover {
// or something; assume it'll be added back immediately, so keep it
// to avoid moving it again
windows.push(...data.windows.filter(
w => !windows.includes(w) && w.get_compositor_private() !== null
w => !windows.includes(w) && w.get_compositor_private() != null
));
let workspaceNum = this._appConfigs.get(app.id);
@@ -104,13 +105,13 @@ class WindowMover {
});
data.windows = windows;
}
}
};
let prevCheckWorkspaces;
let winMover;
function init() {
ExtensionUtils.initTranslations();
Convenience.initTranslations();
}
function myCheckWorkspaces() {
@@ -124,9 +125,9 @@ function myCheckWorkspaces() {
}
// make sure the original method only removes empty workspaces at the end
keepAliveWorkspaces.forEach(ws => (ws._keepAliveId = 1));
keepAliveWorkspaces.forEach(ws => { ws._keepAliveId = 1; });
prevCheckWorkspaces.call(this);
keepAliveWorkspaces.forEach(ws => delete ws._keepAliveId);
keepAliveWorkspaces.forEach(ws => { delete ws._keepAliveId; });
return false;
}

View File

@@ -1,14 +1,17 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Start apps on custom workspaces
/* exported init buildPrefsWidget */
const { Gio, GObject, Gtk } = imports.gi;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = e => e;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const SETTINGS_KEY = 'application-list';
@@ -19,62 +22,50 @@ const Columns = {
DISPLAY_NAME: 1,
ICON: 2,
WORKSPACE: 3,
ADJUSTMENT: 4,
ADJUSTMENT: 4
};
const Widget = GObject.registerClass(
class Widget extends Gtk.Grid {
const Widget = GObject.registerClass({
GTypeName: 'AutoMoveWindowsPrefsWidget',
}, class Widget extends Gtk.Grid {
_init(params) {
super._init(params);
this.set_orientation(Gtk.Orientation.VERTICAL);
this._settings = ExtensionUtils.getSettings();
this._settings = Convenience.getSettings();
this._settings.connect('changed', this._refresh.bind(this));
this._changedPermitted = false;
this._store = new Gtk.ListStore();
this._store.set_column_types([
Gio.AppInfo,
GObject.TYPE_STRING,
Gio.Icon,
GObject.TYPE_INT,
Gtk.Adjustment,
]);
this._store.set_column_types([Gio.AppInfo, GObject.TYPE_STRING, Gio.Icon, GObject.TYPE_INT,
Gtk.Adjustment]);
let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN });
let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN});
scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.add(scrolled);
this._treeView = new Gtk.TreeView({
model: this._store,
hexpand: true,
vexpand: true,
});
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.DISPLAY_NAME,
title: _('Application'),
});
let iconRenderer = new Gtk.CellRendererPixbuf();
let appColumn = new Gtk.TreeViewColumn({ expand: true, sort_column_id: Columns.DISPLAY_NAME,
title: _("Application") });
let iconRenderer = new Gtk.CellRendererPixbuf;
appColumn.pack_start(iconRenderer, false);
appColumn.add_attribute(iconRenderer, 'gicon', Columns.ICON);
let nameRenderer = new Gtk.CellRendererText();
appColumn.add_attribute(iconRenderer, "gicon", Columns.ICON);
let nameRenderer = new Gtk.CellRendererText;
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, 'text', Columns.DISPLAY_NAME);
appColumn.add_attribute(nameRenderer, "text", Columns.DISPLAY_NAME);
this._treeView.append_column(appColumn);
let workspaceColumn = new Gtk.TreeViewColumn({
title: _('Workspace'),
sort_column_id: Columns.WORKSPACE,
});
let workspaceColumn = new Gtk.TreeViewColumn({ title: _("Workspace"),
sort_column_id: Columns.WORKSPACE });
let workspaceRenderer = new Gtk.CellRendererSpin({ editable: true });
workspaceRenderer.connect('edited', this._workspaceEdited.bind(this));
workspaceColumn.pack_start(workspaceRenderer, true);
workspaceColumn.add_attribute(workspaceRenderer, 'adjustment', Columns.ADJUSTMENT);
workspaceColumn.add_attribute(workspaceRenderer, 'text', Columns.WORKSPACE);
workspaceColumn.add_attribute(workspaceRenderer, "adjustment", Columns.ADJUSTMENT);
workspaceColumn.add_attribute(workspaceRenderer, "text", Columns.WORKSPACE);
this._treeView.append_column(workspaceColumn);
scrolled.add(this._treeView);
@@ -83,15 +74,13 @@ class Widget extends Gtk.Grid {
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
this.add(toolbar);
let newButton = new Gtk.ToolButton({
icon_name: 'bookmark-new-symbolic',
label: _('Add Rule'),
is_important: true,
});
let newButton = new Gtk.ToolButton({ icon_name: 'bookmark-new-symbolic',
label: _("Add Rule"),
is_important: true });
newButton.connect('clicked', this._createNew.bind(this));
toolbar.add(newButton);
let delButton = new Gtk.ToolButton({ icon_name: 'edit-delete-symbolic' });
let delButton = new Gtk.ToolButton({ icon_name: 'edit-delete-symbolic' });
delButton.connect('clicked', this._deleteSelected.bind(this));
toolbar.add(delButton);
@@ -106,21 +95,17 @@ class Widget extends Gtk.Grid {
}
_createNew() {
let dialog = new Gtk.Dialog({
title: _('Create new matching rule'),
transient_for: this.get_toplevel(),
use_header_bar: true,
modal: true,
});
let dialog = new Gtk.Dialog({ title: _("Create new matching rule"),
transient_for: this.get_toplevel(),
use_header_bar: true,
modal: true });
dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
let addButton = dialog.add_button(_('Add'), Gtk.ResponseType.OK);
let addButton = dialog.add_button(_("Add"), Gtk.ResponseType.OK);
dialog.set_default_response(Gtk.ResponseType.OK);
let grid = new Gtk.Grid({
column_spacing: 10,
row_spacing: 15,
margin: 10,
});
let grid = new Gtk.Grid({ column_spacing: 10,
row_spacing: 15,
margin: 10 });
dialog._appChooser = new Gtk.AppChooserWidget({ show_all: true });
dialog._appChooser.connect('application-selected', (w, appInfo) => {
addButton.sensitive = appInfo && this._checkId(appInfo.get_id());
@@ -129,30 +114,25 @@ class Widget extends Gtk.Grid {
addButton.sensitive = appInfo && this._checkId(appInfo.get_id());
grid.attach(dialog._appChooser, 0, 0, 2, 1);
grid.attach(new Gtk.Label({
label: _('Workspace'),
halign: Gtk.Align.END,
}), 0, 1, 1, 1);
let adjustment = new Gtk.Adjustment({
lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1,
});
dialog._spin = new Gtk.SpinButton({
adjustment,
snap_to_ticks: true,
});
grid.attach(new Gtk.Label({ label: _("Workspace"),
halign: Gtk.Align.END }), 0, 1, 1, 1);
let adjustment = new Gtk.Adjustment({ lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1
});
dialog._spin = new Gtk.SpinButton({ adjustment: adjustment,
snap_to_ticks: true });
dialog._spin.set_value(1);
grid.attach(dialog._spin, 1, 1, 1, 1);
dialog.get_content_area().add(grid);
dialog.connect('response', (dlg, id) => {
if (id !== Gtk.ResponseType.OK) {
dialog.connect('response', (dialog, id) => {
if (id != Gtk.ResponseType.OK) {
dialog.destroy();
return;
}
appInfo = dialog._appChooser.get_app_info();
let appInfo = dialog._appChooser.get_app_info();
if (!appInfo)
return;
let index = Math.floor(dialog._spin.value);
@@ -163,7 +143,14 @@ class Widget extends Gtk.Grid {
this._appendItem(appInfo.get_id(), index);
this._changedPermitted = true;
this._appendRow(appInfo, index);
let iter = this._store.append();
let adj = new Gtk.Adjustment({ lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1,
value: index });
this._store.set(iter,
[Columns.APPINFO, Columns.ICON, Columns.DISPLAY_NAME, Columns.WORKSPACE, Columns.ADJUSTMENT],
[appInfo, appInfo.get_icon(), appInfo.get_display_name(), index, adj]);
dialog.destroy();
});
@@ -171,7 +158,7 @@ class Widget extends Gtk.Grid {
}
_deleteSelected() {
let [any, model_, iter] = this._treeView.get_selection().get_selected();
let [any, model, iter] = this._treeView.get_selection().get_selected();
if (any) {
let appInfo = this._store.get_value(iter, Columns.APPINFO);
@@ -188,7 +175,7 @@ class Widget extends Gtk.Grid {
if (isNaN(index) || index < 0)
index = 1;
let path = Gtk.TreePath.new_from_string(pathString);
let [model_, iter] = this._store.get_iter(path);
let [model, iter] = this._store.get_iter(path);
let appInfo = this._store.get_value(iter, Columns.APPINFO);
this._changedPermitted = false;
@@ -205,7 +192,7 @@ class Widget extends Gtk.Grid {
this._store.clear();
let currentItems = this._settings.get_strv(SETTINGS_KEY);
let validItems = [];
let validItems = [ ];
for (let i = 0; i < currentItems.length; i++) {
let [id, index] = currentItems[i].split(':');
let appInfo = Gio.DesktopAppInfo.new(id);
@@ -213,37 +200,28 @@ class Widget extends Gtk.Grid {
continue;
validItems.push(currentItems[i]);
this._appendRow(appInfo, parseInt(index));
let iter = this._store.append();
let adj = new Gtk.Adjustment({ lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1,
value: index });
this._store.set(iter,
[Columns.APPINFO, Columns.ICON, Columns.DISPLAY_NAME, Columns.WORKSPACE, Columns.ADJUSTMENT],
[appInfo, appInfo.get_icon(), appInfo.get_display_name(), parseInt(index), adj]);
}
if (validItems.length !== currentItems.length) // some items were filtered out
if (validItems.length != currentItems.length) // some items were filtered out
this._settings.set_strv(SETTINGS_KEY, validItems);
}
_appendRow(appInfo, workspace) {
let iter = this._store.append();
let icon = appInfo.get_icon();
let displayName = appInfo.get_display_name();
let adj = new Gtk.Adjustment({
lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1,
value: workspace,
});
let { APPINFO, ICON, DISPLAY_NAME, WORKSPACE, ADJUSTMENT } = Columns;
this._store.set(iter,
[APPINFO, ICON, DISPLAY_NAME, WORKSPACE, ADJUSTMENT],
[appInfo, icon, displayName, workspace, adj]);
}
_checkId(id) {
let items = this._settings.get_strv(SETTINGS_KEY);
return !items.some(i => i.startsWith(`${id}:`));
return !items.some(i => i.startsWith(id + ':'));
}
_appendItem(id, workspace) {
let currentItems = this._settings.get_strv(SETTINGS_KEY);
currentItems.push(`${id}:${workspace}`);
currentItems.push(id + ':' + workspace);
this._settings.set_strv(SETTINGS_KEY, currentItems);
}
@@ -262,16 +240,16 @@ class Widget extends Gtk.Grid {
let index = currentItems.map(el => el.split(':')[0]).indexOf(id);
if (index < 0)
currentItems.push(`${id}:${workspace}`);
currentItems.push(id + ':' + workspace);
else
currentItems[index] = `${id}:${workspace}`;
currentItems[index] = id + ':' + workspace;
this._settings.set_strv(SETTINGS_KEY, currentItems);
}
});
function init() {
ExtensionUtils.initTranslations();
Convenience.initTranslations();
}
function buildPrefsWidget() {

View File

@@ -1,42 +1,43 @@
/* exported init enable disable */
// Drive menu extension
const { Gio, GObject, Shell, St } = imports.gi;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const ShellMountOperation = imports.ui.shellMountOperation;
var MountMenuItem = GObject.registerClass(
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(mount) {
super._init();
constructor(mount) {
super();
this.label = new St.Label({ text: mount.get_name() });
this.add_child(this.label);
this.label_actor = this.label;
this.actor.add(this.label, { expand: true });
this.actor.label_actor = this.label;
this.mount = mount;
this.connect('destroy', this._onDestroy.bind(this));
let ejectIcon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon',
});
let ejectIcon = new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon ' });
let ejectButton = new St.Button({ child: ejectIcon });
ejectButton.connect('clicked', this._eject.bind(this));
this.add(ejectButton);
this.actor.add(ejectButton);
this._changedId = mount.connect('changed', this._syncVisibility.bind(this));
this._syncVisibility();
}
_onDestroy() {
destroy() {
if (this._changedId) {
this.mount.disconnect(this._changedId);
this._changedId = 0;
@@ -53,39 +54,38 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
let volume = this.mount.get_volume();
if (!volume) {
if (volume == null) {
// probably a GDaemonMount, could be network or
// local, but we can't tell; assume it's local for now
return true;
}
return volume.get_identifier('class') !== 'network';
return volume.get_identifier('class') != 'network';
}
_syncVisibility() {
this.visible = this._isInteresting();
this.actor.visible = this._isInteresting();
}
_eject() {
let unmountArgs = [
Gio.MountUnmountFlags.NONE,
new ShellMountOperation.ShellMountOperation(this.mount).mountOp,
null, // Gio.Cancellable
];
let mountOp = new ShellMountOperation.ShellMountOperation(this.mount);
if (this.mount.can_eject()) {
this.mount.eject_with_operation(...unmountArgs,
this._ejectFinish.bind(this));
} else {
this.mount.unmount_with_operation(...unmountArgs,
this._unmountFinish.bind(this));
}
if (this.mount.can_eject())
this.mount.eject_with_operation(Gio.MountUnmountFlags.NONE,
mountOp.mountOp,
null, // Gio.Cancellable
this._ejectFinish.bind(this));
else
this.mount.unmount_with_operation(Gio.MountUnmountFlags.NONE,
mountOp.mountOp,
null, // Gio.Cancellable
this._unmountFinish.bind(this));
}
_unmountFinish(mount, result) {
try {
mount.unmount_with_operation_finish(result);
} catch (e) {
} catch(e) {
this._reportFailure(e);
}
}
@@ -93,40 +93,37 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
_ejectFinish(mount, result) {
try {
mount.eject_with_operation_finish(result);
} catch (e) {
} catch(e) {
this._reportFailure(e);
}
}
_reportFailure(exception) {
// TRANSLATORS: %s is the filesystem name
let msg = _('Ejecting drive “%s” failed:').format(this.mount.get_name());
let msg = _("Ejecting drive “%s” failed:").format(this.mount.get_name());
Main.notifyError(msg, exception.message);
}
activate(event) {
let uri = this.mount.get_root().get_uri();
let context = global.create_app_launch_context(event.get_time(), -1);
Gio.AppInfo.launch_default_for_uri(uri, context);
Gio.AppInfo.launch_default_for_uri(this.mount.get_root().get_uri(),
context);
super.activate(event);
}
});
};
let DriveMenu = GObject.registerClass(
class DriveMenu extends PanelMenu.Button {
_init() {
super._init(0.0, _('Removable devices'));
constructor() {
super(0.0, _("Removable devices"));
let hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
let icon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'system-status-icon',
});
let icon = new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'system-status-icon' });
hbox.add_child(icon);
hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.add_child(hbox);
this.actor.add_child(hbox);
this._monitor = Gio.VolumeMonitor.get();
this._addedId = this._monitor.connect('mount-added', (monitor, mount) => {
@@ -138,12 +135,12 @@ class DriveMenu extends PanelMenu.Button {
this._updateMenuVisibility();
});
this._mounts = [];
this._mounts = [ ];
this._monitor.get_mounts().forEach(this._addMount.bind(this));
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_('Open Files'), event => {
this.menu.addAction(_("Open Files"), event => {
let appSystem = Shell.AppSystem.get_default();
let app = appSystem.lookup_app('org.gnome.Nautilus.desktop');
app.activate_full(-1, event.get_time());
@@ -153,10 +150,10 @@ class DriveMenu extends PanelMenu.Button {
}
_updateMenuVisibility() {
if (this._mounts.filter(i => i.visible).length > 0)
this.show();
if (this._mounts.filter(i => i.actor.visible).length > 0)
this.actor.show();
else
this.hide();
this.actor.hide();
}
_addMount(mount) {
@@ -168,35 +165,35 @@ class DriveMenu extends PanelMenu.Button {
_removeMount(mount) {
for (let i = 0; i < this._mounts.length; i++) {
let item = this._mounts[i];
if (item.mount === mount) {
if (item.mount == mount) {
item.destroy();
this._mounts.splice(i, 1);
return;
}
}
log('Removing a mount that was never added to the menu');
log ('Removing a mount that was never added to the menu');
}
_onDestroy() {
if (this._addedId) {
this._monitor.disconnect(this._addedId);
this._monitor.disconnect(this._removedId);
this._addedId = 0;
this._removedId = 0;
destroy() {
if (this._connectedId) {
this._monitor.disconnect(this._connectedId);
this._monitor.disconnect(this._disconnectedId);
this._connectedId = 0;
this._disconnectedId = 0;
}
super._onDestroy();
super.destroy();
}
});
};
function init() {
ExtensionUtils.initTranslations();
Convenience.initTranslations();
}
let _indicator;
function enable() {
_indicator = new DriveMenu();
_indicator = new DriveMenu;
Main.panel.addToStatusArea('drive-menu', _indicator);
}

View File

@@ -0,0 +1,49 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Sample extension code, makes clicking on the panel show a message
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
function _showHello() {
let settings = Convenience.getSettings();
let text = settings.get_string('hello-text') || _("Hello, world!");
let label = new St.Label({ style_class: 'helloworld-label', text: text });
let monitor = Main.layoutManager.primaryMonitor;
global.stage.add_actor(label);
label.set_position(Math.floor (monitor.width / 2 - label.width / 2), Math.floor(monitor.height / 2 - label.height / 2));
Mainloop.timeout_add(3000, () => { label.destroy(); });
}
// Put your extension initialization code here
function init(metadata) {
log ('Example extension initalized');
Convenience.initTranslations();
}
let signalId;
function enable() {
log ('Example extension enabled');
Main.panel.actor.reactive = true;
signalId = Main.panel.actor.connect('button-release-event', _showHello);
}
function disable() {
log ('Example extension disabled');
if (signalId) {
Main.panel.actor.disconnect(signalId);
signalId = 0;
}
}

View File

@@ -0,0 +1,8 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_sources += files('prefs.js')
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -0,0 +1,10 @@
{
"extension-id": "@extension_id@",
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Hello, World!",
"description": "An example extension to show how it works. Shows Hello, world when clicking on the top panel.",
"shell-version": [ "@shell_current@" ],
"url": "@url@"
}

View File

@@ -0,0 +1,9 @@
<schemalist gettext-domain="gnome-shell-extensions">
<schema id="org.gnome.shell.extensions.example" path="/org/gnome/shell/extensions/example/">
<key name="hello-text" type="s">
<default>''</default>
<summary>Alternative greeting text.</summary>
<description>If not empty, it contains the text that will be shown when clicking on the panel.</description>
</key>
</schema>
</schemalist>

View File

@@ -0,0 +1,54 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
function init() {
Convenience.initTranslations();
}
const ExamplePrefsWidget = GObject.registerClass(
class ExamplePrefsWidget extends Gtk.Grid {
_init(params) {
super._init(params);
this.margin = 12;
this.row_spacing = this.column_spacing = 6;
this.set_orientation(Gtk.Orientation.VERTICAL);
this.add(new Gtk.Label({ label: '<b>' + _("Message") + '</b>',
use_markup: true,
halign: Gtk.Align.START }));
let entry = new Gtk.Entry({ hexpand: true,
margin_bottom: 12 });
this.add(entry);
this._settings = Convenience.getSettings();
this._settings.bind('hello-text', entry, 'text', Gio.SettingsBindFlags.DEFAULT);
// TRANSLATORS: Example is the name of the extension, should not be
// translated
let primaryText = _("Example aims to show how to build well behaved \
extensions for the Shell and as such it has little functionality on its own.\n\
Nevertheless its possible to customize the greeting message.");
this.add(new Gtk.Label({ label: primaryText,
wrap: true, xalign: 0 }));
}
});
function buildPrefsWidget() {
let widget = new ExamplePrefsWidget();
widget.show_all();
return widget;
}

View File

@@ -0,0 +1,8 @@
/* Example stylesheet */
.helloworld-label {
font-size: 36px;
font-weight: bold;
color: #ffffff;
background-color: rgba(10,10,10,0.7);
border-radius: 5px;
}

View File

@@ -1,38 +0,0 @@
/* exported init */
const { Meta } = imports.gi;
const { ThumbnailsBox } = imports.ui.workspaceThumbnail;
class Extension {
constructor() {
this._origUpdateSwitcherVisibility =
ThumbnailsBox.prototype._updateSwitcherVisibility;
}
enable() {
global.workspace_manager.override_workspace_layout(
Meta.DisplayCorner.TOPLEFT,
false,
1,
-1);
ThumbnailsBox.prototype._updateSwitcherVisibility = function () {
this.hide();
};
}
disable() {
global.workspace_manager.override_workspace_layout(
Meta.DisplayCorner.TOPLEFT,
false,
-1,
1);
ThumbnailsBox.prototype._updateSwitcherVisibility =
this._origUpdateSwitcherVisibility;
}
}
function init() {
return new Extension();
}

View File

@@ -1,10 +0,0 @@
{
"extension-id": "@extension_id@",
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Horizontal workspaces",
"description": "Use a horizontal workspace layout",
"shell-version": [ "@shell_current@" ],
"url": "@url@"
}

View File

@@ -1,15 +1,17 @@
/* exported enable disable */
const AppDisplay = imports.ui.appDisplay;
let _activateOriginal = null;
function init() {
}
function enable() {
_activateOriginal = AppDisplay.AppIcon.prototype.activate;
AppDisplay.AppIcon.prototype.activate = function () {
_activateOriginal.call(this, 2);
};
_activateOriginal = AppDisplay.AppIcon.prototype.activate;
AppDisplay.AppIcon.prototype.activate = function() {
_activateOriginal.call(this, 2);
};
}
function disable() {
AppDisplay.AppIcon.prototype.activate = _activateOriginal;
AppDisplay.AppIcon.prototype.activate = _activateOriginal;
}

View File

@@ -1,5 +1,5 @@
extension_schemas = []
js_sources = []
js_sources = extensionlib
metadata_name = 'metadata.json'
@@ -22,7 +22,7 @@ foreach e : all_extensions
js_sources += extension_sources
if (enabled_extensions.contains(e))
install_data (extension_sources + extension_data,
install_data (extension_sources + extension_data + extensionlib,
install_dir: join_paths(extensiondir, uuid)
)
endif
@@ -33,11 +33,11 @@ install_data (extension_schemas,
)
foreach js_source : js_sources
if (js60.found())
if (js52.found())
path_array = '@0@'.format(js_source).split('/')
name = join_paths(path_array[-2], path_array[-1])
test('Checking syntax of ' + name, js60,
test('Checking syntax of ' + name, js52,
args: ['-s', '-c', js_source],
workdir: meson.current_source_dir()
)

View File

@@ -1,9 +1,13 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported enable disable */
const ExtensionUtils = imports.misc.extensionUtils;
const Workspace = imports.ui.workspace;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
// testing settings for natural window placement strategy:
const WINDOW_PLACEMENT_NATURAL_FILLGAPS = true; // enlarge windows at the end to fill gaps // not implemented yet
const WINDOW_PLACEMENT_NATURAL_GRID_FALLBACK = true; // fallback to grid mode if all windows have the same size and positions. // not implemented yet
const WINDOW_PLACEMENT_NATURAL_ACCURACY = 20; // accuracy of window translate moves (KDE-default: 20)
const WINDOW_PLACEMENT_NATURAL_GAPS = 5; // half of the minimum gap between windows
const WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS = 5000; // safety limit for preventing endless loop if something is wrong in the algorithm
@@ -13,25 +17,29 @@ class Rect {
[this.x, this.y, this.width, this.height] = [x, y, width, height];
}
// used in _calculateWindowTransformationsNatural to replace Meta.Rectangle that is too slow.
/**
* used in _calculateWindowTransformationsNatural to replace Meta.Rectangle that is too slow.
*/
copy() {
return new Rect(this.x, this.y, this.width, this.height);
}
union(rect2) {
let dest = this.copy();
if (rect2.x < dest.x) {
if (rect2.x < dest.x)
{
dest.width += dest.x - rect2.x;
dest.x = rect2.x;
}
if (rect2.y < dest.y) {
}
if (rect2.y < dest.y)
{
dest.height += dest.y - rect2.y;
dest.y = rect2.y;
}
}
if (rect2.x + rect2.width > dest.x + dest.width)
dest.width = rect2.x + rect2.width - dest.x;
dest.width = rect2.x + rect2.width - dest.x;
if (rect2.y + rect2.height > dest.y + dest.height)
dest.height = rect2.y + rect2.height - dest.y;
dest.height = rect2.y + rect2.height - dest.y;
return dest;
}
@@ -46,10 +54,10 @@ class Rect {
}
overlap(rect2) {
return !(this.x + this.width <= rect2.x ||
rect2.x + rect2.width <= this.x ||
this.y + this.height <= rect2.y ||
rect2.y + rect2.height <= this.y);
return !((this.x + this.width <= rect2.x) ||
(rect2.x + rect2.width <= this.x) ||
(this.y + this.height <= rect2.y) ||
(rect2.y + rect2.height <= this.y));
}
center() {
@@ -60,7 +68,7 @@ class Rect {
this.x += dx;
this.y += dy;
}
}
};
class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
constructor(settings) {
@@ -72,7 +80,7 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
layout.windows = windows;
}
/*
/**
* Returns clones with matching target coordinates and scales to arrange windows in a natural way that no overlap exists and relative window size is preserved.
* This function is almost a 1:1 copy of the function
* PresentWindowsEffect::calculateWindowTransformationsNatural() from KDE, see:
@@ -82,8 +90,8 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
// As we are using pseudo-random movement (See "slot") we need to make sure the list
// is always sorted the same way no matter which window is currently active.
let areaRect = new Rect(area.x, area.y, area.width, area.height);
let bounds = areaRect.copy();
let area_rect = new Rect(area.x, area.y, area.width, area.height);
let bounds = area_rect.copy();
let clones = layout.windows;
let direction = 0;
@@ -98,37 +106,36 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
// This is used when the window is on the edge of the screen to try to use as much screen real estate as possible.
directions[i] = direction;
direction++;
if (direction === 4)
if (direction == 4) {
direction = 0;
}
}
let loopCounter = 0;
let loop_counter = 0;
let overlap;
do {
overlap = false;
for (let i = 0; i < rects.length; i++) {
for (let j = 0; j < rects.length; j++) {
let adjustments = [-1, -1, 1, 1]
.map(v => (v *= WINDOW_PLACEMENT_NATURAL_GAPS));
let iAdjusted = rects[i].adjusted(...adjustments);
let jAdjusted = rects[j].adjusted(...adjustments);
if (i !== j && iAdjusted.overlap(jAdjusted)) {
loopCounter++;
if (i != j && rects[i].adjusted(-WINDOW_PLACEMENT_NATURAL_GAPS, -WINDOW_PLACEMENT_NATURAL_GAPS,
WINDOW_PLACEMENT_NATURAL_GAPS, WINDOW_PLACEMENT_NATURAL_GAPS).overlap(
rects[j].adjusted(-WINDOW_PLACEMENT_NATURAL_GAPS, -WINDOW_PLACEMENT_NATURAL_GAPS,
WINDOW_PLACEMENT_NATURAL_GAPS, WINDOW_PLACEMENT_NATURAL_GAPS))) {
loop_counter++;
overlap = true;
// TODO: something like a Point2D would be nicer here:
// Determine pushing direction
let iCenter = rects[i].center();
let jCenter = rects[j].center();
let diff = [jCenter[0] - iCenter[0], jCenter[1] - iCenter[1]];
let i_center = rects[i].center();
let j_center = rects[j].center();
let diff = [j_center[0] - i_center[0], j_center[1] - i_center[1]];
// Prevent dividing by zero and non-movement
if (diff[0] === 0 && diff[1] === 0)
if (diff[0] == 0 && diff[1] == 0)
diff[0] = 1;
// Try to keep screen/workspace aspect ratio
if (bounds.height / bounds.width > areaRect.height / areaRect.width)
if ( bounds.height / bounds.width > area_rect.height / area_rect.width )
diff[0] *= 2;
else
diff[1] *= 2;
@@ -157,33 +164,33 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
let xSection = Math.round((rects[i].x - bounds.x) / (bounds.width / 3));
let ySection = Math.round((rects[i].y - bounds.y) / (bounds.height / 3));
iCenter = rects[i].center();
let i_center = rects[i].center();
diff[0] = 0;
diff[1] = 0;
if (xSection !== 1 || ySection !== 1) { // Remove this if you want the center to pull as well
if (xSection === 1)
xSection = directions[i] / 2 ? 2 : 0;
if (ySection === 1)
ySection = directions[i] % 2 ? 2 : 0;
if (xSection != 1 || ySection != 1) { // Remove this if you want the center to pull as well
if (xSection == 1)
xSection = (directions[i] / 2 ? 2 : 0);
if (ySection == 1)
ySection = (directions[i] % 2 ? 2 : 0);
}
if (xSection === 0 && ySection === 0) {
diff[0] = bounds.x - iCenter[0];
diff[1] = bounds.y - iCenter[1];
if (xSection == 0 && ySection == 0) {
diff[0] = bounds.x - i_center[0];
diff[1] = bounds.y - i_center[1];
}
if (xSection === 2 && ySection === 0) {
diff[0] = bounds.x + bounds.width - iCenter[0];
diff[1] = bounds.y - iCenter[1];
if (xSection == 2 && ySection == 0) {
diff[0] = bounds.x + bounds.width - i_center[0];
diff[1] = bounds.y - i_center[1];
}
if (xSection === 2 && ySection === 2) {
diff[0] = bounds.x + bounds.width - iCenter[0];
diff[1] = bounds.y + bounds.height - iCenter[1];
if (xSection == 2 && ySection == 2) {
diff[0] = bounds.x + bounds.width - i_center[0];
diff[1] = bounds.y + bounds.height - i_center[1];
}
if (xSection === 0 && ySection === 2) {
diff[0] = bounds.x - iCenter[0];
diff[1] = bounds.y + bounds.height - iCenter[1];
if (xSection == 0 && ySection == 2) {
diff[0] = bounds.x - i_center[0];
diff[1] = bounds.y + bounds.height - i_center[1];
}
if (diff[0] !== 0 || diff[1] !== 0) {
length = Math.sqrt(diff[0] * diff[0] + diff[1] * diff[1]);
if (diff[0] != 0 || diff[1] != 0) {
let length = Math.sqrt(diff[0]*diff[0] + diff[1]*diff[1]);
diff[0] *= WINDOW_PLACEMENT_NATURAL_ACCURACY / length / 2; // /2 to make it less influencing than the normal center-move above
diff[1] *= WINDOW_PLACEMENT_NATURAL_ACCURACY / length / 2;
rects[i].translate(diff[0], diff[1]);
@@ -196,38 +203,44 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
}
}
}
} while (overlap && loopCounter < WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS);
} while (overlap && loop_counter < WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS);
// Work out scaling by getting the most top-left and most bottom-right window coords.
let scale;
scale = Math.min(
areaRect.width / bounds.width,
areaRect.height / bounds.height,
1.0);
scale = Math.min(area_rect.width / bounds.width,
area_rect.height / bounds.height,
1.0);
// Make bounding rect fill the screen size for later steps
bounds.x -= (areaRect.width - bounds.width * scale) / 2;
bounds.y -= (areaRect.height - bounds.height * scale) / 2;
bounds.width = areaRect.width / scale;
bounds.height = areaRect.height / scale;
bounds.x = bounds.x - (area_rect.width - bounds.width * scale) / 2;
bounds.y = bounds.y - (area_rect.height - bounds.height * scale) / 2;
bounds.width = area_rect.width / scale;
bounds.height = area_rect.height / scale;
// Move all windows back onto the screen and set their scale
for (let i = 0; i < rects.length; i++)
for (let i = 0; i < rects.length; i++) {
rects[i].translate(-bounds.x, -bounds.y);
}
// TODO: Implement the KDE part "Try to fill the gaps by enlarging windows if they have the space" here. (If this is wanted)
// rescale to workspace
let scales = [];
let buttonOuterHeight, captionHeight;
let buttonOuterWidth = 0;
let slots = [];
for (let i = 0; i < rects.length; i++) {
rects[i].x = rects[i].x * scale + areaRect.x;
rects[i].y = rects[i].y * scale + areaRect.y;
rects[i].x = rects[i].x * scale + area_rect.x;
rects[i].y = rects[i].y * scale + area_rect.y;
slots.push([rects[i].x, rects[i].y, scale, clones[i]]);
}
return slots;
}
}
};
let winInjections, workspaceInjections;
@@ -239,20 +252,20 @@ function resetState() {
function enable() {
resetState();
let settings = ExtensionUtils.getSettings();
let settings = Convenience.getSettings();
workspaceInjections['_getBestLayout'] = Workspace.Workspace.prototype._getBestLayout;
Workspace.Workspace.prototype._getBestLayout = function (windows) {
Workspace.Workspace.prototype._getBestLayout = function(windows) {
let strategy = new NaturalLayoutStrategy(settings);
let layout = { strategy };
strategy.computeLayout(windows, layout);
return layout;
};
}
// position window titles on top of windows in overlay
/// position window titles on top of windows in overlay ////
winInjections['relayout'] = Workspace.WindowOverlay.prototype.relayout;
Workspace.WindowOverlay.prototype.relayout = function (animate) {
Workspace.WindowOverlay.prototype.relayout = function(animate) {
if (settings.get_boolean('window-captions-on-top')) {
let [, , , cloneHeight] = this._windowClone.slot;
this.title.translation_y = -cloneHeight;
@@ -280,3 +293,7 @@ function disable() {
global.stage.queue_relayout();
resetState();
}
function init() {
/* do nothing */
}

View File

@@ -1,49 +1,49 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported init enable disable */
const { Clutter, GObject, St } = imports.gi;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Panel = imports.ui.panel;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = x => x;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const PlaceDisplay = Me.imports.placeDisplay;
const PLACE_ICON_SIZE = 16;
var PlaceMenuItem = GObject.registerClass(
class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(info) {
super._init();
constructor(info) {
super();
this._info = info;
this._icon = new St.Icon({
gicon: info.icon,
icon_size: PLACE_ICON_SIZE,
});
this.add_child(this._icon);
this._icon = new St.Icon({ gicon: info.icon,
icon_size: PLACE_ICON_SIZE });
this.actor.add_child(this._icon);
this._label = new St.Label({ text: info.name, x_expand: true });
this.add_child(this._label);
this.actor.add_child(this._label);
if (info.isRemovable()) {
this._ejectIcon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon',
});
this._ejectIcon = new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon ' });
this._ejectButton = new St.Button({ child: this._ejectIcon });
this._ejectButton.connect('clicked', info.eject.bind(info));
this.add_child(this._ejectButton);
this.actor.add_child(this._ejectButton);
}
this._changedId = info.connect('changed',
this._propertiesChanged.bind(this));
this._propertiesChanged.bind(this));
}
destroy() {
@@ -65,38 +65,35 @@ class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem {
this._icon.gicon = info.icon;
this._label.text = info.name;
}
});
};
const SECTIONS = [
'special',
'devices',
'bookmarks',
'network',
];
'network'
]
let PlacesMenu = GObject.registerClass(
class PlacesMenu extends PanelMenu.Button {
_init() {
super._init(0.0, _('Places'));
constructor() {
super(0.0, _("Places"));
let hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
let label = new St.Label({
text: _('Places'),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
let label = new St.Label({ text: _("Places"),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
hbox.add_child(label);
hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.add_actor(hbox);
this.actor.add_actor(hbox);
this.placesManager = new PlaceDisplay.PlacesManager();
this._sections = { };
for (let i = 0; i < SECTIONS.length; i++) {
for (let i=0; i < SECTIONS.length; i++) {
let id = SECTIONS[i];
this._sections[id] = new PopupMenu.PopupMenuSection();
this.placesManager.connect(`${id}-updated`, () => {
this.placesManager.connect(id + '-updated', () => {
this._redisplay(id);
});
@@ -106,10 +103,10 @@ class PlacesMenu extends PanelMenu.Button {
}
}
_onDestroy() {
destroy() {
this.placesManager.destroy();
super._onDestroy();
super.destroy();
}
_redisplay(id) {
@@ -125,20 +122,20 @@ class PlacesMenu extends PanelMenu.Button {
this._sections[id].actor.visible = places.length > 0;
}
});
};
function init() {
ExtensionUtils.initTranslations();
Convenience.initTranslations();
}
let _indicator;
function enable() {
_indicator = new PlacesMenu();
_indicator = new PlacesMenu;
let pos = Main.sessionMode.panel.left.indexOf('appMenu');
let pos = 1;
if ('apps-menu' in Main.panel.statusArea)
pos++;
pos = 2;
Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left');
}

View File

@@ -1,10 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Gio, GLib, Shell } = imports.gi;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const St = imports.gi.St;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Search = imports.ui.search;
const ShellMountOperation = imports.ui.shellMountOperation;
const Util = imports.misc.util;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
@@ -20,8 +28,8 @@ const Hostname1Iface = '<node> \
const Hostname1 = Gio.DBusProxy.makeProxyWrapper(Hostname1Iface);
class PlaceInfo {
constructor(...params) {
this._init(...params);
constructor() {
this._init.apply(this, arguments);
}
_init(kind, file, name, icon) {
@@ -38,54 +46,61 @@ class PlaceInfo {
return false;
}
async _ensureMountAndLaunch(context, tryMount) {
try {
await this._launchDefaultForUri(this.file.get_uri(), context, null);
} catch (err) {
if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) {
Main.notifyError(_('Failed to launch “%s”').format(this.name), err.message);
return;
}
let source = {
get_icon: () => this.icon,
};
let op = new ShellMountOperation.ShellMountOperation(source);
_createLaunchCallback(launchContext, tryMount) {
return (_ignored, result) => {
try {
await this._mountEnclosingVolume(0, op.mountOp, null);
Gio.AppInfo.launch_default_for_uri_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) {
let source = {
get_icon: () => { return this.icon; }
};
let op = new ShellMountOperation.ShellMountOperation(source);
this.file.mount_enclosing_volume(0, op.mountOp, null, (file, result) => {
try {
op.close();
file.mount_enclosing_volume_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED)) {
// e.g. user canceled the password dialog
return;
} catch(e) {
Main.notifyError(_("Failed to mount volume for “%s”").format(this.name), e.message);
return;
}
if (tryMount)
this._ensureMountAndLaunch(context, false);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
Main.notifyError(_('Failed to mount volume for “%s”').format(this.name), e.message);
} finally {
op.close();
if (tryMount) {
let callback = this._createLaunchCallback(launchContext, false);
Gio.AppInfo.launch_default_for_uri_async(file.get_uri(),
launchContext,
null,
callback);
}
});
} catch(e) {
Main.notifyError(_("Failed to launch “%s”").format(this.name), e.message);
}
}
}
launch(timestamp) {
let launchContext = global.create_app_launch_context(timestamp, -1);
this._ensureMountAndLaunch(launchContext, true);
let callback = this._createLaunchCallback(launchContext, true);
Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(),
launchContext,
null,
callback);
}
getIcon() {
this.file.query_info_async('standard::symbolic-icon',
Gio.FileQueryInfoFlags.NONE,
0,
null,
(file, result) => {
try {
let info = file.query_info_finish(result);
this.icon = info.get_symbolic_icon();
this.emit('changed');
} catch (e) {
if (e instanceof Gio.IOErrorEnum)
return;
throw e;
}
});
this.file.query_info_async('standard::symbolic-icon', 0, 0, null,
(file, result) => {
try {
let info = file.query_info_finish(result);
this.icon = info.get_symbolic_icon();
this.emit('changed');
} catch(e if e instanceof Gio.IOErrorEnum) {
return;
}
});
// return a generic icon for this kind for now, until we have the
// icon from the query info above
@@ -108,44 +123,16 @@ class PlaceInfo {
try {
let info = this.file.query_info('standard::display-name', 0, null);
return info.get_display_name();
} catch (e) {
if (e instanceof Gio.IOErrorEnum)
return this.file.get_basename();
throw e;
} catch(e if e instanceof Gio.IOErrorEnum) {
return this.file.get_basename();
}
}
_launchDefaultForUri(uri, context, cancel) {
return new Promise((resolve, reject) => {
Gio.AppInfo.launch_default_for_uri_async(uri, context, cancel, (o, res) => {
try {
Gio.AppInfo.launch_default_for_uri_finish(res);
resolve();
} catch (e) {
reject(e);
}
});
});
}
_mountEnclosingVolume(flags, mountOp, cancel) {
return new Promise((resolve, reject) => {
this.file.mount_enclosing_volume(flags, mountOp, cancel, (o, res) => {
try {
this.file.mount_enclosing_volume_finish(res);
resolve();
} catch (e) {
reject(e);
}
});
});
}
}
};
Signals.addSignalMethods(PlaceInfo.prototype);
class RootInfo extends PlaceInfo {
_init() {
super._init('devices', Gio.File.new_for_path('/'), _('Computer'));
super._init('devices', Gio.File.new_for_path('/'), _("Computer"));
let busName = 'org.freedesktop.hostname1';
let objPath = '/org/freedesktop/hostname1';
@@ -155,7 +142,7 @@ class RootInfo extends PlaceInfo {
this._proxy = obj;
this._proxy.connect('g-properties-changed',
this._propertiesChanged.bind(this));
this._propertiesChanged.bind(this));
this._propertiesChanged(obj);
});
}
@@ -168,7 +155,7 @@ class RootInfo extends PlaceInfo {
// GDBusProxy will emit a g-properties-changed when hostname1 goes down
// ignore it
if (proxy.g_name_owner) {
this.name = proxy.PrettyHostname || _('Computer');
this.name = proxy.PrettyHostname || _("Computer");
this.emit('changed');
}
}
@@ -180,7 +167,7 @@ class RootInfo extends PlaceInfo {
}
super.destroy();
}
}
};
class PlaceDeviceInfo extends PlaceInfo {
@@ -198,25 +185,24 @@ class PlaceDeviceInfo extends PlaceInfo {
}
eject() {
let unmountArgs = [
Gio.MountUnmountFlags.NONE,
new ShellMountOperation.ShellMountOperation(this._mount).mountOp,
null, // Gio.Cancellable
];
let mountOp = new ShellMountOperation.ShellMountOperation(this._mount);
if (this._mount.can_eject()) {
this._mount.eject_with_operation(...unmountArgs,
this._ejectFinish.bind(this));
} else {
this._mount.unmount_with_operation(...unmountArgs,
this._unmountFinish.bind(this));
}
if (this._mount.can_eject())
this._mount.eject_with_operation(Gio.MountUnmountFlags.NONE,
mountOp.mountOp,
null, // Gio.Cancellable
this._ejectFinish.bind(this));
else
this._mount.unmount_with_operation(Gio.MountUnmountFlags.NONE,
mountOp.mountOp,
null, // Gio.Cancellable
this._unmountFinish.bind(this));
}
_ejectFinish(mount, result) {
try {
mount.eject_with_operation_finish(result);
} catch (e) {
} catch(e) {
this._reportFailure(e);
}
}
@@ -224,16 +210,16 @@ class PlaceDeviceInfo extends PlaceInfo {
_unmountFinish(mount, result) {
try {
mount.unmount_with_operation_finish(result);
} catch (e) {
} catch(e) {
this._reportFailure(e);
}
}
_reportFailure(exception) {
let msg = _('Ejecting drive “%s” failed:').format(this._mount.get_name());
let msg = _("Ejecting drive “%s” failed:").format(this._mount.get_name());
Main.notifyError(msg, exception.message);
}
}
};
class PlaceVolumeInfo extends PlaceInfo {
_init(kind, volume) {
@@ -259,7 +245,7 @@ class PlaceVolumeInfo extends PlaceInfo {
getIcon() {
return this._volume.get_symbolic_icon();
}
}
};
const DEFAULT_DIRECTORIES = [
GLib.UserDirectory.DIRECTORY_DOCUMENTS,
@@ -279,8 +265,9 @@ var PlacesManager = class {
};
this._settings = new Gio.Settings({ schema_id: BACKGROUND_SCHEMA });
this._showDesktopIconsChangedId = this._settings.connect(
'changed::show-desktop-icons', this._updateSpecials.bind(this));
this._showDesktopIconsChangedId =
this._settings.connect('changed::show-desktop-icons',
this._updateSpecials.bind(this));
this._updateSpecials();
/*
@@ -290,7 +277,7 @@ var PlacesManager = class {
this._connectVolumeMonitorSignals();
this._updateMounts();
this._bookmarksFile = this._findBookmarksFile();
this._bookmarksFile = this._findBookmarksFile()
this._bookmarkTimeoutId = 0;
this._monitor = null;
@@ -300,12 +287,11 @@ var PlacesManager = class {
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
this._bookmarkTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, 100, () => {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
});
this._bookmarkTimeoutId = Mainloop.timeout_add(100, () => {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
});
});
this._reloadBookmarks();
@@ -313,17 +299,9 @@ var PlacesManager = class {
}
_connectVolumeMonitorSignals() {
const signals = [
'volume-added',
'volume-removed',
'volume-changed',
'mount-added',
'mount-removed',
'mount-changed',
'drive-connected',
'drive-disconnected',
'drive-changed',
];
const signals = ['volume-added', 'volume-removed', 'volume-changed',
'mount-added', 'mount-removed', 'mount-changed',
'drive-connected', 'drive-disconnected', 'drive-changed'];
this._volumeMonitorSignals = [];
let func = this._updateMounts.bind(this);
@@ -344,19 +322,18 @@ var PlacesManager = class {
if (this._monitor)
this._monitor.cancel();
if (this._bookmarkTimeoutId)
GLib.source_remove(this._bookmarkTimeoutId);
Mainloop.source_remove(this._bookmarkTimeoutId);
}
_updateSpecials() {
this._places.special.forEach(p => p.destroy());
this._places.special.forEach(p => { p.destroy(); });
this._places.special = [];
let homePath = GLib.get_home_dir();
this._places.special.push(new PlaceInfo(
'special',
Gio.File.new_for_path(homePath),
_('Home')));
this._places.special.push(new PlaceInfo('special',
Gio.File.new_for_path(homePath),
_("Home")));
let specials = [];
let dirs = DEFAULT_DIRECTORIES.slice();
@@ -366,16 +343,14 @@ var PlacesManager = class {
for (let i = 0; i < dirs.length; i++) {
let specialPath = GLib.get_user_special_dir(dirs[i]);
if (!specialPath || specialPath === homePath)
if (specialPath == null || specialPath == homePath)
continue;
let file = Gio.File.new_for_path(specialPath), info;
try {
info = new PlaceInfo('special', file);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
continue;
throw e;
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
continue;
}
specials.push(info);
@@ -391,31 +366,30 @@ var PlacesManager = class {
let networkMounts = [];
let networkVolumes = [];
this._places.devices.forEach(p => p.destroy());
this._places.devices.forEach(p => { p.destroy(); });
this._places.devices = [];
this._places.network.forEach(p => p.destroy());
this._places.network.forEach(p => { p.destroy(); });
this._places.network = [];
/* Add standard places */
this._places.devices.push(new RootInfo());
this._places.network.push(new PlaceInfo(
'network',
Gio.File.new_for_uri('network:///'),
_('Browse Network'),
'network-workgroup-symbolic'));
this._places.network.push(new PlaceInfo('network',
Gio.File.new_for_uri('network:///'),
_("Browse Network"),
'network-workgroup-symbolic'));
/* first go through all connected drives */
let drives = this._volumeMonitor.get_connected_drives();
for (let i = 0; i < drives.length; i++) {
let volumes = drives[i].get_volumes();
for (let j = 0; j < volumes.length; j++) {
for(let j = 0; j < volumes.length; j++) {
let identifier = volumes[j].get_identifier('class');
if (identifier && identifier.includes('network')) {
networkVolumes.push(volumes[j]);
} else {
let mount = volumes[j].get_mount();
if (mount)
if(mount != null)
this._addMount('devices', mount);
}
}
@@ -423,8 +397,8 @@ var PlacesManager = class {
/* add all volumes that is not associated with a drive */
let volumes = this._volumeMonitor.get_volumes();
for (let i = 0; i < volumes.length; i++) {
if (volumes[i].get_drive())
for(let i = 0; i < volumes.length; i++) {
if(volumes[i].get_drive() != null)
continue;
let identifier = volumes[i].get_identifier('class');
@@ -432,18 +406,18 @@ var PlacesManager = class {
networkVolumes.push(volumes[i]);
} else {
let mount = volumes[i].get_mount();
if (mount)
if(mount != null)
this._addMount('devices', mount);
}
}
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
let mounts = this._volumeMonitor.get_mounts();
for (let i = 0; i < mounts.length; i++) {
if (mounts[i].is_shadowed())
for(let i = 0; i < mounts.length; i++) {
if(mounts[i].is_shadowed())
continue;
if (mounts[i].get_volume())
if(mounts[i].get_volume())
continue;
let root = mounts[i].get_default_location();
@@ -463,9 +437,9 @@ var PlacesManager = class {
this._addVolume('network', networkVolumes[i]);
}
for (let i = 0; i < networkMounts.length; i++)
for (let i = 0; i < networkMounts.length; i++) {
this._addMount('network', networkMounts[i]);
}
this.emit('devices-updated');
this.emit('network-updated');
@@ -496,7 +470,7 @@ var PlacesManager = class {
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
let components = line.split(' ');
let [bookmark] = components;
let bookmark = components[0];
if (!bookmark)
continue;
@@ -506,16 +480,16 @@ var PlacesManager = class {
continue;
let duplicate = false;
for (let j = 0; j < this._places.special.length; j++) {
if (file.equal(this._places.special[j].file)) {
for (let i = 0; i < this._places.special.length; i++) {
if (file.equal(this._places.special[i].file)) {
duplicate = true;
break;
}
}
if (duplicate)
continue;
for (let j = 0; j < bookmarks.length; j++) {
if (file.equal(bookmarks[j].file)) {
for (let i = 0; i < bookmarks.length; i++) {
if (file.equal(bookmarks[i].file)) {
duplicate = true;
break;
}
@@ -540,10 +514,8 @@ var PlacesManager = class {
try {
devItem = new PlaceDeviceInfo(kind, mount);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
return;
throw e;
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
return;
}
this._places[kind].push(devItem);
@@ -554,10 +526,8 @@ var PlacesManager = class {
try {
volItem = new PlaceVolumeInfo(kind, volume);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
return;
throw e;
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
return;
}
this._places[kind].push(volItem);

View File

@@ -1,4 +1,3 @@
/* exported enable disable */
/* Screenshot Window Sizer for Gnome Shell
*
* Copyright (c) 2013 Owen Taylor <otaylor@redhat.com>
@@ -19,14 +18,21 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
const { Clutter, Meta, Shell, St } = imports.gi;
const Gio = imports.gi.Gio;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const MESSAGE_FADE_TIME = 2000;
const MESSAGE_FADE_TIME = 2;
let text;
let text, button;
function hideMessage() {
text.destroy();
@@ -39,22 +45,20 @@ function flashMessage(message) {
Main.uiGroup.add_actor(text);
}
text.remove_all_transitions();
Tweener.removeTweens(text);
text.text = message;
text.opacity = 255;
let monitor = Main.layoutManager.primaryMonitor;
text.set_position(
monitor.x + Math.floor(monitor.width / 2 - text.width / 2),
monitor.y + Math.floor(monitor.height / 2 - text.height / 2));
text.set_position(monitor.x + Math.floor(monitor.width / 2 - text.width / 2),
monitor.y + Math.floor(monitor.height / 2 - text.height / 2));
text.ease({
opacity: 0,
duration: MESSAGE_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: hideMessage,
});
Tweener.addTween(text,
{ opacity: 0,
time: MESSAGE_FADE_TIME,
transition: 'easeOutQuad',
onComplete: hideMessage });
}
let SIZES = [
@@ -62,28 +66,25 @@ let SIZES = [
[800, 450],
[1024, 576],
[1200, 675],
[1600, 900],
[360, 654], // Phone portrait maximized
[720, 360], // Phone landscape fullscreen
[1600, 900]
];
function cycleScreenshotSizes(display, window, binding) {
function cycleScreenshotSizes(display, screen, window, binding) {
// Probably this isn't useful with 5 sizes, but you can decrease instead
// of increase by holding down shift.
let modifiers = binding.get_modifiers();
let backwards = (modifiers & Meta.VirtualModifier.SHIFT_MASK) !== 0;
let backwards = (modifiers & Meta.VirtualModifier.SHIFT_MASK) != 0;
// Unmaximize first
if (window.get_maximized() !== 0)
window.unmaximize(Meta.MaximizeFlags.BOTH);
if (window.maximized_horizontally || window.maximizedVertically)
window.unmaximize(Meta.MaximizeFlags.HORIZONTAL | Meta.MaximizeFlags.VERTICAL);
let workArea = window.get_work_area_current_monitor();
let outerRect = window.get_frame_rect();
// Double both axes if on a hidpi display
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let scaledSizes = SIZES.map(size => size.map(wh => wh * scaleFactor))
.filter(([w, h]) => w <= workArea.width && h <= workArea.height);
let scaledSizes = SIZES.map(size => size.map(wh => wh * scaleFactor));
// Find the nearest 16:9 size for the current window size
let nearestIndex;
@@ -98,7 +99,7 @@ function cycleScreenshotSizes(display, window, binding) {
// get the best initial window size
let error = Math.abs(width - outerRect.width) + Math.abs(height - outerRect.height);
if (nearestIndex === undefined || error < nearestError) {
if (nearestIndex == null || error < nearestError) {
nearestIndex = i;
nearestError = error;
}
@@ -106,7 +107,10 @@ function cycleScreenshotSizes(display, window, binding) {
// get the next size up or down from ideal
let newIndex = (nearestIndex + (backwards ? -1 : 1)) % scaledSizes.length;
let [newWidth, newHeight] = scaledSizes[newIndex];
let newWidth, newHeight;
[newWidth, newHeight] = scaledSizes[newIndex];
if (newWidth > workArea.width || newHeight > workArea.height)
[newWidth, newHeight] = scaledSizes[0];
// Push the window onscreen if it would be resized offscreen
let newX = outerRect.x;
@@ -120,32 +124,34 @@ function cycleScreenshotSizes(display, window, binding) {
let newOuterRect = window.get_frame_rect();
let message = '%d×%d'.format(
newOuterRect.width / scaleFactor,
newOuterRect.height / scaleFactor);
(newOuterRect.width / scaleFactor),
(newOuterRect.height / scaleFactor));
// The new size might have been constrained by geometry hints (e.g. for
// a terminal) - in that case, include the actual ratio to the message
// we flash
let actualNumerator = 9 * newOuterRect.width / newOuterRect.height;
let actualNumerator = (newOuterRect.width / newOuterRect.height) * 9;
if (Math.abs(actualNumerator - 16) > 0.01)
message += ' (%.2f:9)'.format(actualNumerator);
flashMessage(message);
}
function init() {
}
function enable() {
Main.wm.addKeybinding(
'cycle-screenshot-sizes',
ExtensionUtils.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
Main.wm.addKeybinding(
'cycle-screenshot-sizes-backward',
ExtensionUtils.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW | Meta.KeyBindingFlags.IS_REVERSED,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
Main.wm.addKeybinding('cycle-screenshot-sizes',
Convenience.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
Main.wm.addKeybinding('cycle-screenshot-sizes-backward',
Convenience.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW |
Meta.KeyBindingFlags.IS_REVERSED,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
}
function disable() {

View File

@@ -1,21 +1,23 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Load shell theme from ~/.local/share/themes/name/gnome-shell
/* exported init */
// Load shell theme from ~/.themes/name/gnome-shell
const { Gio, GLib } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Main = imports.ui.main;
const SETTINGS_KEY = 'name';
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
class ThemeManager {
constructor() {
this._settings = ExtensionUtils.getSettings();
this._settings = Convenience.getSettings();
}
enable() {
this._changedId = this._settings.connect(`changed::${SETTINGS_KEY}`, this._changeTheme.bind(this));
this._changedId = this._settings.connect('changed::'+SETTINGS_KEY, this._changeTheme.bind(this));
this._changeTheme();
}
@@ -30,32 +32,36 @@ class ThemeManager {
}
_changeTheme() {
let stylesheet = null;
let themeName = this._settings.get_string(SETTINGS_KEY);
let _stylesheet = null;
let _themeName = this._settings.get_string(SETTINGS_KEY);
if (themeName) {
let stylesheetPaths = [
[GLib.get_home_dir(), '.themes'],
[GLib.get_user_data_dir(), 'themes'],
...GLib.get_system_data_dirs().map(dir => [dir, 'themes']),
].map(themeDir => GLib.build_filenamev([
...themeDir, themeName, 'gnome-shell', 'gnome-shell.css',
]));
stylesheet = stylesheetPaths.find(path => {
let file = Gio.file_new_for_path(path);
return file.query_exists(null);
});
if (_themeName) {
let _userCssStylesheet = GLib.get_home_dir() + '/.themes/' + _themeName + '/gnome-shell/gnome-shell.css';
let file = Gio.file_new_for_path(_userCssStylesheet);
if (file.query_exists(null))
_stylesheet = _userCssStylesheet;
else {
let sysdirs = GLib.get_system_data_dirs();
sysdirs.unshift(GLib.get_user_data_dir());
for (let i = 0; i < sysdirs.length; i++) {
_userCssStylesheet = sysdirs[i] + '/themes/' + _themeName + '/gnome-shell/gnome-shell.css';
let file = Gio.file_new_for_path(_userCssStylesheet);
if (file.query_exists(null)) {
_stylesheet = _userCssStylesheet;
break;
}
}
}
}
if (stylesheet)
global.log(`loading user theme: ${stylesheet}`);
if (_stylesheet)
global.log('loading user theme: ' + _stylesheet);
else
global.log('loading default theme (Adwaita)');
Main.setThemeStylesheet(stylesheet);
Main.setThemeStylesheet(_stylesheet);
Main.loadTheme();
}
}
};
function init() {
return new ThemeManager();

View File

@@ -4,39 +4,36 @@
border-top-width: 1px;
border-bottom-width: 0px;
height: 2.25em ;
padding: 2px;
}
.bottom-panel .window-button > StWidget,
.bottom-panel .window-picker-toggle > StWidget {
color: #2e3436;
background-color: #eee;
border-radius: 3px;
padding: 3px 6px 1px;
box-shadow: none;
text-shadow: none;
border: 1px solid rgba(0,0,0,0.2);
}
.bottom-panel .window-button > StWidget {
background-gradient-drection: vertical;
background-color: #fff;
background-gradient-start: #fff;
background-gradient-end: #eee;
color: #000;
-st-natural-width: 18.7em;
max-width: 18.75em;
color: #2e3436;
background-color: #eee;
border-radius: 2px;
padding: 3px 6px 1px;
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
text-shadow: 0 0 transparent;
}
.bottom-panel .window-button:hover > StWidget,
.bottom-panel .window-picker-toggle:hover > StWidget {
.bottom-panel .window-button:hover > StWidget {
background-color: #f9f9f9;
}
.bottom-panel .window-button:active > StWidget,
.bottom-panel .window-button:focus > StWidget {
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5);
}
.bottom-panel .window-button.focused > StWidget,
.bottom-panel .window-picker-toggle:checked > StWidget {
background-color: #ccc;
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
.bottom-panel .window-button.focused > StWidget {
background-color: #ddd;
box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5);
}
.bottom-panel .window-button.focused:hover > StWidget {
@@ -45,24 +42,5 @@
.bottom-panel .window-button.minimized > StWidget {
color: #888;
box-shadow: none;
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
}
/* workspace switcher */
.window-list-workspace-indicator .workspace {
background-color: #ddd;
}
.window-list-workspace-indicator .workspace.active {
background-color: #ccc;
}
.window-list-window-preview {
background-color: #ededed;
border: 1px solid #ccc;
}
.window-list-window-preview.active {
background-color: #f6f5f4;
border: 2px solid #888;
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ extension_data += configure_file(
configuration: metadata_conf
)
extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js')
extension_sources += files('prefs.js')
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
if classic_mode_enabled

View File

@@ -15,13 +15,6 @@
window list. Possible values are “never”, “auto” and “always”.
</description>
</key>
<key name="display-all-workspaces" type="b">
<default>false</default>
<summary>Show windows from all workspaces</summary>
<description>
Whether to show windows from all workspaces or only the current one.
</description>
</key>
<key name="show-on-all-monitors" type="b">
<default>false</default>
<summary>Show the window list on all monitors</summary>

View File

@@ -1,16 +1,19 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported init buildPrefsWidget */
const { Gio, GObject, Gtk } = imports.gi;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
function init() {
ExtensionUtils.initTranslations();
Convenience.initTranslations();
}
const WindowListPrefsWidget = GObject.registerClass(
@@ -22,31 +25,27 @@ class WindowListPrefsWidget extends Gtk.Grid {
this.row_spacing = 6;
this.orientation = Gtk.Orientation.VERTICAL;
let groupingLabel = '<b>%s</b>'.format(_('Window Grouping'));
this.add(new Gtk.Label({
label: groupingLabel, use_markup: true,
halign: Gtk.Align.START,
}));
let groupingLabel = '<b>' + _("Window Grouping") + '</b>';
this.add(new Gtk.Label({ label: groupingLabel, use_markup: true,
halign: Gtk.Align.START }));
let align = new Gtk.Alignment({ left_padding: 12 });
this.add(align);
let grid = new Gtk.Grid({
orientation: Gtk.Orientation.VERTICAL,
row_spacing: 6,
column_spacing: 6,
});
let grid = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
row_spacing: 6,
column_spacing: 6 });
align.add(grid);
this._settings = ExtensionUtils.getSettings();
this._settings = Convenience.getSettings();
let currentMode = this._settings.get_string('grouping-mode');
let range = this._settings.get_range('grouping-mode');
let modes = range.deep_unpack()[1].deep_unpack();
let modeLabels = {
'never': _('Never group windows'),
'auto': _('Group windows when space is limited'),
'always': _('Always group windows'),
'never': _("Never group windows"),
'auto': _("Group windows when space is limited"),
'always': _("Always group windows")
};
let radio = null;
@@ -54,15 +53,13 @@ class WindowListPrefsWidget extends Gtk.Grid {
let mode = modes[i];
let label = modeLabels[mode];
if (!label) {
log('Unhandled option "%s" for grouping-mode'.format(mode));
continue;
log('Unhandled option "%s" for grouping-mode'.format(mode));
continue;
}
radio = new Gtk.RadioButton({
active: currentMode === mode,
label,
group: radio,
});
radio = new Gtk.RadioButton({ active: currentMode == mode,
label: label,
group: radio });
grid.add(radio);
radio.connect('toggled', button => {
@@ -71,19 +68,10 @@ class WindowListPrefsWidget extends Gtk.Grid {
});
}
let check = new Gtk.CheckButton({
label: _('Show on all monitors'),
margin_top: 6,
});
let check = new Gtk.CheckButton({ label: _("Show on all monitors"),
margin_top: 6 });
this._settings.bind('show-on-all-monitors', check, 'active', Gio.SettingsBindFlags.DEFAULT);
this.add(check);
check = new Gtk.CheckButton({
label: _('Show windows from all workspaces'),
margin_top: 6,
});
this._settings.bind('display-all-workspaces', check, 'active', Gio.SettingsBindFlags.DEFAULT);
this.add(check);
}
});

View File

@@ -26,8 +26,9 @@
spacing: 4px;
}
.window-button > StWidget,
.window-picker-toggle > StWidget {
.window-button > StWidget {
-st-natural-width: 18.75em;
max-width: 18.75em;
color: #bbb;
background-color: black;
border-radius: 4px;
@@ -36,21 +37,7 @@
text-shadow: 1px 1px 4px rgba(0,0,0,0.8);
}
.window-picker-toggle {
padding: 3px;
}
.window-picker-toggle > StWidet {
border: 1px solid rgba(255,255,255,0.3);
}
.window-button > StWidget {
-st-natural-width: 18.75em;
max-width: 18.75em;
}
.window-button:hover > StWidget,
.window-picker-toggle:hover > StWidget {
.window-button:hover > StWidget {
color: white;
background-color: #1f1f1f;
}
@@ -60,14 +47,12 @@
box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5);
}
.window-button.focused > StWidget,
.window-picker-toggle:checked > StWidget {
.window-button.focused > StWidget {
color: white;
box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7);
}
.window-button.focused:active > StWidget,
.window-picker-toggle:checked:active > StWidget {
.window-button.focused:active > StWidget {
box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7);
}
@@ -85,50 +70,13 @@
height: 24px;
}
.window-list-workspace-indicator .status-label-bin {
background-color: rgba(200, 200, 200, .3);
border: 1px solid #cccccc;
padding: 0 3px;
margin: 3px 0;
}
.window-list-workspace-indicator .workspaces-box {
spacing: 3px;
.window-list-workspace-indicator {
padding: 3px;
}
.window-list-workspace-indicator .workspace {
border: 1px solid #cccccc;
width: 52px;
}
.window-list-workspace-indicator .workspace:first-child:last-child:ltr,
.window-list-workspace-indicator .workspace:first-child:last-child:rtl {
border-radius: 4px;
}
.window-list-workspace-indicator .workspace:first-child:ltr,
.window-list-workspace-indicator .workspace:last-child:rtl {
border-radius: 4px 0 0 4px;
}
.window-list-workspace-indicator .workspace:first-child:rtl,
.window-list-workspace-indicator .workspace:last-child:ltr {
border-radius: 0 4px 4px 0;
}
.window-list-workspace-indicator .workspace.active {
.window-list-workspace-indicator > StWidget {
background-color: rgba(200, 200, 200, .3);
}
.window-list-window-preview {
background-color: #252525;
border: 1px solid #ccc;
}
.window-list-window-preview.active {
background-color: #353535;
border: 2px solid #ccc;
border: 1px solid #cccccc;
}
.notification {

View File

@@ -1,305 +0,0 @@
/* exported WindowPicker, WindowPickerToggle */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const { WorkspacesDisplay } = imports.ui.workspacesView;
let MyWorkspacesDisplay = GObject.registerClass(
class MyWorkspacesDisplay extends WorkspacesDisplay {
_init() {
let workspaceManager = global.workspace_manager;
this._workspaceAdjustment = new St.Adjustment({
value: workspaceManager.get_active_workspace_index(),
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: workspaceManager.n_workspaces,
});
this._nWorkspacesChangedId =
workspaceManager.connect('notify::n-workspaces',
this._updateAdjustment.bind(this));
super._init(this._workspaceAdjustment);
this.add_constraint(
new Layout.MonitorConstraint({
primary: true,
work_area: true,
}));
this._workareasChangedId = global.display.connect('workareas-changed',
this._onWorkAreasChanged.bind(this));
this._onWorkAreasChanged();
}
show(...args) {
if (!this._scrollEventId) {
this._scrollEventId = Main.windowPicker.connect('scroll-event',
this._onScrollEvent.bind(this));
}
super.show(...args);
}
hide(...args) {
if (this._scrollEventId > 0)
Main.windowPicker.disconnect(this._scrollEventId);
this._scrollEventId = 0;
super.hide(...args);
}
_onWorkAreasChanged() {
let { primaryIndex } = Main.layoutManager;
let workarea = Main.layoutManager.getWorkAreaForMonitor(primaryIndex);
this.setWorkspacesFullGeometry(workarea);
}
_updateAdjustment() {
let workspaceManager = global.workspace_manager;
this._workspaceAdjustment.set({
upper: workspaceManager.n_workspaces,
value: workspaceManager.get_active_workspace_index(),
});
}
_updateWorkspacesViews() {
super._updateWorkspacesViews();
this._workspacesViews.forEach(v => {
Main.layoutManager.overviewGroup.remove_actor(v);
Main.windowPicker.add_actor(v);
});
}
_onDestroy() {
if (this._workareasChangedId)
global.display.disconnect(this._workareasChangedId);
this._workareasChangedId = 0;
if (this._nWorkspacesChangedId)
global.workspace_manager.disconnect(this._nWorkspacesNotifyId);
this._nWorkspacesNotifyId = 0;
super._onDestroy();
}
});
var WindowPicker = GObject.registerClass({
Signals: {
'open-state-changed': { param_types: [GObject.TYPE_BOOLEAN] },
},
}, class extends Clutter.Actor {
_init() {
this._visible = false;
this._modal = false;
this._overlayKeyId = 0;
this._stageKeyPressId = 0;
super._init();
this.connect('destroy', this._onDestroy.bind(this));
global.bind_property('screen-width',
this, 'width',
GObject.BindingFlags.SYNC_CREATE);
global.bind_property('screen-height',
this, 'height',
GObject.BindingFlags.SYNC_CREATE);
this._backgroundGroup = new Meta.BackgroundGroup({ reactive: true });
this.add_child(this._backgroundGroup);
this._backgroundGroup.connect('scroll-event', (a, ev) => {
this.emit('scroll-event', ev);
});
// Trick WorkspacesDisplay constructor into adding actions here
let addActionOrig = Main.overview.addAction;
Main.overview.addAction = a => this._backgroundGroup.add_action(a);
this._workspacesDisplay = new MyWorkspacesDisplay();
this.add_child(this._workspacesDisplay);
Main.overview.addAction = addActionOrig;
this._bgManagers = [];
this._monitorsChangedId = Main.layoutManager.connect('monitors-changed',
this._updateBackgrounds.bind(this));
this._updateBackgrounds();
Main.uiGroup.insert_child_below(this, global.window_group);
if (!Main.sessionMode.hasOverview) {
this._overlayKeyId = global.display.connect('overlay-key', () => {
if (!this._visible)
this.open();
else
this.close();
});
}
}
get visible() {
return this._visible;
}
open() {
if (this._visible)
return;
this._visible = true;
if (!this._syncGrab())
return;
this._fakeOverviewVisible(true);
this._shadeBackgrounds();
this._fakeOverviewAnimation();
this._workspacesDisplay.show(false);
this._stageKeyPressId = global.stage.connect('key-press-event',
(a, event) => {
let sym = event.get_key_symbol();
if (sym === Clutter.KEY_Escape) {
this.close();
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
});
this.emit('open-state-changed', this._visible);
}
close() {
if (!this._visible)
return;
this._visible = false;
if (!this._syncGrab())
return;
this._workspacesDisplay.animateFromOverview(false);
this._unshadeBackgrounds();
this._fakeOverviewAnimation(() => {
this._workspacesDisplay.hide();
this._fakeOverviewVisible(false);
});
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
this.emit('open-state-changed', this._visible);
}
_fakeOverviewAnimation(onComplete) {
Main.overview._animationInProgress = true;
GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
Overview.ANIMATION_TIME,
() => {
Main.overview._animationInProgress = false;
if (onComplete)
onComplete();
});
}
_fakeOverviewVisible(visible) {
// Fake overview state for WorkspacesDisplay
Main.overview._visible = visible;
// Hide real windows
Main.layoutManager._inOverview = visible;
Main.layoutManager._updateVisibility();
}
_syncGrab() {
if (this._visible) {
if (this._modal)
return true;
this._modal = Main.pushModal(this, {
actionMode: Shell.ActionMode.OVERVIEW,
});
if (!this._modal) {
this.hide();
return false;
}
} else if (this._modal) {
Main.popModal(this);
this._modal = false;
}
return true;
}
_onDestroy() {
if (this._monitorsChangedId)
Main.layoutManager.disconnect(this._monitorsChangedId);
this._monitorsChangedId = 0;
if (this._overlayKeyId)
global.display.disconnect(this._overlayKeyId);
this._overlayKeyId = 0;
if (this._stageKeyPressId)
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
}
_updateBackgrounds() {
Main.overview._updateBackgrounds.call(this);
}
_shadeBackgrounds() {
Main.overview._shadeBackgrounds.call(this);
}
_unshadeBackgrounds() {
Main.overview._unshadeBackgrounds.call(this);
}
});
var WindowPickerToggle = GObject.registerClass(
class WindowPickerToggle extends St.Button {
_init() {
let iconBin = new St.Widget({
layout_manager: new Clutter.BinLayout(),
});
iconBin.add_child(new St.Icon({
icon_name: 'focus-windows-symbolic',
icon_size: 16,
x_expand: true,
y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
}));
super._init({
style_class: 'window-picker-toggle',
child: iconBin,
visible: !Main.sessionMode.hasOverview,
x_fill: true,
y_fill: true,
toggle_mode: true,
});
this.connect('notify::checked', () => {
if (this.checked)
Main.windowPicker.open();
else
Main.windowPicker.close();
});
Main.windowPicker.connect('open-state-changed', () => {
this.checked = Main.windowPicker.visible;
});
}
});

View File

@@ -1,399 +0,0 @@
/* exported WorkspaceIndicator */
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
let WindowPreview = GObject.registerClass(
class WindowPreview extends St.Button {
_init(window) {
super._init({
style_class: 'window-list-window-preview',
});
this._delegate = this;
DND.makeDraggable(this, { restoreOnSuccess: true });
this._window = window;
this.connect('destroy', this._onDestroy.bind(this));
this._sizeChangedId = this._window.connect('size-changed',
this._relayout.bind(this));
this._positionChangedId = this._window.connect('position-changed',
this._relayout.bind(this));
this._minimizedChangedId = this._window.connect('notify::minimized',
this._relayout.bind(this));
this._monitorEnteredId = global.display.connect('window-entered-monitor',
this._relayout.bind(this));
this._monitorLeftId = global.display.connect('window-left-monitor',
this._relayout.bind(this));
// Do initial layout when we get a parent
let id = this.connect('parent-set', () => {
this.disconnect(id);
if (!this.get_parent())
return;
this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._laterId = 0;
this._relayout();
return false;
});
});
this._focusChangedId = global.display.connect('notify::focus-window',
this._onFocusChanged.bind(this));
this._onFocusChanged();
}
// needed for DND
get realWindow() {
return this._window.get_compositor_private();
}
_onDestroy() {
this._window.disconnect(this._sizeChangedId);
this._window.disconnect(this._positionChangedId);
this._window.disconnect(this._minimizedChangedId);
global.display.disconnect(this._monitorEnteredId);
global.display.disconnect(this._monitorLeftId);
global.display.disconnect(this._focusChangedId);
if (this._laterId)
Meta.later_remove(this._laterId);
}
_onFocusChanged() {
if (global.display.focus_window === this._window)
this.add_style_class_name('active');
else
this.remove_style_class_name('active');
}
_relayout() {
let monitor = Main.layoutManager.findIndexForActor(this);
this.visible = monitor === this._window.get_monitor() &&
this._window.window_type !== Meta.WindowType.DESKTOP &&
this._window.showing_on_its_workspace();
if (!this.visible)
return;
let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
let hscale = this.get_parent().allocation.get_width() / workArea.width;
let vscale = this.get_parent().allocation.get_height() / workArea.height;
let frameRect = this._window.get_frame_rect();
this.set_size(
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
this.set_position(
Math.round(frameRect.x * hscale),
Math.round(frameRect.y * vscale));
}
});
let WorkspaceThumbnail = GObject.registerClass(
class WorkspaceThumbnail extends St.Button {
_init(index) {
super._init({
style_class: 'workspace',
child: new Clutter.Actor({
layout_manager: new Clutter.BinLayout(),
clip_to_allocation: true,
}),
x_fill: true,
y_fill: true,
});
this.connect('destroy', this._onDestroy.bind(this));
this._index = index;
this._delegate = this; // needed for DND
this._windowPreviews = new Map();
let workspaceManager = global.workspace_manager;
this._workspace = workspaceManager.get_workspace_by_index(index);
this._windowAddedId = this._workspace.connect('window-added',
(ws, window) => {
this._addWindow(window);
});
this._windowRemovedId = this._workspace.connect('window-removed',
(ws, window) => {
this._removeWindow(window);
});
this._restackedId = global.display.connect('restacked',
this._onRestacked.bind(this));
this._workspace.list_windows().forEach(w => this._addWindow(w));
this._onRestacked();
}
acceptDrop(source) {
if (!source.realWindow)
return false;
let window = source.realWindow.get_meta_window();
this._moveWindow(window);
return true;
}
handleDragOver(source) {
if (source.realWindow)
return DND.DragMotionResult.MOVE_DROP;
else
return DND.DragMotionResult.CONTINUE;
}
_addWindow(window) {
if (this._windowPreviews.has(window))
return;
let preview = new WindowPreview(window);
preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
this._windowPreviews.set(window, preview);
this.child.add_child(preview);
}
_removeWindow(window) {
let preview = this._windowPreviews.get(window);
if (!preview)
return;
this._windowPreviews.delete(window);
preview.destroy();
}
_onRestacked() {
let lastPreview = null;
let windows = global.get_window_actors().map(a => a.meta_window);
for (let i = 0; i < windows.length; i++) {
let preview = this._windowPreviews.get(windows[i]);
if (!preview)
continue;
this.child.set_child_above_sibling(preview, lastPreview);
lastPreview = preview;
}
}
_moveWindow(window) {
let monitorIndex = Main.layoutManager.findIndexForActor(this);
if (monitorIndex !== window.get_monitor())
window.move_to_monitor(monitorIndex);
window.change_workspace_by_index(this._index, false);
}
on_clicked() {
let ws = global.workspace_manager.get_workspace_by_index(this._index);
if (ws)
ws.activate(global.get_current_time());
}
_onDestroy() {
this._workspace.disconnect(this._windowAddedId);
this._workspace.disconnect(this._windowRemovedId);
global.display.disconnect(this._restackedId);
}
});
var WorkspaceIndicator = GObject.registerClass(
class WorkspaceIndicator extends PanelMenu.Button {
_init() {
super._init(0.0, _('Workspace Indicator'), true);
this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
this.add_style_class_name('window-list-workspace-indicator');
this.menu.actor.remove_style_class_name('panel-menu');
let container = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this.add_actor(container);
let workspaceManager = global.workspace_manager;
this._currentWorkspace = workspaceManager.get_active_workspace_index();
this._statusLabel = new St.Label({ text: this._getStatusText() });
this._statusBin = new St.Bin({
style_class: 'status-label-bin',
x_expand: true,
y_expand: true,
child: this._statusLabel,
});
container.add_actor(this._statusBin);
this._thumbnailsBox = new St.BoxLayout({
style_class: 'workspaces-box',
y_expand: true,
reactive: true,
});
this._thumbnailsBox.connect('scroll-event',
this._onScrollEvent.bind(this));
container.add_actor(this._thumbnailsBox);
this._workspacesItems = [];
this._workspaceManagerSignals = [
workspaceManager.connect('notify::n-workspaces',
this._nWorkspacesChanged.bind(this)),
workspaceManager.connect_after('workspace-switched',
this._onWorkspaceSwitched.bind(this)),
workspaceManager.connect('notify::layout-rows',
this._onWorkspaceOrientationChanged.bind(this)),
];
this.connect('scroll-event', this._onScrollEvent.bind(this));
this._updateMenu();
this._updateThumbnails();
this._onWorkspaceOrientationChanged();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
this._settingsChangedId = this._settings.connect(
'changed::workspace-names', this._updateMenuLabels.bind(this));
}
_onDestroy() {
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
if (this._settingsChangedId) {
this._settings.disconnect(this._settingsChangedId);
this._settingsChangedId = 0;
}
super._onDestroy();
}
_onWorkspaceOrientationChanged() {
let vertical = global.workspace_manager.layout_rows === -1;
this.reactive = vertical;
this._statusBin.visible = vertical;
this._thumbnailsBox.visible = !vertical;
}
_onWorkspaceSwitched() {
let workspaceManager = global.workspace_manager;
this._currentWorkspace = workspaceManager.get_active_workspace_index();
this._updateMenuOrnament();
this._updateActiveThumbnail();
this._statusLabel.set_text(this._getStatusText());
}
_nWorkspacesChanged() {
this._updateMenu();
this._updateThumbnails();
}
_updateMenuOrnament() {
for (let i = 0; i < this._workspacesItems.length; i++) {
this._workspacesItems[i].setOrnament(i === this._currentWorkspace
? PopupMenu.Ornament.DOT
: PopupMenu.Ornament.NONE);
}
}
_updateActiveThumbnail() {
let thumbs = this._thumbnailsBox.get_children();
for (let i = 0; i < thumbs.length; i++) {
if (i === this._currentWorkspace)
thumbs[i].add_style_class_name('active');
else
thumbs[i].remove_style_class_name('active');
}
}
_getStatusText() {
let workspaceManager = global.workspace_manager;
let current = workspaceManager.get_active_workspace_index();
let total = workspaceManager.n_workspaces;
return '%d / %d'.format(current + 1, total);
}
_updateMenuLabels() {
for (let i = 0; i < this._workspacesItems.length; i++) {
let item = this._workspacesItems[i];
let name = Meta.prefs_get_workspace_name(i);
item.label.text = name;
}
}
_updateMenu() {
let workspaceManager = global.workspace_manager;
this.menu.removeAll();
this._workspacesItems = [];
this._currentWorkspace = workspaceManager.get_active_workspace_index();
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
let name = Meta.prefs_get_workspace_name(i);
let item = new PopupMenu.PopupMenuItem(name);
item.workspaceId = i;
item.connect('activate', () => {
this._activate(item.workspaceId);
});
if (i === this._currentWorkspace)
item.setOrnament(PopupMenu.Ornament.DOT);
this.menu.addMenuItem(item);
this._workspacesItems[i] = item;
}
this._statusLabel.set_text(this._getStatusText());
}
_updateThumbnails() {
let workspaceManager = global.workspace_manager;
this._thumbnailsBox.destroy_all_children();
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
let thumb = new WorkspaceThumbnail(i);
this._thumbnailsBox.add_actor(thumb);
}
this._updateActiveThumbnail();
}
_activate(index) {
let workspaceManager = global.workspace_manager;
if (index >= 0 && index < workspaceManager.n_workspaces) {
let metaWorkspace = workspaceManager.get_workspace_by_index(index);
metaWorkspace.activate(global.get_current_time());
}
}
_onScrollEvent(actor, event) {
let direction = event.get_scroll_direction();
let diff = 0;
if (direction === Clutter.ScrollDirection.DOWN)
diff = 1;
else if (direction === Clutter.ScrollDirection.UP)
diff = -1;
else
return;
let newIndex = this._currentWorkspace + diff;
this._activate(newIndex);
}
_allocate(actor, box, flags) {
if (actor.get_n_children() > 0)
actor.get_first_child().allocate(box, flags);
}
});

View File

@@ -1,74 +1,58 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported init */
const { Clutter, GObject, St } = imports.gi;
const Clutter = imports.gi.Clutter;
const Mainloop = imports.mainloop;
const St = imports.gi.St;
const Main = imports.ui.main;
const Workspace = imports.ui.workspace;
const WorkspacesView = imports.ui.workspacesView;
class MyWindowOverlay extends Workspace.WindowOverlay {
constructor(windowClone, parentActor) {
super(windowClone, parentActor);
this._id = null;
this._text = new St.Label({
style_class: 'extension-windowsNavigator-window-tooltip',
visible: false,
});
parentActor.add_actor(this._text);
function injectToFunction(parent, name, func) {
let origin = parent[name];
parent[name] = function() {
let ret;
ret = origin.apply(this, arguments);
if (ret === undefined)
ret = func.apply(this, arguments);
return ret;
}
return origin;
}
showTooltip() {
this._parentActor.set_child_below_sibling(this._text, null);
let winInjections, workspaceInjections, workViewInjections, createdActors, connectedSignals;
function resetState() {
winInjections = { };
workspaceInjections = { };
workViewInjections = { };
createdActors = [ ];
connectedSignals = [ ];
}
function enable() {
resetState();
Workspace.WindowOverlay.prototype.showTooltip = function() {
this._text.raise_top();
this._text.show();
this._text.text = (this._windowClone.slotId + 1).toString();
}
winInjections['showTooltip'] = undefined;
hideTooltip() {
Workspace.WindowOverlay.prototype.hideTooltip = function() {
if (this._text && this._text.visible)
this._text.hide();
}
winInjections['hideTooltip'] = undefined;
relayout(animate) {
super.relayout(animate);
let [cloneX, cloneY, cloneWidth_, cloneHeight_] = this._windowClone.slot;
let textX = cloneX - 2;
let textY = cloneY - 2;
this._text.set_position(Math.floor(textX) + 5, Math.floor(textY) + 5);
this._parentActor.set_child_below_sibling(this._text, null);
}
}
var MyWorkspace = GObject.registerClass(
class MyWorkspace extends Workspace.Workspace {
_init(metaWorkspace, monitorIndex) {
super._init(metaWorkspace, monitorIndex);
if (metaWorkspace && metaWorkspace.index() < 9) {
this._tip = new St.Label({
style_class: 'extension-windowsNavigator-window-tooltip',
visible: false,
});
this.add_actor(this._tip);
this.connect('notify::scale-x', () => {
this._tip.set_scale(1 / this.scale_x, 1 / this.scale_x);
});
} else {
this._tip = null;
}
}
showTooltip() {
if (!this._tip || !this._actualGeometry)
Workspace.Workspace.prototype.showTooltip = function() {
if (this._tip == null || this._actualGeometry == null)
return;
this._tip.text = (this.metaWorkspace.index() + 1).toString();
// Hand code this instead of using _getSpacingAndPadding
// because that fails on empty workspaces
let node = this.get_theme_node();
let node = this.actor.get_theme_node();
let padding = {
left: node.get_padding(St.Side.LEFT),
top: node.get_padding(St.Side.TOP),
@@ -80,106 +64,90 @@ class MyWorkspace extends Workspace.Workspace {
this._tip.x = area.x;
this._tip.y = area.y;
this._tip.show();
this.set_child_below_sibling(this._tip, null);
this._tip.raise_top();
}
workspaceInjections['showTooltip'] = undefined;
hideTooltip() {
if (!this._tip)
Workspace.Workspace.prototype.hideTooltip = function() {
if (this._tip == null)
return;
if (!this._tip.get_parent())
return;
this._tip.hide();
}
workspaceInjections['hideTooltip'] = undefined;
getWindowWithTooltip(id) {
Workspace.Workspace.prototype.getWindowWithTooltip = function(id) {
for (let i = 0; i < this._windows.length; i++) {
if (this._windows[i].slotId + 1 === id)
if ((this._windows[i].slotId + 1) == id)
return this._windows[i].metaWindow;
}
return null;
}
workspaceInjections['getWindowWithTooltip'] = undefined;
showWindowsTooltips() {
Workspace.Workspace.prototype.showWindowsTooltips = function() {
for (let i in this._windowOverlays) {
if (this._windowOverlays[i])
if (this._windowOverlays[i] != null)
this._windowOverlays[i].showTooltip();
}
}
workspaceInjections['showWindowsTooltips'] = undefined;
hideWindowsTooltips() {
Workspace.Workspace.prototype.hideWindowsTooltips = function() {
for (let i in this._windowOverlays) {
if (this._windowOverlays[i])
if (this._windowOverlays[i] != null)
this._windowOverlays[i].hideTooltip();
}
}
});
workspaceInjections['hideWindowsTooltips'] = undefined;
var MyWorkspacesView = GObject.registerClass(
class MyWorkspacesView extends WorkspacesView.WorkspacesView {
_init(width, height, x, y, workspaces) {
super._init(width, height, x, y, workspaces);
this._pickWorkspace = false;
this._pickWindow = false;
this._keyPressEventId =
global.stage.connect('key-press-event', this._onKeyPress.bind(this));
this._keyReleaseEventId =
global.stage.connect('key-release-event', this._onKeyRelease.bind(this));
}
_onDestroy() {
super._onDestroy();
global.stage.disconnect(this._keyPressEventId);
global.stage.disconnect(this._keyReleaseEventId);
}
_hideTooltips() {
if (global.stage.get_key_focus() === global.stage)
WorkspacesView.WorkspacesView.prototype._hideTooltips = function() {
if (global.stage.get_key_focus() == global.stage)
global.stage.set_key_focus(this._prevFocusActor);
this._pickWindow = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].hideWindowsTooltips();
}
workViewInjections['_hideTooltips'] = undefined;
_hideWorkspacesTooltips() {
WorkspacesView.WorkspacesView.prototype._hideWorkspacesTooltips = function() {
global.stage.set_key_focus(this._prevFocusActor);
this._pickWorkspace = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].hideTooltip();
}
workViewInjections['_hideWorkspacesTooltips'] = undefined;
_onKeyRelease(s, o) {
WorkspacesView.WorkspacesView.prototype._onKeyRelease = function(s, o) {
if (this._pickWindow &&
(o.get_key_symbol() === Clutter.KEY_Alt_L ||
o.get_key_symbol() === Clutter.KEY_Alt_R))
(o.get_key_symbol() == Clutter.KEY_Alt_L ||
o.get_key_symbol() == Clutter.KEY_Alt_R))
this._hideTooltips();
if (this._pickWorkspace &&
(o.get_key_symbol() === Clutter.KEY_Control_L ||
o.get_key_symbol() === Clutter.KEY_Control_R))
(o.get_key_symbol() == Clutter.KEY_Control_L ||
o.get_key_symbol() == Clutter.KEY_Control_R))
this._hideWorkspacesTooltips();
}
workViewInjections['_onKeyRelease'] = undefined;
_onKeyPress(s, o) {
let { viewSelector } = Main.overview;
if (viewSelector._activePage !== viewSelector._workspacesPage)
WorkspacesView.WorkspacesView.prototype._onKeyPress = function(s, o) {
if(Main.overview.viewSelector._activePage != Main.overview.viewSelector._workspacesPage)
return false;
let workspaceManager = global.workspace_manager;
if ((o.get_key_symbol() === Clutter.KEY_Alt_L ||
o.get_key_symbol() === Clutter.KEY_Alt_R) &&
!this._pickWorkspace) {
if ((o.get_key_symbol() == Clutter.KEY_Alt_L ||
o.get_key_symbol() == Clutter.KEY_Alt_R)
&& !this._pickWorkspace) {
this._prevFocusActor = global.stage.get_key_focus();
global.stage.set_key_focus(null);
this._active = workspaceManager.get_active_workspace_index();
this._active = global.screen.get_active_workspace_index();
this._pickWindow = true;
this._workspaces[workspaceManager.get_active_workspace_index()].showWindowsTooltips();
this._workspaces[global.screen.get_active_workspace_index()].showWindowsTooltips();
return true;
}
if ((o.get_key_symbol() === Clutter.KEY_Control_L ||
o.get_key_symbol() === Clutter.KEY_Control_R) &&
!this._pickWindow) {
if ((o.get_key_symbol() == Clutter.KEY_Control_L ||
o.get_key_symbol() == Clutter.KEY_Control_R)
&& !this._pickWindow) {
this._prevFocusActor = global.stage.get_key_focus();
global.stage.set_key_focus(null);
this._pickWorkspace = true;
@@ -188,17 +156,17 @@ class MyWorkspacesView extends WorkspacesView.WorkspacesView {
return true;
}
if (global.stage.get_key_focus() !== global.stage)
if (global.stage.get_key_focus() != global.stage)
return false;
// ignore shift presses, they're required to get numerals in azerty keyboards
if ((this._pickWindow || this._pickWorkspace) &&
(o.get_key_symbol() === Clutter.KEY_Shift_L ||
o.get_key_symbol() === Clutter.KEY_Shift_R))
(o.get_key_symbol() == Clutter.KEY_Shift_L ||
o.get_key_symbol() == Clutter.KEY_Shift_R))
return true;
if (this._pickWindow) {
if (this._active !== workspaceManager.get_active_workspace_index()) {
if (this._active != global.screen.get_active_workspace_index()) {
this._hideTooltips();
return false;
}
@@ -240,28 +208,82 @@ class MyWorkspacesView extends WorkspacesView.WorkspacesView {
}
return false;
}
});
workViewInjections['_onKeyPress'] = undefined;
class Extension {
constructor() {
this._origWindowOverlay = Workspace.WindowOverlay;
this._origWorkspace = Workspace.Workspace;
this._origWorkspacesView = WorkspacesView.WorkspacesView;
}
winInjections['_init'] = injectToFunction(Workspace.WindowOverlay.prototype, '_init', function(windowClone, parentActor) {
this._id = null;
createdActors.push(this._text = new St.Label({ style_class: 'extension-windowsNavigator-window-tooltip' }));
this._text.hide();
parentActor.add_actor(this._text);
});
enable() {
Workspace.WindowOverlay = MyWindowOverlay;
Workspace.Workspace = MyWorkspace;
WorkspacesView.WorkspacesView = MyWorkspacesView;
}
winInjections['relayout'] = injectToFunction(Workspace.WindowOverlay.prototype, 'relayout', function(animate) {
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
disable() {
Workspace.WindowOverlay = this._origWindowOverlay;
Workspace.Workspace = this._origWorkspace;
WorkspacesView.WorkspacesView = this._origWorkspacesView;
}
let textX = cloneX - 2;
let textY = cloneY - 2;
this._text.set_position(Math.floor(textX) + 5, Math.floor(textY) + 5);
this._text.raise_top();
});
workspaceInjections['_init'] = injectToFunction(Workspace.Workspace.prototype, '_init', function(metaWorkspace) {
if (metaWorkspace && metaWorkspace.index() < 9) {
createdActors.push(this._tip = new St.Label({ style_class: 'extension-windowsNavigator-window-tooltip',
visible: false }));
this.actor.add_actor(this._tip);
let signalId = this.actor.connect('notify::scale-x', () => {
this._tip.set_scale(1 / this.actor.scale_x, 1 / this.actor.scale_x);
});
connectedSignals.push({ obj: this.actor, id: signalId });
} else
this._tip = null;
});
workViewInjections['_init'] = injectToFunction(WorkspacesView.WorkspacesView.prototype, '_init', function(width, height, x, y, workspaces) {
this._pickWorkspace = false;
this._pickWindow = false;
this._keyPressEventId =
global.stage.connect('key-press-event', this._onKeyPress.bind(this));
this._keyReleaseEventId =
global.stage.connect('key-release-event', this._onKeyRelease.bind(this));
connectedSignals.push({ obj: global.stage, id: this._keyPressEventId });
connectedSignals.push({ obj: global.stage, id: this._keyReleaseEventId });
});
workViewInjections['_onDestroy'] = injectToFunction(WorkspacesView.WorkspacesView.prototype, '_onDestroy', function() {
global.stage.disconnect(this._keyPressEventId);
global.stage.disconnect(this._keyReleaseEventId);
connectedSignals = [ ];
});
}
function removeInjection(object, injection, name) {
if (injection[name] === undefined)
delete object[name];
else
object[name] = injection[name];
}
function disable() {
let i;
for (i in workspaceInjections)
removeInjection(Workspace.Workspace.prototype, workspaceInjections, i);
for (i in winInjections)
removeInjection(Workspace.WindowOverlay.prototype, winInjections, i);
for (i in workViewInjections)
removeInjection(WorkspacesView.WorkspacesView.prototype, workViewInjections, i);
for (i of connectedSignals)
i.obj.disconnect(i.id);
for (i of createdActors)
i.destroy();
resetState();
}
function init() {
return new Extension();
/* do nothing */
}

View File

@@ -1,384 +1,113 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported init enable disable */
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
const DND = imports.ui.dnd;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const Gio = imports.gi.Gio;
const Meta = imports.gi.Meta;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Panel = imports.ui.panel;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
const WORKSPACE_KEY = 'workspace-names';
let WindowPreview = GObject.registerClass(
class WindowPreview extends St.Button {
_init(window) {
super._init({
style_class: 'workspace-indicator-window-preview',
});
this._delegate = this;
DND.makeDraggable(this, { restoreOnSuccess: true });
this._window = window;
this.connect('destroy', this._onDestroy.bind(this));
this._sizeChangedId = this._window.connect('size-changed',
this._relayout.bind(this));
this._positionChangedId = this._window.connect('position-changed',
this._relayout.bind(this));
this._minimizedChangedId = this._window.connect('notify::minimized',
this._relayout.bind(this));
this._monitorEnteredId = global.display.connect('window-entered-monitor',
this._relayout.bind(this));
this._monitorLeftId = global.display.connect('window-left-monitor',
this._relayout.bind(this));
// Do initial layout when we get a parent
let id = this.connect('parent-set', () => {
this.disconnect(id);
if (!this.get_parent())
return;
this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._laterId = 0;
this._relayout();
return false;
});
});
this._focusChangedId = global.display.connect('notify::focus-window',
this._onFocusChanged.bind(this));
this._onFocusChanged();
}
// needed for DND
get realWindow() {
return this._window.get_compositor_private();
}
_onDestroy() {
this._window.disconnect(this._sizeChangedId);
this._window.disconnect(this._positionChangedId);
this._window.disconnect(this._minimizedChangedId);
global.display.disconnect(this._monitorEnteredId);
global.display.disconnect(this._monitorLeftId);
global.display.disconnect(this._focusChangedId);
if (this._laterId)
Meta.later_remove(this._laterId);
}
_onFocusChanged() {
if (global.display.focus_window === this._window)
this.add_style_class_name('active');
else
this.remove_style_class_name('active');
}
_relayout() {
let monitor = Main.layoutManager.findIndexForActor(this);
this.visible = monitor === this._window.get_monitor() &&
this._window.window_type !== Meta.WindowType.DESKTOP &&
this._window.showing_on_its_workspace();
if (!this.visible)
return;
let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
let hscale = this.get_parent().allocation.get_width() / workArea.width;
let vscale = this.get_parent().allocation.get_height() / workArea.height;
let frameRect = this._window.get_frame_rect();
this.set_size(
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
this.set_position(
Math.round(frameRect.x * hscale),
Math.round(frameRect.y * vscale));
}
});
let WorkspaceThumbnail = GObject.registerClass(
class WorkspaceThumbnail extends St.Button {
_init(index) {
super._init({
style_class: 'workspace',
child: new Clutter.Actor({
layout_manager: new Clutter.BinLayout(),
clip_to_allocation: true,
}),
x_fill: true,
y_fill: true,
});
this.connect('destroy', this._onDestroy.bind(this));
this._index = index;
this._delegate = this; // needed for DND
this._windowPreviews = new Map();
let workspaceManager = global.workspace_manager;
this._workspace = workspaceManager.get_workspace_by_index(index);
this._windowAddedId = this._workspace.connect('window-added',
(ws, window) => {
this._addWindow(window);
});
this._windowRemovedId = this._workspace.connect('window-removed',
(ws, window) => {
this._removeWindow(window);
});
this._restackedId = global.display.connect('restacked',
this._onRestacked.bind(this));
this._workspace.list_windows().forEach(w => this._addWindow(w));
this._onRestacked();
}
acceptDrop(source) {
if (!source.realWindow)
return false;
let window = source.realWindow.get_meta_window();
this._moveWindow(window);
return true;
}
handleDragOver(source) {
if (source.realWindow)
return DND.DragMotionResult.MOVE_DROP;
else
return DND.DragMotionResult.CONTINUE;
}
_addWindow(window) {
if (this._windowPreviews.has(window))
return;
let preview = new WindowPreview(window);
preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
this._windowPreviews.set(window, preview);
this.child.add_child(preview);
}
_removeWindow(window) {
let preview = this._windowPreviews.get(window);
if (!preview)
return;
this._windowPreviews.delete(window);
preview.destroy();
}
_onRestacked() {
let lastPreview = null;
let windows = global.get_window_actors().map(a => a.meta_window);
for (let i = 0; i < windows.length; i++) {
let preview = this._windowPreviews.get(windows[i]);
if (!preview)
continue;
this.child.set_child_above_sibling(preview, lastPreview);
lastPreview = preview;
}
}
_moveWindow(window) {
let monitorIndex = Main.layoutManager.findIndexForActor(this);
if (monitorIndex !== window.get_monitor())
window.move_to_monitor(monitorIndex);
window.change_workspace_by_index(this._index, false);
}
on_clicked() {
let ws = global.workspace_manager.get_workspace_by_index(this._index);
if (ws)
ws.activate(global.get_current_time());
}
_onDestroy() {
this._workspace.disconnect(this._windowAddedId);
this._workspace.disconnect(this._windowRemovedId);
global.display.disconnect(this._restackedId);
}
});
let WorkspaceIndicator = GObject.registerClass(
class WorkspaceIndicator extends PanelMenu.Button {
_init() {
super._init(0.0, _('Workspace Indicator'));
constructor() {
super(0.0, _("Workspace Indicator"));
let container = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this.add_actor(container);
this._currentWorkspace = global.screen.get_active_workspace().index();
this.statusLabel = new St.Label({ y_align: Clutter.ActorAlign.CENTER,
text: this._labelText() });
let workspaceManager = global.workspace_manager;
this.actor.add_actor(this.statusLabel);
this._currentWorkspace = workspaceManager.get_active_workspace_index();
this._statusLabel = new St.Label({
style_class: 'panel-workspace-indicator',
y_align: Clutter.ActorAlign.CENTER,
text: this._labelText(),
});
container.add_actor(this._statusLabel);
this._thumbnailsBox = new St.BoxLayout({
style_class: 'panel-workspace-indicator-box',
y_expand: true,
reactive: true,
});
container.add_actor(this._thumbnailsBox);
this._workspacesItems = [];
this.workspacesItems = [];
this._workspaceSection = new PopupMenu.PopupMenuSection();
this.menu.addMenuItem(this._workspaceSection);
this._workspaceManagerSignals = [
workspaceManager.connect_after('notify::n-workspaces',
this._nWorkspacesChanged.bind(this)),
workspaceManager.connect_after('workspace-switched',
this._onWorkspaceSwitched.bind(this)),
workspaceManager.connect('notify::layout-rows',
this._onWorkspaceOrientationChanged.bind(this)),
];
this._screenSignals = [];
this._screenSignals.push(global.screen.connect_after('workspace-added', this._createWorkspacesSection.bind(this)));
this._screenSignals.push(global.screen.connect_after('workspace-removed',
this._createWorkspacesSection.bind(this)));
this._screenSignals.push(global.screen.connect_after('workspace-switched',
this._updateIndicator.bind(this)));
this.connect('scroll-event', this._onScrollEvent.bind(this));
this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
this.actor.connect('scroll-event', this._onScrollEvent.bind(this));
this._createWorkspacesSection();
this._updateThumbnails();
this._onWorkspaceOrientationChanged();
//styling
this.statusLabel.add_style_class_name('panel-workspace-indicator');
this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
this._settingsChangedId = this._settings.connect(
`changed::${WORKSPACE_KEY}`,
this._updateMenuLabels.bind(this));
this._settingsChangedId =
this._settings.connect('changed::' + WORKSPACE_KEY,
this._createWorkspacesSection.bind(this));
}
_onDestroy() {
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
destroy() {
for (let i = 0; i < this._screenSignals.length; i++)
global.screen.disconnect(this._screenSignals[i]);
if (this._settingsChangedId) {
this._settings.disconnect(this._settingsChangedId);
this._settingsChangedId = 0;
}
Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
super._onDestroy();
super.destroy();
}
_onWorkspaceOrientationChanged() {
let vertical = global.workspace_manager.layout_rows === -1;
this.reactive = vertical;
_updateIndicator() {
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
this._currentWorkspace = global.screen.get_active_workspace().index();
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
this._statusLabel.visible = vertical;
this._thumbnailsBox.visible = !vertical;
// Disable offscreen-redirect when showing the workspace switcher
// so that clip-to-allocation works
Main.panel.set_offscreen_redirect(vertical
? Clutter.OffscreenRedirect.ALWAYS
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
}
_onWorkspaceSwitched() {
this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
this._updateMenuOrnament();
this._updateActiveThumbnail();
this._statusLabel.set_text(this._labelText());
}
_nWorkspacesChanged() {
this._createWorkspacesSection();
this._updateThumbnails();
}
_updateMenuOrnament() {
for (let i = 0; i < this._workspacesItems.length; i++) {
this._workspacesItems[i].setOrnament(i === this._currentWorkspace
? PopupMenu.Ornament.DOT
: PopupMenu.Ornament.NONE);
}
}
_updateActiveThumbnail() {
let thumbs = this._thumbnailsBox.get_children();
for (let i = 0; i < thumbs.length; i++) {
if (i === this._currentWorkspace)
thumbs[i].add_style_class_name('active');
else
thumbs[i].remove_style_class_name('active');
}
this.statusLabel.set_text(this._labelText());
}
_labelText(workspaceIndex) {
if (workspaceIndex === undefined) {
if(workspaceIndex == undefined) {
workspaceIndex = this._currentWorkspace;
return (workspaceIndex + 1).toString();
}
return Meta.prefs_get_workspace_name(workspaceIndex);
}
_updateMenuLabels() {
for (let i = 0; i < this._workspacesItems.length; i++)
this._workspacesItems[i].label.text = this._labelText(i);
}
_createWorkspacesSection() {
let workspaceManager = global.workspace_manager;
this._workspaceSection.removeAll();
this._workspacesItems = [];
this._currentWorkspace = workspaceManager.get_active_workspace_index();
this.workspacesItems = [];
this._currentWorkspace = global.screen.get_active_workspace().index();
let i = 0;
for (; i < workspaceManager.n_workspaces; i++) {
this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
this._workspaceSection.addMenuItem(this._workspacesItems[i]);
this._workspacesItems[i].workspaceId = i;
this._workspacesItems[i].label_actor = this._statusLabel;
this._workspacesItems[i].connect('activate', (actor, _event) => {
for(; i < global.screen.n_workspaces; i++) {
this.workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
this._workspaceSection.addMenuItem(this.workspacesItems[i]);
this.workspacesItems[i].workspaceId = i;
this.workspacesItems[i].label_actor = this.statusLabel;
let self = this;
this.workspacesItems[i].connect('activate', (actor, event) => {
this._activate(actor.workspaceId);
});
if (i === this._currentWorkspace)
this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
if (i == this._currentWorkspace)
this.workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
}
this._statusLabel.set_text(this._labelText());
}
_updateThumbnails() {
let workspaceManager = global.workspace_manager;
this._thumbnailsBox.destroy_all_children();
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
let thumb = new WorkspaceThumbnail(i);
this._thumbnailsBox.add_actor(thumb);
}
this._updateActiveThumbnail();
this.statusLabel.set_text(this._labelText());
}
_activate(index) {
let workspaceManager = global.workspace_manager;
if (index >= 0 && index < workspaceManager.n_workspaces) {
let metaWorkspace = workspaceManager.get_workspace_by_index(index);
if(index >= 0 && index < global.screen.n_workspaces) {
let metaWorkspace = global.screen.get_workspace_by_index(index);
metaWorkspace.activate(global.get_current_time());
}
}
@@ -386,27 +115,27 @@ class WorkspaceIndicator extends PanelMenu.Button {
_onScrollEvent(actor, event) {
let direction = event.get_scroll_direction();
let diff = 0;
if (direction === Clutter.ScrollDirection.DOWN)
if (direction == Clutter.ScrollDirection.DOWN) {
diff = 1;
else if (direction === Clutter.ScrollDirection.UP)
} else if (direction == Clutter.ScrollDirection.UP) {
diff = -1;
else
} else {
return;
}
let newIndex = global.workspace_manager.get_active_workspace_index() + diff;
let newIndex = global.screen.get_active_workspace().index() + diff;
this._activate(newIndex);
}
});
};
function init() {
ExtensionUtils.initTranslations();
function init(meta) {
Convenience.initTranslations();
}
let _indicator;
function enable() {
_indicator = new WorkspaceIndicator();
_indicator = new WorkspaceIndicator;
Main.panel.addToStatusArea('workspace-indicator', _indicator);
}

View File

@@ -1,13 +1,17 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported init buildPrefsWidget */
const { Gio, GObject, Gtk } = imports.gi;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = e => e;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
const WORKSPACE_KEY = 'workspace-names';
@@ -23,6 +27,8 @@ class WorkspaceNameModel extends Gtk.ListStore {
};
this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
//this._settings.connect('changed::workspace-names', this._reloadFromSettings.bind(this));
this._reloadFromSettings();
// overriding class closure doesn't work, because GtkTreeModel
@@ -51,7 +57,7 @@ class WorkspaceNameModel extends Gtk.ListStore {
while (ok)
ok = this.remove(iter);
for (; i < newNames.length; i++) {
for ( ; i < newNames.length; i++) {
iter = this.append();
this.set(iter, [this.Columns.LABEL], [newNames[i]]);
}
@@ -109,7 +115,7 @@ class WorkspaceNameModel extends Gtk.ListStore {
names.splice(index, 1);
// compact the array
for (let i = names.length - 1; i >= 0 && !names[i]; i++)
for (let i = names.length -1; i >= 0 && !names[i]; i++)
names.pop();
this._settings.set_strv(WORKSPACE_KEY, names);
@@ -125,28 +131,23 @@ class WorkspaceSettingsWidget extends Gtk.Grid {
this.margin = 12;
this.orientation = Gtk.Orientation.VERTICAL;
this.add(new Gtk.Label({
label: '<b>%s</b>'.format(_('Workspace Names')),
use_markup: true,
margin_bottom: 6,
hexpand: true,
halign: Gtk.Align.START,
}));
this.add(new Gtk.Label({ label: '<b>' + _("Workspace Names") + '</b>',
use_markup: true, margin_bottom: 6,
hexpand: true, halign: Gtk.Align.START }));
let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN });
scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.add(scrolled);
this._store = new WorkspaceNameModel();
this._treeView = new Gtk.TreeView({
model: this._store,
headers_visible: false,
reorderable: true,
hexpand: true,
vexpand: true,
});
this._treeView = new Gtk.TreeView({ model: this._store,
headers_visible: false,
reorderable: true,
hexpand: true,
vexpand: true
});
let column = new Gtk.TreeViewColumn({ title: _('Name') });
let column = new Gtk.TreeViewColumn({ title: _("Name") });
let renderer = new Gtk.CellRendererText({ editable: true });
renderer.connect('edited', this._cellEdited.bind(this));
column.pack_start(renderer, true);
@@ -175,23 +176,23 @@ class WorkspaceSettingsWidget extends Gtk.Grid {
this.add(toolbar);
}
_cellEdited(renderer, path, newText) {
_cellEdited(renderer, path, new_text) {
let [ok, iter] = this._store.get_iter_from_string(path);
if (ok)
this._store.set(iter, [this._store.Columns.LABEL], [newText]);
this._store.set(iter, [this._store.Columns.LABEL], [new_text]);
}
_newClicked() {
let iter = this._store.append();
let index = this._store.get_path(iter).get_indices()[0];
let label = _('Workspace %d').format(index + 1);
let label = _("Workspace %d").format(index + 1);
this._store.set(iter, [this._store.Columns.LABEL], [label]);
}
_delClicked() {
let [any, model_, iter] = this._treeView.get_selection().get_selected();
let [any, model, iter] = this._treeView.get_selection().get_selected();
if (any)
this._store.remove(iter);
@@ -199,7 +200,7 @@ class WorkspaceSettingsWidget extends Gtk.Grid {
});
function init() {
ExtensionUtils.initTranslations();
Convenience.initTranslations();
}
function buildPrefsWidget() {

View File

@@ -1,40 +1,5 @@
.panel-workspace-indicator {
padding: 0 8px;
}
.panel-workspace-indicator-box {
padding: 2px 0;
}
.panel-workspace-indicator-box .workspace {
width: 40px;
}
.panel-workspace-indicator,
.panel-workspace-indicator-box .workspace {
background-color: rgba(200, 200, 200, .5);
border: 1px solid #cccccc;
}
.panel-workspace-indicator,
.panel-workspace-indicator-box .workspace.active {
background-color: rgba(200, 200, 200, .5);
}
.panel-workspace-indicator-box .workspace {
background-color: rgba(200, 200, 200, .3);
border-left-width: 0;
}
.panel-workspace-indicator-box .workspace:first-child {
border-left-width: 1px;
}
.workspace-indicator-window-preview {
background-color: #252525;
border: 1px solid #ccc;
}
.workspace-indicator-window-preview.active {
background-color: #353535;
border: 2px solid #ccc;
}

93
lib/convenience.js Normal file
View File

@@ -0,0 +1,93 @@
/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
Copyright (c) 2011-2012, Giovanni Campagna <scampa.giovanni@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the GNOME nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const Gettext = imports.gettext;
const Gio = imports.gi.Gio;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
/**
* initTranslations:
* @domain: (optional): the gettext domain to use
*
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
*/
function initTranslations(domain) {
let extension = ExtensionUtils.getCurrentExtension();
domain = domain || extension.metadata['gettext-domain'];
// check if this extension was built with "make zip-file", and thus
// has the locale files in a subfolder
// otherwise assume that extension has been installed in the
// same prefix as gnome-shell
let localeDir = extension.dir.get_child('locale');
if (localeDir.query_exists(null))
Gettext.bindtextdomain(domain, localeDir.get_path());
else
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
}
/**
* getSettings:
* @schema: (optional): the GSettings schema id
*
* Builds and return a GSettings schema for @schema, using schema files
* in extensionsdir/schemas. If @schema is not provided, it is taken from
* metadata['settings-schema'].
*/
function getSettings(schema) {
let extension = ExtensionUtils.getCurrentExtension();
schema = schema || extension.metadata['settings-schema'];
const GioSSS = Gio.SettingsSchemaSource;
// check if this extension was built with "make zip-file", and thus
// has the schema files in a subfolder
// otherwise assume that extension has been installed in the
// same prefix as gnome-shell (and therefore schemas are available
// in the standard folders)
let schemaDir = extension.dir.get_child('schemas');
let schemaSource;
if (schemaDir.query_exists(null))
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
GioSSS.get_default(),
false);
else
schemaSource = GioSSS.get_default();
let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj)
throw new Error('Schema ' + schema + ' could not be found for extension '
+ extension.metadata.uuid + '. Please check your installation.');
return new Gio.Settings({ settings_schema: schemaObj });
}

View File

@@ -1,228 +0,0 @@
---
env:
es6: true
extends: 'eslint:recommended'
rules:
array-bracket-newline:
- error
- consistent
array-bracket-spacing:
- error
- never
array-callback-return: error
arrow-parens:
- error
- as-needed
arrow-spacing: error
block-scoped-var: error
block-spacing: error
brace-style: error
# Waiting for this to have matured a bit in eslint
# camelcase:
# - error
# - properties: never
# allow: [^vfunc_, ^on_, _instance_init]
comma-dangle:
- error
- always-multiline
comma-spacing:
- error
- before: false
after: true
comma-style:
- error
- last
computed-property-spacing: error
curly:
- error
- multi-or-nest
- consistent
dot-location:
- error
- property
eol-last: error
eqeqeq: error
func-call-spacing: error
func-name-matching: error
func-style:
- error
- declaration
- allowArrowFunctions: true
indent:
- error
- 4
- ignoredNodes:
# Allow not indenting the body of GObject.registerClass, since in the
# future it's intended to be a decorator
- 'CallExpression[callee.object.name=GObject][callee.property.name=registerClass] > ClassExpression:first-child'
# Allow dedenting chained member expressions
MemberExpression: 'off'
key-spacing:
- error
- beforeColon: false
afterColon: true
keyword-spacing:
- error
- before: true
after: true
linebreak-style:
- error
- unix
lines-between-class-members: error
max-nested-callbacks: error
max-statements-per-line: error
new-parens: error
no-array-constructor: error
no-await-in-loop: error
no-caller: error
no-constant-condition:
- error
- checkLoops: false
no-div-regex: error
no-empty:
- error
- allowEmptyCatch: true
no-extra-bind: error
no-extra-parens:
- error
- all
- conditionalAssign: false
returnAssign: false
no-implicit-coercion:
- error
- allow:
- '!!'
no-invalid-this: error
no-iterator: error
no-label-var: error
no-lonely-if: error
no-loop-func: error
no-nested-ternary: error
no-new-object: error
no-new-wrappers: error
no-octal-escape: error
no-proto: error
no-prototype-builtins: 'off'
no-restricted-properties:
- error
- object: Lang
property: bind
message: Use arrow notation or Function.prototype.bind()
- object: Lang
property: Class
message: Use ES6 classes
- object: imports
property: mainloop
message: Use GLib main loops and timeouts
no-restricted-syntax:
- error
- selector: >-
MethodDefinition[key.name="_init"] >
FunctionExpression[params.length=1] >
BlockStatement[body.length=1]
CallExpression[arguments.length=1][callee.object.type="Super"][callee.property.name="_init"] >
Identifier:first-child
message: _init() that only calls super._init() is unnecessary
- selector: >-
MethodDefinition[key.name="_init"] >
FunctionExpression[params.length=0] >
BlockStatement[body.length=1]
CallExpression[arguments.length=0][callee.object.type="Super"][callee.property.name="_init"]
message: _init() that only calls super._init() is unnecessary
no-return-assign: error
no-return-await: error
no-self-compare: error
no-shadow: error
no-shadow-restricted-names: error
no-spaced-func: error
no-tabs: error
no-template-curly-in-string: error
no-throw-literal: error
no-trailing-spaces: error
no-undef-init: error
no-unneeded-ternary: error
no-unused-expressions: error
no-unused-vars:
- error
# Vars use a suffix _ instead of a prefix because of file-scope private vars
- varsIgnorePattern: (^unused|_$)
argsIgnorePattern: ^(unused|_)
no-useless-call: error
no-useless-computed-key: error
no-useless-concat: error
no-useless-constructor: error
no-useless-rename: error
no-useless-return: error
no-whitespace-before-property: error
no-with: error
nonblock-statement-body-position:
- error
- below
object-curly-newline:
- error
- consistent: true
object-curly-spacing: error
object-shorthand: error
operator-assignment: error
operator-linebreak: error
# These may be a bit controversial, we can try them out and enable them later
# prefer-const: error
# prefer-destructuring: error
prefer-numeric-literals: error
prefer-promise-reject-errors: error
prefer-rest-params: error
prefer-spread: error
prefer-template: error
quotes:
- error
- single
- avoidEscape: true
require-await: error
rest-spread-spacing: error
semi:
- error
- always
semi-spacing:
- error
- before: false
after: true
semi-style: error
space-before-blocks: error
space-before-function-paren:
- error
- named: never
# for `function ()` and `async () =>`, preserve space around keywords
anonymous: always
asyncArrow: always
space-in-parens: error
space-infix-ops:
- error
- int32Hint: false
space-unary-ops: error
spaced-comment: error
switch-colon-spacing: error
symbol-description: error
template-curly-spacing: error
template-tag-spacing: error
unicode-bom: error
valid-jsdoc:
- error
- requireReturn: false
wrap-iife:
- error
- inside
yield-star-spacing: error
yoda: error
globals:
ARGV: readonly
Debugger: readonly
GIRepositoryGType: readonly
imports: readonly
Intl: readonly
log: readonly
logError: readonly
print: readonly
printerr: readonly
window: readonly
parserOptions:
ecmaVersion: 2017

Some files were not shown because too many files have changed in this diff Show More