Replace window realm frame decorations with nicer label decorations
This commit is contained in:
parent
c5277c949a
commit
1ee48a7649
@ -7,10 +7,22 @@
|
|||||||
padding: .5em;
|
padding: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.realm-frame-label {
|
.realm-window-label {
|
||||||
|
color: rgb(40, 40, 40);
|
||||||
|
padding: 6px 1em;
|
||||||
|
border-radius: 999px;
|
||||||
|
text-align: center;
|
||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
.realm-app-icon-label {
|
||||||
|
border-width: 3px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: rgb(40, 40, 40);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 2px 1em;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.realm-config-icon {
|
.realm-config-icon {
|
||||||
color: #8e8e80;
|
color: #8e8e80;
|
||||||
|
@ -160,7 +160,7 @@
|
|||||||
<file>ui/realms/realmManager.js</file>
|
<file>ui/realms/realmManager.js</file>
|
||||||
<file>ui/realms/realmSearchProvider.js</file>
|
<file>ui/realms/realmSearchProvider.js</file>
|
||||||
<file>ui/realms/realmSwitcher.js</file>
|
<file>ui/realms/realmSwitcher.js</file>
|
||||||
<file>ui/realms/realmWindowFrame.js</file>
|
<file>ui/realms/realmLabels.js</file>
|
||||||
<file>ui/realms/realmWindowMenu.js</file>
|
<file>ui/realms/realmWindowMenu.js</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
@ -3009,6 +3009,14 @@ export const AppIcon = GObject.registerClass({
|
|||||||
iconParams['createIcon'] = this._createIcon.bind(this);
|
iconParams['createIcon'] = this._createIcon.bind(this);
|
||||||
iconParams['setSizeManually'] = true;
|
iconParams['setSizeManually'] = true;
|
||||||
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
|
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
|
||||||
|
|
||||||
|
if (Main.realmManager.appIconLabelsEnabled()) {
|
||||||
|
const realmLabel = Main.realmManager.createRealmLabelForApp(app);
|
||||||
|
if (realmLabel) {
|
||||||
|
this.icon._box.insert_child_at_index(realmLabel, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._iconContainer.add_child(this.icon);
|
this._iconContainer.add_child(this.icon);
|
||||||
|
|
||||||
this._dot = new St.Widget({
|
this._dot = new St.Widget({
|
||||||
|
431
js/ui/realms/realmLabels.js
Normal file
431
js/ui/realms/realmLabels.js
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
import Clutter from 'gi://Clutter';
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Meta from 'gi://Meta';
|
||||||
|
import Shell from 'gi://Shell';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import St from 'gi://St';
|
||||||
|
|
||||||
|
const LABEL_FADE_TIMEOUT = 1500;
|
||||||
|
const LABEL_FADEIN_TIME = 250;
|
||||||
|
|
||||||
|
const CITADEL_SETTINGS_SCHEMA = 'com.subgraph.citadel';
|
||||||
|
const LABEL_COLOR_LIST_KEY = 'label-color-list';
|
||||||
|
const REALM_LABEL_COLORS_KEY = 'realm-label-colors';
|
||||||
|
const REALM_LABEL_SHOW_CITADEL_KEY = 'realm-label-show-citadel';
|
||||||
|
const REALM_LABEL_SHOW_ALL_KEY = 'realm-label-show-all';
|
||||||
|
const REALM_LABEL_SHOW_APP_ICONS = 'realm-label-show-app-icons';
|
||||||
|
|
||||||
|
const CITADEL_LABEL_COLOR = 'rgb(200,0,0)';
|
||||||
|
const CITADEL_REALM_NAME = 'Citadel';
|
||||||
|
|
||||||
|
const WindowLabelColors = class WindowLabelColors {
|
||||||
|
|
||||||
|
constructor(settings) {
|
||||||
|
this._realm_label_colors = new Map();
|
||||||
|
this._defaultColors = [];
|
||||||
|
const [_ok, color] = Clutter.Color.from_string(CITADEL_LABEL_COLOR);
|
||||||
|
this.citadelColor = color;
|
||||||
|
this._citadelSettings = settings;
|
||||||
|
this.reloadColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadColors() {
|
||||||
|
this._loadDefaultColors();
|
||||||
|
this._loadRealmColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
colorForRealmName(name) {
|
||||||
|
if (name === CITADEL_REALM_NAME) {
|
||||||
|
return this.citadelColor;
|
||||||
|
} else if (this._realm_label_colors.has(name)) {
|
||||||
|
return this._realm_label_colors.get(name);
|
||||||
|
} else {
|
||||||
|
let color = this._allocateColor();
|
||||||
|
this._realm_label_colors.set(name, color);
|
||||||
|
this._storeColors();
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_storeColors() {
|
||||||
|
let entries = [];
|
||||||
|
for(let [name,color] of this._realm_label_colors) {
|
||||||
|
entries.push(`${name}:${color.to_string()}`);
|
||||||
|
}
|
||||||
|
entries.sort();
|
||||||
|
this._citadelSettings.set_strv(REALM_LABEL_COLORS_KEY, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadDefaultColors() {
|
||||||
|
this._defaultColors = [];
|
||||||
|
let entries = this._citadelSettings.get_strv(LABEL_COLOR_LIST_KEY);
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let [ok,color] = Clutter.Color.from_string(entry);
|
||||||
|
if (ok) {
|
||||||
|
this._defaultColors.push(color);
|
||||||
|
} else {
|
||||||
|
log(`RealmLabels: failed to parse default color entry: ${entry}`)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadRealmColors() {
|
||||||
|
this._realm_label_colors.clear();
|
||||||
|
let entries = this._citadelSettings.get_strv(REALM_LABEL_COLORS_KEY);
|
||||||
|
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let parts = entry.split(":");
|
||||||
|
if (parts.length === 2) {
|
||||||
|
let [ok,color] = Clutter.Color.from_string(parts[1]);
|
||||||
|
if (ok) {
|
||||||
|
this._realm_label_colors.set(parts[0], color);
|
||||||
|
} else {
|
||||||
|
log(`RealmLabels: Failed to parse color from realm color entry: ${entry}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log(`RealmLabels: Invalid realm color entry: ${entry}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_allocateColor() {
|
||||||
|
// 1) No default colors? return a built in color
|
||||||
|
if (this._defaultColors.length == 0) {
|
||||||
|
return Clutter.Color.new(153, 193, 241, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) No default colors? Find first color on default color list that isn't used already
|
||||||
|
let used_colors = Array.from(this._realm_label_colors.values());
|
||||||
|
for (const color of this._defaultColors) {
|
||||||
|
if (!used_colors.some(c => c.equal(color))) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Choose a random element of the default list
|
||||||
|
let index = Math.floor(Math.random() * this._defaultColors.length);
|
||||||
|
return this._defaultColors[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RealmLabelManager = class RealmLabelManager {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
this._realms = Shell.Realms.get_default();
|
||||||
|
this._citadelSettings = new Gio.Settings({ schema_id: CITADEL_SETTINGS_SCHEMA });
|
||||||
|
this._colors = new WindowLabelColors(this._citadelSettings);
|
||||||
|
this._showCitadelLabels = this._citadelSettings.get_boolean(REALM_LABEL_SHOW_CITADEL_KEY);
|
||||||
|
this._showAllLabels = this._citadelSettings.get_boolean(REALM_LABEL_SHOW_ALL_KEY);
|
||||||
|
this._showAppIconLabels = this._citadelSettings.get_boolean(REALM_LABEL_SHOW_APP_ICONS);
|
||||||
|
this._citadelSettings.connect('changed', this._syncSettings.bind(this));
|
||||||
|
|
||||||
|
this._window_labels = new Map();
|
||||||
|
|
||||||
|
global.window_manager.connect('map', this._handleWindowMap.bind(this));
|
||||||
|
global.workspace_manager.connect('context-window-moved', this._onContextWindowMoved.bind(this));
|
||||||
|
global.workspace_manager.connect('context-removed', this._onContextRemoved.bind(this));
|
||||||
|
|
||||||
|
this._syncAllWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
_syncSettings() {
|
||||||
|
this._colors.reloadColors();
|
||||||
|
for (const label of this._window_labels.values()) {
|
||||||
|
let color = this.colorForWindow(label.window);
|
||||||
|
label.setColor(color);
|
||||||
|
}
|
||||||
|
this._showCitadelLabels = this._citadelSettings.get_boolean(REALM_LABEL_SHOW_CITADEL_KEY);
|
||||||
|
this._showAllLabels = this._citadelSettings.get_boolean(REALM_LABEL_SHOW_ALL_KEY);
|
||||||
|
this._showAppIconLabels = this._citadelSettings.get_boolean(REALM_LABEL_SHOW_APP_ICONS);
|
||||||
|
this._syncAllWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onContextWindowMoved(workspaceManager, window) {
|
||||||
|
const actor = window.get_compositor_private();
|
||||||
|
if (actor) {
|
||||||
|
this._syncWindow(actor);
|
||||||
|
}
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleWindowMap(shellwm, actor) {
|
||||||
|
this._syncWindow(actor);
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onContextRemoved(workspaceManager, id) {
|
||||||
|
this._syncAllWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
_syncAllWindows() {
|
||||||
|
const actors = global.get_window_actors();
|
||||||
|
actors.forEach(a => this._syncWindow(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
createAppIconLabelForRealm(realmName) {
|
||||||
|
if (!realmName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const color = this._colors.colorForRealmName(realmName);
|
||||||
|
return new RealmAppIconLabel(realmName, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
appIconLabelsEnabled() {
|
||||||
|
return this._showAppIconLabels;
|
||||||
|
}
|
||||||
|
|
||||||
|
addLabelToWindow(actor, window) {
|
||||||
|
const win_id = window.get_stable_sequence();
|
||||||
|
const name = this.realmNameForWindow(window);
|
||||||
|
const color = this.colorForWindow(window);
|
||||||
|
if (name && color) {
|
||||||
|
this._window_labels.set(win_id, new RealmWindowLabel(actor, color, name));
|
||||||
|
window.connectObject('unmanaged', window => this.removeLabelFromWindow(window), this);
|
||||||
|
} else {
|
||||||
|
log(`RealmLabels: failed to add label to window`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeLabelFromWindow(window) {
|
||||||
|
const win_id = window.get_stable_sequence();
|
||||||
|
const label = this._window_labels.get(win_id);
|
||||||
|
if (label) {
|
||||||
|
label.destroy();
|
||||||
|
this._window_labels.delete(win_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getWindowLabel(window) {
|
||||||
|
const win_id = window.get_stable_sequence();
|
||||||
|
return this._window_labels.get(win_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
_syncWindow(actor) {
|
||||||
|
const window = actor.metaWindow;
|
||||||
|
const label = this._getWindowLabel(window);
|
||||||
|
const needsLabel = this.windowNeedsLabel(window);
|
||||||
|
|
||||||
|
if (label && !needsLabel) {
|
||||||
|
this.removeLabelFromWindow(window);
|
||||||
|
} else if (!label && needsLabel) {
|
||||||
|
this.addLabelToWindow(actor, window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return 'true' if 'window' should have a label.
|
||||||
|
windowNeedsLabel(window) {
|
||||||
|
// Only show labels on window type 'NORMAL'
|
||||||
|
if (window.get_window_type() !== Meta.WindowType.NORMAL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Only show labels on citadel windows if showCitadelLabels is enabled.
|
||||||
|
if (this._realms.is_citadel_window(window)) {
|
||||||
|
return this._showCitadelLabels;
|
||||||
|
}
|
||||||
|
// Unless showAllLabels is enabled only show label on 'foreign' windows
|
||||||
|
return this._showAllLabels || this._realms.is_foreign_window(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
realmNameForWindow(window) {
|
||||||
|
if (this._realms.is_citadel_window(window)) {
|
||||||
|
return "Citadel";
|
||||||
|
}
|
||||||
|
const realm = this._realms.realm_by_window(window);
|
||||||
|
if (realm) {
|
||||||
|
return realm.get_realm_name();
|
||||||
|
} else {
|
||||||
|
log(`RealmLabels: No realm found for window`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
colorForWindow(window) {
|
||||||
|
if (this._realms.is_citadel_window(window)) {
|
||||||
|
return this._colors.citadelColor;
|
||||||
|
}
|
||||||
|
const realmName = this.realmNameForWindow(window);
|
||||||
|
if (!realmName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const color = this._colors.colorForRealmName(realmName);
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWindowLabelEnabled(window) {
|
||||||
|
const label = this._getWindowLabel(window);
|
||||||
|
return label && label.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
setWindowLabelEnabled(window, enabled) {
|
||||||
|
const label = this._getWindowLabel(window);
|
||||||
|
if (!label) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
label.show();
|
||||||
|
} else {
|
||||||
|
label.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RealmAppIconLabel = GObject.registerClass(
|
||||||
|
class RealmAppIconLabel extends St.Label {
|
||||||
|
constructor(realmName, color) {
|
||||||
|
super({
|
||||||
|
style_class: 'realm-app-icon-label',
|
||||||
|
x_align: Clutter.ActorAlign.CENTER,
|
||||||
|
});
|
||||||
|
this.set_text(realmName);
|
||||||
|
this._color = null;
|
||||||
|
this.setColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(color) {
|
||||||
|
if (this._color && this._color.equal(color)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(color) {
|
||||||
|
this._color = color;
|
||||||
|
let c = color.to_string().substring(0, 7);
|
||||||
|
this.set_style(`border-color: ${c};`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const RealmWindowLabel = GObject.registerClass(
|
||||||
|
class RealmWindowLabel extends St.Label {
|
||||||
|
constructor(actor, color, realmName) {
|
||||||
|
super({
|
||||||
|
style_class: 'realm-window-label',
|
||||||
|
});
|
||||||
|
|
||||||
|
this.set_text(realmName);
|
||||||
|
this._color = null;
|
||||||
|
this.setColor(color);
|
||||||
|
|
||||||
|
this.set_reactive(true);
|
||||||
|
|
||||||
|
this._changedId = actor.metaWindow.connect('size-changed', window => {
|
||||||
|
this._update(window);
|
||||||
|
});
|
||||||
|
|
||||||
|
actor.add_child(this);
|
||||||
|
this._actor = actor;
|
||||||
|
|
||||||
|
this._update(actor.metaWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(color) {
|
||||||
|
if (this._color && this._color.equal(color)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(color) {
|
||||||
|
this._color = color;
|
||||||
|
let c = color.to_string().substring(0, 7);
|
||||||
|
this.set_style(`background-color: ${c};`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get window() {
|
||||||
|
return this._actor.metaWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
if (this._timeoutId) {
|
||||||
|
GLib.source_remove(this._timeoutId);
|
||||||
|
this._timeoutId = 0;
|
||||||
|
}
|
||||||
|
this._actor.metaWindow.disconnect(this._changedId);
|
||||||
|
this._actor.remove_child(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_easeOpacity(target) {
|
||||||
|
this.ease({
|
||||||
|
opacity: target,
|
||||||
|
duration: LABEL_FADEIN_TIME,
|
||||||
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_setDimmedLabel() {
|
||||||
|
this.opacity = 50;
|
||||||
|
this._resetTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
_restoreDimmedLabel() {
|
||||||
|
this._easeOpacity(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updatePosition(window) {
|
||||||
|
let frame_rect = window.get_frame_rect();
|
||||||
|
let buffer_rect = window.get_buffer_rect();
|
||||||
|
|
||||||
|
let offsetX = frame_rect.x - buffer_rect.x;
|
||||||
|
let offsetY = frame_rect.y - buffer_rect.y;
|
||||||
|
this.set_position(offsetX + 4, offsetY + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
_update(window) {
|
||||||
|
if (window.is_fullscreen()) {
|
||||||
|
this.hide();
|
||||||
|
} else {
|
||||||
|
this.show();
|
||||||
|
this._updatePosition(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_resendEvent(event) {
|
||||||
|
// Window actors receive events on a different path (via an event filter)
|
||||||
|
// than other actors on the stage. By setting (reactive = false) on the
|
||||||
|
// RealmWindowLabel and resending the event, it will be processed by the
|
||||||
|
// window actor. Afterward we set back (reactive = true).
|
||||||
|
this.set_reactive(false);
|
||||||
|
event.put();
|
||||||
|
this.set_reactive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_resetTimer() {
|
||||||
|
if (this._timeoutId) {
|
||||||
|
GLib.source_remove(this._timeoutId);
|
||||||
|
this._timeoutId = 0;
|
||||||
|
}
|
||||||
|
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, LABEL_FADE_TIMEOUT, () => {
|
||||||
|
this._timeoutId = 0;
|
||||||
|
this._restoreDimmedLabel();
|
||||||
|
return GLib.SOURCE_REMOVE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_enter_event(event) {
|
||||||
|
this._resendEvent(event);
|
||||||
|
super.vfunc_enter_event(event);
|
||||||
|
this._setDimmedLabel();
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_leave_event(event) {
|
||||||
|
super.vfunc_leave_event(event);
|
||||||
|
this._restoreDimmedLabel();
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_motion_event(event) {
|
||||||
|
this._resendEvent(event);
|
||||||
|
this._setDimmedLabel();
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_button_press_event(event) {
|
||||||
|
this._resendEvent(event);
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_button_release_event(event) {
|
||||||
|
this._resendEvent(event);
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
})
|
@ -1,15 +1,11 @@
|
|||||||
import Clutter from 'gi://Clutter'
|
|
||||||
import Gio from 'gi://Gio'
|
import Gio from 'gi://Gio'
|
||||||
import Meta from 'gi://Meta'
|
import Meta from 'gi://Meta'
|
||||||
import Shell from 'gi://Shell'
|
import Shell from 'gi://Shell'
|
||||||
import St from 'gi://St'
|
|
||||||
|
|
||||||
import * as Main from '../main.js';
|
import * as Main from '../main.js';
|
||||||
import * as RealmIndicator from './realmIndicator.js';
|
import * as RealmIndicator from './realmIndicator.js';
|
||||||
import * as RealmSwitcher from './realmSwitcher.js';
|
import * as RealmSwitcher from './realmSwitcher.js';
|
||||||
import * as Lightbox from '../lightbox.js';
|
import * as RealmLabels from './realmLabels.js';
|
||||||
import * as RealmSearchProvider from './realmSearchProvider.js';
|
|
||||||
import * as RealmWindowFrame from './realmWindowFrame.js';
|
|
||||||
|
|
||||||
export const RealmManager = class {
|
export const RealmManager = class {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -39,17 +35,20 @@ export const RealmManager = class {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this._switchAnimation = new RealmSwitcher.ContextSwitchAnimationController(this._realmIndicator);
|
this._switchAnimation = new RealmSwitcher.ContextSwitchAnimationController(this._realmIndicator);
|
||||||
|
this.labelManager = new RealmLabels.RealmLabelManager();
|
||||||
|
}
|
||||||
|
|
||||||
if (Main.overview._overview) {
|
createRealmLabelForApp(app) {
|
||||||
this._searchResults = Main.overview._overview.controls._searchController._searchResults;
|
let realmName = app.get_realm_name();
|
||||||
this._searchProvider = new RealmSearchProvider.RealmSearchProvider();
|
if (this.labelManager.appIconLabelsEnabled() && realmName) {
|
||||||
this._searchProvider.createResultDisplay(this._searchResults);
|
return this.labelManager.createAppIconLabelForRealm(realmName);
|
||||||
this._searchResults._registerProvider(this._searchProvider);
|
|
||||||
} else {
|
} else {
|
||||||
log("Not creating search provider because Main.overview._overview does not exist");
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._frameManager = new RealmWindowFrame.WindowFrameManager();
|
appIconLabelsEnabled() {
|
||||||
|
return this.labelManager.appIconLabelsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
animateSwitch(from, to, onComplete) {
|
animateSwitch(from, to, onComplete) {
|
||||||
@ -61,5 +60,4 @@ export const RealmManager = class {
|
|||||||
if (!popup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
|
if (!popup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
|
||||||
popup.fadeAndDestroy();
|
popup.fadeAndDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,332 +0,0 @@
|
|||||||
import Clutter from 'gi://Clutter';
|
|
||||||
import Cogl from 'gi://Cogl';
|
|
||||||
import GObject from 'gi://GObject';
|
|
||||||
import Meta from 'gi://Meta';
|
|
||||||
import Shell from 'gi://Shell';
|
|
||||||
import St from 'gi://St';
|
|
||||||
|
|
||||||
export const WindowFrameManager = class WindowFrameManager {
|
|
||||||
constructor() {
|
|
||||||
this._realms = Shell.Realms.get_default();
|
|
||||||
let frames = this._realms.window_frames();
|
|
||||||
this._frame_effects = [];
|
|
||||||
|
|
||||||
global.window_manager.connect('map', this._handleWindowMap.bind(this));
|
|
||||||
global.workspace_manager.connect('context-window-moved', this._onContextWindowMoved.bind(this));
|
|
||||||
global.workspace_manager.connect('context-removed', this._onContextRemoved.bind(this));
|
|
||||||
frames.connect('realm-frame-colors-changed', this._onFrameColorsChanged.bind(this));
|
|
||||||
|
|
||||||
this.trackWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onContextWindowMoved(workspaceManager, window) {
|
|
||||||
let actor = window.get_compositor_private();
|
|
||||||
if (actor) {
|
|
||||||
this.handleWindow(actor);
|
|
||||||
}
|
|
||||||
return Clutter.EVENT_PROPAGATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleWindowMap(shellwm, actor) {
|
|
||||||
this.handleWindow(actor);
|
|
||||||
return Clutter.EVENT_PROPAGATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onContextRemoved(workspaceManager, id) {
|
|
||||||
this.trackWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onFrameColorsChanged(realms) {
|
|
||||||
this.trackWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
trackWindows() {
|
|
||||||
var actors = global.get_window_actors();
|
|
||||||
actors.forEach(a => this.handleWindow(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleWindow(actor) {
|
|
||||||
let win = actor.metaWindow;
|
|
||||||
let win_id = win.get_stable_sequence();
|
|
||||||
let effect = this._frame_effects[win_id];
|
|
||||||
|
|
||||||
let frames = this._realms.window_frames();
|
|
||||||
|
|
||||||
if (frames.has_frame(win) && frames.is_frame_enabled(win)) {
|
|
||||||
let color = frames.color_for_window(win);
|
|
||||||
|
|
||||||
if (effect) {
|
|
||||||
effect.setColor(color);
|
|
||||||
} else {
|
|
||||||
let label = frames.label_for_window(win);
|
|
||||||
effect = new RealmFrameEffect(actor, color, label);
|
|
||||||
this._frame_effects[win_id] = effect;
|
|
||||||
}
|
|
||||||
} else if (effect) {
|
|
||||||
effect.removeEffect(actor);
|
|
||||||
this._frame_effects[win_id] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const RealmFrameEffect = GObject.registerClass(
|
|
||||||
class RealmFrameEffect extends Clutter.Effect {
|
|
||||||
_init(actor, color, label_text) {
|
|
||||||
super._init();
|
|
||||||
this._frame_width = 2;
|
|
||||||
this._pipeline = null;
|
|
||||||
this._color = color;
|
|
||||||
this._label_on_top = true;
|
|
||||||
this._label = null;
|
|
||||||
this._label_text = label_text;
|
|
||||||
|
|
||||||
if (label_text) {
|
|
||||||
this._updateLabel(actor.metaWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._sizeChangedId = actor.metaWindow.connect('size-changed', window => {
|
|
||||||
this._updateLabel(window);
|
|
||||||
});
|
|
||||||
|
|
||||||
actor.add_effect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeEffect(actor) {
|
|
||||||
if (this._label) {
|
|
||||||
actor.remove_child(this._label);
|
|
||||||
this._label = null;
|
|
||||||
}
|
|
||||||
if (this._sizeChangedId) {
|
|
||||||
let win = actor.metaWindow;
|
|
||||||
win.disconnect(this._sizeChangedId);
|
|
||||||
this._sizeChangedId = 0;
|
|
||||||
}
|
|
||||||
actor.remove_effect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_createLabel(actor, label_text) {
|
|
||||||
let label = new St.Label({
|
|
||||||
style_class: 'realm-frame-label',
|
|
||||||
z_position: 1.0,
|
|
||||||
|
|
||||||
});
|
|
||||||
label.set_text(' '+label_text+' ');
|
|
||||||
actor.add_child(label);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateLabel(window) {
|
|
||||||
if (!this._label_text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.is_fullscreen()) {
|
|
||||||
if (this._label) {
|
|
||||||
let actor = window.get_compositor_private();
|
|
||||||
actor.remove_child(this._label);
|
|
||||||
this._label = null;
|
|
||||||
}
|
|
||||||
} else if (!this._label) {
|
|
||||||
let actor = window.get_compositor_private();
|
|
||||||
this._label = this._createLabel(actor, this._label_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._label) {
|
|
||||||
this._updateLabelPosition(window);
|
|
||||||
this._updateLabelColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateLabelPosition(window) {
|
|
||||||
|
|
||||||
if (!this._label_height) {
|
|
||||||
// If we scale the text, the reported size of the label will not be the value we need so
|
|
||||||
// save the initial value.
|
|
||||||
this._label_height = this._label.get_height();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let maximized = window.is_fullscreen() === true || // Fullscreen
|
|
||||||
[Meta.MaximizeFlags.BOTH, Meta.MaximizeFlags.VERTICAL].includes(window.get_maximized()); // Maximized
|
|
||||||
|
|
||||||
this._label_on_top = !maximized;
|
|
||||||
|
|
||||||
let frame_rect = window.get_frame_rect();
|
|
||||||
let buffer_rect = window.get_buffer_rect();
|
|
||||||
|
|
||||||
let offsetX = frame_rect.x - buffer_rect.x;
|
|
||||||
let offsetY = frame_rect.y - buffer_rect.y;
|
|
||||||
|
|
||||||
|
|
||||||
if (window.get_client_type() === Meta.WindowClientType.WAYLAND) {
|
|
||||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
|
||||||
if (scaleFactor !== 1) {
|
|
||||||
offsetX = offsetX / scaleFactor;
|
|
||||||
this._label.set_style(`font-size: ${12 / scaleFactor}pt;`);
|
|
||||||
}
|
|
||||||
offsetX -= 1;
|
|
||||||
offsetY -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If label is on top and there is enough space above title bar move position up by label height
|
|
||||||
if (this._label_on_top && this._label_height <= offsetY) {
|
|
||||||
offsetY -= this._label_height;
|
|
||||||
} else if (maximized) {
|
|
||||||
offsetX = 0;
|
|
||||||
offsetY = 0;
|
|
||||||
}
|
|
||||||
this._label.set_position(offsetX, offsetY);
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateLabelColor() {
|
|
||||||
let fg = new Clutter.Color({
|
|
||||||
red: 0,
|
|
||||||
green: 0,
|
|
||||||
blue: 0,
|
|
||||||
alpha: 96,
|
|
||||||
});
|
|
||||||
|
|
||||||
let bg = this._color.copy();
|
|
||||||
|
|
||||||
if (this._label_on_top) {
|
|
||||||
bg.alpha = 100;
|
|
||||||
} else {
|
|
||||||
bg.alpha = 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
let clutter_text = this._label.get_clutter_text();
|
|
||||||
clutter_text.set_color(fg);
|
|
||||||
clutter_text.set_background_color(bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setColor(color) {
|
|
||||||
if (this._color && this._color.equal(color)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._color = color;
|
|
||||||
this.setPipelineColor();
|
|
||||||
if (this._label) {
|
|
||||||
this._updateLabelColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setPipelineColor() {
|
|
||||||
if (!this._color || !this._pipeline) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let s = this._color.to_string();
|
|
||||||
|
|
||||||
let cogl_color = new Cogl.Color();
|
|
||||||
cogl_color.init_from_4f(
|
|
||||||
this._color.red / 255.0,
|
|
||||||
this._color.green / 255.0,
|
|
||||||
this._color.blue / 255.0,
|
|
||||||
0xc4 / 255.0);
|
|
||||||
this._pipeline.set_color(cogl_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
_calculate_frame_box(window, allocation) {
|
|
||||||
let frame_rect = window.get_frame_rect();
|
|
||||||
let buffer_rect = window.get_buffer_rect();
|
|
||||||
|
|
||||||
let offsetX = frame_rect.x - buffer_rect.x;
|
|
||||||
let offsetY = frame_rect.y - buffer_rect.y;
|
|
||||||
|
|
||||||
let top = offsetY - 3;
|
|
||||||
let bottom = offsetY - 1;
|
|
||||||
let left = offsetX - 3;
|
|
||||||
let right = offsetX - 1;
|
|
||||||
|
|
||||||
let wayland = window.get_client_type() == Meta.WindowClientType.WAYLAND;
|
|
||||||
|
|
||||||
if (wayland) {
|
|
||||||
bottom += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
let fw = this._frame_width;
|
|
||||||
|
|
||||||
|
|
||||||
switch (window.get_maximized()) {
|
|
||||||
case Meta.MaximizeFlags.BOTH:
|
|
||||||
top += fw;
|
|
||||||
right += fw;
|
|
||||||
bottom += fw - (wayland ? 5 : 0);
|
|
||||||
left += fw;
|
|
||||||
break;
|
|
||||||
case Meta.MaximizeFlags.HORIZONTAL:
|
|
||||||
right += fw;
|
|
||||||
left += fw;
|
|
||||||
break;
|
|
||||||
case Meta.MaximizeFlags.VERTICAL:
|
|
||||||
top += fw;
|
|
||||||
bottom += fw;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.is_fullscreen()) {
|
|
||||||
top += 3;
|
|
||||||
right += 2;
|
|
||||||
bottom -= (wayland ? 3 : 0);
|
|
||||||
left += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wayland && !window.decorated && !window.is_fullscreen() && (window.get_maximized() !== Meta.MaximizeFlags.BOTH)) {
|
|
||||||
bottom += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
let x = left;
|
|
||||||
let y = top + fw;
|
|
||||||
let w = allocation.get_width() - (right + left);
|
|
||||||
let h = allocation.get_height() - (bottom + top + fw);
|
|
||||||
|
|
||||||
return [x, y, w, h];
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_rect(node, x, y, width, height) {
|
|
||||||
const box = new Clutter.ActorBox();
|
|
||||||
box.set_origin(x, y);
|
|
||||||
box.set_size(width, height);
|
|
||||||
node.add_rectangle(box);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_hline(node, x, y, width, width_factor = 1) {
|
|
||||||
this.draw_rect(node, x, y, width, this._frame_width * width_factor);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_vline(node, x, y, height, width_factor = 1) {
|
|
||||||
this.draw_rect(node, x, y, this._frame_width * width_factor, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
vfunc_paint_node(node, ctx) {
|
|
||||||
let actor = this.get_actor();
|
|
||||||
|
|
||||||
const actorNode = new Clutter.ActorNode(actor, -1);
|
|
||||||
node.add_child(actorNode);
|
|
||||||
|
|
||||||
if (!this._pipeline) {
|
|
||||||
let framebuffer = ctx.get_framebuffer();
|
|
||||||
let coglContext = framebuffer.get_context();
|
|
||||||
this._pipeline = Cogl.Pipeline.new(coglContext);
|
|
||||||
this.setPipelineColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
const pipelineNode = new Clutter.PipelineNode(this._pipeline);
|
|
||||||
pipelineNode.set_name('Realm Frame');
|
|
||||||
node.add_child(pipelineNode);
|
|
||||||
|
|
||||||
let [x, y, width, height] = this._calculate_frame_box(actor.metaWindow, actor.get_allocation_box());
|
|
||||||
|
|
||||||
// Top
|
|
||||||
this.draw_hline(pipelineNode, x, y, width, 2);
|
|
||||||
|
|
||||||
// Right
|
|
||||||
this.draw_vline(pipelineNode, x + width, y, height);
|
|
||||||
|
|
||||||
// Bottom
|
|
||||||
this.draw_hline(pipelineNode, x, y + height, width);
|
|
||||||
|
|
||||||
// Left
|
|
||||||
this.draw_vline(pipelineNode, x, y, height);
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,7 +1,7 @@
|
|||||||
import GObject from 'gi://GObject';
|
|
||||||
import Shell from 'gi://Shell';
|
import Shell from 'gi://Shell';
|
||||||
|
|
||||||
import * as PopupMenu from '../popupMenu.js';
|
import * as PopupMenu from '../popupMenu.js';
|
||||||
|
import * as Main from '../main.js';
|
||||||
|
|
||||||
function _windowAppId(window) {
|
function _windowAppId(window) {
|
||||||
const tracker = Shell.WindowTracker.get_default();
|
const tracker = Shell.WindowTracker.get_default();
|
||||||
@ -79,22 +79,20 @@ function windowContextRealmName(window) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function enableFrameItem(window) {
|
export function enableLabelItem(window) {
|
||||||
const realms = Shell.Realms.get_default();
|
const labelManager = Main.realmManager.labelManager;
|
||||||
const frames = realms.window_frames();
|
|
||||||
if (!frames.has_frame(window)) {
|
if (!labelManager.windowNeedsLabel(window)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let enabled = frames.is_frame_enabled(window);
|
let enabled = labelManager.getWindowLabelEnabled(window);
|
||||||
let item = new PopupMenu.PopupMenuItem("Display colored window frame");
|
let item = new PopupMenu.PopupMenuItem("Display realm label on window");
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
item.setOrnament(PopupMenu.Ornament.CHECK);
|
item.setOrnament(PopupMenu.Ornament.CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
item.connect('activate', () => {
|
item.connect('activate', () => {
|
||||||
let realms = Shell.Realms.get_default();
|
Main.realmManager.labelManager.setWindowLabelEnabled(window, !enabled);
|
||||||
const frames = realms.window_frames();
|
|
||||||
frames.set_frame_enabled(window, !enabled);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
@ -31,7 +31,7 @@ export class WindowMenu extends PopupMenu.PopupMenu {
|
|||||||
|
|
||||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem(s));
|
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem(s));
|
||||||
|
|
||||||
item = RealmWindowMenu.enableFrameItem(window);
|
item = RealmWindowMenu.enableLabelItem(window);
|
||||||
if (item) {
|
if (item) {
|
||||||
this.addMenuItem(item);
|
this.addMenuItem(item);
|
||||||
}
|
}
|
||||||
|
@ -160,8 +160,6 @@ libshell_sources = [
|
|||||||
'shell-polkit-authentication-agent.h',
|
'shell-polkit-authentication-agent.h',
|
||||||
'shell-realm-item.c',
|
'shell-realm-item.c',
|
||||||
'shell-realm-item.h',
|
'shell-realm-item.h',
|
||||||
'shell-realms-window-frames.c',
|
|
||||||
'shell-realms-window-frames.h',
|
|
||||||
'shell-realms.c',
|
'shell-realms.c',
|
||||||
'shell-realms.h',
|
'shell-realms.h',
|
||||||
'shell-realm-tracker.c',
|
'shell-realm-tracker.c',
|
||||||
|
@ -83,6 +83,8 @@ struct _ShellApp
|
|||||||
|
|
||||||
ShellAppRunningState *running_state;
|
ShellAppRunningState *running_state;
|
||||||
|
|
||||||
|
char *realm_name;
|
||||||
|
|
||||||
char *window_id_string;
|
char *window_id_string;
|
||||||
char *name_collation_key;
|
char *name_collation_key;
|
||||||
};
|
};
|
||||||
@ -177,6 +179,43 @@ shell_app_get_id (ShellApp *app)
|
|||||||
return app->window_id_string;
|
return app->window_id_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
shell_app_realm_name_from_app (ShellApp *app)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!app->info) {
|
||||||
|
return g_strdup("??");
|
||||||
|
}
|
||||||
|
const char *app_id = g_app_info_get_id (G_APP_INFO (app->info));
|
||||||
|
|
||||||
|
if (!app_id) {
|
||||||
|
return g_strdup("??");
|
||||||
|
}
|
||||||
|
|
||||||
|
char *realm_name = NULL;
|
||||||
|
char **split = g_strsplit(app_id, ".", 2);
|
||||||
|
if (g_str_has_prefix(split[0], "realm-")) {
|
||||||
|
realm_name = g_strdup(split[0] + 6);
|
||||||
|
} else {
|
||||||
|
realm_name = g_strdup("Citadel");
|
||||||
|
}
|
||||||
|
g_strfreev(split);
|
||||||
|
return realm_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
shell_app_get_realm_name (ShellApp *app)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!app->realm_name) {
|
||||||
|
app->realm_name = shell_app_realm_name_from_app(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
return app->realm_name;
|
||||||
|
}
|
||||||
|
|
||||||
static MetaWindow *
|
static MetaWindow *
|
||||||
window_backed_app_get_window (ShellApp *app)
|
window_backed_app_get_window (ShellApp *app)
|
||||||
{
|
{
|
||||||
@ -894,6 +933,7 @@ _shell_app_set_app_info (ShellApp *app,
|
|||||||
g_set_object (&app->info, info);
|
g_set_object (&app->info, info);
|
||||||
|
|
||||||
g_clear_pointer (&app->name_collation_key, g_free);
|
g_clear_pointer (&app->name_collation_key, g_free);
|
||||||
|
g_clear_pointer (&app->realm_name, g_free);
|
||||||
if (app->info)
|
if (app->info)
|
||||||
app->name_collation_key = g_utf8_collate_key (shell_app_get_name (app), -1);
|
app->name_collation_key = g_utf8_collate_key (shell_app_get_name (app), -1);
|
||||||
}
|
}
|
||||||
@ -1781,6 +1821,8 @@ shell_app_finalize (GObject *object)
|
|||||||
{
|
{
|
||||||
ShellApp *app = SHELL_APP (object);
|
ShellApp *app = SHELL_APP (object);
|
||||||
|
|
||||||
|
g_free(app->realm_name);
|
||||||
|
|
||||||
g_free (app->window_id_string);
|
g_free (app->window_id_string);
|
||||||
|
|
||||||
g_free (app->name_collation_key);
|
g_free (app->name_collation_key);
|
||||||
|
@ -26,6 +26,8 @@ typedef enum {
|
|||||||
|
|
||||||
const char *shell_app_get_id (ShellApp *app);
|
const char *shell_app_get_id (ShellApp *app);
|
||||||
|
|
||||||
|
const char *shell_app_get_realm_name (ShellApp *app);
|
||||||
|
|
||||||
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
|
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
|
||||||
|
|
||||||
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
|
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#define __SHELL_REALMS_PRIVATE_H__
|
#define __SHELL_REALMS_PRIVATE_H__
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include "shell-realms.h"
|
#include "shell-realms.h"
|
||||||
#include "shell-realms-window-frames.h"
|
|
||||||
|
|
||||||
#define CITADEL_REALM_TAG "[CITADEL]"
|
#define CITADEL_REALM_TAG "[CITADEL]"
|
||||||
|
|
||||||
|
@ -1,390 +0,0 @@
|
|||||||
#include "shell-realms-window-frames.h"
|
|
||||||
#include "shell-realms.h"
|
|
||||||
|
|
||||||
#define CITADEL_SETTINGS_SCHEMA "com.subgraph.citadel"
|
|
||||||
#define FRAME_COLOR_LIST_KEY "frame-color-list"
|
|
||||||
#define REALM_FRAME_COLORS_KEY "realm-frame-colors"
|
|
||||||
|
|
||||||
#define REALM_FRAME_ALPHA 200
|
|
||||||
|
|
||||||
struct _ShellRealmsWindowFrames {
|
|
||||||
GObject parent;
|
|
||||||
ShellRealms *realms;
|
|
||||||
GSettings *settings;
|
|
||||||
GHashTable *realm_frame_colors;
|
|
||||||
GList *default_colors;
|
|
||||||
GList *frame_disabled_windows;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (ShellRealmsWindowFrames, shell_realms_window_frames, G_TYPE_OBJECT);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
REALM_FRAME_COLORS_CHANGED,
|
|
||||||
LAST_SIGNAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static guint shell_realms_window_frames_signals [LAST_SIGNAL] = { 0 };
|
|
||||||
|
|
||||||
ShellRealmsWindowFrames *
|
|
||||||
shell_realms_window_frames_new (ShellRealms *realms)
|
|
||||||
{
|
|
||||||
ShellRealmsWindowFrames *frames;
|
|
||||||
|
|
||||||
frames = g_object_new (SHELL_TYPE_REALMS_WINDOW_FRAMES, NULL);
|
|
||||||
|
|
||||||
frames->realms = realms;
|
|
||||||
return frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_realms_window_frames_process_color (ShellRealmsWindowFrames *frames, const char *entry)
|
|
||||||
{
|
|
||||||
ClutterColor *rgba = clutter_color_alloc();
|
|
||||||
|
|
||||||
gchar **split = g_strsplit (entry, ":", -1);
|
|
||||||
|
|
||||||
if (g_strv_length (split) != 2) {
|
|
||||||
g_warning ("ShellRealmsWindowFrames: Unable to parse realm-frame-colors entry: %s", entry);
|
|
||||||
clutter_color_free(rgba);
|
|
||||||
g_strfreev (split);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!clutter_color_from_string(rgba, split[1])) {
|
|
||||||
g_warning ("ShellRealmsWindowFrames: Failed to parse RGBA component of realm frame color entry: %s", entry);
|
|
||||||
clutter_color_free(rgba);
|
|
||||||
} else {
|
|
||||||
g_hash_table_insert (frames->realm_frame_colors, g_strdup (split[0]), rgba);
|
|
||||||
}
|
|
||||||
g_strfreev (split);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
load_realm_frame_colors (ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
guint n_entries, i;
|
|
||||||
char **entries;
|
|
||||||
|
|
||||||
entries = g_settings_get_strv (frames->settings, REALM_FRAME_COLORS_KEY);
|
|
||||||
n_entries = g_strv_length (entries);
|
|
||||||
|
|
||||||
for (i = 0; i < n_entries; i++) {
|
|
||||||
shell_realms_window_frames_process_color (frames, entries[i]);
|
|
||||||
}
|
|
||||||
g_strfreev (entries);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_realm_frame_colors_changed (GSettings *settings, const gchar *key, ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
load_realm_frame_colors (frames);
|
|
||||||
g_signal_emit (frames, shell_realms_window_frames_signals[REALM_FRAME_COLORS_CHANGED], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
load_default_colors (ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
guint n_entries, i;
|
|
||||||
char **entries;
|
|
||||||
ClutterColor *rgba = clutter_color_alloc();
|
|
||||||
|
|
||||||
entries = g_settings_get_strv (frames->settings, FRAME_COLOR_LIST_KEY);
|
|
||||||
n_entries = g_strv_length (entries);
|
|
||||||
|
|
||||||
g_clear_list (&frames->default_colors, (GDestroyNotify) clutter_color_free);
|
|
||||||
|
|
||||||
for (i = 0; i < n_entries; i++) {
|
|
||||||
if (clutter_color_from_string(rgba, entries[i])) {
|
|
||||||
frames->default_colors = g_list_append (frames->default_colors, clutter_color_copy(rgba));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clutter_color_free(rgba);
|
|
||||||
g_strfreev (entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_frame_color_list_changed (GSettings *settings, const gchar *key, ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
load_default_colors (frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_realms_window_frames_init (ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
frames->settings = g_settings_new (CITADEL_SETTINGS_SCHEMA);
|
|
||||||
frames->realm_frame_colors = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) clutter_color_free);
|
|
||||||
frames->default_colors = NULL;
|
|
||||||
frames->frame_disabled_windows = NULL;
|
|
||||||
|
|
||||||
g_signal_connect (frames->settings,
|
|
||||||
"changed::" FRAME_COLOR_LIST_KEY,
|
|
||||||
G_CALLBACK(on_frame_color_list_changed),
|
|
||||||
frames);
|
|
||||||
|
|
||||||
g_signal_connect (frames->settings,
|
|
||||||
"changed::" REALM_FRAME_COLORS_KEY,
|
|
||||||
G_CALLBACK(on_realm_frame_colors_changed),
|
|
||||||
frames);
|
|
||||||
|
|
||||||
|
|
||||||
load_default_colors (frames);
|
|
||||||
load_realm_frame_colors (frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_realms_window_frames_finalize (GObject *obj)
|
|
||||||
{
|
|
||||||
ShellRealmsWindowFrames *frames = SHELL_REALMS_WINDOW_FRAMES (obj);
|
|
||||||
g_object_unref (frames->settings);
|
|
||||||
g_hash_table_destroy (frames->realm_frame_colors);
|
|
||||||
g_list_free_full (frames->default_colors, (GDestroyNotify) clutter_color_free);
|
|
||||||
g_list_free (frames->frame_disabled_windows);
|
|
||||||
G_OBJECT_CLASS (shell_realms_window_frames_parent_class)->finalize (obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_realms_window_frames_class_init (ShellRealmsWindowFramesClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
object_class->finalize = shell_realms_window_frames_finalize;
|
|
||||||
|
|
||||||
shell_realms_window_frames_signals[REALM_FRAME_COLORS_CHANGED] =
|
|
||||||
g_signal_new ("realm-frame-colors-changed",
|
|
||||||
G_TYPE_FROM_CLASS(klass),
|
|
||||||
G_SIGNAL_RUN_LAST,
|
|
||||||
0,
|
|
||||||
NULL, NULL, NULL,
|
|
||||||
G_TYPE_NONE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
disabled_list_contains (ShellRealmsWindowFrames *frames, guint32 window_id)
|
|
||||||
{
|
|
||||||
return g_list_find (frames->frame_disabled_windows, GUINT_TO_POINTER(window_id)) != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
remove_from_disabled_list (ShellRealmsWindowFrames *frames, guint32 window_id)
|
|
||||||
{
|
|
||||||
if (disabled_list_contains (frames, window_id)) {
|
|
||||||
frames->frame_disabled_windows = g_list_remove (frames->frame_disabled_windows, GUINT_TO_POINTER(window_id));
|
|
||||||
g_signal_emit (frames, shell_realms_window_frames_signals[REALM_FRAME_COLORS_CHANGED], 0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
add_to_disabled_list (ShellRealmsWindowFrames *frames, guint32 window_id)
|
|
||||||
{
|
|
||||||
if (!disabled_list_contains (frames, window_id)) {
|
|
||||||
frames->frame_disabled_windows = g_list_append (frames->frame_disabled_windows, GUINT_TO_POINTER(window_id));
|
|
||||||
g_signal_emit (frames, shell_realms_window_frames_signals[REALM_FRAME_COLORS_CHANGED], 0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
color_compare (gconstpointer c1, gconstpointer c2) {
|
|
||||||
return clutter_color_equal(c1, c2) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClutterColor *
|
|
||||||
allocate_color (ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
guint n_colors = g_list_length (frames->default_colors);
|
|
||||||
|
|
||||||
// 1) No default colors? return a built in color
|
|
||||||
if (n_colors == 0) {
|
|
||||||
return clutter_color_new(153, 193, 241, REALM_FRAME_ALPHA);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) No default colors? Find first color on default color list that isn't used already
|
|
||||||
GList *used_colors = g_hash_table_get_values (frames->realm_frame_colors);
|
|
||||||
for (GList *iter = frames->default_colors; iter; iter = iter->next) {
|
|
||||||
ClutterColor *rgba = iter->data;
|
|
||||||
if (!g_list_find_custom (used_colors, rgba, color_compare)) {
|
|
||||||
return rgba;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_list_free (used_colors);
|
|
||||||
|
|
||||||
// 3) Choose a random element of the default list
|
|
||||||
guint index = (guint) g_random_int_range (0, (gint32) n_colors);
|
|
||||||
return g_list_nth_data (frames->default_colors, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_realms_window_frames_store_colors (ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key, value;
|
|
||||||
|
|
||||||
GPtrArray *entries = g_ptr_array_new_with_free_func (g_free);
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, frames->realm_frame_colors);
|
|
||||||
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
||||||
gchar *name = key;
|
|
||||||
ClutterColor *rgba = value;
|
|
||||||
char *rgba_str = clutter_color_to_string(rgba);
|
|
||||||
gchar *entry = g_strconcat (name, ":", rgba_str, NULL);
|
|
||||||
g_ptr_array_add (entries, entry);
|
|
||||||
g_free (rgba_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_ptr_array_sort (entries, (GCompareFunc) g_strcmp0);
|
|
||||||
g_ptr_array_add (entries, NULL);
|
|
||||||
g_settings_set_strv (frames->settings, REALM_FRAME_COLORS_KEY, (const gchar * const *) entries->pdata);
|
|
||||||
|
|
||||||
g_ptr_array_unref (entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
shell_realms_window_frames_realm_name_for_window (ShellRealmsWindowFrames *frames, MetaWindow *window)
|
|
||||||
{
|
|
||||||
|
|
||||||
ShellRealmItem *realm = shell_realms_realm_by_window (frames->realms, window);
|
|
||||||
|
|
||||||
if (realm) {
|
|
||||||
return shell_realm_item_get_realm_name (realm);
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_window_unmanaged (MetaWindow *window, ShellRealmsWindowFrames *frames)
|
|
||||||
{
|
|
||||||
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_unmanaged), frames);
|
|
||||||
guint32 id = meta_window_get_stable_sequence (window);
|
|
||||||
remove_from_disabled_list (frames, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_ignored_window (MetaWindow *window)
|
|
||||||
{
|
|
||||||
switch (meta_window_get_window_type (window)) {
|
|
||||||
case META_WINDOW_MENU:
|
|
||||||
case META_WINDOW_TOOLTIP:
|
|
||||||
case META_WINDOW_POPUP_MENU:
|
|
||||||
case META_WINDOW_DROPDOWN_MENU:
|
|
||||||
return TRUE;
|
|
||||||
default:
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_realms_window_frames_is_frame_enabled:
|
|
||||||
* @frames: a #ShellRealmsWindowFrames instance
|
|
||||||
* @window: a #MetaWindow
|
|
||||||
*
|
|
||||||
* Return #TRUE if frame has not been disabled for this window.
|
|
||||||
*
|
|
||||||
* Returns: #TRUE if frame has not been disabled for this window.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
shell_realms_window_frames_is_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window)
|
|
||||||
{
|
|
||||||
guint32 id = meta_window_get_stable_sequence (window);
|
|
||||||
return !disabled_list_contains (frames, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_realms_window_frames_has_frame:
|
|
||||||
* @frames: a #ShellRealmsWindowFrames instance
|
|
||||||
* @window: a #MetaWindow
|
|
||||||
*
|
|
||||||
* Return #TRUE if this window needs a frame.
|
|
||||||
*
|
|
||||||
* Returns: #TRUE if a frame should be drawn for this window.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
shell_realms_window_frames_has_frame (ShellRealmsWindowFrames *frames, MetaWindow *window)
|
|
||||||
{
|
|
||||||
return !is_ignored_window (window) && shell_realms_is_foreign_window (frames->realms, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_realms_window_frames_set_frame_enabled:
|
|
||||||
* @frames: a #ShellRealmsWindowFrames instance
|
|
||||||
* @window: a #MetaWindow
|
|
||||||
* @enabled: Set to #FALSE to disable drawing frame for this window
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
shell_realms_window_frames_set_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window, gboolean enabled)
|
|
||||||
{
|
|
||||||
guint32 id = meta_window_get_stable_sequence (window);
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
if (remove_from_disabled_list (frames, id)) {
|
|
||||||
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_unmanaged), frames);
|
|
||||||
}
|
|
||||||
} else if (add_to_disabled_list (frames, id)) {
|
|
||||||
g_signal_connect_object (window, "unmanaged", G_CALLBACK(on_window_unmanaged), frames, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_realms_window_frames_color_for_window:
|
|
||||||
* @frames: a #ShellRealmsWindowFrames instance
|
|
||||||
* @window: a #MetaWindow
|
|
||||||
*
|
|
||||||
* Returns a color to use for painting window frame.
|
|
||||||
*
|
|
||||||
* Return value: (transfer full) (nullable): The frame color or %NULL if no frame should be drawn.
|
|
||||||
*/
|
|
||||||
ClutterColor *
|
|
||||||
shell_realms_window_frames_color_for_window (ShellRealmsWindowFrames *frames, MetaWindow *window)
|
|
||||||
{
|
|
||||||
if (!shell_realms_window_frames_has_frame (frames, window)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gchar *name = shell_realms_window_frames_realm_name_for_window (frames, window);
|
|
||||||
|
|
||||||
if (name == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClutterColor *rgba = g_hash_table_lookup (frames->realm_frame_colors, name);
|
|
||||||
|
|
||||||
if (!rgba) {
|
|
||||||
rgba = allocate_color (frames);
|
|
||||||
g_hash_table_insert (frames->realm_frame_colors, g_strdup(name), rgba);
|
|
||||||
shell_realms_window_frames_store_colors (frames);
|
|
||||||
}
|
|
||||||
ClutterColor *copy = clutter_color_copy(rgba);
|
|
||||||
copy->alpha = REALM_FRAME_ALPHA;
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_realms_window_frames_label_for_window:
|
|
||||||
* @frames: a #ShellRealmsWindowFrames instance
|
|
||||||
* @window: a #MetaWindow
|
|
||||||
*
|
|
||||||
* Return the label text for window if the window requires a frame.
|
|
||||||
*
|
|
||||||
* Return value: (transfer none) (nullable): The label text or %NULL if no label should be displayed
|
|
||||||
*/
|
|
||||||
const gchar *
|
|
||||||
shell_realms_window_frames_label_for_window (ShellRealmsWindowFrames *frames, MetaWindow *window)
|
|
||||||
{
|
|
||||||
if (!shell_realms_window_frames_has_frame (frames, window)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (meta_window_get_window_type (window) != META_WINDOW_NORMAL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shell_realms_is_citadel_window (frames->realms, window)) {
|
|
||||||
return "Citadel";
|
|
||||||
} else {
|
|
||||||
return shell_realms_window_frames_realm_name_for_window (frames, window);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
#ifndef __SHELL_REALMS_WINDOW_FRAMES_H__
|
|
||||||
#define __SHELL_REALMS_WINDOW_FRAMES_H__
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
#include <gdk/gdk.h>
|
|
||||||
#include <meta/window.h>
|
|
||||||
|
|
||||||
#define SHELL_TYPE_REALMS_WINDOW_FRAMES (shell_realms_window_frames_get_type())
|
|
||||||
G_DECLARE_FINAL_TYPE (ShellRealmsWindowFrames, shell_realms_window_frames, SHELL, REALMS_WINDOW_FRAMES, GObject)
|
|
||||||
|
|
||||||
typedef struct _ShellRealms ShellRealms;
|
|
||||||
|
|
||||||
ShellRealmsWindowFrames *shell_realms_window_frames_new (ShellRealms *realms);
|
|
||||||
gboolean shell_realms_window_frames_has_frame (ShellRealmsWindowFrames *frames, MetaWindow *window);
|
|
||||||
gboolean shell_realms_window_frames_is_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window);
|
|
||||||
void shell_realms_window_frames_set_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window, gboolean enabled);
|
|
||||||
ClutterColor *shell_realms_window_frames_color_for_window (ShellRealmsWindowFrames *frames, MetaWindow *window);
|
|
||||||
const gchar *shell_realms_window_frames_label_for_window (ShellRealmsWindowFrames *frames, MetaWindow *window);
|
|
||||||
|
|
||||||
#endif // __SHELL_REALMS_WINDOW_FRAMES_H__
|
|
@ -11,7 +11,6 @@ struct _ShellRealms {
|
|||||||
GHashTable *realms;
|
GHashTable *realms;
|
||||||
GList *running_realms;
|
GList *running_realms;
|
||||||
ShellRealmItem *current_realm;
|
ShellRealmItem *current_realm;
|
||||||
ShellRealmsWindowFrames *frames;
|
|
||||||
MetaWorkspaceContext *detached_context;
|
MetaWorkspaceContext *detached_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -185,20 +184,6 @@ shell_realms_get_all_realms (ShellRealms *realms)
|
|||||||
return g_hash_table_get_values (realms->realms);
|
return g_hash_table_get_values (realms->realms);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_realms_window_frames:
|
|
||||||
* @realms: the #ShellRealms instance
|
|
||||||
*
|
|
||||||
* Returns the window frames manager.
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): a #ShellRealmsWindowFrames instance
|
|
||||||
*/
|
|
||||||
ShellRealmsWindowFrames *
|
|
||||||
shell_realms_window_frames (ShellRealms *realms)
|
|
||||||
{
|
|
||||||
return realms->frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
shell_realms_is_on_running_list (ShellRealms *realms, ShellRealmItem *item)
|
shell_realms_is_on_running_list (ShellRealms *realms, ShellRealmItem *item)
|
||||||
{
|
{
|
||||||
@ -597,8 +582,6 @@ shell_realms_finalize (GObject *obj)
|
|||||||
realms->current_realm = NULL;
|
realms->current_realm = NULL;
|
||||||
g_list_free_full (realms->running_realms, g_object_unref);
|
g_list_free_full (realms->running_realms, g_object_unref);
|
||||||
g_hash_table_destroy (realms->realms);
|
g_hash_table_destroy (realms->realms);
|
||||||
g_object_unref (realms->frames);
|
|
||||||
realms->frames = NULL;
|
|
||||||
G_OBJECT_CLASS (shell_realms_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (shell_realms_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <meta/window.h>
|
#include <meta/window.h>
|
||||||
#include "shell-realm-item.h"
|
#include "shell-realm-item.h"
|
||||||
#include "shell-realms-window-frames.h"
|
|
||||||
|
|
||||||
#define SHELL_TYPE_REALMS (shell_realms_get_type())
|
#define SHELL_TYPE_REALMS (shell_realms_get_type())
|
||||||
G_DECLARE_FINAL_TYPE(ShellRealms, shell_realms, SHELL, REALMS, GObject)
|
G_DECLARE_FINAL_TYPE(ShellRealms, shell_realms, SHELL, REALMS, GObject)
|
||||||
@ -19,8 +18,6 @@ ShellRealmItem *shell_realms_realm_by_window (ShellRealms *realms, MetaWindow *w
|
|||||||
gboolean shell_realms_is_citadel_window (ShellRealms *realms, MetaWindow *window);
|
gboolean shell_realms_is_citadel_window (ShellRealms *realms, MetaWindow *window);
|
||||||
gboolean shell_realms_is_foreign_window (ShellRealms *realms, MetaWindow *window);
|
gboolean shell_realms_is_foreign_window (ShellRealms *realms, MetaWindow *window);
|
||||||
|
|
||||||
ShellRealmsWindowFrames *shell_realms_window_frames (ShellRealms *realms);
|
|
||||||
|
|
||||||
GList *shell_realms_get_running_realms (ShellRealms *realms);
|
GList *shell_realms_get_running_realms (ShellRealms *realms);
|
||||||
GList *shell_realms_get_all_realms (ShellRealms *realms);
|
GList *shell_realms_get_all_realms (ShellRealms *realms);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user