diff --git a/NEWS b/NEWS index 0dddc214..41717f9f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,63 @@ +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 ====== diff --git a/README.md b/README.md index 1587a97d..3b84cb18 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ Bugs should be reported to the GNOME [bug tracking system][bug-tracker]. ## Extensions + * alternate-tab (**OBSOLETE**) + + 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 Lets you reach an application using gnome 2.x style menu on the panel. @@ -74,3 +80,4 @@ 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/ diff --git a/data/classic.json.in b/data/classic.json.in index fdb37626..c1c05442 100644 --- a/data/classic.json.in +++ b/data/classic.json.in @@ -1,8 +1,9 @@ { "parentMode": "user", "stylesheetName": "gnome-classic.css", + "hasOverview": false, "enabledExtensions": [@CLASSIC_EXTENSIONS@], - "panel": { "left": ["activities", "appMenu"], + "panel": { "left": ["appMenu"], "center": [], "right": ["a11y", "keyboard", "dateMenu", "aggregateMenu"] } diff --git a/data/gnome-classic.scss b/data/gnome-classic.scss index 9e23506a..edf24d66 100644 --- a/data/gnome-classic.scss +++ b/data/gnome-classic.scss @@ -32,18 +32,20 @@ $variant: 'light'; font-weight: normal; color: $fg_color; text-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 !important; - color: $selected_fg_color !important; - box-shadow: none; - & > .system-status-icon { icon-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; + box-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 { @@ -60,9 +62,9 @@ $variant: 'light'; &.lock-screen, &.unlock-screen, &.login-screen { - 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); + background-color: transparentize($bg_color, 0.5); + background-gradient-start: transparentize($bg_color, 0.5); + background-gradient-end: transparentize($bg_color, 0.5); border-bottom: none; .panel-button { color: $osd_fg_color; } } @@ -91,15 +93,3 @@ $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%); } - } -} diff --git a/data/gnome-shell-sass/_colors.scss b/data/gnome-shell-sass/_colors.scss index 447ad70b..d14a440a 100644 --- a/data/gnome-shell-sass/_colors.scss +++ b/data/gnome-shell-sass/_colors.scss @@ -3,11 +3,11 @@ $base_color: if($variant == 'light', #ffffff, lighten(desaturate(#241f31, 20%), 2%)); -$bg_color: if($variant == 'light', #f6f5f4, desaturate(#3d3846, 10%)); +$bg_color: if($variant == 'light', #f6f5f4, darken(desaturate(#3d3846, 100%), 4%)); $fg_color: if($variant == 'light', #2e3436, #eeeeec); $selected_fg_color: #ffffff; -$selected_bg_color: if($variant == 'light', #3584e4, darken(#3584e4, 20%)); +$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, 10%)); $borders_edge: if($variant == 'light', transparentize(white, 0.2), transparentize($fg_color, 0.93)); @@ -16,16 +16,20 @@ $link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), li $top_hilight: $borders_edge; $warning_color: #f57900; -$error_color: #cc0000; +$error_color: #ff8080; $success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%)); $destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%)); $osd_fg_color: #eeeeec; -$osd_bg_color: #2e3436; +$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_borders_color: transparentize(black, 0.3); -$osd_outer_borders_color: transparentize(white, 0.9); +$osd_outer_borders_color: transparentize(white, 0.84); $tooltip_borders_color: $osd_outer_borders_color; +$shadow_color: transparentize(black, 0.9); //insensitive state derived colors $insensitive_fg_color: mix($fg_color, $bg_color, 50%); diff --git a/data/gnome-shell-sass/_common.scss b/data/gnome-shell-sass/_common.scss index 2ac87d42..8731ba48 100644 --- a/data/gnome-shell-sass/_common.scss +++ b/data/gnome-shell-sass/_common.scss @@ -4,8 +4,6 @@ $cakeisalie: "This stylesheet is generated, DO NOT EDIT"; /* #{$cakeisalie} */ -$panel-corner-radius: 6px; - /* Copyright 2009, 2015 Red Hat, Inc. * * Portions adapted from Mx's data/style/default.css @@ -25,13 +23,20 @@ $panel-corner-radius: 6px; * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ - /* GLOBALS */ + + +$modal_radius: 9px; +$button_radius: 5px; +$panel-corner-radius: $button_radius + 1; + +$_trough_color: transparentize($fg_color, 0.9); +$_bubble_borders_color: lighten($borders_color, if($variant=='light', 0%, 5%)); +$_hover_bg_color: lighten($bg_color,if($variant=='light', 5%, 3%)); +$_active_bg_color: if($variant == 'light', darken($bg_color, 14%), darken($bg_color, 9%)); + $font-size: 11; $font-family: Cantarell, Sans-Serif; -$_bubble_bg_color: opacify($osd_bg_color,0.25); -$_bubble_fg_color: $osd_fg_color; -$_bubble_borders_color: transparentize($osd_fg_color,0.8); stage { font-family: $font-family; @@ -42,42 +47,44 @@ stage { /* WIDGETS */ /* Buttons */ -.button { - border-radius: 3px; +.button, %button { + border-radius: $button_radius; border-width: 1px; + min-height: 22px; padding: 4px 32px; @include button(normal); - &:focus { @include button(focus); } - &:hover { @include button(hover); } + &:focus { @include button(focus, $c:$_hover_bg_color, $tc:$fg_color); } + &:hover { @include button(hover, $c:$_hover_bg_color, $tc:$fg_color); } &:insensitive { @include button(insensitive); } - &:active { @include button(active); } + &:active { @include button(active, $c:$_active_bg_color, $tc:$fg_color); } } -.modal-dialog-linked-button { +.modal-dialog-linked-button, %bubble_button { border-right-width: 1px; - @include button(normal); - &:insensitive { @include button(insensitive); } - &:hover { @include button(hover); } - &:focus { @include button(focus); } - &:active { @include button(active); } + @include button(normal, $c:$bg_color, $tc:$fg_color); + &:insensitive { @include button(insensitive, $c:$bg_color, $tc:$fg_color); } + &:hover { @include button(hover, $c:$_hover_bg_color, $tc:$fg_color); } + &:focus { @include button(focus, $c:$_hover_bg_color, $tc:$fg_color); } + &:active { @include button(active, $c:$_active_bg_color, $tc:$fg_color); } padding: 12px; + border-top: 1px solid $_bubble_borders_color; &:first-child { - border-radius: 0px 0px 0px 6px; + border-radius: 0px 0px 0px $modal_radius; } &:last-child { border-right-width: 0px; - border-radius: 0px 0px 6px 0px; + border-radius: 0px 0px $modal_radius 0px; } &:first-child:last-child { border-right-width: 0px; - border-radius: 0px 0px 6px 6px; + border-radius: 0px 0px $modal_radius $modal_radius; } } /* Entries */ StEntry { - border-radius: 3px; + border-radius: $button_radius; padding: 4px; border-width: 1px; color: $fg_color; @@ -130,15 +137,20 @@ StScrollBar { .slider { height: 1em; -barlevel-height: 0.3em; - -barlevel-background-color: $insensitive_bg_color; //background of the trough + -barlevel-background-color: transparentize($fg_color, 0.9); //background of the trough -barlevel-border-color: $borders_color; //trough border color -barlevel-active-background-color: $selected_bg_color; //active trough fill - -barlevel-active-border-color: darken($selected_bg_color,10%); //active trough border + -barlevel-active-border-color: $selected_borders_color; //active trough border -barlevel-overdrive-color: $destructive_color; -barlevel-overdrive-border-color: darken($destructive_color,10%); -barlevel-overdrive-separator-width: 0.2em; -barlevel-border-width: 1px; - -slider-handle-radius: 6px; + -slider-handle-radius: 8px; + -slider-handle-border-width: 1px; + -slider-handle-border-color: $borders_color; + color: if($variant == 'light', lighten($bg_color, 10%), darken($bg_color,4%)); + &:hover { color: $_hover_bg_color; } + &:active { color: $_active_bg_color; } } /* Check Boxes */ @@ -157,17 +169,17 @@ StScrollBar { /* Switches */ .toggle-switch { - width: 65px; + color: $fg_color; + width: 46px; height: 22px; background-size: contain; -} - - @each $v in us, intl { - .toggle-switch-#{$v} { - background-image: url("resource:///org/gnome/shell/theme/toggle-off-#{$v}.svg"); - &:checked { background-image: url("resource:///org/gnome/shell/theme/toggle-on-#{$v}.svg"); } - } + 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")); } +} /* links */ .shell-link { @@ -182,10 +194,8 @@ StScrollBar { .flashspot { background-color: white; } .modal-dialog { - border-radius: 9px; - color: $osd_fg_color; - background-color: transparentize(darken($osd_bg_color,10%),0.05); - border: 1px solid $_bubble_borders_color; + border-radius: $modal_radius; + @extend %bubble-panel; .modal-dialog-content-box { padding: 24px; } @@ -197,8 +207,8 @@ StScrollBar { .run-dialog-button-box { padding-top: 1em; } .run-dialog-label { @include fontsize($font-size + 1.1); - font-weight: bold; - color: darken($osd_fg_color,10%); + font-weight: normal; + color: $fg_color; padding-bottom: .4em; } @@ -230,7 +240,7 @@ StScrollBar { } .message-dialog-subtitle { - color: darken($fg_color,40%); + color: $fg_color; font-weight: bold; } @@ -353,7 +363,7 @@ StScrollBar { } .mount-dialog-app-list-item { - color: darken($fg_color,10%); + color: lighten($fg_color,10%); &:hover { color: $fg_color; } &:ltr { padding-right: 1em; } &:rtl { padding-left: 1em; } @@ -372,13 +382,13 @@ StScrollBar { /* Password or Authentication Dialog */ .prompt-dialog { + @extend %bubble-panel; //this is the width of the entire modal popup width: 34em; - border: 3px solid $_bubble_borders_color; .message-dialog-main-layout { spacing: 24px; padding: 10px; } .message-dialog-content { spacing: 16px; } - .message-dialog-title { color: darken($osd_fg_color,25%); } + .message-dialog-title { color: lighten($fg_color,15%); } } .prompt-dialog-description:rtl { @@ -392,7 +402,7 @@ StScrollBar { .prompt-dialog-error-label { font-size: 10pt; - color: $error_color; + color: $warning_color; padding-bottom: 8px; } @@ -410,6 +420,23 @@ StScrollBar { padding-bottom: 8px; } + .prompt-dialog-pim-box { + spacing: 1em; + } + + .prompt-dialog-grid { + spacing-rows: 15px; + spacing-columns: 1em; + } + + .prompt-dialog-keyfiles-box { + spacing: 1em; + } + + .prompt-dialog-button.button { + padding: 8px; + } + /* Polkit Dialog */ @@ -435,6 +462,7 @@ StScrollBar { /* Audio selection dialog */ .audio-device-selection-dialog { + @extend %bubble-panel; spacing: 30px; } @@ -455,7 +483,11 @@ StScrollBar { .audio-selection-device { border: 1px solid $_bubble_borders_color; border-radius: 12px; - &:active,&:hover,&:focus { background-color: $selected_bg_color; } + &:hover,&:focus { background-color: $_hover_bg_color; } + &:active { + background-color: $selected_bg_color; + color: $selected_fg_color; + } } .audio-selection-device-box { @@ -469,22 +501,26 @@ StScrollBar { /* Access Dialog */ .access-dialog { + @extend %bubble-panel; spacing: 30px; } /* Geolocation Dialog */ .geolocation-dialog { + @extend %bubble-panel; spacing: 30px; } /* Extension Dialog */ .extension-dialog { + @extend %bubble-panel; .message-dialog-main-layout { spacing: 24px; padding: 10px; } - .message-dialog-title { color: darken($osd_fg_color,25%); } + .message-dialog-title { font-weight: normal; color: $fg_color; } } /* Inhibit-Shortcuts Dialog */ .inhibit-shortcuts-dialog { + @extend %bubble-panel; spacing: 30px; } @@ -504,12 +540,13 @@ StScrollBar { .popup-menu { min-width: 15em; + color: $fg_color; + border-color: $_bubble_borders_color; .popup-menu-arrow { } //defined globally in the TOP BAR .popup-sub-menu { - padding-bottom: 1px; - background-color: darken($bg_color,2%); - box-shadow: inset 0 -1px 0px lighten($borders_color,5%); + background-color: darken($bg_color,5%); + box-shadow: inset 0 -1px 0px $_bubble_borders_color; } .popup-menu-content { padding: 1em 0em; } @@ -519,12 +556,18 @@ StScrollBar { &:ltr { padding: .4em 1.75em .4em 0em; } &:rtl { padding: .4em 0em .4em 1.75em; } &:checked { - background-color: darken($bg_color,2%); - box-shadow: inset 0 1px 0px lighten($borders_color,5%); + background-color: $bg_color; + box-shadow: inset 0 -1px 0px $_bubble_borders_color; font-weight: bold; } - &.selected { background-color: transparentize($fg_color,0.9); color: $fg_color; } - &:active { background-color: $selected_bg_color; color: $selected_fg_color; } + &.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,.5); } } @@ -548,10 +591,10 @@ StScrollBar { } .popup-menu-boxpointer, .candidate-popup-boxpointer { - -arrow-border-radius: 3px; + -arrow-border-radius: $button_radius+4; -arrow-background-color: $bg_color; -arrow-border-width: 1px; - -arrow-border-color: $borders_color; + -arrow-border-color: if($variant=='light', transparentize(black, 0.6), $borders_color); -arrow-base: 24px; -arrow-rise: 11px; -arrow-box-shadow: 0 1px 3px black; //dreaming. bug #689995 @@ -562,7 +605,7 @@ StScrollBar { height: 1px; //not really the whole box margin: 6px 64px; background-color: transparent; - border-color: lighten($borders_color,10%); + border-color: $_bubble_borders_color; border-bottom-width: 1px; border-bottom-style: solid; } @@ -576,6 +619,18 @@ StScrollBar { app menu inside the main app window itself rather than the top bar */ +/************* + * App Icons * + *************/ +/* Outline for low res icons */ +.lowres-icon { + icon-shadow: 0 1px 2px rgba(0,0,0,0.3); +} + +/* Drapshadow for large icons */ +.icon-dropshadow { + icon-shadow: 0 1px 2px rgba(0,0,0,0.4); +} /* OSD */ .osd-window { @@ -590,7 +645,7 @@ StScrollBar { .level { height: 0.6em; -barlevel-height: 0.6em; - -barlevel-background-color: transparentize(darken($osd_bg_color,15%),0.5); + -barlevel-background-color: transparentize($fg_color, if($variant=='light', 0.2, 0.9)); -barlevel-active-background-color: $osd_fg_color; -barlevel-overdrive-color: $destructive_color; -barlevel-overdrive-separator-width: 0.2em; @@ -635,7 +690,7 @@ StScrollBar { } .switcher-list .item-box:selected { - background-color: $selected_bg_color; + background-color: transparentize($osd_fg_color, 0.7); color: $selected_fg_color; } @@ -685,7 +740,8 @@ StScrollBar { spacing: 8px; } - .ws-switcher-active-up, .ws-switcher-active-down { + .ws-switcher-active-up, .ws-switcher-active-down, + .ws-switcher-active-left, .ws-switcher-active-right { height: 50px; background-color: $selected_bg_color; color: $selected_fg_color; @@ -701,13 +757,43 @@ StScrollBar { } %osd-panel { - color: $_bubble_fg_color; - background-color: $_bubble_bg_color; - border: 1px solid $_bubble_borders_color; + color: $osd_fg_color; + background-color: $osd_bg_color; + border: 1px solid $osd_outer_borders_color; border-radius: 12px; padding: 12px; } +%bubble-entry { + color: $fg_color; + background-color: darken($bg_color, 2%); + border-color: $_bubble_borders_color; + box-shadow: none; + &:focus { border: 2px solid $selected_bg_color; } +} + +%bubble-panel { + color: $fg_color; + background-color: $bg_color; + border: 1px solid if($variant=='light', transparentize(black, 0.6), $borders_color); + + StEntry { @extend %bubble-entry; } + .button { + &, &:hover, &:focus, &:active, &:disabled { + box-shadow: none; + border-color: $_bubble_borders_color; + } + background-color: $bg_color; + color: $fg_color; + &:hover { background-color: $_hover_bg_color; } + &:active { + background-color: $selected_bg_color; + color: $selected_fg_color; + } + &:disabled { color: $insensitive_fg_color; } + } +} + /* Tiled window previews */ .tile-preview { background-color: transparentize($selected_bg_color,0.5); @@ -775,7 +861,7 @@ StScrollBar { } &:hover { - color: lighten($fg_color, 10%); + color: $selected_fg_color; } &:active, &:overview, &:focus, &:checked { @@ -783,7 +869,7 @@ StScrollBar { // a box-shadow background-color: rgba(0, 0, 0, 0.01); box-shadow: inset 0 -2px 0px lighten($selected_bg_color,5%); - color: lighten($fg_color,10%); + color: $selected_fg_color; } .system-status-icon { icon-size: 1.09em; padding: 0 5px; } @@ -831,7 +917,7 @@ StScrollBar { .datemenu-displays-box { spacing: 1em; } .datemenu-calendar-column { - border: 0 solid lighten($bg_color,5%); + border: 0 solid $_bubble_borders_color; &:ltr { border-left-width: 1px; } &:rtl { border-right-width: 1px; } } @@ -856,11 +942,8 @@ StScrollBar { .world-clocks-button, .weather-button, .events-section-title { - &:hover,&:focus { background-color: lighten($bg_color,5%); } - &:active { - color: lighten($selected_fg_color,5%); - background-color: $selected_bg_color; - } + &:hover, &:focus { background-color: $_hover_bg_color } + &:active { background-color: $_active_bg_color } } .datemenu-today-button .day-label { @@ -905,7 +988,7 @@ StScrollBar { } .world-clocks-timezone { - color: darken($fg_color,40%); + color: $fg_color; font-feature-settings: "tnum"; font-size: 0.9em; } @@ -920,7 +1003,7 @@ StScrollBar { } .calendar-month-label { - color: darken($fg_color,5%); + color: lighten($fg_color,5%); font-weight: bold; padding: 8px 0; &:focus {} @@ -930,8 +1013,8 @@ StScrollBar { background-color: transparent; width: 32px; border-radius: 4px; - &:hover, &:focus { background-color: transparentize($fg_color,0.95); } - &:active { background-color: transparentize($bg_color,0.95); } + &:hover, &:focus { background-color: $_hover_bg_color; } + &:active { background-color: transparentize($fg_color, 0.84); } } .calendar-change-month-back StIcon, .calendar-change-month-forward StIcon { // arrows @@ -946,14 +1029,14 @@ StScrollBar { margin: 2px; border-radius: 1.4em; font-feature-settings: "tnum"; - &:hover,&:focus { background-color: lighten($bg_color,5%); } + &:hover, &:focus { background-color: $_hover_bg_color; } &:active,&:selected { color: lighten($selected_fg_color,5%); background-color: $selected_bg_color; border-color: transparent; //avoid jumparound due to today } &.calendar-day-heading { //day of week heading - color: darken($fg_color,40%); + color: lighten($fg_color,5%); margin-top: 1em; font-size: 70%; } @@ -973,7 +1056,7 @@ StScrollBar { font-weight: bold; //color: lighten($fg_color,10%); //background-color: darken($bg_color,5%); - border: 1px solid transparentize($borders_color,0.5); + border: 1px solid $_bubble_borders_color; } .calendar-day-with-events { color: lighten($fg_color,10%); @@ -981,7 +1064,7 @@ StScrollBar { background-image: url("resource:///org/gnome/shell/theme/calendar-today.svg"); } .calendar-other-month-day { - color: transparentize($fg_color,0.85); + color: transparentize($fg_color ,0.5); opacity: 0.5; } .calendar-week-number { @@ -991,8 +1074,8 @@ StScrollBar { border-radius: 2px; padding: 0.5em 0 0; margin: 6px; - background-color: transparentize($fg_color,0.7); - color: $bg_color; + background-color: $_bubble_borders_color; + color: $fg_color; } /* Message list */ @@ -1001,8 +1084,7 @@ StScrollBar { } .message-list-clear-button.button { - background-color: transparent; - &:hover,&:focus { background-color: lighten($bg_color,5%); } + @extend %button; margin: 1.5em 1.5em 0; } @@ -1016,8 +1098,11 @@ StScrollBar { } .message { - &:hover,&:focus { background-color: lighten($bg_color,5%); } - border-radius: 3px; + border: 1px solid $_bubble_borders_color; + background-color: lighten($bg_color, 2%); + &:hover,&:focus { background-color: $_hover_bg_color; } + &:active { background-color: transparentize($fg_color, 0.84) } + border-radius: 5px; } .message-icon-bin { @@ -1026,7 +1111,7 @@ StScrollBar { } .message-icon-bin > StIcon { - color: darken($fg_color,20%); + color: $fg_color; icon-size: 1.09em; -st-icon-style: symbolic; } @@ -1041,7 +1126,7 @@ StScrollBar { } .message-secondary-bin > .event-time { - color: darken($fg_color,40%); + color: $fg_color; font-size: 0.7em; /* HACK: the label should be baseline-aligned with a 1em label, fake this with some bottom padding */ @@ -1053,17 +1138,17 @@ StScrollBar { } .message-title { - color: darken($fg_color,5%); + color: $fg_color; } .message-content { - color: darken($fg_color,20%); + color: darken($fg_color, 10%); padding: 10px; } .message-media-control { padding: 12px; - color: darken($fg_color, 20%); + color: lighten($fg_color, 15%); &:last-child:ltr { padding-right: 18px; } &:last-child:rtl { padding-left: 18px; } @@ -1074,9 +1159,9 @@ StScrollBar { .media-message-cover-icon { icon-size: 48px !important; &.fallback { - color: lighten($bg_color,10%); + color: lighten($fg_color,10%); background-color: $bg_color; - border: 2px solid $bg_color; + border: 1px solid $bg_color; border-radius: 2px; icon-size: 32px !important; padding: 6px; } @@ -1085,13 +1170,7 @@ StScrollBar { // a little unstructured mess: - .system-switch-user-submenu-icon { - icon-size: 16px; - padding: 0 4px; - } - #appMenu { - spinner-image: url("resource:///org/gnome/shell/theme/process-working.svg"); spacing: 4px; .label-shadow { color: transparent; } @@ -1118,15 +1197,18 @@ StScrollBar { color: $fg_color; border-radius: 32px; /* wish we could do 50% */ padding: 13px; - border: 1px solid lighten($borders_color,5%); + border: 1px solid $_bubble_borders_color; &:hover, &:focus { - background-color: transparentize($fg_color,0.9); + background-color: $_hover_bg_color; color: $fg_color; border: none; padding: 14px; } - &:active { background-color: $selected_bg_color; color: $selected_fg_color; } + &:active { + background-color: $selected_bg_color; + color: $selected_fg_color; + } & > StIcon { icon-size: 16px; } } @@ -1142,6 +1224,21 @@ StScrollBar { .ripple-box:rtl { border-radius: 0 0 0 52px; } // just a simple change to the border radius position +// Rubberband for select-area screenshots +.select-area-rubberband { + background-color: transparentize($selected_bg_color,0.7); + border: 1px solid $selected_bg_color; +} + +// Pointer location +.ripple-pointer-location { + width: 50px; + height: 50px; + border-radius: 25px 25px 25px 25px; // radius the size of the box 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%); +} + // not really top bar only .popup-menu-arrow { icon-size: 1.09em; } .popup-menu-icon { icon-size: 1.09em; } @@ -1149,31 +1246,39 @@ StScrollBar { //close buttons .window-close { - background-color: white; + background-color: $selected_bg_color; + color: white; border-radius: 24px; - border: 4px solid $selected_bg_color; - box-shadow: inset 0 -4px 0 0 transparentize($selected_bg_color, 0.5); - color: $selected_bg_color; + border: 2px solid $selected_bg_color; height: 24px; width: 24px; - -shell-close-overlap: 14px; + -shell-close-overlap: 11px; + box-shadow: -1px 1px 5px 0px transparentize(black, 0.5); &:hover { - background-color: $selected_bg_color; - border-color: white; - color: white; + background-color: lighten($selected_bg_color, 5%); + border-color: lighten($selected_bg_color, 5%); } &:active { - background-color: mix(white, $selected_bg_color, 75%); - border-color: $selected_bg_color; - color: $selected_bg_color; + background-color: darken($selected_bg_color, 5%); + border-color: darken($selected_bg_color, 5%); } } +// 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%); +} + /* NETWORK DIALOGS */ .nm-dialog { + @extend %bubble-panel; max-height: 34em; min-height: 31em; min-width: 32em; @@ -1232,13 +1337,14 @@ StScrollBar { } .window-clone-border { - border: 4px solid $selected_bg_color; - border-radius: 4px; + $_bg: transparentize(white, 0.65); + border: 7px solid $_bg; + border-radius: $modal_radius; // 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 0px 0px 0px 1px $selected_bg_color; - } + box-shadow: inset 0 0 0 1px $_bg; +} .window-caption { spacing: 25px; color: $selected_fg_color; @@ -1248,33 +1354,30 @@ StScrollBar { } //search entry - .search-entry { + .search-entry, %search_entry { width: 320px; padding: 7px 9px; - border-radius: 6px; - border-color: darken($osd_fg_color,50%); - color: $osd_fg_color; - background-color: $osd_bg_color; + border-radius: 18px; + color: $fg_color; + background-color: $base_color; + border-color: $borders_color; &:focus { padding: 6px 8px; border-width: 2px; border-color: $selected_bg_color; } - .search-entry-icon { icon-size: 1em; padding: 0 4px; color: transparentize($fg_color,.3); } + .search-entry-icon { icon-size: 1em; padding: 0 4px; color: $fg_color; } &:hover, &:focus { - .search-entry-icon { color: $fg_color; } + .search-entry-icon { color: transparentize($fg_color,.3); } } } //search results - #searchResultsBin { - max-width: 1000px; - } - #searchResultsContent { + max-width: 1000px; padding-left: 20px; padding-right: 20px; spacing: 16px; @@ -1293,7 +1396,7 @@ StScrollBar { .list-search-result-content { spacing: 30px; } .list-search-result-title { color: darken($osd_fg_color,5%); spacing: 12px; } - .list-search-result-description { color: transparentize(darken($osd_fg_color,15%), 0.5); } + .list-search-result-description { color: darken($osd_fg_color, 30%); } .list-search-provider-details { width: 150px; color: darken($osd_fg_color,5%); margin-top: 0.24em; } .list-search-provider-content { spacing: 20px; } .search-provider-icon { padding: 15px; } @@ -1302,12 +1405,9 @@ StScrollBar { /* DASHBOARD */ #dash { + @extend %overview-panel; font-size: 9pt; - color: $_bubble_fg_color; - background-color: $_bubble_bg_color; padding: 4px 0; - border: 1px solid rgba(128, 128, 128, 0.4); - border-left: 0px; border-radius: 0px 9px 9px 0px; &:rtl { @@ -1335,7 +1435,8 @@ StScrollBar { border-radius: 7px; padding: 4px 12px; color: $osd_fg_color; - background-color: transparentize($osd_bg_color,0.3); + background-color: transparentize($osd_bg_color,0.05); + border: 1px solid $osd_outer_borders_color; text-align: center; -x-offset: 8px; } @@ -1362,13 +1463,29 @@ StScrollBar { } .app-view-control { //favorties | all toggle button padding: 4px 32px; - &:checked { @include button(active); } + margin: 0 4px; + &, &:hover, &:checked { @include button(undecorated); } + + &, &:hover { color: darken($osd_fg_color, 25%); } + + &:hover { 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: 3px 0 0 3px; + border-radius: 0; } + &:last-child { - border-radius: 0 3px 3px 0; + border-radius: 0; } } @@ -1376,11 +1493,11 @@ StScrollBar { .search-provider-icon, .list-search-result { @extend %icon_tile; - &:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); } &:focus, &:selected, &:hover { background-color: transparentize($osd_fg_color,.9); transition-duration: 200ms; } + &:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); } } .app-well-app, .app-well-app.app-folder, @@ -1389,11 +1506,6 @@ StScrollBar { & .overview-icon { @extend %icon_tile; } - &:active .overview-icon, - &:checked .overview-icon { - background-color: transparentize(darken($osd_bg_color,10%),.1); - box-shadow: inset 0 1px 2px $osd_borders_color; - } &:hover .overview-icon, &:focus .overview-icon, &:selected .overview-icon { @@ -1402,7 +1514,13 @@ StScrollBar { border-image: none; background-image: none; } - + &:drop .overview-icon { + background-color: transparentize($selected_bg_color,.15); + } + &:active .overview-icon, + &:checked .overview-icon { + background-color: transparentize(darken($osd_bg_color,10%), 0.5); + } } .app-well-app-running-dot { //running apps indicator @@ -1413,7 +1531,7 @@ StScrollBar { %icon_tile { color: $osd_fg_color; - border-radius: 4px; + border-radius: $button_radius+4; padding: 6px; border: 1px solid transparent; transition-duration: 100ms; @@ -1434,7 +1552,7 @@ StScrollBar { // Collections .app-folder-popup { //expanded collection -arrow-border-radius: 8px; - -arrow-background-color: transparentize($osd_bg_color,0.7); + -arrow-background-color: transparentize(darken($osd_bg_color,10%), 0.5); -arrow-base: 24px; -arrow-rise: 11px; } @@ -1453,13 +1571,13 @@ StScrollBar { height: 12px; background-color: transparent; border: 2px solid rgba(255, 255, 255, 0.4); - border-radius:12px; + border-radius: 12px; } &:hover .page-indicator-icon { border-color: white; } - &:active .page-indicator-icon { border: none; margin: 2px; background-color:#fff; } + &:active .page-indicator-icon { border: none; margin: 2px; background-color: white; } &:checked .page-indicator-icon, - &:checked:active { background-color: #fff;} + &:checked:active .page-indicator-icon { background-color: white;} } .no-frequent-applications-label { @extend %status_text; } @@ -1487,12 +1605,11 @@ StScrollBar { } } .workspace-thumbnail-indicator { - border: 4px solid $selected_bg_color; + border: 2px solid $selected_bg_color; padding: 1px; } //Some hacks I don't even - .search-display > StBoxLayout, .all-apps, .frequent-apps > StBoxLayout { // horizontal padding to make sure scrollbars or dash don't overlap content @@ -1500,15 +1617,15 @@ StScrollBar { } %overview-panel { - color: $_bubble_fg_color; - background-color: $_bubble_bg_color; - border: 1px solid $_bubble_borders_color; + color: $osd_fg_color; + background-color: transparentize($osd_bg_color, 0.1); + border: none; } %status_text { font-size: 2em; font-weight: bold; - color: $fg_color; + color: $osd_fg_color; } /* NOTIFICATIONS & MESSAGE TRAY */ @@ -1520,28 +1637,38 @@ StScrollBar { font-size: 11pt; width: 34em; margin: 5px; - border-radius: 6px; - color: $_bubble_fg_color; - background-color: $_bubble_bg_color; - border: 1px solid $borders_color; - //box-shadow: 0 1px 4px black; - &:hover { background-color: $_bubble_bg_color; } - &:focus { background-color: $_bubble_bg_color; } + border-radius: $modal_radius; + border: if($variant == 'light', none, $_bubble_borders_color); + min-height: 64px; + box-shadow: 0 1px 2px transparentize(black, 0.7); + &:hover { background: $bg_color; } + &, &:focus, &:active { + background-color: $bg_color; + .message-title { color: $fg_color } + .message-content { color: $fg_color; } + } - .notification-icon { padding: 5px; } + .message-icon-bin > StIcon { + color: $fg_color; + } + + StEntry { @extend %bubble-entry; } + + .notification-icon { padding: 5px; } .notification-content { padding: 5px; spacing: 5px; } .secondary-icon { icon-size: 1.09em; } .notification-actions { - background-color: $borders_color; - padding-top: 2px; - spacing: 1px; + padding-top: 0; + color: $fg_color; + border-top: 1px solid $_bubble_borders_color; + spacing: 0px; } .notification-button { - padding: 4px 4px 5px; - background-color: darken($_bubble_bg_color,5%); - &:first-child { border-radius: 0 0 0 6px; } - &:last-child { border-radius: 0 0 6px 0; } - &:hover, &focus { background-color: darken($_bubble_bg_color,2%); } + @extend %bubble_button; + &:focus { box-shadow: none; } + padding: 0 16px; + min-height: 35px; + border: none; } } .summary-source-counter { @@ -1552,7 +1679,7 @@ StScrollBar { -shell-counter-overlap-y: 3px; background-color: $selected_bg_color; color: $selected_fg_color; - border: 2px solid $osd_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%; } @@ -1570,14 +1697,14 @@ StScrollBar { } .chat-sent { padding-left: 18pt; - color: darken($fg_color, 15%); + color: lighten($fg_color, 15%); &:rtl { padding-left: 0; padding-right: 18pt; } } .chat-meta-message { padding-left: 4px; font-size: 9pt; font-weight: bold; - color: darken($fg_color,20%); + color: lighten($fg_color,18%); &:rtl { padding-left: 0; padding-right: 4px; } } @@ -1587,6 +1714,8 @@ StScrollBar { padding: 2px 72px 2px 12px; } .hotplug-notification-item { + @extend %bubble_button; + border: none; box-shadow: none; padding: 2px 10px; &:focus { padding: 1px 71px 1px 11px; } } @@ -1601,7 +1730,7 @@ StScrollBar { .hotplug-resident-mount { spacing: 8px; border-radius: 4px; - &:hover { background-color: transparentize($bg_color,0.7); } + &:hover { background-color: $_hover_bg_color; } } .hotplug-resident-mount-label { @@ -1660,30 +1789,36 @@ StScrollBar { } .keyboard-key { - background-color: #393f3f; + $_key_bg: opacify(lighten($osd_bg_color, 9%), 1); + background-color: $_key_bg; min-height: 1.2em; min-width: 1.2em; font-size: 16pt; - border-radius: 3px; - border: 1px solid #464d4d; - color: #e5e5e5; + border-radius: $button_radius; + border: 1px solid $osd_outer_borders_color; + color: $osd_fg_color; &:focus { @include button(focus); } - &:hover,&:checked { @include button(hover); } - &:active { @include button(active);} + &:hover, &:checked { background-color: lighten($_key_bg, 3%); } + &:active { background-color: darken($_key_bg, 2%); } &:grayed { //FIXME background-color: $osd_bg_color; color: $osd_fg_color; border-color: $osd_borders_color; } &.default-key { - border-color: #2d3232; - background-color: #1d2020; + $_default_key_bg: opacify($osd_bg_color, 1); + border-color: $osd_outer_borders_color; + background-color: $_default_key_bg; background-size: 20px; + &:hover, &:checked { background-color: lighten($_default_key_bg, 3%); } + &:active { background-color: darken($_default_key_bg, 2%); } } &.enter-key { - border-color: #005684; - background-color: #006098; + border-color: lighten($selected_bg_color, 5%); + background-color: $selected_bg_color; background-image: url("resource:///org/gnome/shell/theme/key-enter.svg"); + &:hover, &:checked { background-color: lighten($selected_bg_color, 3%); } + &:active { background-color: darken($selected_bg_color, 2%); } } &.shift-key-lowercase { background-image: url("resource:///org/gnome/shell/theme/key-shift.svg"); @@ -1707,7 +1842,7 @@ StScrollBar { -arrow-border-radius: 10px; -arrow-background-color: transparentize($osd_bg_color, 0.3); -arrow-border-width: 2px; - -arrow-border-color: $_bubble_borders_color; + -arrow-border-color: $osd_outer_borders_color; -arrow-base: 20px; -arrow-rise: 10px; -boxpointer-gap: 5px; @@ -1722,8 +1857,8 @@ StScrollBar { .emoji-panel { .keyboard-key:latched { - border-color: #005684; - background-color: #006098; + border-color: lighten($selected_bg_color, 5%); + background-color: $selected_bg_color; } } @@ -1782,18 +1917,68 @@ StScrollBar { border: none; background-color: transparent; - .modal-dialog-button-box { spacing: 3px; } - .modal-dialog-button { - padding: 3px 18px; - &:default { - @include button(normal,$c:$selected_bg_color); - &:hover,&:focus { @include button(hover,$c:$selected_bg_color); } - &:active { @include button(active,$c:$selected_bg_color); } - &:insensitive { @include button(insensitive); } + $_gdm_fg: #f6f5f4; + $_gdm_bg: lighten(#2e3436, 19%); + StEntry { + @extend %search_entry; + border-radius: $button_radius; + @if $variant=='dark' { + $_gdm_entry_bg: transparentize(lighten(desaturate(#241f31, 20%), 2%), 0.5); + background-color: $_gdm_entry_bg; + border-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 transparentize($shadow_color, 0.02); + background-color: $_gdm_bg; + border-color: $_gdm_bg; + color: $_gdm_fg; + + $_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($_gdm_fg, 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); + } + } + } } .login-dialog-logo-bin { padding: 24px 0px; } @@ -1875,6 +2060,8 @@ StScrollBar { //SCREEN SHIELD +$_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726); + .screen-shield-arrows { padding-bottom: 3em; } @@ -1884,12 +2071,12 @@ StScrollBar { width: 80px; height: 48px; -arrow-thickness: 12px; - -arrow-shadow: 0 1px 1px rgba(0,0,0,0.4); + -arrow-shadow: $_screenshield_shadow; } .screen-shield-clock { color: white; - text-shadow: 0px 1px 2px rgba(0,0,0,0.6); + text-shadow: $_screenshield_shadow; font-weight: bold; text-align: center; padding-bottom: 1.5em; @@ -1897,7 +2084,7 @@ StScrollBar { .screen-shield-clock-time { font-size: 72pt; - text-shadow: 0px 2px 2px rgba(0,0,0,0.4); + text-shadow: $_screenshield_shadow; font-feature-settings: "tnum"; } @@ -1919,9 +2106,9 @@ StScrollBar { .notification, .screen-shield-notification-source { padding: 12px 6px; - border: 1px solid $_bubble_borders_color; + border: 1px solid $osd_outer_borders_color; background-color: transparentize($osd_bg_color,0.5); - color: $_bubble_fg_color; + color: $osd_fg_color; border-radius: 4px; } .notification { margin-right: 15px; } //compensate for space allocated to the scrollbar @@ -1935,7 +2122,7 @@ StScrollBar { .screen-shield-notification-count-text { padding: 0px 0px 0px 12px; } -#panel.lock-screen { background-color: transparentize($_bubble_bg_color, 0.5); } +#panel.lock-screen { background-color: transparentize($osd_bg_color, 0.5); } .screen-shield-background { //just the shadow, really background: black; @@ -1943,7 +2130,7 @@ StScrollBar { } #lockDialogGroup { - background: #2e3436 url(resource:///org/gnome/shell/theme/noise-texture.png); + background: lighten(#2e3436, 8%) url(resource:///org/gnome/shell/theme/noise-texture.png); background-repeat: repeat; } diff --git a/data/gnome-shell-sass/_drawing.scss b/data/gnome-shell-sass/_drawing.scss index 7ac18b1b..8f4611c3 100644 --- a/data/gnome-shell-sass/_drawing.scss +++ b/data/gnome-shell-sass/_drawing.scss @@ -37,16 +37,13 @@ // 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%)); @@ -111,7 +108,7 @@ } } -@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) { +@mixin button($t, $c:$bg_color, $tc:$fg_color, $edge: $borders_edge) { // // Button drawing function // @@ -130,46 +127,39 @@ $_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))); - + $_button_shadow: 0 1px 2px transparentize($shadow_color, 0.03); @if $t==normal { // // normal button // - $_bg: if($c!=$osd_bg_color, transparentize($c, 0.5), - $osd_bg_color); - color: $osd_fg_color; - background-color: $_bg; - border-color: $osd_borders_color; - box-shadow: inset 0 1px lighten($osd_bg_color,10%); + color: $tc; + background-color: $c; + border-color: $borders_color; + box-shadow: $_button_shadow; text-shadow: 0 1px black; icon-shadow: 0 1px black; } @if $t==focus { // // focused button - // - $_bg: if($c!=$osd_bg_color, transparentize($c, 0.3), - lighten($osd_bg_color,3%)); - - color: $osd_fg_color; + // + color: $tc; text-shadow: 0 1px black; icon-shadow: 0 1px black; - box-shadow: inset 0px 0px 0px 1px $selected_bg_color; + box-shadow: inset 0px 0px 0px 2px $selected_bg_color; + //border-color: $selected_bg_color; } @else if $t==hover { // // active osd button // - $_bg: if($c!=$osd_bg_color, transparentize($c, 0.3), - lighten($osd_bg_color,3%)); - - color: white; - border-color: $osd_borders_color; - background-color: $_bg; - box-shadow: inset 0 1px lighten($osd_bg_color,20%); + color: $tc; + border-color: $borders_color; + background-color: $c; + box-shadow: $_button_shadow; text-shadow: 0 1px black; icon-shadow: 0 1px black; @@ -178,27 +168,18 @@ // // active osd button // - $_bg: if($c!=$bg_color, $c, $osd_borders_color); - - color: white; - border-color: $osd_borders_color; - background-color: $selected_bg_color; - // 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; + color: $tc; + border-color: $borders_color; + background-color: $c; text-shadow: none; icon-shadow: none; + box-shadow: none; } @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: $osd_borders_color; - background-color: $_bg; + border-color: $insensitive_borders_color; + background-color: $insensitive_bg_color; box-shadow: none; text-shadow: none; icon-shadow: none; diff --git a/data/gnome-shell-sass/_high-contrast-colors.scss b/data/gnome-shell-sass/_high-contrast-colors.scss index af1e52f0..cba0145a 100644 --- a/data/gnome-shell-sass/_high-contrast-colors.scss +++ b/data/gnome-shell-sass/_high-contrast-colors.scss @@ -26,6 +26,7 @@ $osd_borders_color: transparentize(black, 0.3); $osd_outer_borders_color: transparentize(white, 0.9); $tooltip_borders_color: $osd_outer_borders_color; +$shadow_color: transparentize(black, 0.9); //insensitive state derived colors $insensitive_fg_color: mix($fg_color, $bg_color, 50%); diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index d7ba570a..9667d3f2 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -4,17 +4,17 @@ const { Atk, Clutter, Gio, GLib, GMenu, GObject, Gtk, Meta, Shell, St } = imports.gi; +const Signals = imports.signals; + const DND = imports.ui.dnd; +const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const Signals = imports.signals; const Gettext = imports.gettext.domain('gnome-shell-extensions'); const _ = Gettext.gettext; -const ExtensionUtils = imports.misc.extensionUtils; - const appSys = Shell.AppSystem.get_default(); const APPLICATION_ICON_SIZE = 32; @@ -25,47 +25,34 @@ 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 { - constructor(button, app) { - super(); + _init(button, app) { + super._init(); this._app = app; this._button = button; this._iconBin = new St.Bin(); - this.actor.add_child(this._iconBin); + this.add_child(this._iconBin); 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; + this.add_child(appLabel); + this.label_actor = appLabel; let textureCache = St.TextureCache.get_default(); let iconThemeChangedId = textureCache.connect('icon-theme-changed', - this._updateIcon.bind(this)); - this.actor.connect('destroy', () => { + this._updateIcon.bind(this)); + this.connect('destroy', () => { textureCache.disconnect(iconThemeChangedId); }); this._updateIcon(); - this.actor._delegate = this; - let draggable = DND.makeDraggable(this.actor); + this._delegate = this; + let draggable = DND.makeDraggable(this); let maybeStartDrag = draggable._maybeStartDrag; draggable._maybeStartDrag = (event) => { @@ -80,6 +67,8 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { this._button.selectCategory(null); this._button.menu.toggle(); super.activate(event); + + Main.overview.hide(); } setActive(active, params) { @@ -101,13 +90,16 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { } _updateIcon() { - this._iconBin.set_child(this.getDragActor()); + let icon = this.getDragActor(); + icon.style_class = 'icon-dropshadow'; + this._iconBin.set_child(icon); } -} +}); +var CategoryMenuItem = GObject.registerClass( class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { - constructor(button, category) { - super(); + _init(button, category) { + super._init(); this._category = category; this._button = button; @@ -120,8 +112,9 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { else name = _('Favorites'); - this.actor.add_child(new St.Label({ text: name })); - this.actor.connect('motion-event', this._onMotionEvent.bind(this)); + this.add_child(new St.Label({ text: name })); + this.connect('motion-event', this._onMotionEvent.bind(this)); + this.connect('notify::active', this._onActiveChanged.bind(this)); } activate(event) { @@ -131,7 +124,7 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { } _isNavigatingSubmenu([x, y]) { - let [posX, posY] = this.actor.get_transformed_position(); + let [posX, posY] = this.get_transformed_position(); if (this._oldX == -1) { this._oldX = x; @@ -146,11 +139,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.actor.width < x) + if (posX > x || posX + this.width < x) return false; // If it lies inside the menu item then it is definitely inside. - if (posY <= y && posY + this.actor.height >= y) + if (posY <= y && posY + this.height >= y) return true; // We want the keep-up triangle only if the movement is more @@ -171,17 +164,17 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { // only check for triangle ABC. if (posY > y) { let offset = posY - y; - y = posY + this.actor.height + offset; + y = posY + this.height + offset; } // Ensure that A is (0, 0). x -= posX; - y -= posY + this.actor.height; + y -= posY + this.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.actor.width * y) - (NAVIGATION_REGION_OVERSHOOT * x)) <= 0) + if (((this.width * y) - (NAVIGATION_REGION_OVERSHOOT * x)) <= 0) return true; return false; @@ -191,16 +184,16 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { if (!Clutter.get_pointer_grab()) { this._oldX = -1; this._oldY = -1; - Clutter.grab_pointer(this.actor); + Clutter.grab_pointer(this); } - this.actor.hover = true; + this.hover = true; if (this._isNavigatingSubmenu(event.get_coords())) return true; this._oldX = -1; this._oldY = -1; - this.actor.hover = false; + this.hover = false; Clutter.ungrab_pointer(); let source = event.get_source(); @@ -210,14 +203,14 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { return false; } - setActive(active, params) { - if (active) { - this._button.selectCategory(this._category); - this._button.scrollToCatButton(this); - } - super.setActive(active, params); + _onActiveChanged() { + if (!this.active) + return; + + this._button.selectCategory(this._category); + this._button.scrollToCatButton(this); } -} +}); class ApplicationsMenu extends PopupMenu.PopupMenu { constructor(sourceActor, arrowAlignment, arrowSide, button) { @@ -229,28 +222,9 @@ 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) { + if (this.isOpen) this._button.selectCategory(null); - } else { - if (Main.overview.visible) - Main.overview.hide(); - } super.toggle(); } } @@ -262,7 +236,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); @@ -322,8 +296,8 @@ class DesktopTarget { // Hack: force nautilus to reload file info info = new Gio.FileInfo(); - info.set_attribute_uint64(Gio.FILE_ATTRIBUTE_TIME_ACCESS, - GLib.get_real_time()); + 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) { @@ -402,8 +376,6 @@ class ApplicationsButton extends PanelMenu.Button { this.name = 'panelApplications'; this.label_actor = this._label; - this.connect('captured-event', this._onCapturedEvent.bind(this)); - this._showingId = Main.overview.connect('showing', () => { this.add_accessible_state (Atk.StateType.CHECKED); }); @@ -411,7 +383,7 @@ class ApplicationsButton extends PanelMenu.Button { this.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(); @@ -426,14 +398,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() { @@ -445,10 +417,6 @@ 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', @@ -459,30 +427,23 @@ class ApplicationsButton extends PanelMenu.Button { } _onDestroy() { + super._onDestroy(); + Main.overview.disconnect(this._showingId); Main.overview.disconnect(this._hidingId); appSys.disconnect(this._installedChangedId); this._tree.disconnect(this._treeChangedId); this._tree = null; - let handler = Main.sessionMode.hasOverview ? - Main.overview.toggle.bind(Main.overview) : null; Main.wm.setCustomKeybindingHandler('panel-main-menu', - Shell.ActionMode.NORMAL | - Shell.ActionMode.OVERVIEW, - handler); + 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) { @@ -522,9 +483,8 @@ class ApplicationsButton extends PanelMenu.Button { _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() { @@ -565,7 +525,7 @@ 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.actor.get_allocation_box(); + let buttonAlloc = button.get_allocation_box(); let newScrollValue = currentScrollValue; if (currentScrollValue > buttonAlloc.y1 - 10) newScrollValue = buttonAlloc.y1 - 10; @@ -580,7 +540,7 @@ 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.actor.get_allocation_box(); + let buttonAlloc = button.get_allocation_box(); let newScrollValue = currentScrollValue; if (currentScrollValue > buttonAlloc.y1 - 10) newScrollValue = buttonAlloc.y1 - 10; @@ -626,14 +586,6 @@ class ApplicationsButton extends PanelMenu.Button { 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); this.categoriesBox = new St.BoxLayout({ vertical: true }); @@ -663,7 +615,7 @@ class ApplicationsButton extends PanelMenu.Button { this._tree.load_sync(); let root = this._tree.get_root_directory(); let categoryMenuItem = new CategoryMenuItem(this, null); - this.categoriesBox.add_actor(categoryMenuItem.actor); + this.categoriesBox.add_actor(categoryMenuItem); let iter = root.iter(); let nextType; while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) { @@ -679,7 +631,7 @@ class ApplicationsButton extends PanelMenu.Button { this._loadCategory(categoryId, dir); if (this.applicationsByCategory[categoryId].length > 0) { let categoryMenuItem = new CategoryMenuItem(this, dir); - this.categoriesBox.add_actor(categoryMenuItem.actor); + this.categoriesBox.add_actor(categoryMenuItem); } } @@ -720,8 +672,8 @@ class ApplicationsButton extends PanelMenu.Button { 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); } } @@ -745,19 +697,16 @@ class ApplicationsButton extends PanelMenu.Button { }); let appsMenuButton; -let activitiesButton; function enable() { - activitiesButton = Main.panel.statusArea['activities']; - activitiesButton.container.hide(); appsMenuButton = new ApplicationsButton(); - Main.panel.addToStatusArea('apps-menu', appsMenuButton, 1, 'left'); + let index = Main.sessionMode.panel.left.indexOf('activities') + 1; + Main.panel.addToStatusArea('apps-menu', appsMenuButton, index, 'left'); } function disable() { Main.panel.menuManager.removeMenu(appsMenuButton.menu); appsMenuButton.destroy(); - activitiesButton.container.show(); } function init() { diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js index 646156aa..aec7bc33 100644 --- a/extensions/auto-move-windows/extension.js +++ b/extensions/auto-move-windows/extension.js @@ -4,9 +4,8 @@ const Shell = imports.gi.Shell; -const Main = imports.ui.main; - const ExtensionUtils = imports.misc.extensionUtils; +const Main = imports.ui.main; class WindowMover { constructor() { @@ -17,7 +16,7 @@ class WindowMover { 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(); @@ -50,7 +49,7 @@ class WindowMover { addedApps.forEach(app => { let data = { windowsChangedId: app.connect('windows-changed', - this._appWindowsChanged.bind(this)), + this._appWindowsChanged.bind(this)), moveWindowsId: 0, windows: app.get_windows() }; diff --git a/extensions/auto-move-windows/prefs.js b/extensions/auto-move-windows/prefs.js index f9c4699e..62eeee9f 100644 --- a/extensions/auto-move-windows/prefs.js +++ b/extensions/auto-move-windows/prefs.js @@ -233,8 +233,8 @@ const Widget = GObject.registerClass({ }); let { APPINFO, ICON, DISPLAY_NAME, WORKSPACE, ADJUSTMENT } = Columns; this._store.set(iter, - [APPINFO, ICON, DISPLAY_NAME, WORKSPACE, ADJUSTMENT], - [appInfo, icon, displayName, workspace, adj]); + [APPINFO, ICON, DISPLAY_NAME, WORKSPACE, ADJUSTMENT], + [appInfo, icon, displayName, workspace, adj]); } _checkId(id) { diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index 7c8e36cf..963abfe8 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -5,36 +5,38 @@ const { Gio, GObject, Shell, St } = imports.gi; const Gettext = imports.gettext.domain('gnome-shell-extensions'); const _ = Gettext.gettext; +const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; const ShellMountOperation = imports.ui.shellMountOperation; -const ExtensionUtils = imports.misc.extensionUtils; - +var MountMenuItem = GObject.registerClass( class MountMenuItem extends PopupMenu.PopupBaseMenuItem { - constructor(mount) { - super(); + _init(mount) { + super._init(); this.label = new St.Label({ text: mount.get_name() }); - this.actor.add(this.label, { expand: true }); - this.actor.label_actor = this.label; + this.add(this.label, { expand: true }); + this.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 ejectButton = new St.Button({ child: ejectIcon }); ejectButton.connect('clicked', this._eject.bind(this)); - this.actor.add(ejectButton); + this.add(ejectButton); this._changedId = mount.connect('changed', this._syncVisibility.bind(this)); this._syncVisibility(); } - destroy() { + _onDestroy() { if (this._changedId) { this.mount.disconnect(this._changedId); this._changedId = 0; @@ -61,7 +63,7 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem { } _syncVisibility() { - this.actor.visible = this._isInteresting(); + this.visible = this._isInteresting(); } _eject() { @@ -73,10 +75,10 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem { if (this.mount.can_eject()) this.mount.eject_with_operation(...unmountArgs, - this._ejectFinish.bind(this)); + this._ejectFinish.bind(this)); else this.mount.unmount_with_operation(...unmountArgs, - this._unmountFinish.bind(this)); + this._unmountFinish.bind(this)); } _unmountFinish(mount, result) { @@ -102,13 +104,13 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem { } 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(this.mount.get_root().get_uri(), - context); + Gio.AppInfo.launch_default_for_uri(uri, context); super.activate(event); } -} +}); let DriveMenu = GObject.registerClass( class DriveMenu extends PanelMenu.Button { @@ -150,7 +152,7 @@ class DriveMenu extends PanelMenu.Button { } _updateMenuVisibility() { - if (this._mounts.filter(i => i.actor.visible).length > 0) + if (this._mounts.filter(i => i.visible).length > 0) this.show(); else this.hide(); diff --git a/extensions/horizontal-workspaces/extension.js b/extensions/horizontal-workspaces/extension.js new file mode 100644 index 00000000..b5f04355 --- /dev/null +++ b/extensions/horizontal-workspaces/extension.js @@ -0,0 +1,38 @@ +/* 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(); +} diff --git a/extensions/horizontal-workspaces/meson.build b/extensions/horizontal-workspaces/meson.build new file mode 100644 index 00000000..48504f63 --- /dev/null +++ b/extensions/horizontal-workspaces/meson.build @@ -0,0 +1,5 @@ +extension_data += configure_file( + input: metadata_name + '.in', + output: metadata_name, + configuration: metadata_conf +) diff --git a/extensions/horizontal-workspaces/metadata.json.in b/extensions/horizontal-workspaces/metadata.json.in new file mode 100644 index 00000000..f109e068 --- /dev/null +++ b/extensions/horizontal-workspaces/metadata.json.in @@ -0,0 +1,10 @@ +{ +"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@" +} diff --git a/extensions/horizontal-workspaces/stylesheet.css b/extensions/horizontal-workspaces/stylesheet.css new file mode 100644 index 00000000..25134b65 --- /dev/null +++ b/extensions/horizontal-workspaces/stylesheet.css @@ -0,0 +1 @@ +/* This extensions requires no special styling */ diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js index 8a8b0937..04ad250d 100644 --- a/extensions/native-window-placement/extension.js +++ b/extensions/native-window-placement/extension.js @@ -1,8 +1,7 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- /* exported enable disable */ -const Workspace = imports.ui.workspace; - const ExtensionUtils = imports.misc.extensionUtils; +const Workspace = imports.ui.workspace; // testing settings for natural window placement strategy: const WINDOW_PLACEMENT_NATURAL_ACCURACY = 20; // accuracy of window translate moves (KDE-default: 20) @@ -203,9 +202,10 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy { // 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( + areaRect.width / bounds.width, + areaRect.height / bounds.height, + 1.0); // Make bounding rect fill the screen size for later steps bounds.x = bounds.x - (areaRect.width - bounds.width * scale) / 2; diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index c477a4ac..92c6d690 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -3,6 +3,7 @@ const { Clutter, GObject, St } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; @@ -11,25 +12,25 @@ 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 PlaceDisplay = Me.imports.placeDisplay; const PLACE_ICON_SIZE = 16; +var PlaceMenuItem = GObject.registerClass( class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem { - constructor(info) { - super(); + _init(info) { + super._init(); this._info = info; this._icon = new St.Icon({ gicon: info.icon, icon_size: PLACE_ICON_SIZE }); - this.actor.add_child(this._icon); + this.add_child(this._icon); this._label = new St.Label({ text: info.name, x_expand: true }); - this.actor.add_child(this._label); + this.add_child(this._label); if (info.isRemovable()) { this._ejectIcon = new St.Icon({ @@ -38,11 +39,11 @@ class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem { }); this._ejectButton = new St.Button({ child: this._ejectIcon }); this._ejectButton.connect('clicked', info.eject.bind(info)); - this.actor.add_child(this._ejectButton); + this.add_child(this._ejectButton); } this._changedId = info.connect('changed', - this._propertiesChanged.bind(this)); + this._propertiesChanged.bind(this)); } destroy() { @@ -64,7 +65,7 @@ class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem { this._icon.gicon = info.icon; this._label.text = info.name; } -} +}); const SECTIONS = [ 'special', @@ -135,9 +136,9 @@ let _indicator; function enable() { _indicator = new PlacesMenu; - let pos = 1; + let pos = Main.sessionMode.panel.left.indexOf('appMenu'); if ('apps-menu' in Main.panel.statusArea) - pos = 2; + pos++; Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left'); } diff --git a/extensions/places-menu/placeDisplay.js b/extensions/places-menu/placeDisplay.js index e97cef4f..ff41eb07 100644 --- a/extensions/places-menu/placeDisplay.js +++ b/extensions/places-menu/placeDisplay.js @@ -71,18 +71,21 @@ class PlaceInfo { } getIcon() { - 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; - throw e; - } - }); + 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; + } + }); // return a generic icon for this kind for now, until we have the // icon from the query info above @@ -152,7 +155,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); }); } @@ -203,10 +206,10 @@ class PlaceDeviceInfo extends PlaceInfo { if (this._mount.can_eject()) this._mount.eject_with_operation(...unmountArgs, - this._ejectFinish.bind(this)); + this._ejectFinish.bind(this)); else this._mount.unmount_with_operation(...unmountArgs, - this._unmountFinish.bind(this)); + this._unmountFinish.bind(this)); } _ejectFinish(mount, result) { @@ -275,9 +278,8 @@ 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(); /* @@ -350,9 +352,10 @@ var PlacesManager = class { 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(); @@ -394,10 +397,11 @@ var PlacesManager = class { /* 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(); diff --git a/extensions/screenshot-window-sizer/extension.js b/extensions/screenshot-window-sizer/extension.js index 41c4c853..44bad8e9 100644 --- a/extensions/screenshot-window-sizer/extension.js +++ b/extensions/screenshot-window-sizer/extension.js @@ -21,12 +21,11 @@ const { Meta, Shell, St } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const Tweener = imports.ui.tweener; -const ExtensionUtils = imports.misc.extensionUtils; - -const MESSAGE_FADE_TIME = 2; +const MESSAGE_FADE_TIME = 2000; let text; @@ -41,20 +40,21 @@ function flashMessage(message) { Main.uiGroup.add_actor(text); } - Tweener.removeTweens(text); + text.remove_all_transitions(); 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)); - Tweener.addTween(text, { + text.ease({ opacity: 0, - time: MESSAGE_FADE_TIME, - transition: 'easeOutQuad', - onComplete: hideMessage + duration: MESSAGE_FADE_TIME, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: hideMessage, }); } @@ -63,7 +63,9 @@ let SIZES = [ [800, 450], [1024, 576], [1200, 675], - [1600, 900] + [1600, 900], + [360, 654], // Phone portrait maximized + [720, 360] // Phone landscape fullscreen ]; function cycleScreenshotSizes(display, window, binding) { @@ -135,17 +137,18 @@ function cycleScreenshotSizes(display, window, binding) { } 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', + 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); } function disable() { diff --git a/extensions/user-theme/extension.js b/extensions/user-theme/extension.js index d00c0774..0c316844 100644 --- a/extensions/user-theme/extension.js +++ b/extensions/user-theme/extension.js @@ -3,12 +3,12 @@ /* exported init */ const { Gio, GLib } = imports.gi; + +const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const SETTINGS_KEY = 'name'; -const ExtensionUtils = imports.misc.extensionUtils; - class ThemeManager { constructor() { this._settings = ExtensionUtils.getSettings(); diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css index f3c44a3d..7079d3ef 100644 --- a/extensions/window-list/classic.css +++ b/extensions/window-list/classic.css @@ -4,36 +4,39 @@ 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-button:hover > StWidget, + .bottom-panel .window-picker-toggle:hover > StWidget { background-color: #f9f9f9; } .bottom-panel .window-button:active > StWidget, .bottom-panel .window-button:focus > StWidget { - box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5); + 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 > 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:hover > StWidget { @@ -42,5 +45,24 @@ .bottom-panel .window-button.minimized > StWidget { color: #888; - box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5); + box-shadow: none; } + +/* 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; +} diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index e1ea742e..ec6dbbec 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -2,12 +2,14 @@ const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi; const DND = imports.ui.dnd; +const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; +const Overview = imports.ui.overview; const PopupMenu = imports.ui.popupMenu; -const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); +const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker; +const { WorkspaceIndicator } = Me.imports.workspaceIndicator; const Gettext = imports.gettext.domain('gnome-shell-extensions'); const _ = Gettext.gettext; @@ -72,9 +74,8 @@ class WindowContextMenu extends PopupMenu.PopupMenu { }); this.addMenuItem(this._minimizeItem); - this._notifyMinimizedId = - this._metaWindow.connect('notify::minimized', - this._updateMinimizeItem.bind(this)); + this._notifyMinimizedId = this._metaWindow.connect( + 'notify::minimized', this._updateMinimizeItem.bind(this)); this._updateMinimizeItem(); this._maximizeItem = new PopupMenu.PopupMenuItem(''); @@ -86,12 +87,12 @@ class WindowContextMenu extends PopupMenu.PopupMenu { }); this.addMenuItem(this._maximizeItem); - this._notifyMaximizedHId = - this._metaWindow.connect('notify::maximized-horizontally', - this._updateMaximizeItem.bind(this)); - this._notifyMaximizedVId = - this._metaWindow.connect('notify::maximized-vertically', - this._updateMaximizeItem.bind(this)); + this._notifyMaximizedHId = this._metaWindow.connect( + 'notify::maximized-horizontally', + this._updateMaximizeItem.bind(this)); + this._notifyMaximizedVId = this._metaWindow.connect( + 'notify::maximized-vertically', + this._updateMaximizeItem.bind(this)); this._updateMaximizeItem(); this._closeItem = new PopupMenu.PopupMenuItem(_('Close')); @@ -131,40 +132,38 @@ class WindowContextMenu extends PopupMenu.PopupMenu { } } -class WindowTitle { - constructor(metaWindow) { +const WindowTitle = GObject.registerClass({ + GTypeName: 'WindowListWindowTitle' +}, class WindowTitle extends St.BoxLayout { + _init(metaWindow) { this._metaWindow = metaWindow; - this.actor = new St.BoxLayout({ + + super._init({ style_class: 'window-button-box', x_expand: true, y_expand: true }); this._icon = new St.Bin({ style_class: 'window-button-icon' }); - this.actor.add(this._icon); + this.add(this._icon); this.label_actor = new St.Label({ y_align: Clutter.ActorAlign.CENTER }); - this.actor.add(this.label_actor); + this.add(this.label_actor); this._textureCache = St.TextureCache.get_default(); - this._iconThemeChangedId = - this._textureCache.connect('icon-theme-changed', - this._updateIcon.bind(this)); - this._notifyWmClass = - this._metaWindow.connect_after('notify::wm-class', - this._updateIcon.bind(this)); - this._notifyAppId = - this._metaWindow.connect_after('notify::gtk-application-id', - this._updateIcon.bind(this)); + this._iconThemeChangedId = this._textureCache.connect( + 'icon-theme-changed', this._updateIcon.bind(this)); + this._notifyWmClass = this._metaWindow.connect_after( + 'notify::wm-class', this._updateIcon.bind(this)); + this._notifyAppId = this._metaWindow.connect_after( + 'notify::gtk-application-id', this._updateIcon.bind(this)); this._updateIcon(); - this.actor.connect('destroy', this._onDestroy.bind(this)); + this.connect('destroy', this._onDestroy.bind(this)); - this._notifyTitleId = - this._metaWindow.connect('notify::title', - this._updateTitle.bind(this)); - this._notifyMinimizedId = - this._metaWindow.connect('notify::minimized', - this._minimizedChanged.bind(this)); + this._notifyTitleId = this._metaWindow.connect( + 'notify::title', this._updateTitle.bind(this)); + this._notifyMinimizedId = this._metaWindow.connect( + 'notify::minimized', this._minimizedChanged.bind(this)); this._minimizedChanged(); } @@ -201,61 +200,83 @@ class WindowTitle { this._metaWindow.disconnect(this._notifyWmClass); this._metaWindow.disconnect(this._notifyAppId); } -} +}); -class BaseButton { - constructor(perMonitor, monitorIndex) { - if (this.constructor === BaseButton) - throw new TypeError('Cannot instantiate abstract class BaseButton'); - +const BaseButton = GObject.registerClass({ + GTypeName: 'WindowListBaseButton', + GTypeFlags: GObject.TypeFlags.ABSTRACT, + Properties: { + 'ignore-workspace': GObject.ParamSpec.boolean( + 'ignore-workspace', 'ignore-workspace', 'ignore-workspace', + GObject.ParamFlags.READWRITE, + false) + } +}, class BaseButton extends St.Button { + _init(perMonitor, monitorIndex) { this._perMonitor = perMonitor; this._monitorIndex = monitorIndex; + this._ignoreWorkspace = false; - this.actor = new St.Button({ + super._init({ style_class: 'window-button', x_fill: true, y_fill: true, can_focus: true, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE }); - this.actor._delegate = this; - this.actor.connect('allocation-changed', - this._updateIconGeometry.bind(this)); - this.actor.connect('clicked', this._onClicked.bind(this)); - this.actor.connect('destroy', this._onDestroy.bind(this)); - this.actor.connect('popup-menu', this._onPopupMenu.bind(this)); + this.connect('allocation-changed', + this._updateIconGeometry.bind(this)); + this.connect('clicked', this._onClicked.bind(this)); + this.connect('destroy', this._onDestroy.bind(this)); + this.connect('popup-menu', this._onPopupMenu.bind(this)); this._contextMenuManager = new PopupMenu.PopupMenuManager(this); - this._switchWorkspaceId = - global.window_manager.connect('switch-workspace', - this._updateVisibility.bind(this)); + this._switchWorkspaceId = global.window_manager.connect( + 'switch-workspace', this._updateVisibility.bind(this)); if (this._perMonitor) { - this._windowEnteredMonitorId = - global.display.connect('window-entered-monitor', - this._windowEnteredOrLeftMonitor.bind(this)); - this._windowLeftMonitorId = - global.display.connect('window-left-monitor', - this._windowEnteredOrLeftMonitor.bind(this)); + this._windowEnteredMonitorId = global.display.connect( + 'window-entered-monitor', + this._windowEnteredOrLeftMonitor.bind(this)); + this._windowLeftMonitorId = global.display.connect( + 'window-left-monitor', + this._windowEnteredOrLeftMonitor.bind(this)); } } get active() { - return this.actor.has_style_class_name('focused'); + return this.has_style_class_name('focused'); + } + + // eslint-disable-next-line camelcase + get ignore_workspace() { + return this._ignoreWorkspace; + } + + // eslint-disable-next-line camelcase + set ignore_workspace(ignore) { + if (this._ignoreWorkspace == ignore) + return; + + this._ignoreWorkspace = ignore; + this.notify('ignore-workspace'); + + this._updateVisibility(); } activate() { if (this.active) return; - this._onClicked(this.actor, 1); + this._onClicked(this, 1); } _onClicked(_actor, _button) { - throw new Error('Not implemented'); + throw new GObject.NotImplementedError( + `_onClicked in ${this.constructor.name}`); } _canOpenPopupMenu() { @@ -269,43 +290,47 @@ class BaseButton { } _isFocused() { - throw new Error('Not implemented'); + throw new GObject.NotImplementedError( + `_isFocused in ${this.constructor.name}`); } _updateStyle() { if (this._isFocused()) - this.actor.add_style_class_name('focused'); + this.add_style_class_name('focused'); else - this.actor.remove_style_class_name('focused'); + this.remove_style_class_name('focused'); } _windowEnteredOrLeftMonitor(_metaDisplay, _monitorIndex, _metaWindow) { - throw new Error('Not implemented'); + throw new GObject.NotImplementedError( + `_windowEnteredOrLeftMonitor in ${this.constructor.name}`); } _isWindowVisible(window) { let workspace = global.workspace_manager.get_active_workspace(); return !window.skip_taskbar && - window.located_on_workspace(workspace) && + (this._ignoreWorkspace || window.located_on_workspace(workspace)) && (!this._perMonitor || window.get_monitor() == this._monitorIndex); } _updateVisibility() { - throw new Error('Not implemented'); + throw new GObject.NotImplementedError( + `_updateVisibility in ${this.constructor.name}`); } _getIconGeometry() { let rect = new Meta.Rectangle(); - [rect.x, rect.y] = this.actor.get_transformed_position(); - [rect.width, rect.height] = this.actor.get_transformed_size(); + [rect.x, rect.y] = this.get_transformed_position(); + [rect.width, rect.height] = this.get_transformed_size(); return rect; } _updateIconGeometry() { - throw new Error('Not implemented'); + throw new GObject.NotImplementedError( + `_updateIconGeometry in ${this.constructor.name}`); } _onDestroy() { @@ -319,33 +344,33 @@ class BaseButton { global.display.disconnect(this._windowLeftMonitorId); this._windowLeftMonitorId = 0; } -} +}); -class WindowButton extends BaseButton { - constructor(metaWindow, perMonitor, monitorIndex) { - super(perMonitor, monitorIndex); +const WindowButton = GObject.registerClass({ + GTypeName: 'WindowListWindowButton' +}, class WindowButton extends BaseButton { + _init(metaWindow, perMonitor, monitorIndex) { + super._init(perMonitor, monitorIndex); this.metaWindow = metaWindow; this._updateVisibility(); this._windowTitle = new WindowTitle(this.metaWindow); - this.actor.set_child(this._windowTitle.actor); - this.actor.label_actor = this._windowTitle.label_actor; + this.set_child(this._windowTitle); + this.label_actor = this._windowTitle.label_actor; - this._contextMenu = new WindowContextMenu(this.actor, this.metaWindow); + this._contextMenu = new WindowContextMenu(this, this.metaWindow); this._contextMenu.connect('open-state-changed', _onMenuStateChanged); this._contextMenu.actor.hide(); this._contextMenuManager.addMenu(this._contextMenu); Main.uiGroup.add_actor(this._contextMenu.actor); - this._workspaceChangedId = - this.metaWindow.connect('workspace-changed', - this._updateVisibility.bind(this)); + this._workspaceChangedId = this.metaWindow.connect( + 'workspace-changed', this._updateVisibility.bind(this)); - this._notifyFocusId = - global.display.connect('notify::focus-window', - this._updateStyle.bind(this)); + this._notifyFocusId = global.display.connect( + 'notify::focus-window', this._updateStyle.bind(this)); this._updateStyle(); } @@ -369,9 +394,9 @@ class WindowButton extends BaseButton { super._updateStyle(); if (this.metaWindow.minimized) - this.actor.add_style_class_name('minimized'); + this.add_style_class_name('minimized'); else - this.actor.remove_style_class_name('minimized'); + this.remove_style_class_name('minimized'); } _windowEnteredOrLeftMonitor(metaDisplay, monitorIndex, metaWindow) { @@ -380,7 +405,7 @@ class WindowButton extends BaseButton { } _updateVisibility() { - this.actor.visible = this._isWindowVisible(this.metaWindow); + this.visible = this._isWindowVisible(this.metaWindow); } _updateIconGeometry() { @@ -393,14 +418,14 @@ class WindowButton extends BaseButton { global.display.disconnect(this._notifyFocusId); this._contextMenu.destroy(); } -} +}); class AppContextMenu extends PopupMenu.PopupMenu { - constructor(source, appButton) { + constructor(source) { super(source, 0.5, St.Side.BOTTOM); - this._appButton = appButton; + this._appButton = source; this._minimizeItem = new PopupMenu.PopupMenuItem(_('Minimize all')); this._minimizeItem.connect('activate', () => { @@ -441,12 +466,12 @@ class AppContextMenu extends PopupMenu.PopupMenu { open(animate) { let windows = this._appButton.getWindowList(); - this._minimizeItem.actor.visible = windows.some(w => !w.minimized); - this._unminimizeItem.actor.visible = windows.some(w => w.minimized); - this._maximizeItem.actor.visible = windows.some(w => { + this._minimizeItem.visible = windows.some(w => !w.minimized); + this._unminimizeItem.visible = windows.some(w => w.minimized); + this._maximizeItem.visible = windows.some(w => { return w.get_maximized() != Meta.MaximizeFlags.BOTH; }); - this._unmaximizeItem.actor.visible = windows.some(w => { + this._unmaximizeItem.visible = windows.some(w => { return w.get_maximized() == Meta.MaximizeFlags.BOTH; }); @@ -454,15 +479,17 @@ class AppContextMenu extends PopupMenu.PopupMenu { } } -class AppButton extends BaseButton { - constructor(app, perMonitor, monitorIndex) { - super(perMonitor, monitorIndex); +const AppButton = GObject.registerClass({ + GTypeName: 'WindowListAppButton', +}, class AppButton extends BaseButton { + _init(app, perMonitor, monitorIndex) { + super._init(perMonitor, monitorIndex); this.app = app; this._updateVisibility(); let stack = new St.Widget({ layout_manager: new Clutter.BinLayout() }); - this.actor.set_child(stack); + this.set_child(stack); this._singleWindowTitle = new St.Bin({ x_expand: true, @@ -491,14 +518,14 @@ class AppButton extends BaseButton { this._multiWindowTitle.label_actor = label; this._menuManager = new PopupMenu.PopupMenuManager(this); - this._menu = new PopupMenu.PopupMenu(this.actor, 0.5, St.Side.BOTTOM); + this._menu = new PopupMenu.PopupMenu(this, 0.5, St.Side.BOTTOM); this._menu.connect('open-state-changed', _onMenuStateChanged); this._menu.actor.hide(); this._menu.connect('activate', this._onMenuActivate.bind(this)); this._menuManager.addMenu(this._menu); Main.uiGroup.add_actor(this._menu.actor); - this._appContextMenu = new AppContextMenu(this.actor, this); + this._appContextMenu = new AppContextMenu(this); this._appContextMenu.connect('open-state-changed', _onMenuStateChanged); this._appContextMenu.actor.hide(); Main.uiGroup.add_actor(this._appContextMenu.actor); @@ -509,15 +536,13 @@ class AppButton extends BaseButton { this._icon.child = app.create_icon_texture(ICON_TEXTURE_SIZE); }); - this._windowsChangedId = - this.app.connect('windows-changed', - this._windowsChanged.bind(this)); + this._windowsChangedId = this.app.connect( + 'windows-changed', this._windowsChanged.bind(this)); this._windowsChanged(); this._windowTracker = Shell.WindowTracker.get_default(); - this._notifyFocusId = - this._windowTracker.connect('notify::focus-app', - this._updateStyle.bind(this)); + this._notifyFocusId = this._windowTracker.connect( + 'notify::focus-app', this._updateStyle.bind(this)); this._updateStyle(); } @@ -530,12 +555,14 @@ class AppButton extends BaseButton { } _updateVisibility() { - if (!this._perMonitor) { + if (this._ignoreWorkspace) { + this.visible = true; + } else if (!this._perMonitor) { // fast path: use ShellApp API to avoid iterating over all windows. let workspace = global.workspace_manager.get_active_workspace(); - this.actor.visible = this.app.is_on_workspace(workspace); + this.visible = this.app.is_on_workspace(workspace); } else { - this.actor.visible = this.getWindowList().length >= 1; + this.visible = this.getWindowList().length >= 1; } } @@ -563,17 +590,17 @@ class AppButton extends BaseButton { if (!this._windowTitle) { this.metaWindow = windows[0]; this._windowTitle = new WindowTitle(this.metaWindow); - this._singleWindowTitle.child = this._windowTitle.actor; - this._windowContextMenu = new WindowContextMenu(this.actor, this.metaWindow); - this._windowContextMenu.connect('open-state-changed', - _onMenuStateChanged); + this._singleWindowTitle.child = this._windowTitle; + this._windowContextMenu = new WindowContextMenu(this, this.metaWindow); + this._windowContextMenu.connect( + 'open-state-changed', _onMenuStateChanged); Main.uiGroup.add_actor(this._windowContextMenu.actor); this._windowContextMenu.actor.hide(); this._contextMenuManager.addMenu(this._windowContextMenu); } this._contextMenuManager.removeMenu(this._appContextMenu); this._contextMenu = this._windowContextMenu; - this.actor.label_actor = this._windowTitle.label_actor; + this.label_actor = this._windowTitle.label_actor; } else { if (this._windowTitle) { this.metaWindow = null; @@ -584,7 +611,7 @@ class AppButton extends BaseButton { } this._contextMenu = this._appContextMenu; this._contextMenuManager.addMenu(this._appContextMenu); - this.actor.label_actor = this._multiWindowTitle.label_actor; + this.label_actor = this._multiWindowTitle.label_actor; } } @@ -613,7 +640,7 @@ class AppButton extends BaseButton { for (let i = 0; i < windows.length; i++) { let windowTitle = new WindowTitle(windows[i]); let item = new PopupMenu.PopupBaseMenuItem(); - item.actor.add_actor(windowTitle.actor); + item.add_actor(windowTitle); item._window = windows[i]; this._menu.addMenuItem(item); } @@ -641,151 +668,33 @@ class AppButton extends BaseButton { this.app.disconnect(this._windowsChangedId); this._menu.destroy(); } -} - - -let 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(), - x_align: Clutter.ActorAlign.CENTER, - y_align: Clutter.ActorAlign.CENTER - }); - container.add_actor(this.statusLabel); - - this.workspacesItems = []; - - this._workspaceManagerSignals = []; - this._workspaceManagerSignals.push(workspaceManager.connect('notify::n-workspaces', - this._updateMenu.bind(this))); - this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched', - this._updateIndicator.bind(this))); - - this.connect('scroll-event', this._onScrollEvent.bind(this)); - this._updateMenu(); - - this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); - this._settingsChangedId = - this._settings.connect('changed::workspace-names', - this._updateMenu.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(); - } - - _updateIndicator() { - this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); - this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); - this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); - - this.statusLabel.set_text(this._getStatusText()); - } - - _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); - } - - _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', (item, _event) => { - 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()); - } - - _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); - } }); -class WindowList { - constructor(perMonitor, monitor) { + +const WindowList = GObject.registerClass({ + GTypeName: 'WindowListWindowList', +}, class WindowList extends St.Widget { + _init(perMonitor, monitor) { this._perMonitor = perMonitor; this._monitor = monitor; - this.actor = new St.Widget({ + super._init({ name: 'panel', style_class: 'bottom-panel solid', reactive: true, track_hover: true, layout_manager: new Clutter.BinLayout() }); - this.actor.connect('destroy', this._onDestroy.bind(this)); + this.connect('destroy', this._onDestroy.bind(this)); let box = new St.BoxLayout({ x_expand: true, y_expand: true }); - this.actor.add_actor(box); + this.add_actor(box); + + let toggle = new WindowPickerToggle(); + box.add_actor(toggle); + + toggle.connect('notify::checked', + this._updateWindowListVisibility.bind(this)); let layout = new Clutter.BoxLayout({ homogeneous: true }); this._windowList = new St.Widget({ @@ -812,82 +721,77 @@ class WindowList { indicatorsBox.add(this._workspaceIndicator.container, { expand: false, y_fill: true }); this._mutterSettings = new Gio.Settings({ schema_id: 'org.gnome.mutter' }); - this._workspacesOnlyOnPrimaryChangedId = - this._mutterSettings.connect('changed::workspaces-only-on-primary', - this._updateWorkspaceIndicatorVisibility.bind(this)); - this._dynamicWorkspacesChangedId = - this._mutterSettings.connect('changed::dynamic-workspaces', - this._updateWorkspaceIndicatorVisibility.bind(this)); + this._workspacesOnlyOnPrimaryChangedId = this._mutterSettings.connect( + 'changed::workspaces-only-on-primary', + this._updateWorkspaceIndicatorVisibility.bind(this)); + this._dynamicWorkspacesChangedId = this._mutterSettings.connect( + 'changed::dynamic-workspaces', + this._updateWorkspaceIndicatorVisibility.bind(this)); this._updateWorkspaceIndicatorVisibility(); this._menuManager = new PopupMenu.PopupMenuManager(this); this._menuManager.addMenu(this._workspaceIndicator.menu); - Main.layoutManager.addChrome(this.actor, { + Main.layoutManager.addChrome(this, { affectsStruts: true, trackFullscreen: true }); - Main.uiGroup.set_child_above_sibling(this.actor, Main.layoutManager.panelBox); - Main.ctrlAltTabManager.addGroup(this.actor, _('Window List'), 'start-here-symbolic'); + Main.uiGroup.set_child_above_sibling(this, Main.layoutManager.panelBox); + Main.ctrlAltTabManager.addGroup(this, _('Window List'), 'start-here-symbolic'); - this.actor.width = this._monitor.width; - this.actor.connect('notify::height', this._updatePosition.bind(this)); + this.width = this._monitor.width; + this.connect('notify::height', this._updatePosition.bind(this)); this._updatePosition(); this._appSystem = Shell.AppSystem.get_default(); - this._appStateChangedId = - this._appSystem.connect('app-state-changed', - this._onAppStateChanged.bind(this)); + this._appStateChangedId = this._appSystem.connect( + 'app-state-changed', this._onAppStateChanged.bind(this)); - this._keyboardVisiblechangedId = - Main.layoutManager.connect('keyboard-visible-changed', - (o, state) => { - Main.layoutManager.keyboardBox.visible = state; - let keyboardBox = Main.layoutManager.keyboardBox; - keyboardBox.visible = state; - if (state) - Main.uiGroup.set_child_above_sibling(this.actor, keyboardBox); - else - Main.uiGroup.set_child_above_sibling(this.actor, - Main.layoutManager.panelBox); - this._updateKeyboardAnchor(); - }); + this._keyboardVisiblechangedId = Main.layoutManager.connect( + 'keyboard-visible-changed', + (o, state) => { + Main.layoutManager.keyboardBox.visible = state; + let keyboardBox = Main.layoutManager.keyboardBox; + keyboardBox.visible = state; + if (state) { + Main.uiGroup.set_child_above_sibling( + this, keyboardBox); + } else { + Main.uiGroup.set_child_above_sibling( + this, Main.layoutManager.panelBox); + } + this._updateKeyboardAnchor(); + }); let workspaceManager = global.workspace_manager; this._workspaceSignals = new Map(); - this._nWorkspacesChangedId = - workspaceManager.connect('notify::n-workspaces', - this._onWorkspacesChanged.bind(this)); + this._nWorkspacesChangedId = workspaceManager.connect( + 'notify::n-workspaces', this._onWorkspacesChanged.bind(this)); this._onWorkspacesChanged(); - this._switchWorkspaceId = - global.window_manager.connect('switch-workspace', - this._checkGrouping.bind(this)); + this._switchWorkspaceId = global.window_manager.connect( + 'switch-workspace', this._checkGrouping.bind(this)); - this._overviewShowingId = - Main.overview.connect('showing', () => { - this.actor.hide(); - this._updateKeyboardAnchor(); - }); + this._overviewShowingId = Main.overview.connect('showing', () => { + this.hide(); + this._updateKeyboardAnchor(); + }); - this._overviewHidingId = - Main.overview.connect('hiding', () => { - this.actor.visible = !Main.layoutManager.primaryMonitor.inFullscreen; - this._updateKeyboardAnchor(); - }); + this._overviewHidingId = Main.overview.connect('hiding', () => { + this.visible = !Main.layoutManager.primaryMonitor.inFullscreen; + this._updateKeyboardAnchor(); + }); this._fullscreenChangedId = global.display.connect('in-fullscreen-changed', () => { this._updateKeyboardAnchor(); }); - this._dragBeginId = - Main.xdndHandler.connect('drag-begin', - this._onDragBegin.bind(this)); - this._dragEndId = - Main.xdndHandler.connect('drag-end', - this._onDragEnd.bind(this)); + this._dragBeginId = Main.xdndHandler.connect('drag-begin', + this._onDragBegin.bind(this)); + this._dragEndId = Main.xdndHandler.connect('drag-end', + this._onDragEnd.bind(this)); this._dragMonitor = { dragMotion: this._onDragMotion.bind(this) }; @@ -896,9 +800,8 @@ class WindowList { this._dndWindow = null; this._settings = ExtensionUtils.getSettings(); - this._groupingModeChangedId = - this._settings.connect('changed::grouping-mode', - this._groupingModeChanged.bind(this)); + this._groupingModeChangedId = this._settings.connect( + 'changed::grouping-mode', this._groupingModeChanged.bind(this)); this._grouped = undefined; this._groupingModeChanged(); } @@ -914,16 +817,16 @@ class WindowList { return; let children = this._windowList.get_children() - .filter(c => c.visible) - .map(a => a._delegate); + .filter(c => c.visible); let active = children.findIndex(c => c.active); let newActive = Math.max(0, Math.min(active + diff, children.length - 1)); children[newActive].activate(); } _updatePosition() { - this.actor.set_position(this._monitor.x, - this._monitor.y + this._monitor.height - this.actor.height); + this.set_position( + this._monitor.x, + this._monitor.y + this._monitor.height - this.height); } _updateWorkspaceIndicatorVisibility() { @@ -933,7 +836,20 @@ class WindowList { let workspacesOnMonitor = this._monitor == Main.layoutManager.primaryMonitor || !this._mutterSettings.get_boolean('workspaces-only-on-primary'); - this._workspaceIndicator.actor.visible = hasWorkspaces && workspacesOnMonitor; + this._workspaceIndicator.visible = hasWorkspaces && workspacesOnMonitor; + } + + _updateWindowListVisibility() { + let visible = !Main.windowPicker.visible; + + this._windowList.ease({ + opacity: visible ? 255 : 0, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + duration: Overview.ANIMATION_TIME, + }); + + this._windowList.reactive = visible; + this._windowList.get_children().forEach(c => c.reactive = visible); } _getPreferredUngroupedWindowListWidth() { @@ -956,8 +872,8 @@ class WindowList { } _getMaxWindowListWidth() { - let indicatorsBox = this._workspaceIndicator.actor.get_parent(); - return this.actor.width - indicatorsBox.get_preferred_width(-1)[1]; + let indicatorsBox = this._workspaceIndicator.get_parent(); + return this.width - indicatorsBox.get_preferred_width(-1)[1]; } _groupingModeChanged() { @@ -1009,8 +925,8 @@ class WindowList { if (!Main.keyboard.actor) return; - let anchorY = Main.overview.visible ? 0 : this.actor.height; - Main.keyboard.actor.anchor_y = anchorY; + let translationY = Main.overview.visible ? 0 : this.height; + Main.keyboard.actor.translation_y = -translationY; } _onAppStateChanged(appSys, app) { @@ -1025,15 +941,17 @@ class WindowList { _addApp(app) { let button = new AppButton(app, this._perMonitor, this._monitor.index); - this._windowList.layout_manager.pack(button.actor, - true, true, true, - Clutter.BoxAlignment.START, - Clutter.BoxAlignment.START); + this._settings.bind('display-all-workspaces', + button, 'ignore-workspace', Gio.SettingsBindFlags.GET); + this._windowList.layout_manager.pack(button, + true, true, true, + Clutter.BoxAlignment.START, + Clutter.BoxAlignment.START); } _removeApp(app) { let children = this._windowList.get_children(); - let child = children.find(c => c._delegate.app == app); + let child = children.find(c => c.app == app); if (child) child.destroy(); } @@ -1049,14 +967,16 @@ class WindowList { return; let children = this._windowList.get_children(); - if (children.find(c => c._delegate.metaWindow == win)) + if (children.find(c => c.metaWindow == win)) return; let button = new WindowButton(win, this._perMonitor, this._monitor.index); - this._windowList.layout_manager.pack(button.actor, - true, true, true, - Clutter.BoxAlignment.START, - Clutter.BoxAlignment.START); + this._settings.bind('display-all-workspaces', + button, 'ignore-workspace', Gio.SettingsBindFlags.GET); + this._windowList.layout_manager.pack(button, + true, true, true, + Clutter.BoxAlignment.START, + Clutter.BoxAlignment.START); } _onWindowRemoved(ws, win) { @@ -1070,7 +990,7 @@ class WindowList { return; // not actually removed, just moved to another workspace let children = this._windowList.get_children(); - let child = children.find(c => c._delegate.metaWindow == win); + let child = children.find(c => c.metaWindow == win); if (child) child.destroy(); } @@ -1085,12 +1005,10 @@ class WindowList { continue; let signals = { windowAddedId: 0, windowRemovedId: 0 }; - signals._windowAddedId = - workspace.connect_after('window-added', - this._onWindowAdded.bind(this)); - signals._windowRemovedId = - workspace.connect('window-removed', - this._onWindowRemoved.bind(this)); + signals._windowAddedId = workspace.connect_after( + 'window-added', this._onWindowAdded.bind(this)); + signals._windowRemovedId = workspace.connect( + 'window-removed', this._onWindowRemoved.bind(this)); this._workspaceSignals.set(workspace, signals); } @@ -1121,15 +1039,12 @@ class WindowList { _onDragMotion(dragEvent) { if (Main.overview.visible || - !this.actor.contains(dragEvent.targetActor)) { + !this.contains(dragEvent.targetActor)) { this._removeActivateTimeout(); return DND.DragMotionResult.CONTINUE; } - let hoveredWindow = null; - if (dragEvent.targetActor._delegate) - hoveredWindow = dragEvent.targetActor._delegate.metaWindow; - + let hoveredWindow = dragEvent.targetActor.metaWindow; if (!hoveredWindow || this._dndWindow == hoveredWindow) return DND.DragMotionResult.CONTINUE; @@ -1138,8 +1053,7 @@ class WindowList { this._dndWindow = hoveredWindow; this._dndTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, - DND_ACTIVATE_TIMEOUT, - this._activateWindow.bind(this)); + DND_ACTIVATE_TIMEOUT, this._activateWindow.bind(this)); return DND.DragMotionResult.CONTINUE; } @@ -1155,7 +1069,7 @@ class WindowList { let [x, y] = global.get_pointer(); let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); - if (this._dndWindow && this.actor.contains(pickedActor)) + if (this._dndWindow && this.contains(pickedActor)) this._dndWindow.activate(global.get_current_time()); this._dndWindow = null; this._dndTimeoutId = 0; @@ -1169,7 +1083,7 @@ class WindowList { this._workspaceIndicator.destroy(); - Main.ctrlAltTabManager.removeGroup(this.actor); + Main.ctrlAltTabManager.removeGroup(this); this._appSystem.disconnect(this._appStateChangedId); this._appStateChangedId = 0; @@ -1201,31 +1115,36 @@ class WindowList { for (let i = 0; i < windows.length; i++) windows[i].metaWindow.set_icon_geometry(null); } -} +}); class Extension { constructor() { this._windowLists = null; - this._injections = {}; + this._hideOverviewOrig = Main.overview.hide; } enable() { this._windowLists = []; this._settings = ExtensionUtils.getSettings(); - this._showOnAllMonitorsChangedId = - this._settings.connect('changed::show-on-all-monitors', - this._buildWindowLists.bind(this)); + this._showOnAllMonitorsChangedId = this._settings.connect( + 'changed::show-on-all-monitors', this._buildWindowLists.bind(this)); - this._monitorsChangedId = - Main.layoutManager.connect('monitors-changed', - this._buildWindowLists.bind(this)); + this._monitorsChangedId = Main.layoutManager.connect( + 'monitors-changed', this._buildWindowLists.bind(this)); + + Main.windowPicker = new WindowPicker(); + + Main.overview.hide = () => { + Main.windowPicker.close(); + this._hideOverviewOrig.call(Main.overview); + }; this._buildWindowLists(); } _buildWindowLists() { - this._windowLists.forEach(list => list.actor.destroy()); + this._windowLists.forEach(list => list.destroy()); this._windowLists = []; let showOnAllMonitors = this._settings.get_boolean('show-on-all-monitors'); @@ -1247,14 +1166,19 @@ class Extension { this._monitorsChangedId = 0; this._windowLists.forEach(windowList => { - windowList.actor.hide(); - windowList.actor.destroy(); + windowList.hide(); + windowList.destroy(); }); this._windowLists = null; + + Main.windowPicker.destroy(); + delete Main.windowPicker; + + Main.overview.hide = this._hideOverviewOrig; } someWindowListContains(actor) { - return this._windowLists.some(list => list.actor.contains(actor)); + return this._windowLists.some(list => list.contains(actor)); } } diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build index b4aa4dba..34d7c3fd 100644 --- a/extensions/window-list/meson.build +++ b/extensions/window-list/meson.build @@ -4,7 +4,7 @@ extension_data += configure_file( configuration: metadata_conf ) -extension_sources += files('prefs.js') +extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js') extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') if classic_mode_enabled diff --git a/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml b/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml index b7459417..299864cf 100644 --- a/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml +++ b/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml @@ -15,6 +15,13 @@ window list. Possible values are “never”, “auto” and “always”. + + false + Show windows from all workspaces + + Whether to show windows from all workspaces or only the current one. + + false Show the window list on all monitors diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js index 78792b5a..ea3cb753 100644 --- a/extensions/window-list/prefs.js +++ b/extensions/window-list/prefs.js @@ -77,6 +77,13 @@ class WindowListPrefsWidget extends Gtk.Grid { }); 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); } }); diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css index f5285cb3..79d56bad 100644 --- a/extensions/window-list/stylesheet.css +++ b/extensions/window-list/stylesheet.css @@ -26,9 +26,8 @@ spacing: 4px; } -.window-button > StWidget { - -st-natural-width: 18.75em; - max-width: 18.75em; +.window-button > StWidget, +.window-picker-toggle > StWidget { color: #bbb; background-color: black; border-radius: 4px; @@ -37,7 +36,21 @@ text-shadow: 1px 1px 4px rgba(0,0,0,0.8); } -.window-button:hover > StWidget { +.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 { color: white; background-color: #1f1f1f; } @@ -47,12 +60,14 @@ box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5); } -.window-button.focused > StWidget { +.window-button.focused > StWidget, +.window-picker-toggle:checked > StWidget { color: white; box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7); } -.window-button.focused:active > StWidget { +.window-button.focused:active > StWidget, +.window-picker-toggle:checked:active > StWidget { box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7); } @@ -70,13 +85,50 @@ height: 24px; } -.window-list-workspace-indicator { +.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; padding: 3px; } -.window-list-workspace-indicator > StWidget { - background-color: rgba(200, 200, 200, .3); +.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 { + 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; } .notification { diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js new file mode 100644 index 00000000..bfac17fe --- /dev/null +++ b/extensions/window-list/windowPicker.js @@ -0,0 +1,277 @@ +/* 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 = class extends WorkspacesDisplay { + constructor() { + super(); + + this.actor.add_constraint( + new Layout.MonitorConstraint({ + primary: true, + work_area: true + })); + + this.actor.connect('destroy', this._onDestroy.bind(this)); + + this._workareasChangedId = global.display.connect('workareas-changed', + this._onWorkAreasChanged.bind(this)); + this._onWorkAreasChanged(); + } + + show(...args) { + if (this._scrollEventId == 0) + 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); + } + + _updateWorkspacesViews() { + super._updateWorkspacesViews(); + + this._workspacesViews.forEach(v => { + Main.layoutManager.overviewGroup.remove_actor(v.actor); + Main.windowPicker.add_actor(v.actor); + }); + } + + _onDestroy() { + if (this._workareasChangedId) + global.display.disconnect(this._workareasChangedId); + this._workareasChangedId = 0; + } +}; + +var WindowPicker = GObject.registerClass({ + GTypeName: 'WindowListWindowPicker', + 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.actor); + + 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; + }); + } +}); diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js new file mode 100644 index 00000000..84dccacc --- /dev/null +++ b/extensions/window-list/workspaceIndicator.js @@ -0,0 +1,402 @@ +/* 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({ + GTypeName: 'WindowListWindowPreview' +}, 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.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({ + GTypeName: 'WindowListWorkspaceThumbnail' +}, 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({ + GTypeName: 'WindowListWorkspaceIndicator' +}, 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', (item, _event) => { + 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); + } +}); + diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js index 7d58ebe2..05d29652 100644 --- a/extensions/windowsNavigator/extension.js +++ b/extensions/windowsNavigator/extension.js @@ -1,50 +1,65 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* exported enable disable */ +/* exported init */ const { Clutter, St } = imports.gi; const Main = imports.ui.main; const Workspace = imports.ui.workspace; const WorkspacesView = imports.ui.workspacesView; -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; -} +var MyWindowOverlay = class extends Workspace.WindowOverlay { + constructor(windowClone, parentActor) { + super(windowClone, parentActor); -let winInjections, workspaceInjections, workViewInjections, createdActors, connectedSignals; + this._id = null; + this._text = new St.Label({ + style_class: 'extension-windowsNavigator-window-tooltip', + visible: false + }); + parentActor.add_actor(this._text); + } -function resetState() { - winInjections = {}; - workspaceInjections = {}; - workViewInjections = {}; - createdActors = []; - connectedSignals = []; -} - -function enable() { - resetState(); - - Workspace.WindowOverlay.prototype.showTooltip = function() { + showTooltip() { this._text.raise_top(); this._text.show(); this._text.text = (this._windowClone.slotId + 1).toString(); - }; - winInjections['showTooltip'] = undefined; + } - Workspace.WindowOverlay.prototype.hideTooltip = function() { + hideTooltip() { if (this._text && this._text.visible) this._text.hide(); - }; - winInjections['hideTooltip'] = undefined; + } - Workspace.Workspace.prototype.showTooltip = function() { + 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._text.raise_top(); + } +}; + +var MyWorkspace = class extends Workspace.Workspace { + constructor(metaWorkspace, monitorIndex) { + super(metaWorkspace, monitorIndex); + + if (metaWorkspace && metaWorkspace.index() < 9) { + this._tip = new St.Label({ + style_class: 'extension-windowsNavigator-window-tooltip', + visible: false + }); + this.actor.add_actor(this._tip); + + this.actor.connect('notify::scale-x', () => { + this._tip.set_scale(1 / this.actor.scale_x, 1 / this.actor.scale_x); + }); + } else + this._tip = null; + } + + showTooltip() { if (this._tip == null || this._actualGeometry == null) return; this._tip.text = (this.metaWorkspace.index() + 1).toString(); @@ -64,61 +79,74 @@ function enable() { this._tip.y = area.y; this._tip.show(); this._tip.raise_top(); - }; - workspaceInjections['showTooltip'] = undefined; + } - Workspace.Workspace.prototype.hideTooltip = function() { + hideTooltip() { if (this._tip == null) return; if (!this._tip.get_parent()) return; this._tip.hide(); - }; - workspaceInjections['hideTooltip'] = undefined; + } - Workspace.Workspace.prototype.getWindowWithTooltip = function(id) { + getWindowWithTooltip(id) { for (let i = 0; i < this._windows.length; i++) { if ((this._windows[i].slotId + 1) == id) return this._windows[i].metaWindow; } return null; - }; - workspaceInjections['getWindowWithTooltip'] = undefined; + } - Workspace.Workspace.prototype.showWindowsTooltips = function() { + showWindowsTooltips() { for (let i in this._windowOverlays) { if (this._windowOverlays[i] != null) this._windowOverlays[i].showTooltip(); } - }; - workspaceInjections['showWindowsTooltips'] = undefined; + } - Workspace.Workspace.prototype.hideWindowsTooltips = function() { + hideWindowsTooltips() { for (let i in this._windowOverlays) { if (this._windowOverlays[i] != null) this._windowOverlays[i].hideTooltip(); } - }; - workspaceInjections['hideWindowsTooltips'] = undefined; + } +}; - WorkspacesView.WorkspacesView.prototype._hideTooltips = function() { +var MyWorkspacesView = class extends WorkspacesView.WorkspacesView { + constructor(width, height, x, y, workspaces) { + super(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) 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; + } - WorkspacesView.WorkspacesView.prototype._hideWorkspacesTooltips = function() { + _hideWorkspacesTooltips() { 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; + } - WorkspacesView.WorkspacesView.prototype._onKeyRelease = function(s, o) { + _onKeyRelease(s, o) { if (this._pickWindow && (o.get_key_symbol() == Clutter.KEY_Alt_L || o.get_key_symbol() == Clutter.KEY_Alt_R)) @@ -127,11 +155,11 @@ function enable() { (o.get_key_symbol() == Clutter.KEY_Control_L || o.get_key_symbol() == Clutter.KEY_Control_R)) this._hideWorkspacesTooltips(); - }; - workViewInjections['_onKeyRelease'] = undefined; + } - WorkspacesView.WorkspacesView.prototype._onKeyPress = function(s, o) { - if (Main.overview.viewSelector._activePage != Main.overview.viewSelector._workspacesPage) + _onKeyPress(s, o) { + let viewSelector = Main.overview.viewSelector; + if (viewSelector._activePage != viewSelector._workspacesPage) return false; let workspaceManager = global.workspace_manager; @@ -208,81 +236,29 @@ function enable() { return true; } return false; - }; - workViewInjections['_onKeyPress'] = undefined; + } +}; - 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); - }); +class Extension { + constructor() { + this._origWindowOverlay = Workspace.WindowOverlay; + this._origWorkspace = Workspace.Workspace; + this._origWorkspacesView = WorkspacesView.WorkspacesView; + } - winInjections['relayout'] = injectToFunction(Workspace.WindowOverlay.prototype, 'relayout', function(_animate) { - let [cloneX, cloneY, cloneWidth_, cloneHeight_] = this._windowClone.slot; + enable() { + Workspace.WindowOverlay = MyWindowOverlay; + Workspace.Workspace = MyWorkspace; + WorkspacesView.WorkspacesView = MyWorkspacesView; + } - 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 = []; - }); + disable() { + Workspace.WindowOverlay = this._origWindowOverlay; + Workspace.Workspace = this._origWorkspace; + WorkspacesView.WorkspacesView = this._origWorkspacesView; + } } -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(); } diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js index 3be12686..4a9e5c19 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -2,56 +2,268 @@ /* 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 PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; const Gettext = imports.gettext.domain('gnome-shell-extensions'); const _ = Gettext.gettext; -const Main = imports.ui.main; - -const ExtensionUtils = imports.misc.extensionUtils; - const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; const WORKSPACE_KEY = 'workspace-names'; +let WindowPreview = GObject.registerClass({ + GTypeName: 'WorkspaceIndicatorWindowPreview' +}, 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.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({ + GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail' +}, 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')); + 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({ + 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() }); - this.add_actor(this.statusLabel); + container.add_actor(this._statusLabel); - this.workspacesItems = []; + this._thumbnailsBox = new St.BoxLayout({ + style_class: 'panel-workspace-indicator-box', + y_expand: true, + reactive: true + }); + + container.add_actor(this._thumbnailsBox); + + this._workspacesItems = []; this._workspaceSection = new PopupMenu.PopupMenuSection(); this.menu.addMenuItem(this._workspaceSection); - this._workspaceManagerSignals = []; - this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-added', - this._createWorkspacesSection.bind(this))); - this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-removed', - this._createWorkspacesSection.bind(this))); - this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched', - this._updateIndicator.bind(this))); + 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.connect('scroll-event', this._onScrollEvent.bind(this)); + this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this)); this._createWorkspacesSection(); - - //styling - this.statusLabel.add_style_class_name('panel-workspace-indicator'); + this._updateThumbnails(); + this._onWorkspaceOrientationChanged(); this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA }); - this._settingsChangedId = - this._settings.connect(`changed::${WORKSPACE_KEY}`, - this._createWorkspacesSection.bind(this)); + this._settingsChangedId = this._settings.connect( + `changed::${WORKSPACE_KEY}`, + this._updateMenuLabels.bind(this)); } _onDestroy() { @@ -63,15 +275,55 @@ class WorkspaceIndicator extends PanelMenu.Button { this._settingsChangedId = 0; } + Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); + super._onDestroy(); } - _updateIndicator() { - this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); - this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); - this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); + _onWorkspaceOrientationChanged() { + let vertical = global.workspace_manager.layout_rows == -1; + this.reactive = vertical; - this.statusLabel.set_text(this._labelText()); + 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'); + } } _labelText(workspaceIndex) { @@ -82,34 +334,51 @@ class WorkspaceIndicator extends PanelMenu.Button { 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 = workspaceManager.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) => { + 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) => { this._activate(actor.workspaceId); }); if (i == this._currentWorkspace) - this.workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT); + this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT); } - this.statusLabel.set_text(this._labelText()); + 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(); } _activate(index) { let workspaceManager = global.workspace_manager; - if (index >= 0 && index < workspaceManager.n_workspaces) { + if (index >= 0 && index < workspaceManager.n_workspaces) { let metaWorkspace = workspaceManager.get_workspace_by_index(index); metaWorkspace.activate(global.get_current_time()); } @@ -126,7 +395,7 @@ class WorkspaceIndicator extends PanelMenu.Button { return; } - let newIndex = global.workspace_manager.get_active_workspace().index() + diff; + let newIndex = global.workspace_manager.get_active_workspace_index() + diff; this._activate(newIndex); } }); diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css index 1271f1ce..8601c3e5 100644 --- a/extensions/workspace-indicator/stylesheet.css +++ b/extensions/workspace-indicator/stylesheet.css @@ -1,5 +1,40 @@ .panel-workspace-indicator { padding: 0 8px; - background-color: rgba(200, 200, 200, .5); +} + +.panel-workspace-indicator-box { + padding: 2px 0; +} + +.panel-workspace-indicator-box .workspace { + width: 40px; +} + +.panel-workspace-indicator, +.panel-workspace-indicator-box .workspace { 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; +} diff --git a/lint/eslintrc-legacy.json b/lint/eslintrc-legacy.json deleted file mode 100644 index aca79adf..00000000 --- a/lint/eslintrc-legacy.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "rules": { - "indent": [ - "error", - 4, - { - "ignoredNodes": [ - "CallExpression > ArrowFunctionExpression", - "CallExpression[callee.object.name=GObject][callee.property.name=registerClass] > ClassExpression:first-child" - ], - "CallExpression": { "arguments": "first" }, - "MemberExpression": "off" - } - ] - } -} diff --git a/lint/eslintrc-shell.json b/lint/eslintrc-shell.json index fc6f5819..c7be5981 100644 --- a/lint/eslintrc-shell.json +++ b/lint/eslintrc-shell.json @@ -4,7 +4,7 @@ "error", { "properties": "never", - "allow": ["^vfunc_"] + "allow": ["^vfunc_", "^on_"] } ], "no-unused-vars": [ @@ -21,10 +21,6 @@ "prefer-arrow-callback": "error" }, "globals": { - "global": false, - "_": false, - "C_": false, - "N_": false, - "ngettext": false + "global": false } } diff --git a/lint/generate-report.sh b/lint/generate-report.sh deleted file mode 100644 index 1d34401e..00000000 --- a/lint/generate-report.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh -SEP=`printf '\t'` -OUTPUT=/dev/stderr -CWD=`pwd` -SRCDIR=`dirname $0` - -run_lint() { - eslint -f unix "$@" . -} - -parse_opts() { - tmp=`getopt -l output: o: "$@"` - [ $? -ne 0 ] && exit 1 - - eval set -- $tmp - while true - do - case $1 in - --output|-o) - OUTPUT=`realpath $2`; shift 2; continue ;; - --) - shift; break ;; - esac - done -} - -# delete lines that don't start with '/', -# replace the first space with tab, sort -process_for_join() { - sed -E "/\//!d; s|(\S+)\s|\1$SEP|" | sort -k 1b,1 -} - -# re-replace tab with space -process_post_join() { - sed -E "s|$SEP| |" -} - -create_report() { - tmp1=`mktemp --tmpdir lint-XXXX` - run_lint | process_for_join > $tmp1 - - tmp2=`mktemp --tmpdir lint-XXXX` - run_lint -c lint/eslintrc-legacy.json | process_for_join > $tmp2 - - join -t"$SEP" -o '0,1.2' $tmp1 $tmp2 | process_post_join - rm $tmp1 $tmp2 -} - - -parse_opts "$@" - -cd $SRCDIR/.. - -create_report | tee $OUTPUT | grep -q . -rv=$(( $? == 0 )) - -cd $CWD - -[ $rv -eq 0 -a -f $OUTPUT ] && rm $OUTPUT - -exit $rv diff --git a/meson.build b/meson.build index 7d96d1c8..c32f57cf 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('gnome-shell-extensions', - version: '3.32.0', + version: '3.33.90', meson_version: '>= 0.44.0', license: 'GPL2+' ) @@ -33,6 +33,7 @@ uuid_suffix = '@gnome-shell-extensions.gcampax.github.com' classic_extensions = [ 'apps-menu', + 'horizontal-workspaces', 'places-menu', 'launch-new-instance', 'window-list' diff --git a/po/LINGUAS b/po/LINGUAS index 514d53e4..a6ab394e 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -38,6 +38,7 @@ kn ko lt lv +mjw ml mr ms diff --git a/po/POTFILES.in b/po/POTFILES.in index 9c1438ac..8b74e88b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -15,6 +15,7 @@ extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml extensions/window-list/extension.js extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml extensions/window-list/prefs.js +extensions/window-list/workspaceIndicator.js extensions/windowsNavigator/extension.js extensions/workspace-indicator/extension.js extensions/workspace-indicator/prefs.js diff --git a/po/mjw.po b/po/mjw.po new file mode 100644 index 00000000..6777da99 --- /dev/null +++ b/po/mjw.po @@ -0,0 +1,249 @@ +# Karbi (India) translation for gnome-shell-extensions. +# Copyright (C) 2019 gnome-shell-extensions's Free Software Foundation, Inc. +# This file is distributed under the same license as the gnome-shell-extensions package. +# Jor Teron , 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: gnome-shell-extensions master\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/" +"issues\n" +"POT-Creation-Date: 2019-07-02 19:23+0000\n" +"PO-Revision-Date: 2019-07-25 00:00+0530\n" +"Last-Translator: Jor Teron \n" +"Language-Team: Karbi \n" +"Language: mjw\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: gedit 3.28.1\n" + +#: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 +msgid "GNOME Classic" +msgstr "GNOME Classic" + +#: data/gnome-classic.desktop.in:4 +msgid "This session logs you into GNOME Classic" +msgstr "" + +#: extensions/apps-menu/extension.js:111 +msgid "Favorites" +msgstr "" + +#: extensions/apps-menu/extension.js:366 +msgid "Applications" +msgstr "" + +#: extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml:6 +msgid "Application and workspace list" +msgstr "" + +#: extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml:7 +msgid "" +"A list of strings, each containing an application id (desktop file name), " +"followed by a colon and the workspace number" +msgstr "" + +#: extensions/auto-move-windows/prefs.js:60 +msgid "Application" +msgstr "" + +#: extensions/auto-move-windows/prefs.js:71 +#: extensions/auto-move-windows/prefs.js:134 +msgid "Workspace" +msgstr "" + +#: extensions/auto-move-windows/prefs.js:89 +msgid "Add Rule" +msgstr "" + +#: extensions/auto-move-windows/prefs.js:111 +msgid "Create new matching rule" +msgstr "" + +#: extensions/auto-move-windows/prefs.js:117 +msgid "Add" +msgstr "Kethap" + +#. TRANSLATORS: %s is the filesystem name +#: extensions/drive-menu/extension.js:102 +#: extensions/places-menu/placeDisplay.js:232 +#, javascript-format +msgid "Ejecting drive “%s” failed:" +msgstr "Drive “%s” patet un-eh:" + +#: extensions/drive-menu/extension.js:118 +msgid "Removable devices" +msgstr "" + +#: extensions/drive-menu/extension.js:145 +msgid "Open Files" +msgstr "Files kangpu" + +#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:5 +msgid "Use more screen for windows" +msgstr "" + +#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:6 +msgid "" +"Try to use more screen for placing window thumbnails by adapting to screen " +"aspect ratio, and consolidating them further to reduce the bounding box. " +"This setting applies only with the natural placement strategy." +msgstr "" + +#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:11 +msgid "Place window captions on top" +msgstr "" + +#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:12 +msgid "" +"If true, place window captions on top the respective thumbnail, overriding " +"shell default of placing it at the bottom. Changing this setting requires " +"restarting the shell to have any effect." +msgstr "" + +#: extensions/places-menu/extension.js:80 +#: extensions/places-menu/extension.js:84 +msgid "Places" +msgstr "" + +#: extensions/places-menu/placeDisplay.js:46 +#, javascript-format +msgid "Failed to launch “%s”" +msgstr "“%s” Ingpu un-eh" + +#: extensions/places-menu/placeDisplay.js:61 +#, javascript-format +msgid "Failed to mount volume for “%s”" +msgstr "" + +#: extensions/places-menu/placeDisplay.js:148 +#: extensions/places-menu/placeDisplay.js:171 +msgid "Computer" +msgstr "Computer" + +#: extensions/places-menu/placeDisplay.js:358 +msgid "Home" +msgstr "Home" + +#: extensions/places-menu/placeDisplay.js:403 +msgid "Browse Network" +msgstr "Network kelang" + +#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:7 +msgid "Cycle Screenshot Sizes" +msgstr "" + +#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:11 +msgid "Cycle Screenshot Sizes Backward" +msgstr "" + +#: extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml:5 +msgid "Theme name" +msgstr "Theme amen" + +#: extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml:6 +msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell" +msgstr "Theme amem, kewan ji pen ~/.themes/name/gnome-shell" + +#: extensions/window-list/extension.js:99 +msgid "Close" +msgstr "Kanghap" + +#: extensions/window-list/extension.js:119 +msgid "Unminimize" +msgstr "Pabi-thuthe" + +#: extensions/window-list/extension.js:119 +msgid "Minimize" +msgstr "Pabi" + +#: extensions/window-list/extension.js:126 +msgid "Unmaximize" +msgstr "Pathe-thuthe" + +#: extensions/window-list/extension.js:126 +msgid "Maximize" +msgstr "Pathe" + +#: extensions/window-list/extension.js:399 +msgid "Minimize all" +msgstr "Kado-kawe pabi" + +#: extensions/window-list/extension.js:405 +msgid "Unminimize all" +msgstr "Kado-kawe pabi-thuthe" + +#: extensions/window-list/extension.js:411 +msgid "Maximize all" +msgstr "Kathe-kawe pathe" + +#: extensions/window-list/extension.js:419 +msgid "Unmaximize all" +msgstr "Kado-kawe pathe-thuthe" + +#: extensions/window-list/extension.js:427 +msgid "Close all" +msgstr "Kado-kawe kanghap" + +#: extensions/window-list/extension.js:642 +#: extensions/workspace-indicator/extension.js:20 +msgid "Workspace Indicator" +msgstr "" + +#: extensions/window-list/extension.js:829 +msgid "Window List" +msgstr "" + +#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:12 +msgid "When to group windows" +msgstr "Mentu hutsi windows muluk nangji" + +#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:13 +msgid "" +"Decides when to group windows from the same application on the window list. " +"Possible values are “never”, “auto” and “always”." +msgstr "" + +#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:20 +msgid "Show the window list on all monitors" +msgstr "" + +#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:21 +msgid "" +"Whether to show the window list on all connected monitors or only on the " +"primary one." +msgstr "" + +#: extensions/window-list/prefs.js:25 +msgid "Window Grouping" +msgstr "Windows muluk" + +#: extensions/window-list/prefs.js:47 +msgid "Never group windows" +msgstr "Windows muluk ri" + +#: extensions/window-list/prefs.js:48 +msgid "Group windows when space is limited" +msgstr "Adim bihek te windows muluk noi" + +#: extensions/window-list/prefs.js:49 +msgid "Always group windows" +msgstr "Windows muluk vek nangji" + +#: extensions/window-list/prefs.js:75 +msgid "Show on all monitors" +msgstr "" + +#: extensions/workspace-indicator/prefs.js:131 +msgid "Workspace Names" +msgstr "Workspace amen hai" + +#: extensions/workspace-indicator/prefs.js:151 +msgid "Name" +msgstr "Men" + +#: extensions/workspace-indicator/prefs.js:191 +#, javascript-format +msgid "Workspace %d" +msgstr "Workspace amen %d"