summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfujiwarat <takao.fujiwara1@gmail.com>2022-07-19 22:58:09 +0900
committerfujiwarat <takao.fujiwara1@gmail.com>2022-07-19 22:58:09 +0900
commitab0d176477b17b1981879005846aaedc588f79cc (patch)
tree7b4fa88e4804ae86f29ed2ac2247cdc1bbfc4f28
parent79e446ec99691d62ec2110c728e69da4c889eee2 (diff)
downloadibus-ab0d176477b17b1981879005846aaedc588f79cc.tar.gz
tools: Enable ibus restart in GNOME desktop
If ibus-daemon is called via systemd, IBus restart API cannot restart ibus-daemon but just terminates it. Now ibus restart command checks the systemd avaiability and restart ibus-daemon via systemd. ibus start command is also added to launch ibus-daemon with systemd. BUG=https://github.com/ibus/ibus/issues/2407
-rw-r--r--po/ibus10.pot80
-rw-r--r--tools/Makefile.am3
-rw-r--r--tools/ibus.1.in30
-rw-r--r--tools/main.vala261
4 files changed, 330 insertions, 44 deletions
diff --git a/po/ibus10.pot b/po/ibus10.pot
index 3f9843dd..09c09be7 100644
--- a/po/ibus10.pot
+++ b/po/ibus10.pot
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ibus 1.5.26\n"
"Report-Msgid-Bugs-To: https://github.com/ibus/ibus/issues\n"
-"POT-Creation-Date: 2022-06-20 20:30+0900\n"
-"PO-Revision-Date: 2022-06-20 20:30+0900\n"
+"POT-Creation-Date: 2022-07-06 22:08+0900\n"
+"PO-Revision-Date: 2022-07-06 22:08+0900\n"
"Last-Translator: Takao Fujiwara <takao.fujiwara1@gmail.com>\n"
"Language-Team: Source\n"
"Language: \n"
@@ -3099,129 +3099,145 @@ msgstr ""
msgid "Supplementary Private Use Area-B"
msgstr ""
-#: tools/main.vala:51
+#: tools/main.vala:182
msgid "List engine name only"
msgstr ""
-#: tools/main.vala:67 tools/main.vala:192 tools/main.vala:202
+#: tools/main.vala:198 tools/main.vala:395 tools/main.vala:437
msgid "Can't connect to IBus.\n"
msgstr ""
-#: tools/main.vala:93
+#: tools/main.vala:224
#, c-format
msgid "language: %s\n"
msgstr ""
-#: tools/main.vala:161
+#: tools/main.vala:294
msgid "No engine is set.\n"
msgstr ""
-#: tools/main.vala:169
+#: tools/main.vala:302
msgid "Set global engine failed.\n"
msgstr ""
-#: tools/main.vala:174
+#: tools/main.vala:307
msgid "Get global engine failed.\n"
msgstr ""
-#: tools/main.vala:217
+#: tools/main.vala:328
+msgid "Start or restart daemon with \"direct\" or \"systemd\" TYPE."
+msgstr ""
+
+#: tools/main.vala:331
+msgid "Start or restart daemon with SYSTEMD_SERVICE file."
+msgstr ""
+
+#: tools/main.vala:334
+msgid "Show debug messages."
+msgstr ""
+
+#: tools/main.vala:454
msgid "Read the system registry cache."
msgstr ""
-#: tools/main.vala:219
+#: tools/main.vala:456
msgid "Read the registry cache FILE."
msgstr ""
-#: tools/main.vala:237 tools/main.vala:242
+#: tools/main.vala:474 tools/main.vala:479
msgid "The registry cache is invalid.\n"
msgstr ""
-#: tools/main.vala:257
+#: tools/main.vala:495
msgid "Write the system registry cache."
msgstr ""
-#: tools/main.vala:259
+#: tools/main.vala:497
msgid "Write the registry cache FILE."
msgstr ""
-#: tools/main.vala:295
+#: tools/main.vala:535
msgid ""
"Use engine schema paths instead of ibus core, which can be comma-separated "
"values."
msgstr ""
-#: tools/main.vala:381
+#: tools/main.vala:624
msgid "Resetting…"
msgstr ""
-#: tools/main.vala:399
+#: tools/main.vala:642
msgid "Done"
msgstr ""
-#: tools/main.vala:444
+#: tools/main.vala:691
msgid "Set or get engine"
msgstr ""
-#: tools/main.vala:445
+#: tools/main.vala:692
msgid "Exit ibus-daemon"
msgstr ""
-#: tools/main.vala:446
+#: tools/main.vala:693
msgid "Show available engines"
msgstr ""
-#: tools/main.vala:447
+#: tools/main.vala:694
msgid "(Not implemented)"
msgstr ""
-#: tools/main.vala:448
+#: tools/main.vala:695
msgid "Restart ibus-daemon"
msgstr ""
-#: tools/main.vala:449
+#: tools/main.vala:696
+msgid "Start ibus-daemon"
+msgstr ""
+
+#: tools/main.vala:697
msgid "Show version"
msgstr ""
-#: tools/main.vala:450
+#: tools/main.vala:698
msgid "Show the content of registry cache"
msgstr ""
-#: tools/main.vala:451
+#: tools/main.vala:699
msgid "Create registry cache"
msgstr ""
-#: tools/main.vala:452
+#: tools/main.vala:700
msgid "Print the D-Bus address of ibus-daemon"
msgstr ""
-#: tools/main.vala:453
+#: tools/main.vala:701
msgid "Show the configuration values"
msgstr ""
-#: tools/main.vala:454
+#: tools/main.vala:702
msgid "Reset the configuration values"
msgstr ""
-#: tools/main.vala:456
+#: tools/main.vala:704
msgid "Save emoji on dialog to clipboard"
msgstr ""
-#: tools/main.vala:458
+#: tools/main.vala:706
msgid "Show this information"
msgstr ""
-#: tools/main.vala:464
+#: tools/main.vala:713
#, c-format
msgid ""
"Usage: %s COMMAND [OPTION...]\n"
"\n"
msgstr ""
-#: tools/main.vala:465
+#: tools/main.vala:714
msgid "Commands:\n"
msgstr ""
-#: tools/main.vala:494
+#: tools/main.vala:744
#, c-format
msgid "%s is unknown command!\n"
msgstr ""
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 5c18d3d6..e380a9aa 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -3,7 +3,7 @@
# ibus - The Input Bus
#
# Copyright (c) 2007-2013 Peng Huang <shawn.p.huang@gmail.com>
-# Copyright (c) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2015-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
# Copyright (c) 2007-2017 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
@@ -57,6 +57,7 @@ AM_LDADD = \
AM_VALAFLAGS = \
--vapidir=$(top_builddir)/bindings/vala \
--vapidir=$(top_srcdir)/bindings/vala \
+ --pkg=gio-2.0 \
--pkg=ibus-1.0 \
--pkg=posix \
--pkg=config \
diff --git a/tools/ibus.1.in b/tools/ibus.1.in
index 525d972e..fe1b7157 100644
--- a/tools/ibus.1.in
+++ b/tools/ibus.1.in
@@ -3,7 +3,7 @@
.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2013-2017.
.\" Copyright (c) Peng Huang <shawn.p.huang@gmail.com>, 2013.
.\"
-.TH "IBUS" 1 "May 2017" "@VERSION@" "User Commands"
+.TH "IBUS" 1 "Jul 2022" "@VERSION@" "User Commands"
.SH NAME
.B ibus
\- command line utility for ibus
@@ -45,13 +45,33 @@ Exit ibus-daemon.
\fBlist-engine\fR
Show ibus engines list.
.TP
-\fBrestart\fR
-Restart ibus-daemon.
+\fBrestart\fR [\fB\-\-type=TYPE|\-\-verbose|\-\-help\fR]
+Restart ibus-daemon. This command tries to restart ibus-daemon via systemd
+firstly and directly secondary by default. If
+.B \-\-type=systemd
+is given, It tries to restart via systemd only. If
+.B \-\-type=direct
+is given, It tries to restart with an IBus API only. GNOME desktop runs
+ibus-daemon via systemd and other desktops run ibus-daemon directly.
+.TP
+\fBstart\fR [\fB\-\-type=TYPE|\-\-verbose|\-\-help\fR]
+Start ibus-daemon. This command tries to start ibus-daemon via systemd
+firstly and directly secondary by default. If
+.B \-\-type=systemd
+is given, It tries to start as a background process via systemd only. If
+.B \-\-type=direct
+is given, It tries to start directly only as a foreground process and other
+option arguments of ibus command are sent to ibus-daemon. E.g.
+ibus start
+.B \-\-type=direct
+.B \-\-xim
+&
+GNOME desktop runs ibus-daemon via systemd and other desktops run ibus-daemon directly.
.TP
\fBversion\fR
Show the ibus version.
.TP
-\fBread\-cache\fR [\fB\-\-system|\-\-file=FILE\fR]
+\fBread\-cache\fR [\fB\-\-system|\-\-file=FILE|\-\-help\fR]
Show the content of the user registry cache if
.B \-\-system
is not given.
@@ -64,7 +84,7 @@ if
.B \-\-file=FILE
is given.
.TP
-\fBwrite\-cache\fR [\fB\-\-system|\-\-file=FILE\fR]
+\fBwrite\-cache\fR [\fB\-\-system|\-\-file=FILE|\-\-help\fR]
Save the user registry cache if
.B \-\-system
is not given.
diff --git a/tools/main.vala b/tools/main.vala
index 26e7fd88..407eaf74 100644
--- a/tools/main.vala
+++ b/tools/main.vala
@@ -3,7 +3,7 @@
* ibus - The Input Bus
*
* Copyright(c) 2013 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright(c) 2015-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright(c) 2015-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,17 +27,23 @@ private const string IBUS_SCHEMAS_GENERAL_HOTKEY =
private const string IBUS_SCHEMAS_PANEL = "org.freedesktop.ibus.panel";
private const string IBUS_SCHEMAS_PANEL_EMOJI =
"org.freedesktop.ibus.panel.emoji";
+private const string SYSTEMD_SESSION_GNOME_FILE =
+ "org.freedesktop.IBus.session.GNOME.service";
bool name_only = false;
/* system() exists as a public API. */
bool is_system = false;
string cache_file = null;
string engine_id = null;
+bool verbose = false;
+string daemon_type = null;
+string systemd_service_file = null;
class EngineList {
public IBus.EngineDesc[] data = {};
}
+
IBus.Bus? get_bus() {
var bus = new IBus.Bus();
if (!bus.is_connected ())
@@ -45,6 +51,131 @@ IBus.Bus? get_bus() {
return bus;
}
+
+GLib.DBusConnection? get_session_bus(bool verbose) {
+ try {
+ return GLib.Bus.get_sync (GLib.BusType.SESSION, null);
+ } catch (GLib.IOError e) {
+ if (verbose)
+ stderr.printf("%s\n", e.message);
+ }
+ return null;
+}
+
+string?
+get_ibus_systemd_object_path(GLib.DBusConnection connection,
+ bool verbose) {
+ string object_path = null;
+ assert(systemd_service_file != null);
+ try {
+ var variant = connection.call_sync (
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnit",
+ new GLib.Variant("(s)", systemd_service_file),
+ new GLib.VariantType("(o)"),
+ GLib.DBusCallFlags.NONE,
+ -1,
+ null);
+ variant.get("(o)", ref object_path);
+ if (verbose) {
+ stderr.printf("Succeed to get an object path \"%s\" for IBus " +
+ "systemd service file \"%s\".\n",
+ object_path, systemd_service_file);
+ }
+ return object_path;
+ } catch (GLib.Error e) {
+ if (verbose) {
+ stderr.printf("IBus systemd service file \"%s\" is not installed " +
+ "in your system: %s\n",
+ systemd_service_file, e.message);
+ }
+ }
+ return null;
+}
+
+
+bool
+is_running_daemon_via_systemd(GLib.DBusConnection connection,
+ string object_path,
+ bool verbose) {
+ string? state = null;
+ try {
+ while (true) {
+ var variant = connection.call_sync (
+ "org.freedesktop.systemd1",
+ object_path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ new GLib.Variant("(ss)",
+ "org.freedesktop.systemd1.Unit",
+ "ActiveState"),
+ new GLib.VariantType("(v)"),
+ GLib.DBusCallFlags.NONE,
+ -1,
+ null);
+ GLib.Variant child = null;
+ variant.get("(v)", ref child);
+ state = child.dup_string();
+ if (verbose) {
+ stderr.printf("systemd state is \"%s\" for an object " +
+ "path \"%s\".\n", state, object_path);
+ }
+ if (state != "activating")
+ break;
+ Posix.sleep(1);
+ }
+ } catch (GLib.Error e) {
+ if (verbose)
+ stderr.printf("%s\n", e.message);
+ return false;
+ }
+ if (state == "active")
+ return true;
+ return false;
+}
+
+
+bool
+start_daemon_via_systemd(GLib.DBusConnection connection,
+ bool restart,
+ bool verbose) {
+ string object_path = null;
+ string method = "StartUnit";
+ assert(systemd_service_file != null);
+ if (restart)
+ method = "RestartUnit";
+ try {
+ var variant = connection.call_sync (
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ method,
+ new GLib.Variant("(ss)", systemd_service_file, "fail"),
+ new GLib.VariantType("(o)"),
+ GLib.DBusCallFlags.NONE,
+ -1,
+ null);
+ variant.get("(o)", ref object_path);
+ if (verbose) {
+ stderr.printf("Succeed to restart IBus daemon via IBus systemd " +
+ "service file \"%s\": \"%s\"\n",
+ systemd_service_file, object_path);
+ }
+ return true;
+ } catch (GLib.Error e) {
+ if (verbose) {
+ stderr.printf("Failed to %s IBus daemon via IBus systemd " +
+ "service file \"%s\": %s\n",
+ restart ? "restart" : "start",
+ systemd_service_file, e.message);
+ }
+ }
+ return false;
+}
+
+
int list_engine(string[] argv) {
const OptionEntry[] options = {
{ "name-only", 0, 0, OptionArg.NONE, out name_only,
@@ -99,6 +230,7 @@ int list_engine(string[] argv) {
return Posix.EXIT_SUCCESS;
}
+
private int exec_setxkbmap(IBus.EngineDesc engine) {
string layout = engine.get_layout();
string variant = engine.get_layout_variant();
@@ -149,6 +281,7 @@ private int exec_setxkbmap(IBus.EngineDesc engine) {
return Posix.EXIT_SUCCESS;
}
+
int get_set_engine(string[] argv) {
var bus = get_bus();
string engine = null;
@@ -182,20 +315,121 @@ int get_set_engine(string[] argv) {
return Posix.EXIT_SUCCESS;
}
+
int message_watch(string[] argv) {
return Posix.EXIT_SUCCESS;
}
-int restart_daemon(string[] argv) {
- var bus = get_bus();
- if (bus == null) {
- stderr.printf(_("Can't connect to IBus.\n"));
+
+int start_daemon_real(string[] argv,
+ bool restart) {
+ const OptionEntry[] options = {
+ { "type", 0, 0, OptionArg.STRING, out daemon_type,
+ N_("Start or restart daemon with \"direct\" or \"systemd\" TYPE."),
+ "TYPE" },
+ { "service-file", 0, 0, OptionArg.STRING, out systemd_service_file,
+ N_("Start or restart daemon with SYSTEMD_SERVICE file."),
+ "SYSTEMD_SERVICE" },
+ { "verbose", 0, 0, OptionArg.NONE, out verbose,
+ N_("Show debug messages."), null },
+ { null }
+ };
+
+ var option = new OptionContext();
+ option.add_main_entries(options, Config.GETTEXT_PACKAGE);
+ option.set_ignore_unknown_options(true);
+
+ try {
+ option.parse(ref argv);
+ } catch (OptionError e) {
+ stderr.printf("%s\n", e.message);
+ return Posix.EXIT_FAILURE;
+ }
+ if (daemon_type != null && daemon_type != "direct" &&
+ daemon_type != "systemd") {
+ stderr.printf("type argument must be \"direct\" or \"systemd\"\n");
+ return Posix.EXIT_FAILURE;
+ }
+ if (systemd_service_file == null)
+ systemd_service_file = SYSTEMD_SESSION_GNOME_FILE;
+
+ do {
+ if (daemon_type == "direct")
+ break;
+ GLib.DBusConnection? connection = get_session_bus(verbose);
+ if (connection == null)
+ break;
+ string? object_path = null;
+ if (restart) {
+ object_path = get_ibus_systemd_object_path(connection, verbose);
+ if (object_path == null)
+ break;
+ if (!is_running_daemon_via_systemd(connection,
+ object_path,
+ verbose)) {
+ break;
+ }
+ }
+ if (!start_daemon_via_systemd(connection, restart, verbose))
+ break;
+ // Do not check the systemd state in case of restart because
+ // the systemd file validation is already done and also stopping
+ // daemon and starting daemon take time and the state could be
+ // "inactive" with the time lag.
+ if (restart)
+ return Posix.EXIT_SUCCESS;
+ object_path = get_ibus_systemd_object_path(connection, verbose);
+ if (object_path == null)
+ break;
+ if (!is_running_daemon_via_systemd(connection, object_path, verbose))
+ break;
+ return Posix.EXIT_SUCCESS;
+ } while (false);
+
+ if (daemon_type == "systemd")
return Posix.EXIT_FAILURE;
+ if (restart) {
+ var bus = get_bus();
+ if (bus == null) {
+ stderr.printf(_("Can't connect to IBus.\n"));
+ return Posix.EXIT_FAILURE;
+ }
+ bus.exit(true);
+ if (verbose) {
+ stderr.printf("Succeed to restart ibus-daemon with an IBus API " +
+ "directly.\n");
+ }
+ } else {
+ string startarg = "ibus-daemon";
+ argv[0] = startarg;
+ var paths = GLib.Environment.get_variable("PATH").split(":");
+ foreach (unowned string path in paths) {
+ var full_path = "%s/%s".printf(path, startarg);
+ if (GLib.FileUtils.test(full_path, GLib.FileTest.IS_EXECUTABLE)) {
+ startarg = full_path;
+ break;
+ }
+ }
+ // When ibus-daemon is launched by GLib.Process.spawn_async(),
+ // the parent process will be systemd
+ if (verbose) {
+ stderr.printf("Running \"%s\" directly as a foreground " +
+ "process.\n", startarg);
+ }
+ Posix.execv(startarg, argv);
}
- bus.exit(true);
return Posix.EXIT_SUCCESS;
}
+
+int restart_daemon(string[] argv) {
+ return start_daemon_real(argv, true);
+}
+
+int start_daemon(string[] argv) {
+ return start_daemon_real(argv, false);
+}
+
int exit_daemon(string[] argv) {
var bus = get_bus();
if (bus == null) {
@@ -206,11 +440,13 @@ int exit_daemon(string[] argv) {
return Posix.EXIT_SUCCESS;
}
+
int print_version(string[] argv) {
print("IBus %s\n", Config.PACKAGE_VERSION);
return Posix.EXIT_SUCCESS;
}
+
int read_cache (string[] argv) {
const OptionEntry[] options = {
{ "system", 0, 0, OptionArg.NONE, out is_system,
@@ -251,6 +487,7 @@ int read_cache (string[] argv) {
return Posix.EXIT_SUCCESS;
}
+
int write_cache (string[] argv) {
const OptionEntry[] options = {
{ "system", 0, 0, OptionArg.NONE, out is_system,
@@ -283,12 +520,14 @@ int write_cache (string[] argv) {
Posix.EXIT_SUCCESS : Posix.EXIT_FAILURE;
}
+
int print_address(string[] argv) {
string address = IBus.get_address();
print("%s\n", address != null ? address : "(null)");
return Posix.EXIT_SUCCESS;
}
+
private int read_config_options(string[] argv) {
const OptionEntry[] options = {
{ "engine-id", 0, 0, OptionArg.STRING, out engine_id,
@@ -309,6 +548,7 @@ private int read_config_options(string[] argv) {
return Posix.EXIT_SUCCESS;
}
+
private GLib.SList<string> get_ibus_schemas() {
string[] ids = {};
if (engine_id != null) {
@@ -342,6 +582,7 @@ private GLib.SList<string> get_ibus_schemas() {
return ibus_schemas;
}
+
int read_config(string[] argv) {
if (read_config_options(argv) == Posix.EXIT_FAILURE)
return Posix.EXIT_FAILURE;
@@ -370,6 +611,7 @@ int read_config(string[] argv) {
return Posix.EXIT_SUCCESS;
}
+
int reset_config(string[] argv) {
if (read_config_options(argv) == Posix.EXIT_FAILURE)
return Posix.EXIT_FAILURE;
@@ -401,6 +643,7 @@ int reset_config(string[] argv) {
return Posix.EXIT_SUCCESS;
}
+
#if EMOJI_DICT
int emoji_dialog(string[] argv) {
string cmd = Config.LIBEXECDIR + "/ibus-ui-emojier";
@@ -427,11 +670,13 @@ int emoji_dialog(string[] argv) {
}
#endif
+
int print_help(string[] argv) {
print_usage(stdout);
return Posix.EXIT_SUCCESS;
}
+
delegate int EntryFunc(string[] argv);
struct CommandEntry {
@@ -440,12 +685,14 @@ struct CommandEntry {
unowned EntryFunc entry;
}
+
const CommandEntry commands[] = {
{ "engine", N_("Set or get engine"), get_set_engine },
{ "exit", N_("Exit ibus-daemon"), exit_daemon },
{ "list-engine", N_("Show available engines"), list_engine },
{ "watch", N_("(Not implemented)"), message_watch },
{ "restart", N_("Restart ibus-daemon"), restart_daemon },
+ { "start", N_("Start ibus-daemon"), start_daemon },
{ "version", N_("Show version"), print_version },
{ "read-cache", N_("Show the content of registry cache"), read_cache },
{ "write-cache", N_("Create registry cache"), write_cache },
@@ -460,6 +707,7 @@ const CommandEntry commands[] = {
static string program_name;
+
void print_usage(FileStream stream) {
stream.printf(_("Usage: %s COMMAND [OPTION...]\n\n"), program_name);
stream.printf(_("Commands:\n"));
@@ -470,6 +718,7 @@ void print_usage(FileStream stream) {
}
}
+
public int main(string[] argv) {
GLib.Intl.setlocale(GLib.LocaleCategory.ALL, "");
GLib.Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);