diff --git a/data/theme/gnome-shell-sass/widgets/_misc.scss b/data/theme/gnome-shell-sass/widgets/_misc.scss index aa543a0e5..8b40e7006 100644 --- a/data/theme/gnome-shell-sass/widgets/_misc.scss +++ b/data/theme/gnome-shell-sass/widgets/_misc.scss @@ -53,3 +53,8 @@ @include fontsize($base_font_size - 1); color: $warning_color; } + +.screen-corner { + -screen-corner-radius: $panel_corner_radius; + -screen-corner-background-color: black; +} diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml index c0a77eddc..91babbb44 100644 --- a/js/js-resources.gresource.xml +++ b/js/js-resources.gresource.xml @@ -89,6 +89,7 @@ ui/remoteSearch.js ui/ripples.js ui/runDialog.js + ui/screenCorner.js ui/screenShield.js ui/screencast.js ui/screenshot.js diff --git a/js/ui/layout.js b/js/ui/layout.js index 9013aa97b..bd97d0cc8 100644 --- a/js/ui/layout.js +++ b/js/ui/layout.js @@ -12,6 +12,7 @@ const DND = imports.ui.dnd; const Main = imports.ui.main; const Params = imports.misc.params; const Ripples = imports.ui.ripples; +const ScreenCorner = imports.ui.screenCorner; var STARTUP_ANIMATION_TIME = 500; var KEYBOARD_ANIMATION_TIME = 150; @@ -200,6 +201,7 @@ var LayoutManager = GObject.registerClass({ this.primaryMonitor = null; this.primaryIndex = -1; this.hotCorners = []; + this._screenCorners = []; this._keyboardIndex = -1; this._rightPanelBarrier = null; @@ -440,6 +442,25 @@ var LayoutManager = GObject.registerClass({ this.emit('hot-corners-changed'); } + _updateScreenCorners() { + // destroy old corners + this._screenCorners.forEach(corner => { + if (corner) + corner.destroy(); + }); + this._screenCorners = []; + + // build new corners + for (let monitor of this.monitors) { + for (let corner of Object.values(Meta.DisplayCorner)) { + var actor = new ScreenCorner.ScreenCorner(corner, monitor); + + this.addTopChrome(actor, { trackFullscreen: true }); + this._screenCorners.push(actor); + } + } + } + _addBackgroundMenu(bgManager) { BackgroundMenu.addBackgroundMenu(bgManager.backgroundActor, this); } @@ -540,6 +561,7 @@ var LayoutManager = GObject.registerClass({ this._updateMonitors(); this._updateBoxes(); this._updateHotCorners(); + this._updateScreenCorners(); this._updateBackgrounds(); this._updateFullscreen(); this._updateVisibility(); diff --git a/js/ui/screenCorner.js b/js/ui/screenCorner.js new file mode 100644 index 000000000..e7d296813 --- /dev/null +++ b/js/ui/screenCorner.js @@ -0,0 +1,79 @@ +// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +/* exported ScreenCorner */ + +const { Clutter, GObject, Meta, St } = imports.gi; +const Cairo = imports.cairo; + +const Layout = imports.ui.layout; + +var ScreenCorner = GObject.registerClass( +class ScreenCorner extends St.DrawingArea { + _init(corner, monitor) { + super._init({ style_class: 'screen-corner' }); + + this._corner = corner; + + this.add_constraint(new Layout.MonitorConstraint({ index: monitor.index })); + + if (corner === Meta.DisplayCorner.TOPRIGHT || + corner === Meta.DisplayCorner.BOTTOMRIGHT) + this.x_align = Clutter.ActorAlign.END; + + if (corner === Meta.DisplayCorner.BOTTOMLEFT || + corner === Meta.DisplayCorner.BOTTOMRIGHT) + this.y_align = Clutter.ActorAlign.END; + } + + vfunc_repaint() { + let node = this.get_theme_node(); + + let cornerRadius = node.get_length("-screen-corner-radius"); + let backgroundColor = node.get_color('-screen-corner-background-color'); + + let cr = this.get_context(); + cr.setOperator(Cairo.Operator.SOURCE); + + switch (this._corner) { + case Meta.DisplayCorner.TOPLEFT: + cr.arc(cornerRadius, cornerRadius, + cornerRadius, Math.PI, 3 * Math.PI / 2); + cr.lineTo(0, 0); + break; + + case Meta.DisplayCorner.TOPRIGHT: + cr.arc(0, cornerRadius, + cornerRadius, 3 * Math.PI / 2, 2 * Math.PI); + cr.lineTo(cornerRadius, 0); + break; + + case Meta.DisplayCorner.BOTTOMLEFT: + cr.arc(cornerRadius, 0, + cornerRadius, Math.PI / 2, Math.PI); + cr.lineTo(0, cornerRadius); + break; + + case Meta.DisplayCorner.BOTTOMRIGHT: + cr.arc(0, 0, + cornerRadius, 0, Math.PI / 2); + cr.lineTo(cornerRadius, cornerRadius); + break; + } + + cr.closePath(); + + Clutter.cairo_set_source_color(cr, backgroundColor); + cr.fill(); + + cr.$dispose(); + } + + vfunc_style_changed() { + super.vfunc_style_changed(); + + let node = this.get_theme_node(); + + let cornerRadius = node.get_length("-screen-corner-radius"); + + this.set_size(cornerRadius, cornerRadius); + } +});