Compare commits

..

3 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
d6345a5c8b altTab: Switch to MetaWindowContent 2019-10-17 08:42:37 +02:00
Georges Basile Stavracas Neto
628b34e96f overview: Switch to MetaWindowContent 2019-10-16 18:17:47 +02:00
Georges Basile Stavracas Neto
5743b52ec8 workspace: Replace ClutterClone by MetaWindowContent 2019-10-16 18:16:12 +02:00
22 changed files with 896 additions and 1034 deletions

View File

@@ -16,14 +16,8 @@ run_eslint() {
ARGS_LEGACY='--config lint/eslintrc-legacy.json' ARGS_LEGACY='--config lint/eslintrc-legacy.json'
local extra_args=ARGS_$1 local extra_args=ARGS_$1
local output_var=OUTPUT_$1 local output=OUTPUT_$1
local output=${!output_var} eslint -f unix ${!extra_args} -o ${!output} js
# ensure output exists even if eslint doesn't report any errors
mkdir -p $(dirname $output)
touch $output
eslint -f unix ${!extra_args} -o $output js
} }
list_commit_range_additions() { list_commit_range_additions() {
@@ -76,13 +70,10 @@ create_common() {
# non-legacy style just yet ... # non-legacy style just yet ...
unset CI_MERGE_REQUEST_TARGET_BRANCH_NAME unset CI_MERGE_REQUEST_TARGET_BRANCH_NAME
REMOTE=${1:-$CI_MERGE_REQUEST_PROJECT_URL.git} if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
BRANCH_NAME=${2:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME} git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
if [ "$BRANCH_NAME" ]; then
git fetch $REMOTE $BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD) branch_point=$(git merge-base HEAD FETCH_HEAD)
commit_range=$branch_point...HEAD commit_range=$branch_point...$CI_COMMIT_SHA
list_commit_range_additions $commit_range > $LINE_CHANGES list_commit_range_additions $commit_range > $LINE_CHANGES
@@ -105,7 +96,7 @@ if ! is_empty $OUTPUT_FINAL; then
fi fi
# Just show the report and succeed when not testing a MR # Just show the report and succeed when not testing a MR
if [ -z "$BRANCH_NAME" ]; then if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
exit 0 exit 0
fi fi

View File

@@ -50,7 +50,7 @@
</description> </description>
</key> </key>
<key name="favorite-apps" type="as"> <key name="favorite-apps" type="as">
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'org.gnome.Shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default> <default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default>
<summary>List of desktop file IDs for favorite applications</summary> <summary>List of desktop file IDs for favorite applications</summary>
<description> <description>
The applications corresponding to these identifiers The applications corresponding to these identifiers

View File

@@ -6,7 +6,6 @@ const { Clutter, GObject, Pango, Shell, St } = imports.gi;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util; const GdmUtil = imports.gdm.util;
const Util = imports.misc.util;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
@@ -17,10 +16,6 @@ var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
var MESSAGE_FADE_OUT_ANIMATION_TIME = 500; var MESSAGE_FADE_OUT_ANIMATION_TIME = 500;
const WIGGLE_OFFSET = 6;
const WIGGLE_DURATION = 65;
const N_WIGGLES = 3;
var AuthPromptMode = { var AuthPromptMode = {
UNLOCK_ONLY: 0, UNLOCK_ONLY: 0,
UNLOCK_OR_LOG_IN: 1 UNLOCK_OR_LOG_IN: 1
@@ -261,12 +256,6 @@ var AuthPrompt = GObject.registerClass({
this.updateSensitivity(canRetry); this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null); this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED; this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
Util.wiggle(this._entry, {
offset: WIGGLE_OFFSET,
duration: WIGGLE_DURATION,
wiggleCount: N_WIGGLES,
});
} }
_onVerificationComplete() { _onVerificationComplete() {

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine, /* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted, formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView, wiggle */ makeCloseButton, ensureActorVisibleInScrollView */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext; const Gettext = imports.gettext;
@@ -429,37 +429,3 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
duration: SCROLL_TIME duration: SCROLL_TIME
}); });
} }
function wiggle(actor, params) {
params = Params.parse(params, {
offset: 0,
duration: 0,
wiggleCount: 0,
});
actor.translation_x = 0;
// Accelerate before wiggling
actor.ease({
translation_x: -params.offset,
duration: params.duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
// Wiggle
actor.ease({
translation_x: params.offset,
duration: params.duration,
mode: Clutter.AnimationMode.LINEAR,
repeatCount: params.wiggleCount,
autoReverse: true,
onComplete: () => {
// Decelerate and return to the original position
actor.ease({
translation_x: 0,
duration: params.duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
});
}
});
}
});
}

View File

@@ -28,14 +28,20 @@ var AppIconMode = {
function _createWindowClone(window, size) { function _createWindowClone(window, size) {
let [width, height] = window.get_size(); let [width, height] = window.get_size();
let scale = Math.min(1.0, size / width, size / height); let scale = Math.min(1.0, size / width, size / height);
return new Clutter.Clone({ source: window,
width: width * scale, let cloneWidth = size;
height: height * scale, let cloneHeight = size;
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER, if (width > height)
// usual hack for the usual bug in ClutterBinLayout... cloneHeight = size * (height / width);
x_expand: true, else
y_expand: true }); cloneWidth = size * (width / height);
return new Clutter.Actor({
content: window.content,
width: cloneWidth,
height: cloneHeight,
});
} }
function getWindows(workspace) { function getWindows(workspace) {
@@ -411,7 +417,7 @@ class CyclerHighlight extends St.Widget {
super._init({ layout_manager: new Clutter.BinLayout() }); super._init({ layout_manager: new Clutter.BinLayout() });
this._window = null; this._window = null;
this._clone = new Clutter.Clone(); this._clone = new Clutter.Actor();
this.add_actor(this._clone); this.add_actor(this._clone);
this._highlight = new St.Widget({ style_class: 'cycler-highlight' }); this._highlight = new St.Widget({ style_class: 'cycler-highlight' });
@@ -433,8 +439,8 @@ class CyclerHighlight extends St.Widget {
this._window = w; this._window = w;
if (this._clone.source) if (this._clone.content)
this._clone.source.sync_visibility(); this._clone.content.window_actor.sync_visibility();
let windowActor = this._window let windowActor = this._window
? this._window.get_compositor_private() : null; ? this._window.get_compositor_private() : null;
@@ -442,7 +448,7 @@ class CyclerHighlight extends St.Widget {
if (windowActor) if (windowActor)
windowActor.hide(); windowActor.hide();
this._clone.source = windowActor; this._clone.content = windowActor.content;
} }
_onAllocationChanged() { _onAllocationChanged() {

View File

@@ -2045,6 +2045,7 @@ var AppFolderPopup = GObject.registerClass({
var AppIcon = GObject.registerClass({ var AppIcon = GObject.registerClass({
GTypeName: 'AppDisplay_AppIcon', GTypeName: 'AppDisplay_AppIcon',
Implements: [Search.SearchResultInterface],
Signals: { Signals: {
'menu-state-changed': { param_types: [GObject.TYPE_BOOLEAN] }, 'menu-state-changed': { param_types: [GObject.TYPE_BOOLEAN] },
'sync-tooltip': {}, 'sync-tooltip': {},
@@ -2513,15 +2514,13 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
this._appendSeparator(); this._appendSeparator();
} }
let wantsDiscreteGpu = appInfo.get_boolean("PreferRunOnDiscreteGPU") ||
appInfo.get_boolean("X-KDE-RunOnDiscreteGpu");
if (discreteGpuAvailable && if (discreteGpuAvailable &&
!wantsDiscreteGpu && this._source.app.state == Shell.AppState.STOPPED &&
this._source.app.state == Shell.AppState.STOPPED) { !actions.includes('activate-discrete-gpu')) {
this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card")); this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card"));
this._onDiscreteGpuMenuItem.connect('activate', () => { this._onDiscreteGpuMenuItem.connect('activate', () => {
this._source.animateLaunch(); this._source.animateLaunch();
this._source.app.launch(0, -1, Shell.AppGpuSelection.DISCRETE); this._source.app.launch(0, -1, true);
this.emit('activate-window', null); this.emit('activate-window', null);
}); });
} }
@@ -2530,7 +2529,8 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
let action = actions[i]; let action = actions[i];
let item = this._appendMenuItem(appInfo.get_action_name(action)); let item = this._appendMenuItem(appInfo.get_action_name(action));
item.connect('activate', (emitter, event) => { item.connect('activate', (emitter, event) => {
if (action == 'new-window') if (action == 'new-window' ||
action == 'activate-discrete-gpu')
this._source.animateLaunch(); this._source.animateLaunch();
this._source.app.launch_action(action, event.get_time(), -1); this._source.app.launch_action(action, event.get_time(), -1);

View File

@@ -55,7 +55,6 @@ const RENAMED_DESKTOP_IDS = {
'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop', 'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop',
'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop', 'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop',
'polari.desktop': 'org.gnome.Polari.desktop', 'polari.desktop': 'org.gnome.Polari.desktop',
'shotwell.desktop': 'org.gnome.Shotwell.desktop',
'tali.desktop': 'org.gnome.Tali.desktop', 'tali.desktop': 'org.gnome.Tali.desktop',
'totem.desktop': 'org.gnome.Totem.desktop', 'totem.desktop': 'org.gnome.Totem.desktop',
'evince.desktop': 'org.gnome.Evince.desktop', 'evince.desktop': 'org.gnome.Evince.desktop',

View File

@@ -573,15 +573,11 @@ var _Draggable = class _Draggable {
while (target) { while (target) {
if (target._delegate && target._delegate.acceptDrop) { if (target._delegate && target._delegate.acceptDrop) {
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY); let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
let accepted = false; if (target._delegate.acceptDrop(this.actor._delegate,
try { this._dragActor,
accepted = target._delegate.acceptDrop(this.actor._delegate, targX,
this._dragActor, targX, targY, event.get_time()); targY,
} catch (e) { event.get_time())) {
// On error, skip this target
logError(e, "Skipping drag target");
}
if (accepted) {
// If it accepted the drop without taking the actor, // If it accepted the drop without taking the actor,
// handle it ourselves. // handle it ourselves.
if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) { if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) {

View File

@@ -105,16 +105,6 @@ function _easeActor(actor, params) {
actor.set_easing_delay(params.delay); actor.set_easing_delay(params.delay);
delete params.delay; delete params.delay;
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
if (params.mode != undefined) if (params.mode != undefined)
actor.set_easing_mode(params.mode); actor.set_easing_mode(params.mode);
delete params.mode; delete params.mode;
@@ -137,12 +127,10 @@ function _easeActor(actor, params) {
else else
Meta.disable_unredirect_for_display(global.display); Meta.disable_unredirect_for_display(global.display);
if (transition) { if (transition)
transition.set({ repeatCount, autoReverse });
transition.connect('stopped', (t, finished) => callback(finished)); transition.connect('stopped', (t, finished) => callback(finished));
} else { else
callback(true); callback(true);
}
} }
function _easeActorProperty(actor, propName, target, params) { function _easeActorProperty(actor, propName, target, params) {
@@ -155,16 +143,6 @@ function _easeActorProperty(actor, propName, target, params) {
params.duration = adjustAnimationTime(params.duration); params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0); let duration = Math.floor(params.duration || 0);
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
// Copy Clutter's behavior for implicit animations, see // Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition() // should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped) if (actor instanceof Clutter.Actor && !actor.mapped)
@@ -190,9 +168,7 @@ function _easeActorProperty(actor, propName, target, params) {
let transition = new Clutter.PropertyTransition(Object.assign({ let transition = new Clutter.PropertyTransition(Object.assign({
property_name: propName, property_name: propName,
interval: new Clutter.Interval({ value_type: pspec.value_type }), interval: new Clutter.Interval({ value_type: pspec.value_type }),
remove_on_complete: true, remove_on_complete: true
repeat_count: repeatCount,
auto_reverse: autoReverse,
}, params)); }, params));
actor.add_transition(propName, transition); actor.add_transition(propName, transition);

View File

@@ -477,16 +477,16 @@ class RedBorderEffect extends Clutter.Effect {
color.init_from_4ub(0xff, 0, 0, 0xc4); color.init_from_4ub(0xff, 0, 0, 0xc4);
Cogl.set_source_color(color); Cogl.set_source_color(color);
let alloc = actor.get_allocation_box(); let geom = actor.get_allocation_geometry();
let width = 2; let width = 2;
// clockwise order // clockwise order
Cogl.rectangle(0, 0, alloc.get_width(), width); Cogl.rectangle(0, 0, geom.width, width);
Cogl.rectangle(alloc.get_width() - width, width, Cogl.rectangle(geom.width - width, width,
alloc.get_width(), alloc.get_height()); geom.width, geom.height);
Cogl.rectangle(0, alloc.get_height(), Cogl.rectangle(0, geom.height,
alloc.get_width() - width, alloc.get_height() - width); geom.width - width, geom.height - width);
Cogl.rectangle(0, alloc.get_height() - width, Cogl.rectangle(0, geom.height - width,
width, width); width, width);
} }
}); });

View File

@@ -400,8 +400,12 @@ var Overview = class {
return null; return null;
let window = windows[0]; let window = windows[0];
let clone = new Clutter.Clone({ source: window, let clone = new Clutter.Actor({
x: window.x, y: window.y }); source: window.content,
request_mode: Clutter.RequestMode.CONTENT_SIZE,
x: window.x,
y: window.y,
});
clone.source.connect('destroy', () => { clone.source.connect('destroy', () => {
clone.destroy(); clone.destroy();
}); });

View File

@@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SearchResultsView */ /* exported SearchResultsView, SearchResultInterface */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
@@ -32,8 +32,17 @@ class MaxWidthBox extends St.BoxLayout {
} }
}); });
var SearchResult = GObject.registerClass( var SearchResultInterface = GObject.registerClass({
class SearchResult extends St.Button { Requires: [Clutter.Actor],
}, class SearchResultInterface extends GObject.Interface {
activate() {
throw new GObject.NotImplementedError('activate in %s'.format(this.constructor.name));
}
});
var SearchResult = GObject.registerClass({
Implements: [SearchResultInterface]
}, class SearchResult extends St.Button {
_init(provider, metaInfo, resultsView) { _init(provider, metaInfo, resultsView) {
this.provider = provider; this.provider = provider;
this.metaInfo = metaInfo; this.metaInfo = metaInfo;
@@ -244,6 +253,8 @@ var SearchResultsBase = GObject.registerClass({
metasNeeded.forEach((resultId, i) => { metasNeeded.forEach((resultId, i) => {
let meta = metas[i]; let meta = metas[i];
let display = this._createResultDisplay(meta); let display = this._createResultDisplay(meta);
if (!(display instanceof SearchResultInterface))
throw new Error(`${display} is not a valid search result`);
display.connect('key-focus-in', this._keyFocusIn.bind(this)); display.connect('key-focus-in', this._keyFocusIn.bind(this));
this._resultDisplays[resultId] = display; this._resultDisplays[resultId] = display;
}); });

View File

@@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Workspace */ /* exported Workspace */
const { Atk, Clutter, GLib, GObject, const { Atk, Clutter, GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
Graphene, Meta, Pango, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
@@ -85,7 +84,7 @@ class WindowCloneLayout extends Clutter.LayoutManager {
if (child == container._windowClone) if (child == container._windowClone)
realWindow = container.realWindow; realWindow = container.realWindow;
else else
realWindow = child.source; realWindow = child.content.window_actor;
child.allocate(this._makeBoxForWindow(realWindow.meta_window), child.allocate(this._makeBoxForWindow(realWindow.meta_window),
flags); flags);
@@ -111,7 +110,7 @@ var WindowClone = GObject.registerClass({
this.metaWindow._delegate = this; this.metaWindow._delegate = this;
this._workspace = workspace; this._workspace = workspace;
this._windowClone = new Clutter.Clone({ source: realWindow }); this._windowClone = new Clutter.Actor({ content: realWindow.content });
// We expect this to be used for all interaction rather than // We expect this to be used for all interaction rather than
// this._windowClone; as the former is reactive and the latter // this._windowClone; as the former is reactive and the latter
// is not, this just works for most cases. However, for DND all // is not, this just works for most cases. However, for DND all
@@ -159,8 +158,6 @@ var WindowClone = GObject.registerClass({
this.x = this._boundingBox.x; this.x = this._boundingBox.x;
this.y = this._boundingBox.y; this.y = this._boundingBox.y;
this._computeWindowCenter();
let clickAction = new Clutter.ClickAction(); let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', this._onClicked.bind(this)); clickAction.connect('clicked', this._onClicked.bind(this));
clickAction.connect('long-press', this._onLongPress.bind(this)); clickAction.connect('long-press', this._onLongPress.bind(this));
@@ -200,7 +197,7 @@ var WindowClone = GObject.registerClass({
// Delete all windows, starting from the bottom-most (most-modal) one // Delete all windows, starting from the bottom-most (most-modal) one
let windows = this.get_children(); let windows = this.get_children();
for (let i = windows.length - 1; i >= 1; i--) { for (let i = windows.length - 1; i >= 1; i--) {
let realWindow = windows[i].source; let realWindow = windows[i].content.window_actor;
let metaWindow = realWindow.meta_window; let metaWindow = realWindow.meta_window;
metaWindow.delete(global.get_current_time()); metaWindow.delete(global.get_current_time());
@@ -232,7 +229,7 @@ var WindowClone = GObject.registerClass({
} }
_doAddAttachedDialog(metaWin, realWin) { _doAddAttachedDialog(metaWin, realWin) {
let clone = new Clutter.Clone({ source: realWin }); let clone = new Clutter.Actor({ content: realWin.content });
clone._sizeChangedId = metaWin.connect('size-changed', clone._sizeChangedId = metaWin.connect('size-changed',
this._onMetaWindowSizeChanged.bind(this)); this._onMetaWindowSizeChanged.bind(this));
clone._posChangedId = metaWin.connect('position-changed', clone._posChangedId = metaWin.connect('position-changed',
@@ -285,7 +282,7 @@ var WindowClone = GObject.registerClass({
if (child == this._windowClone) if (child == this._windowClone)
realWindow = this.realWindow; realWindow = this.realWindow;
else else
realWindow = child.source; realWindow = child.content.window_actor;
let metaWindow = realWindow.meta_window; let metaWindow = realWindow.meta_window;
rect = rect.union(metaWindow.get_frame_rect()); rect = rect.union(metaWindow.get_frame_rect());
@@ -296,18 +293,6 @@ var WindowClone = GObject.registerClass({
this.layout_manager.boundingBox = rect; this.layout_manager.boundingBox = rect;
} }
get windowCenter() {
return this._windowCenter;
}
_computeWindowCenter() {
let box = this.realWindow.get_allocation_box();
this._windowCenter = new Graphene.Point({
x: box.get_x() + box.get_width() / 2,
y: box.get_y() + box.get_height() / 2,
});
}
// Find the actor just below us, respecting reparenting done by DND code // Find the actor just below us, respecting reparenting done by DND code
getActualStackAbove() { getActualStackAbove() {
if (this._stackAbove == null) if (this._stackAbove == null)
@@ -342,7 +327,7 @@ var WindowClone = GObject.registerClass({
if (child == this._windowClone) if (child == this._windowClone)
realWindow = this.realWindow; realWindow = this.realWindow;
else else
realWindow = child.source; realWindow = child.content.window_actor;
realWindow.meta_window.disconnect(child._sizeChangedId); realWindow.meta_window.disconnect(child._sizeChangedId);
realWindow.meta_window.disconnect(child._posChangedId); realWindow.meta_window.disconnect(child._posChangedId);
@@ -1032,7 +1017,11 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
_sortRow(row) { _sortRow(row) {
// Sort windows horizontally to minimize travel distance. // Sort windows horizontally to minimize travel distance.
// This affects in what order the windows end up in a row. // This affects in what order the windows end up in a row.
row.windows.sort((a, b) => a.windowCenter.x - b.windowCenter.x); row.windows.sort((a, b) => {
let aCenter = a.realWindow.x + a.realWindow.width / 2;
let bCenter = b.realWindow.x + b.realWindow.width / 2;
return aCenter - bCenter;
});
} }
computeLayout(windows, layout) { computeLayout(windows, layout) {
@@ -1051,7 +1040,11 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
// Sort windows vertically to minimize travel distance. // Sort windows vertically to minimize travel distance.
// This affects what rows the windows get placed in. // This affects what rows the windows get placed in.
let sortedWindows = windows.slice(); let sortedWindows = windows.slice();
sortedWindows.sort((a, b) => a.windowCenter.y - b.windowCenter.y); sortedWindows.sort((a, b) => {
let aCenter = a.realWindow.y + a.realWindow.height / 2;
let bCenter = b.realWindow.y + b.realWindow.height / 2;
return aCenter - bCenter;
});
let windowIdx = 0; let windowIdx = 0;
for (let i = 0; i < numRows; i++) { for (let i = 0; i < numRows; i++) {

View File

@@ -53,7 +53,8 @@ var WindowClone = GObject.registerClass({
} }
}, class WindowClone extends Clutter.Actor { }, class WindowClone extends Clutter.Actor {
_init(realWindow) { _init(realWindow) {
let clone = new Clutter.Clone({ source: realWindow }); let clone = new Clutter.Actor({ content: realWindow.content,
request_mode: Clutter.RequestMode.CONTENT_SIZE });
super._init({ super._init({
layout_manager: new PrimaryActorLayout(clone), layout_manager: new PrimaryActorLayout(clone),
reactive: true reactive: true
@@ -137,7 +138,8 @@ var WindowClone = GObject.registerClass({
} }
_doAddAttachedDialog(metaDialog, realDialog) { _doAddAttachedDialog(metaDialog, realDialog) {
let clone = new Clutter.Clone({ source: realDialog }); let clone = new Clutter.Actor({ content: realDialog.content,
request_mode: Clutter.RequestMode.CONTENT_SIZE });
this._updateDialogPosition(realDialog, clone); this._updateDialogPosition(realDialog, clone);
clone._updateId = realDialog.connect('notify::position', dialog => { clone._updateId = realDialog.connect('notify::position', dialog => {
@@ -163,7 +165,7 @@ var WindowClone = GObject.registerClass({
_disconnectSignals() { _disconnectSignals() {
this.get_children().forEach(child => { this.get_children().forEach(child => {
let realWindow = child.source; let realWindow = child.content.window_actor;
realWindow.disconnect(child._updateId); realWindow.disconnect(child._updateId);
realWindow.disconnect(child._destroyId); realWindow.disconnect(child._destroyId);

980
po/fa.po

File diff suppressed because it is too large Load Diff

100
po/fur.po
View File

@@ -7,15 +7,15 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: video-subtitles master\n" "Project-Id-Version: video-subtitles master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2019-10-12 20:48+0000\n" "POT-Creation-Date: 2019-09-17 11:44+0000\n"
"PO-Revision-Date: 2019-10-17 15:53+0200\n" "PO-Revision-Date: 2019-09-26 16:19+0200\n"
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n" "Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
"Language-Team: Friulian <fur@li.org>\n" "Language-Team: Friulian <fur@li.org>\n"
"Language: fur\n" "Language: fur\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.2.4\n" "X-Generator: Poedit 2.2.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: data/50-gnome-shell-system.xml:6 #: data/50-gnome-shell-system.xml:6
@@ -467,7 +467,7 @@ msgid "Next"
msgstr "Indenant" msgstr "Indenant"
#: js/gdm/authPrompt.js:197 js/ui/shellMountOperation.js:396 #: js/gdm/authPrompt.js:197 js/ui/shellMountOperation.js:396
#: js/ui/unlockDialog.js:45 #: js/ui/unlockDialog.js:42
msgid "Unlock" msgid "Unlock"
msgstr "Sbloche" msgstr "Sbloche"
@@ -497,8 +497,8 @@ msgstr "(p.e., utent o %s)"
#. TTLS and PEAP are actually much more complicated, but this complication #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (and don't even care of which one)
#: js/gdm/loginDialog.js:884 js/ui/components/networkAgent.js:248 #: js/gdm/loginDialog.js:884 js/ui/components/networkAgent.js:247
#: js/ui/components/networkAgent.js:268 js/ui/components/networkAgent.js:286 #: js/ui/components/networkAgent.js:267 js/ui/components/networkAgent.js:285
msgid "Username: " msgid "Username: "
msgstr "Non utent: " msgstr "Non utent: "
@@ -760,32 +760,32 @@ msgstr "Dispès"
msgid "All" msgid "All"
msgstr "Dutis" msgstr "Dutis"
#: js/ui/appDisplay.js:1745 #: js/ui/appDisplay.js:1749
msgid "Rename" msgid "Rename"
msgstr "Cambie non" msgstr "Cambie non"
#. Translators: This is the heading of a list of open windows #. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2418 js/ui/panel.js:76 #: js/ui/appDisplay.js:2397 js/ui/panel.js:76
msgid "Open Windows" msgid "Open Windows"
msgstr "Barcons vierts" msgstr "Barcons vierts"
#: js/ui/appDisplay.js:2437 js/ui/panel.js:83 #: js/ui/appDisplay.js:2416 js/ui/panel.js:83
msgid "New Window" msgid "New Window"
msgstr "Gnûf barcon" msgstr "Gnûf barcon"
#: js/ui/appDisplay.js:2449 #: js/ui/appDisplay.js:2428
msgid "Launch using Dedicated Graphics Card" msgid "Launch using Dedicated Graphics Card"
msgstr "Invie doprant une schede grafiche dedicade" msgstr "Invie doprant une schede grafiche dedicade"
#: js/ui/appDisplay.js:2478 js/ui/dash.js:239 #: js/ui/appDisplay.js:2457 js/ui/dash.js:239
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Gjave dai preferîts" msgstr "Gjave dai preferîts"
#: js/ui/appDisplay.js:2484 #: js/ui/appDisplay.js:2463
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Zonte tai preferîts" msgstr "Zonte tai preferîts"
#: js/ui/appDisplay.js:2494 js/ui/panel.js:94 #: js/ui/appDisplay.js:2473 js/ui/panel.js:94
msgid "Show Details" msgid "Show Details"
msgstr "Mostre Detais" msgstr "Mostre Detais"
@@ -1017,34 +1017,34 @@ msgid "Connect"
msgstr "Conet" msgstr "Conet"
#. Cisco LEAP #. Cisco LEAP
#: js/ui/components/networkAgent.js:217 js/ui/components/networkAgent.js:229 #: js/ui/components/networkAgent.js:216 js/ui/components/networkAgent.js:228
#: js/ui/components/networkAgent.js:251 js/ui/components/networkAgent.js:270 #: js/ui/components/networkAgent.js:250 js/ui/components/networkAgent.js:269
#: js/ui/components/networkAgent.js:290 js/ui/components/networkAgent.js:300 #: js/ui/components/networkAgent.js:289 js/ui/components/networkAgent.js:299
msgid "Password: " msgid "Password: "
msgstr "Password: " msgstr "Password: "
#. static WEP #. static WEP
#: js/ui/components/networkAgent.js:222 #: js/ui/components/networkAgent.js:221
msgid "Key: " msgid "Key: "
msgstr "Clâf: " msgstr "Clâf: "
#: js/ui/components/networkAgent.js:254 js/ui/components/networkAgent.js:276 #: js/ui/components/networkAgent.js:253 js/ui/components/networkAgent.js:275
msgid "Private key password: " msgid "Private key password: "
msgstr "Password di clâf privade: " msgstr "Password di clâf privade: "
#: js/ui/components/networkAgent.js:274 #: js/ui/components/networkAgent.js:273
msgid "Identity: " msgid "Identity: "
msgstr "Identitât: " msgstr "Identitât: "
#: js/ui/components/networkAgent.js:288 #: js/ui/components/networkAgent.js:287
msgid "Service: " msgid "Service: "
msgstr "Servizi: " msgstr "Servizi: "
#: js/ui/components/networkAgent.js:317 js/ui/components/networkAgent.js:692 #: js/ui/components/networkAgent.js:316 js/ui/components/networkAgent.js:691
msgid "Authentication required by wireless network" msgid "Authentication required by wireless network"
msgstr "La rêt cence fîl e domande autenticazion" msgstr "La rêt cence fîl e domande autenticazion"
#: js/ui/components/networkAgent.js:318 js/ui/components/networkAgent.js:693 #: js/ui/components/networkAgent.js:317 js/ui/components/networkAgent.js:692
#, javascript-format #, javascript-format
msgid "" msgid ""
"Passwords or encryption keys are required to access the wireless network " "Passwords or encryption keys are required to access the wireless network "
@@ -1053,41 +1053,41 @@ msgstr ""
"Si scugne meti une password o une clâf di cifradure par jentrâ te rêt cence " "Si scugne meti une password o une clâf di cifradure par jentrâ te rêt cence "
"fîl \"%s\"." "fîl \"%s\"."
#: js/ui/components/networkAgent.js:322 js/ui/components/networkAgent.js:697 #: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:696
msgid "Wired 802.1X authentication" msgid "Wired 802.1X authentication"
msgstr "Autenticazion vie fîl 802.1X" msgstr "Autenticazion vie fîl 802.1X"
#: js/ui/components/networkAgent.js:324 #: js/ui/components/networkAgent.js:323
msgid "Network name: " msgid "Network name: "
msgstr "Non rêt: " msgstr "Non rêt: "
#: js/ui/components/networkAgent.js:329 js/ui/components/networkAgent.js:701 #: js/ui/components/networkAgent.js:328 js/ui/components/networkAgent.js:700
msgid "DSL authentication" msgid "DSL authentication"
msgstr "Autenticazion DSL" msgstr "Autenticazion DSL"
#: js/ui/components/networkAgent.js:336 js/ui/components/networkAgent.js:706 #: js/ui/components/networkAgent.js:335 js/ui/components/networkAgent.js:705
msgid "PIN code required" msgid "PIN code required"
msgstr "Si pretint un codiç PIN" msgstr "Si pretint un codiç PIN"
#: js/ui/components/networkAgent.js:337 js/ui/components/networkAgent.js:707 #: js/ui/components/networkAgent.js:336 js/ui/components/networkAgent.js:706
msgid "PIN code is needed for the mobile broadband device" msgid "PIN code is needed for the mobile broadband device"
msgstr "Si scugne meti un codiç PIN pal dispositîf a bande largje mobil" msgstr "Si scugne meti un codiç PIN pal dispositîf a bande largje mobil"
#: js/ui/components/networkAgent.js:338 #: js/ui/components/networkAgent.js:337
msgid "PIN: " msgid "PIN: "
msgstr "PIN: " msgstr "PIN: "
#: js/ui/components/networkAgent.js:345 js/ui/components/networkAgent.js:713 #: js/ui/components/networkAgent.js:344 js/ui/components/networkAgent.js:712
msgid "Mobile broadband network password" msgid "Mobile broadband network password"
msgstr "Passowrd rêt mobil a bande largje" msgstr "Passowrd rêt mobil a bande largje"
#: js/ui/components/networkAgent.js:346 js/ui/components/networkAgent.js:698 #: js/ui/components/networkAgent.js:345 js/ui/components/networkAgent.js:697
#: js/ui/components/networkAgent.js:702 js/ui/components/networkAgent.js:714 #: js/ui/components/networkAgent.js:701 js/ui/components/networkAgent.js:713
#, javascript-format #, javascript-format
msgid "A password is required to connect to “%s”." msgid "A password is required to connect to “%s”."
msgstr "A covente une password par tacâsi a '%s'." msgstr "A covente une password par tacâsi a '%s'."
#: js/ui/components/networkAgent.js:681 js/ui/status/network.js:1675 #: js/ui/components/networkAgent.js:680 js/ui/status/network.js:1675
msgid "Network Manager" msgid "Network Manager"
msgstr "Ministradôr di rêt" msgstr "Ministradôr di rêt"
@@ -1475,26 +1475,6 @@ msgstr "Viôt sorzint"
msgid "Web Page" msgid "Web Page"
msgstr "Pagjine Web" msgstr "Pagjine Web"
#: js/ui/main.js:267
msgid "Logged in as a privileged user"
msgstr "Jentre come utent privilegjât"
#: js/ui/main.js:268
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
msgstr ""
"Si varès di evitâ di eseguî une session come utent privilegjât par resons di "
"sigurece. Se pussibil, tu varessis di jentrâ come utent normâl."
#: js/ui/main.js:274
msgid "Screen Lock disabled"
msgstr "Bloc dal schermi disabilitât"
#: js/ui/main.js:275
msgid "Screen Locking requires the GNOME display manager."
msgstr "Il bloc dal schermi al à bisugne dal gjestôr dai visôrs di GNOME."
#: js/ui/messageTray.js:1465 #: js/ui/messageTray.js:1465
msgid "System Information" msgid "System Information"
msgstr "Informazion di sisteme" msgstr "Informazion di sisteme"
@@ -2239,11 +2219,11 @@ msgstr "Dome esterni"
msgid "Built-in Only" msgid "Built-in Only"
msgstr "Dome incorporât" msgstr "Dome incorporât"
#: js/ui/unlockDialog.js:53 #: js/ui/unlockDialog.js:50
msgid "Log in as another user" msgid "Log in as another user"
msgstr "Jentre come altri utent" msgstr "Jentre come altri utent"
#: js/ui/unlockDialog.js:70 #: js/ui/unlockDialog.js:67
msgid "Unlock Window" msgid "Unlock Window"
msgstr "Sbloche barcon" msgstr "Sbloche barcon"
@@ -2286,7 +2266,7 @@ msgstr[1] ""
#. Translators: This represents the size of a window. The first number is #. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height. #. * the width of the window and the second is the height.
#: js/ui/windowManager.js:686 #: js/ui/windowManager.js:683
#, javascript-format #, javascript-format
msgid "%d × %d" msgid "%d × %d"
msgstr "%d × %d" msgstr "%d × %d"
@@ -2370,7 +2350,7 @@ msgstr ""
#: src/extensions-tool/command-create.c:192 src/extensions-tool/main.c:169 #: src/extensions-tool/command-create.c:192 src/extensions-tool/main.c:169
msgid "Name" msgid "Name"
msgstr "Non" msgstr "Non "
#: src/extensions-tool/command-create.c:203 #: src/extensions-tool/command-create.c:203
#, c-format #, c-format
@@ -2624,7 +2604,7 @@ msgstr "Comants:"
msgid "Print help" msgid "Print help"
msgstr "Stampe jutori" msgstr "Stampe jutori"
#: src/extensions-tool/main.c:248 src/main.c:460 #: src/extensions-tool/main.c:248 src/main.c:468
msgid "Print version" msgid "Print version"
msgstr "Stampe version" msgstr "Stampe version"
@@ -2673,15 +2653,15 @@ msgstr "Instale complès di estensions"
msgid "Use “%s” to get detailed help.\n" msgid "Use “%s” to get detailed help.\n"
msgstr "Dopre “%s” par vê un jutori detaiât.\n" msgstr "Dopre “%s” par vê un jutori detaiât.\n"
#: src/main.c:466 #: src/main.c:474
msgid "Mode used by GDM for login screen" msgid "Mode used by GDM for login screen"
msgstr "Modalitât doprade da GDM pe videade di acès" msgstr "Modalitât doprade da GDM pe videade di acès"
#: src/main.c:472 #: src/main.c:480
msgid "Use a specific mode, e.g. “gdm” for login screen" msgid "Use a specific mode, e.g. “gdm” for login screen"
msgstr "Dopre une modalitât specifiche, par esempli “gdm” pe videade di acès" msgstr "Dopre une modalitât specifiche, par esempli “gdm” pe videade di acès"
#: src/main.c:478 #: src/main.c:486
msgid "List possible modes" msgid "List possible modes"
msgstr "Liste modalitâts pussibilis" msgstr "Liste modalitâts pussibilis"

524
po/hr.po

File diff suppressed because it is too large Load Diff

View File

@@ -509,7 +509,7 @@ shell_app_activate_full (ShellApp *app,
case SHELL_APP_STATE_STOPPED: case SHELL_APP_STATE_STOPPED:
{ {
GError *error = NULL; GError *error = NULL;
if (!shell_app_launch (app, timestamp, workspace, SHELL_APP_GPU_SELECTION_AUTO, &error)) if (!shell_app_launch (app, timestamp, workspace, FALSE, &error))
{ {
char *msg; char *msg;
msg = g_strdup_printf (_("Failed to launch “%s”"), shell_app_get_name (app)); msg = g_strdup_printf (_("Failed to launch “%s”"), shell_app_get_name (app));
@@ -584,7 +584,7 @@ shell_app_open_new_window (ShellApp *app,
* instance (Firefox). There are a few less-sensical cases such * instance (Firefox). There are a few less-sensical cases such
* as say Pidgin. * as say Pidgin.
*/ */
shell_app_launch (app, 0, workspace, SHELL_APP_GPU_SELECTION_AUTO, NULL); shell_app_launch (app, 0, workspace, FALSE, NULL);
} }
/** /**
@@ -1255,37 +1255,19 @@ wait_pid (GDesktopAppInfo *appinfo,
g_child_watch_add (pid, (GChildWatchFunc) g_spawn_close_pid, NULL); g_child_watch_add (pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
} }
static gboolean
get_with_discrete_gpu (ShellApp *app,
ShellAppGpuSelection discrete_gpu)
{
switch (discrete_gpu)
{
case SHELL_APP_GPU_SELECTION_INTEGRATED:
return FALSE;
case SHELL_APP_GPU_SELECTION_DISCRETE:
return TRUE;
case SHELL_APP_GPU_SELECTION_AUTO:
return g_desktop_app_info_get_boolean (app->info, "PreferRunOnDiscreteGPU") ||
g_desktop_app_info_get_boolean (app->info, "X-KDE-RunOnDiscreteGpu");
default:
g_assert_not_reached();
}
}
/** /**
* shell_app_launch: * shell_app_launch:
* @timestamp: Event timestamp, or 0 for current event timestamp * @timestamp: Event timestamp, or 0 for current event timestamp
* @workspace: Start on this workspace, or -1 for default * @workspace: Start on this workspace, or -1 for default
* @discrete_gpu: the preferred GPU to launch the application on. * @discrete_gpu: Whether to start on the discrete GPU
* @error: A #GError * @error: A #GError
*/ */
gboolean gboolean
shell_app_launch (ShellApp *app, shell_app_launch (ShellApp *app,
guint timestamp, guint timestamp,
int workspace, int workspace,
ShellAppGpuSelection discrete_gpu, gboolean discrete_gpu,
GError **error) GError **error)
{ {
ShellGlobal *global; ShellGlobal *global;
GAppLaunchContext *context; GAppLaunchContext *context;
@@ -1307,13 +1289,8 @@ shell_app_launch (ShellApp *app,
global = shell_global_get (); global = shell_global_get ();
context = shell_global_create_app_launch_context (global, timestamp, workspace); context = shell_global_create_app_launch_context (global, timestamp, workspace);
/* FIXME: this should probably check whether we're on a dual-GPU system */ if (discrete_gpu)
if (get_with_discrete_gpu (app, discrete_gpu)) g_app_launch_context_setenv (context, "DRI_PRIME", "1");
{
g_app_launch_context_setenv (context, "DRI_PRIME", "1");
g_app_launch_context_setenv (context, "__NV_PRIME_RENDER_OFFLOAD", "1");
g_app_launch_context_setenv (context, "__GLX_VENDOR_LIBRARY_NAME", "nvidia");
}
/* Set LEAVE_DESCRIPTORS_OPEN in order to use an optimized gspawn /* Set LEAVE_DESCRIPTORS_OPEN in order to use an optimized gspawn
* codepath. The shell's open file descriptors should be marked CLOEXEC * codepath. The shell's open file descriptors should be marked CLOEXEC

View File

@@ -18,12 +18,6 @@ typedef enum {
SHELL_APP_STATE_RUNNING SHELL_APP_STATE_RUNNING
} ShellAppState; } ShellAppState;
typedef enum {
SHELL_APP_GPU_SELECTION_AUTO = -1,
SHELL_APP_GPU_SELECTION_INTEGRATED = 0,
SHELL_APP_GPU_SELECTION_DISCRETE = 1
} ShellAppGpuSelection;
const char *shell_app_get_id (ShellApp *app); const char *shell_app_get_id (ShellApp *app);
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app); GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
@@ -57,11 +51,11 @@ GSList *shell_app_get_pids (ShellApp *app);
gboolean shell_app_is_on_workspace (ShellApp *app, MetaWorkspace *workspace); gboolean shell_app_is_on_workspace (ShellApp *app, MetaWorkspace *workspace);
gboolean shell_app_launch (ShellApp *app, gboolean shell_app_launch (ShellApp *app,
guint timestamp, guint timestamp,
int workspace, int workspace,
ShellAppGpuSelection discrete_gpu, gboolean discrete_gpu,
GError **error); GError **error);
void shell_app_launch_action (ShellApp *app, void shell_app_launch_action (ShellApp *app,
const char *action_name, const char *action_name,

View File

@@ -489,7 +489,7 @@ st_box_layout_pick (ClutterActor *actor)
for (child = clutter_actor_get_first_child (actor); for (child = clutter_actor_get_first_child (actor);
child != NULL; child != NULL;
child = clutter_actor_get_next_sibling (child)) child = clutter_actor_get_next_sibling (child))
clutter_actor_pick (child); clutter_actor_paint (child);
if (priv->hadjustment || priv->vadjustment) if (priv->hadjustment || priv->vadjustment)
cogl_framebuffer_pop_clip (fb); cogl_framebuffer_pop_clip (fb);

View File

@@ -302,11 +302,11 @@ st_scroll_view_pick (ClutterActor *actor)
CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor); CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor);
if (priv->child) if (priv->child)
clutter_actor_pick (priv->child); clutter_actor_paint (priv->child);
if (priv->hscrollbar_visible) if (priv->hscrollbar_visible)
clutter_actor_pick (priv->hscroll); clutter_actor_paint (priv->hscroll);
if (priv->vscrollbar_visible) if (priv->vscrollbar_visible)
clutter_actor_pick (priv->vscroll); clutter_actor_paint (priv->vscroll);
} }
static gboolean static gboolean

View File

@@ -36,16 +36,16 @@ function test() {
obin.connect_after('paint', actor => { obin.connect_after('paint', actor => {
Cogl.set_source_color4f(0, 1, 0, 1); Cogl.set_source_color4f(0, 1, 0, 1);
let alloc = actor.get_allocation_box(); let geom = actor.get_allocation_geometry();
let width = 3; let width = 3;
// clockwise order // clockwise order
Cogl.rectangle(0, 0, alloc.get_width(), width); Cogl.rectangle(0, 0, geom.width, width);
Cogl.rectangle(alloc.get_width() - width, width, Cogl.rectangle(geom.width - width, width,
alloc.get_width(), alloc.get_height()); geom.width, geom.height);
Cogl.rectangle(0, alloc.get_height(), Cogl.rectangle(0, geom.height,
alloc.get_width() - width, alloc.get_height() - width); geom.width - width, geom.height - width);
Cogl.rectangle(0, alloc.get_height() - width, Cogl.rectangle(0, geom.height - width,
width, width); width, width);
}); });
tbox.add(obin); tbox.add(obin);