Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/com.github.amezin.ddterm.desktop.in.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Categories=GNOME;GTK;System;TerminalEmulator;
StartupWMClass=Com.github.amezin.ddterm
StartupNotify=true
DBusActivatable=true
SingleMainWindow=true
Actions=toggle;preferences;
OnlyShowIn=GNOME;
X-ExecArg=--
Expand Down
50 changes: 1 addition & 49 deletions ddterm/shell/appcontrol.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later

import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gio from 'gi://Gio';

Expand All @@ -11,54 +10,7 @@ import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import { Service } from './service.js';
import { WindowGeometry } from './geometry.js';
import { WindowMatch } from './windowmatch.js';

async function wait_timeout(message, timeout_ms, cancellable = null) {
await new Promise(resolve => {
const source = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout_ms, () => {
cancellable?.disconnect(cancel_handler);
resolve();
return GLib.SOURCE_REMOVE;
});

const cancel_handler = cancellable?.connect(() => {
GLib.Source.remove(source);
resolve();
});
});

cancellable?.set_error_if_cancelled();
throw GLib.Error.new_literal(Gio.io_error_quark(), Gio.IOErrorEnum.TIMED_OUT, message);
}

async function wait_property(object, property, predicate, cancellable = null) {
const result = await new Promise(resolve => {
let value = object[property];

if (predicate(value)) {
resolve(value);
return;
}

const handler = object.connect(`notify::${property}`, () => {
value = object[property];

if (!predicate(value))
return;

cancellable?.disconnect(cancel_handler);
object.disconnect(handler);
resolve(value);
});

const cancel_handler = cancellable?.connect(() => {
object.disconnect(handler);
resolve();
});
});

cancellable?.set_error_if_cancelled();
return result;
}
import { wait_timeout, wait_property } from '../util/promise.js';

export const AppControl = GObject.registerClass({
Properties: {
Expand Down
31 changes: 14 additions & 17 deletions ddterm/shell/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function create_panel_icon(settings, window_matcher, app_control, icon, gettext_

function install(extension, rollback) {
const installer = new Installer(extension.launcher_path);
installer.install();
const app_info = installer.install();

if (GObject.signal_lookup('shutdown', Shell.Global)) {
const shutdown_handler = global.connect('shutdown', () => {
Expand All @@ -161,6 +161,8 @@ function install(extension, rollback) {

installer.uninstall();
});

return app_info;
}

function bind_keys(settings, app_control, rollback) {
Expand Down Expand Up @@ -235,6 +237,8 @@ class EnabledExtension {
)
));

const app_info = install(this.extension, rollback);

this.notifications = new Notifications({
icon: this.symbolic_icon,
gettext_domain: this.extension,
Expand All @@ -247,7 +251,7 @@ class EnabledExtension {
this.service = new Service({
bus: Gio.DBus.session,
bus_name: APP_ID,
executable: this.extension.launcher_path,
app_info,
subprocess: this.extension.app_process,
});

Expand Down Expand Up @@ -283,19 +287,14 @@ class EnabledExtension {
});

this.service.connect('error', (service, ex) => {
const log_collector = service.subprocess?.log_collector;

if (!log_collector) {
this.notifications.show_error(ex);
return;
}

log_collector.collect().then(output => {
this.notifications.show_error(ex, output);
}).catch(ex2 => {
logError(ex2, 'Failed to collect logs');
this.notifications.show_error(ex);
});
(service.subprocess?.get_logs() ?? Promise.resolve()).then(
output => {
this.notifications.show_error(ex, output);
}, ex2 => {
logError(ex2, 'Failed to collect logs');
this.notifications.show_error(ex);
}
);
});

this.window_geometry = new WindowGeometry();
Expand Down Expand Up @@ -408,8 +407,6 @@ class EnabledExtension {
this.extension,
rollback
);

install(this.extension, rollback);
}

#set_skip_taskbar() {
Expand Down
37 changes: 29 additions & 8 deletions ddterm/shell/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ import GLib from 'gi://GLib';
import Gio from 'gi://Gio';
import Shell from 'gi://Shell';

import Gi from 'gi';

function try_require(namespace, version = undefined) {
try {
return Gi.require(namespace, version);
} catch (ex) {
logError(ex);
return null;
}
}

const GioUnix = GLib.check_version(2, 79, 2) === null ? try_require('GioUnix') : null;
const DesktopAppInfo = GioUnix?.DesktopAppInfo ?? Gio.DesktopAppInfo;

class File {
constructor(source_url, target_file, fallback_files = []) {
const [source_file] = GLib.filename_from_uri(
Expand All @@ -26,21 +40,24 @@ class File {
get_existing_content() {
for (const existing_file of [this.target_file, ...this.fallback_files]) {
try {
return Shell.get_file_contents_utf8_sync(existing_file);
return {
filename: existing_file,
content: Shell.get_file_contents_utf8_sync(existing_file),
};
} catch (ex) {
if (!ex.matches(GLib.file_error_quark(), GLib.FileError.NOENT))
logError(ex, `Can't read ${JSON.stringify(existing_file)}`);
}
}

return null;
return { filename: this.target_file, content: null };
}

install() {
const existing_content = this.get_existing_content();
const { filename, content } = this.get_existing_content();

if (this.content === existing_content)
return false;
if (this.content === content)
return { filename, changed: false };

GLib.mkdir_with_parents(
GLib.path_get_dirname(this.target_file),
Expand All @@ -56,7 +73,7 @@ class File {
0o600
);

return true;
return { filename: this.target_file, changed: true };
}

uninstall() {
Expand Down Expand Up @@ -109,9 +126,11 @@ export class Installer {
}

install() {
this.desktop_entry.install();
const dbus_service = this.dbus_service.install();
const desktop_entry = this.desktop_entry.install();
const app_info = DesktopAppInfo.new_from_filename(desktop_entry.filename);

if (this.dbus_service.install()) {
if (dbus_service.changed) {
Gio.DBus.session.call(
'org.freedesktop.DBus',
'/org/freedesktop/DBus',
Expand All @@ -125,6 +144,8 @@ export class Installer {
null
);
}

return app_info;
}

uninstall() {
Expand Down
Loading
Loading