diff --git a/data/theme/gnome-shell-sass/widgets/_screenshot.scss b/data/theme/gnome-shell-sass/widgets/_screenshot.scss index 1d9cd12aa..5855fbedd 100644 --- a/data/theme/gnome-shell-sass/widgets/_screenshot.scss +++ b/data/theme/gnome-shell-sass/widgets/_screenshot.scss @@ -8,6 +8,8 @@ } } +$screenshot_ui_button_red: #e01b24; + .screenshot-ui-panel { background-color: $osd_bg_color; border-radius: 12px + 21px; @@ -68,6 +70,48 @@ background-color: darken(white, 50%); } } + + &:cast { + .screenshot-ui-capture-button-circle { + background-color: $screenshot_ui_button_red; + } + + &:hover, &:focus { + .screenshot-ui-capture-button-circle { + background-color: darken($screenshot_ui_button_red, 15%); + } + } + + &:active { + .screenshot-ui-capture-button-circle { + background-color: darken($screenshot_ui_button_red, 30%); + } + } + } +} + +.screenshot-ui-shot-cast-container { + background-color: $hover_bg_color; + border-radius: 12px; + padding: $base_padding / 2; + spacing: $base_padding / 2; + + &:ltr { margin-left: 3px; } + &:rtl { margin-right: 3px; } +} + +.screenshot-ui-shot-cast-button { + padding: $base_padding $base_padding * 1.5; + background-color: transparent; + &:hover, &:focus { background-color: lighten($hover_bg_color, 5%); } + &:active { background-color: $active_bg_color; } + &:checked { background-color: white; color: black; } + + border-radius: 12px - 3px; + + StIcon { + icon-size: $base_icon_size; + } } .screenshot-ui-show-pointer-button { diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js index 97f782e52..8c41f4efe 100644 --- a/js/ui/screenshot.js +++ b/js/ui/screenshot.js @@ -1153,6 +1153,46 @@ class ScreenshotUI extends St.Widget { this._bottomRowContainer = new St.Widget({ layout_manager: new Clutter.BinLayout() }); this._panel.add_child(this._bottomRowContainer); + this._shotCastContainer = new St.BoxLayout({ + style_class: 'screenshot-ui-shot-cast-container', + x_align: Clutter.ActorAlign.START, + x_expand: true, + }); + this._bottomRowContainer.add_child(this._shotCastContainer); + + this._shotButton = new St.Button({ + style_class: 'screenshot-ui-shot-cast-button', + checked: true, + }); + this._shotButton.set_child(new St.Icon({ icon_name: 'camera-photo-symbolic' })); + this._shotButton.connect('notify::checked', + this._onShotButtonToggled.bind(this)); + this._shotCastContainer.add_child(this._shotButton); + + this._castButton = new St.Button({ + style_class: 'screenshot-ui-shot-cast-button', + toggle_mode: true, + }); + this._castButton.set_child(new St.Icon({ icon_name: 'camera-web-symbolic' })); + this._castButton.connect('notify::checked', + this._onCastButtonToggled.bind(this)); + this._shotCastContainer.add_child(this._castButton); + + this._shotCastTooltip = new Tooltip(this._shotCastContainer, { + text: _('Screenshot / Screencast'), + style_class: 'screenshot-ui-tooltip', + visible: false, + }); + const shotCastCallback = () => { + if (this._shotButton.hover || this._castButton.hover) + this._shotCastTooltip.open(); + else + this._shotCastTooltip.close(); + }; + this._shotButton.connect('notify::hover', shotCastCallback); + this._castButton.connect('notify::hover', shotCastCallback); + this.add_child(this._shotCastTooltip); + this._captureButton = new St.Button({ style_class: 'screenshot-ui-capture-button' }); this._captureButton.set_child(new St.Widget({ style_class: 'screenshot-ui-capture-button-circle', @@ -1307,7 +1347,8 @@ class ScreenshotUI extends St.Widget { }); } - this._windowButton.reactive = windows.length > 0; + this._windowButton.reactive = + windows.length > 0 && !this._castButton.checked; if (!this._windowButton.reactive) this._selectionButton.checked = true; @@ -1377,6 +1418,9 @@ class ScreenshotUI extends St.Widget { this._shooter = null; + // Switch back to screenshot mode. + this._shotButton.checked = true; + this._stageScreenshotContainer.get_parent().remove_child( this._stageScreenshotContainer); Main.layoutManager.screenshotUIGroup.insert_child_at_index( @@ -1499,6 +1543,54 @@ class ScreenshotUI extends St.Widget { } } + _onShotButtonToggled() { + if (this._shotButton.checked) { + this._shotButton.toggle_mode = false; + this._castButton.checked = false; + + this._stageScreenshotContainer.show(); + this._stageScreenshotContainer.remove_all_transitions(); + this._stageScreenshotContainer.ease({ + opacity: 255, + duration: 200, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + }); + } else { + this._shotButton.toggle_mode = true; + } + } + + _onCastButtonToggled() { + if (this._castButton.checked) { + this._castButton.toggle_mode = false; + this._shotButton.checked = false; + + this._captureButton.add_style_pseudo_class('cast'); + + this._stageScreenshotContainer.remove_all_transitions(); + this._stageScreenshotContainer.ease({ + opacity: 0, + duration: 200, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => this._stageScreenshotContainer.hide(), + }); + + // Screen recording doesn't support window selection yet. + if (this._windowButton.checked) + this._selectionButton.checked = true; + + this._windowButton.reactive = false; + } else { + this._castButton.toggle_mode = true; + + this._captureButton.remove_style_pseudo_class('cast'); + + const windows = + this._windowSelectors.flatMap(selector => selector.windows()); + this._windowButton.reactive = windows.length > 0; + } + } + _getSelectedGeometry() { let x, y, w, h; @@ -1524,7 +1616,8 @@ class ScreenshotUI extends St.Widget { } _onCaptureButtonClicked() { - this._saveScreenshot(); + if (this._shotButton.checked) + this._saveScreenshot(); // TODO: screencasting.