Make Geary DBus-activatable. Bug 775956.

* org.gnome.Geary.service.in: create, and let it be installed by CMake.

* org.gnome.Geary.desktop.in: add `DBusActivatable=true`.

* geary-autostart.desktop.in: use `--gapplication-service` instead of
hidden.

* Change the way arguments are parsed:
  * Use the _command-line_ and _handle-local-options_ signals instead
    of _local-command-line_.
  * Remove the `--hidden` option (replaced by `--gapplication-service`)
  * Use VariantDict (which is a little cleaner)
  * Don't use global variables in Arg, but set them in
  the config instead.
  * We can no longer set a global summary due to the new option handling
  in GApplication. On IRC, I got the feedback that info like this should
  be going into a manpage.

* Since the QUIT-action can now be called without ever activating the
app, make the necessary changes to the `GearyController`:
  * `main_window` and `current_conversations` can be null.
  * use `pending_mailtos()` for the compose action as well.
  * Don't update the UNDO action if we're closing down.

* More instance variables prefixed with this (we're changing the lines
anyway, might as well do it properly).

* `Environment.set_prgname()` is already executed in GApplication.run(),
so no more need for `GearyApplication.PRGNAME`.

Signed-off-by: Niels De Graef <nielsdegraef@gmail.com>
This commit is contained in:
Niels De Graef 2016-12-20 18:21:19 +01:00 committed by Michael James Gratton
parent ddced6f6f4
commit 9acf5d344d
15 changed files with 225 additions and 206 deletions

View file

@ -7,7 +7,7 @@ Keywords=Email;E-mail;Mail;
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=org.gnome.Geary
TryExec=geary
Exec=geary --hidden
Exec=geary --gapplication-service
Type=Application
Terminal=false
Categories=GNOME;GTK;Network;Email;

View file

@ -87,3 +87,18 @@ geary_compiled_schema = gnome.compile_schemas(
install_data('org.gnome.Geary.gschema.xml',
install_dir: join_paths(datadir, 'glib-2.0', 'schemas'),
)
#
# DBus services
#
service_conf = configuration_data()
service_conf.set('bindir', bindir)
configure_file(
input: 'org.gnome.Geary.service.in',
output: 'org.gnome.Geary.service',
configuration: service_conf,
install: true,
install_dir: dbus_services_dir
)

View file

@ -13,6 +13,7 @@ Terminal=false
Categories=GNOME;GTK;Network;Email;
MimeType=x-scheme-handler/mailto;
StartupNotify=true
DBusActivatable=true
X-GNOME-UsesNotifications=true
Actions=Compose;

View file

@ -0,0 +1,3 @@
[D-BUS Service]
Name=org.gnome.Geary
Exec=@bindir@/geary" --gapplication-service

View file

@ -27,6 +27,7 @@ locale_dir = join_paths(geary_prefix, get_option('localedir'))
po_dir = join_paths(meson.source_root(), 'po')
vapi_dir = join_paths(meson.source_root(), 'bindings', 'vapi')
metadata_dir = join_paths(meson.source_root(), 'bindings', 'metadata')
dbus_services_dir = join_paths(datadir, 'dbus-1', 'services')
web_extensions_dir = join_paths(libdir, 'geary', 'web-extensions')
# Make sure Meson can find our custom VAPI's

View file

@ -18,7 +18,6 @@ extern const string GETTEXT_PACKAGE;
public class GearyApplication : Gtk.Application {
public const string NAME = "Geary";
public const string PRGNAME = "geary";
public const string APP_ID = "org.gnome.Geary";
public const string DESCRIPTION = _("Send and receive email");
public const string COPYRIGHT_1 = _("Copyright 2016 Software Freedom Conservancy Inc.");
@ -52,14 +51,14 @@ public class GearyApplication : Gtk.Application {
public const string ACTION_UNDO = "undo";
// App-wide actions
private const string ACTION_ABOUT = "about";
private const string ACTION_ACCOUNTS = "accounts";
private const string ACTION_COMPOSE = "compose";
private const string ACTION_INSPECT = "inspect";
private const string ACTION_HELP = "help";
private const string ACTION_MAILTO = "mailto";
private const string ACTION_PREFERENCES = "preferences";
private const string ACTION_QUIT = "quit";
public const string ACTION_ABOUT = "about";
public const string ACTION_ACCOUNTS = "accounts";
public const string ACTION_COMPOSE = "compose";
public const string ACTION_INSPECT = "inspect";
public const string ACTION_HELP = "help";
public const string ACTION_MAILTO = "mailto";
public const string ACTION_PREFERENCES = "preferences";
public const string ACTION_QUIT = "quit";
private const ActionEntry[] action_entries = {
{ACTION_ABOUT, on_activate_about},
@ -127,10 +126,10 @@ public class GearyApplication : Gtk.Application {
*
* If this returns `true`, then the primary application instance
* will continue to run in the background after the last window is
* closed, instead of existing as usual.
* closed, instead of exiting as usual.
*/
public bool is_background_service {
get { return Args.hidden_startup || this.config.startup_notifications; }
get { return (this.flags & ApplicationFlags.IS_SERVICE) != 0; }
}
private string bin;
@ -238,57 +237,45 @@ public class GearyApplication : Gtk.Application {
public GearyApplication() {
Object(
application_id: APP_ID
application_id: APP_ID,
flags: ApplicationFlags.HANDLES_COMMAND_LINE
);
this.add_main_option_entries(Args.OPTION_ENTRIES);
_instance = this;
}
// Application.run() calls this as an entry point.
public override bool local_command_line(ref unowned string[] args, out int exit_status) {
bin = args[0];
exec_dir = (File.new_for_path(Posix.realpath(Environment.find_program_in_path(bin)))).get_parent();
public override bool local_command_line(ref unowned string[] args,
out int exit_status) {
this.bin = args[0];
string current_path = Posix.realpath(Environment.find_program_in_path(this.bin));
this.exec_dir = File.new_for_path(current_path).get_parent();
try {
register();
} catch (Error e) {
error("Error registering GearyApplication: %s", e.message);
}
return base.local_command_line(ref args, out exit_status);
}
if (!Args.parse(args)) {
exit_status = 1;
return true;
}
public override int handle_local_options(VariantDict options) {
return Args.handle_local_options(options);
}
if (!Args.quit) {
// Normal application startup or activation
activate();
foreach (unowned string arg in args) {
if (arg != null) {
if (arg == Geary.ComposedEmail.MAILTO_SCHEME)
activate_action(ACTION_COMPOSE, null);
else if (arg.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME))
activate_action(ACTION_MAILTO, new Variant.string(arg));
}
}
} else {
// User requested quit, only try to if we aren't running
// already.
if (this.is_remote) {
activate_action(ACTION_QUIT, null);
}
}
public override int command_line(ApplicationCommandLine command_line) {
int exit_value = Args.handle_general_options(this.config, command_line.get_options_dict());
if (exit_value != -1)
return exit_value;
exit_status = 0;
return true;
exit_value = Args.handle_arguments(this, command_line.get_arguments());
if (exit_value != -1)
return exit_value;
activate();
return -1;
}
public override void startup() {
Configuration.init(is_installed(), GSETTINGS_DIR);
Environment.set_application_name(NAME);
Environment.set_prgname(PRGNAME);
International.init(GETTEXT_PACKAGE, bin);
International.init(GETTEXT_PACKAGE, this.bin);
Configuration.init(is_installed(), GSETTINGS_DIR);
Geary.Logging.init();
Geary.Logging.log_to(stderr);
GLib.Log.set_default_handler(Geary.Logging.default_handler);
@ -301,7 +288,12 @@ public class GearyApplication : Gtk.Application {
// Ensure all geary windows have an icon
Gtk.Window.set_default_icon_name(APP_ID);
this.config = new Configuration(APP_ID);
add_action_entries(action_entries, this);
// Use a hold() here (if started as a service, we will shutdown after 10s).
hold();
}
public override void activate() {
@ -340,8 +332,6 @@ public class GearyApplication : Gtk.Application {
message("%s %s prefix=%s exec_dir=%s is_installed=%s", NAME, VERSION, INSTALL_PREFIX,
exec_dir.get_path(), is_installed().to_string());
config = new Configuration(APP_ID);
// Application accels
add_app_accelerators(ACTION_COMPOSE, { "<Ctrl>N" });
add_app_accelerators(ACTION_HELP, { "F1" });
@ -358,7 +348,7 @@ public class GearyApplication : Gtk.Application {
ComposerWidget.add_window_accelerators(this);
Components.Inspector.add_window_accelerators(this);
yield controller.open_async(null);
yield this.controller.open_async(null);
release();
}
@ -367,11 +357,11 @@ public class GearyApplication : Gtk.Application {
// see create_async() for reasoning hold/release is used
hold();
yield controller.close_async();
if (this.controller != null) // If we didn't get activated, controller might be null
yield this.controller.close_async();
release();
is_destroyed = true;
this.is_destroyed = true;
}
public void add_window_accelerators(string action,
@ -479,7 +469,7 @@ public class GearyApplication : Gtk.Application {
// This call will fire "exiting" only if it's not already been fired.
public void exit(int exitcode = 0) {
if (exiting_fired)
if (this.exiting_fired)
return;
this.exitcode = exitcode;
@ -580,7 +570,7 @@ public class GearyApplication : Gtk.Application {
private void on_activate_mailto(SimpleAction action, Variant? param) {
if (this.controller != null && param != null) {
this.controller.compose_mailto(param.get_string());
this.controller.compose(param.get_string());
}
}

View file

@ -6,117 +6,120 @@
namespace Args {
private const OptionEntry[] options = {
{ "hidden", 0, 0, OptionArg.NONE, ref hidden_startup, N_("Start Geary with hidden main window"), null },
{ "debug", 'd', 0, OptionArg.NONE, ref log_debug, N_("Output debugging information"), null },
{ "log-conversations", 0, 0, OptionArg.NONE, ref log_conversations, N_("Log conversation monitoring"), null },
{ "log-deserializer", 0, 0, OptionArg.NONE, ref log_deserializer, N_("Log network deserialization"), null },
{ "log-network", 0, 0, OptionArg.NONE, ref log_network, N_("Log network activity"), null },
// LOCAL OPTIONS
public const string OPTION_VERSION = "version";
// GENERAL OPTIONS
public const string OPTION_LOG_DEBUG = "debug";
public const string OPTION_LOG_NETWORK = "log-conversations";
public const string OPTION_LOG_SERIALIZER = "log-deserializer";
public const string OPTION_LOG_DESERIALIZER = "log-network";
public const string OPTION_LOG_REPLAY_QUEUE = "log-replay-queue";
public const string OPTION_LOG_CONVERSATIONS = "log-serializer";
public const string OPTION_LOG_PERIODIC = "log-periodic";
public const string OPTION_LOG_SQL = "log-sql";
public const string OPTION_LOG_FOLDER_NORMALIZATION = "log-folder-normalization";
public const string OPTION_INSPECTOR = "inspector";
public const string OPTION_REVOKE_CERTS = "revoke-certs";
public const string OPTION_QUIT = "quit";
// This is also the order in which they are presented to the user, so it's probably best to keep
// them alphabetical
public const OptionEntry[] OPTION_ENTRIES = {
{ OPTION_LOG_DEBUG, 'd', 0, OptionArg.NONE, null, N_("Output debugging information"), null },
{ OPTION_INSPECTOR, 'i', 0, OptionArg.NONE, null, N_("Allow inspection of WebView"), null },
{ OPTION_LOG_CONVERSATIONS, 0, 0, OptionArg.NONE, null, N_("Log conversation monitoring"), null },
{ OPTION_LOG_DESERIALIZER, 0, 0, OptionArg.NONE, null, N_("Log network deserialization"), null },
{ OPTION_LOG_NETWORK, 0, 0, OptionArg.NONE, null, N_("Log network activity"), null },
/// The IMAP replay queue is how changes on the server are replicated on the client.
/// It could also be called the IMAP events queue.
{ "log-replay-queue", 0, 0, OptionArg.NONE, ref log_replay_queue, N_("Log IMAP replay queue"), null },
{ OPTION_LOG_REPLAY_QUEUE, 0, 0, OptionArg.NONE, null, N_("Log IMAP replay queue"), null },
/// Serialization is how commands and responses are converted into a stream of bytes for
/// network transmission
{ "log-serializer", 0, 0, OptionArg.NONE, ref log_serializer, N_("Log network serialization"), null },
{ "log-periodic", 0, 0, OptionArg.NONE, ref log_periodic, N_("Log periodic activity"), null },
{ "log-sql", 0, 0, OptionArg.NONE, ref log_sql, N_("Log database queries (generates lots of messages)"), null },
{ OPTION_LOG_SERIALIZER, 0, 0, OptionArg.NONE, null, N_("Log network serialization"), null },
{ OPTION_LOG_PERIODIC, 0, 0, OptionArg.NONE, null, N_("Log periodic activity"), null },
{ OPTION_LOG_SQL, 0, 0, OptionArg.NONE, null, N_("Log database queries (generates lots of messages)"), null },
/// "Normalization" can also be called "synchronization"
{ "log-folder-normalization", 0, 0, OptionArg.NONE, ref log_folder_normalization, N_("Log folder normalization"), null },
{ "inspector", 'i', 0, OptionArg.NONE, ref inspector, N_("Allow inspection of WebView"), null },
{ "revoke-certs", 0, 0, OptionArg.NONE, ref revoke_certs, N_("Revoke all server certificates with TLS warnings"), null },
{ "quit", 'q', 0, OptionArg.NONE, ref quit, N_("Perform a graceful quit"), null },
{ "version", 'V', 0, OptionArg.NONE, ref version, N_("Display program version"), null },
{ OPTION_LOG_FOLDER_NORMALIZATION, 0, 0, OptionArg.NONE, null, N_("Log folder normalization"), null },
{ OPTION_REVOKE_CERTS, 0, 0, OptionArg.NONE, null, N_("Revoke all server certificates with TLS warnings"), null },
{ OPTION_VERSION, 'V', 0, OptionArg.NONE, null, N_("Display program version"), null },
{ OPTION_QUIT, 'q', 0, OptionArg.NONE, null, N_("Perform a graceful quit"), null },
/// Use this to specify arguments in the help section
{ "", 0, 0, OptionArg.NONE, null, null, "[mailto:...]" },
{ null }
};
public bool hidden_startup = false;
public bool log_debug = false;
public bool log_network = false;
public bool log_serializer = false;
public bool log_deserializer = false;
public bool log_replay_queue = false;
public bool log_conversations = false;
public bool log_periodic = false;
public bool log_sql = false;
public bool log_folder_normalization = false;
public bool inspector = false;
public bool quit = false;
public bool revoke_certs = false;
public bool version = false;
public bool parse(string[] args) {
var context = new OptionContext("[%s...]".printf(Geary.ComposedEmail.MAILTO_SCHEME));
context.set_help_enabled(true);
context.add_main_entries(options, null);
context.set_description("%s\n\n%s\n%s\n\n%s\n\t%s\n".printf(
// This gives a command-line hint on how to open new composer windows with mailto:
_("Use %s to open a new composer window").printf(Geary.ComposedEmail.MAILTO_SCHEME),
GearyApplication.COPYRIGHT_1,
GearyApplication.COPYRIGHT_2,
_("Please report comments, suggestions and bugs to:"),
GearyApplication.BUGREPORT));
try {
context.parse(ref args);
} catch (OptionError error) {
// i18n: Command line arguments are invalid
stdout.printf (_("Failed to parse command line options: %s\n"), error.message);
stdout.printf("\n%s", context.get_help(true, null));
return false;
/**
* Handles options for a locally running instance, i.e. options for which you don't need to make
* a connection to a service instance that is already running.
*/
public int handle_local_options(VariantDict local_options) {
if (local_options.contains(OPTION_VERSION)) {
stdout.printf("%s %s\n", Environment.get_prgname(), GearyApplication.VERSION);
return 0;
}
// other than the OptionEntry command-line arguments, the only acceptable arguments are
// mailto:'s
for (int ctr = 1; ctr < args.length; ctr++) {
string arg = args[ctr];
return -1;
}
if (!arg.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
stdout.printf(_("Unrecognized command line option “%s”\n").printf(arg));
stdout.printf("\n%s", context.get_help(true, null));
public int handle_general_options(Configuration config, VariantDict options) {
if (options.contains(OPTION_QUIT))
return 0;
return false;
}
}
if (version) {
stdout.printf("%s %s\n", GearyApplication.PRGNAME, GearyApplication.VERSION);
Process.exit(0);
}
if (log_network)
Geary.Logging.enable_flags(Geary.Logging.Flag.NETWORK);
if (log_serializer)
Geary.Logging.enable_flags(Geary.Logging.Flag.SERIALIZER);
if (log_replay_queue)
Geary.Logging.enable_flags(Geary.Logging.Flag.REPLAY);
if (log_conversations)
Geary.Logging.enable_flags(Geary.Logging.Flag.CONVERSATIONS);
if (log_periodic)
Geary.Logging.enable_flags(Geary.Logging.Flag.PERIODIC);
if (log_sql)
Geary.Logging.enable_flags(Geary.Logging.Flag.SQL);
if (log_folder_normalization)
Geary.Logging.enable_flags(Geary.Logging.Flag.FOLDER_NORMALIZATION);
if (log_deserializer)
Geary.Logging.enable_flags(Geary.Logging.Flag.DESERIALIZER);
if (log_debug) {
bool enable_debug = options.contains(OPTION_LOG_DEBUG);
// Will be logging to stderr until this point
if (enable_debug) {
Geary.Logging.log_to(stdout);
} else {
// We'll be logging to stderror until this point, so stop
// that.
Geary.Logging.log_to(null);
}
return true;
// Logging flags
if (options.contains(OPTION_LOG_NETWORK))
Geary.Logging.enable_flags(Geary.Logging.Flag.NETWORK);
if (options.contains(OPTION_LOG_SERIALIZER))
Geary.Logging.enable_flags(Geary.Logging.Flag.SERIALIZER);
if (options.contains(OPTION_LOG_REPLAY_QUEUE))
Geary.Logging.enable_flags(Geary.Logging.Flag.REPLAY);
if (options.contains(OPTION_LOG_CONVERSATIONS))
Geary.Logging.enable_flags(Geary.Logging.Flag.CONVERSATIONS);
if (options.contains(OPTION_LOG_PERIODIC))
Geary.Logging.enable_flags(Geary.Logging.Flag.PERIODIC);
if (options.contains(OPTION_LOG_SQL))
Geary.Logging.enable_flags(Geary.Logging.Flag.SQL);
if (options.contains(OPTION_LOG_FOLDER_NORMALIZATION))
Geary.Logging.enable_flags(Geary.Logging.Flag.FOLDER_NORMALIZATION);
if (options.contains(OPTION_LOG_DESERIALIZER))
Geary.Logging.enable_flags(Geary.Logging.Flag.DESERIALIZER);
config.enable_debug = enable_debug;
config.enable_inspector = options.contains(OPTION_INSPECTOR);
config.revoke_certs = options.contains(OPTION_REVOKE_CERTS);
return -1;
}
/**
* Handles the actual arguments of the application.
*/
public int handle_arguments(GearyApplication app, string[] args) {
for (int ctr = 1; ctr < args.length; ctr++) {
string arg = args[ctr];
// the only acceptable arguments are mailto:'s
if (arg.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
if (arg == Geary.ComposedEmail.MAILTO_SCHEME)
app.activate_action(GearyApplication.ACTION_COMPOSE, null);
else
app.activate_action(GearyApplication.ACTION_MAILTO, new Variant.string(arg));
} else {
stdout.printf(_("Unrecognized argument: “%s”\n").printf(arg));
stdout.printf(_("Geary only accepts mailto-links as arguments.\n"));
return 1;
}
}
return -1;
}
}

View file

@ -52,6 +52,15 @@ public class Configuration {
public Settings settings { get; private set; }
public Settings gnome_interface { get; private set; }
// Can be set as an arguments
public bool enable_debug { get; set; default = false; }
// Can be set as an arguments
public bool enable_inspector { get; set; default = false; }
// Can be set as an arguments
public bool revoke_certs { get; set; default = false; }
public DesktopEnvironment desktop_environment {
get {
string? xdg_current_desktop = Environment.get_variable("XDG_CURRENT_DESKTOP");

View file

@ -158,7 +158,7 @@ public class GearyController : Geary.BaseObject {
private Geary.Nonblocking.Mutex select_folder_mutex = new Geary.Nonblocking.Mutex();
private Geary.Folder? previous_non_search_folder = null;
private UpgradeDialog upgrade_dialog;
private Gee.List<string> pending_mailtos = new Gee.ArrayList<string>();
private Gee.List<string?> pending_mailtos = new Gee.ArrayList<string>();
private uint operation_count = 0;
private Geary.Revokable? revokable = null;
@ -254,8 +254,7 @@ public class GearyController : Geary.BaseObject {
ClientWebView.init_web_context(
this.application.config,
this.application.get_web_extensions_dir(),
this.application.get_user_cache_directory().get_child("web-resources"),
Args.log_debug
this.application.get_user_cache_directory().get_child("web-resources")
);
try {
ClientWebView.load_resources(
@ -420,23 +419,26 @@ public class GearyController : Geary.BaseObject {
on_conversations_selected(new Gee.HashSet<Geary.App.Conversation>());
on_folder_selected(null);
// Disconnect from various UI signals.
main_window.conversation_list_view.conversations_selected.disconnect(on_conversations_selected);
main_window.conversation_list_view.conversation_activated.disconnect(on_conversation_activated);
main_window.conversation_list_view.load_more.disconnect(on_load_more);
main_window.conversation_list_view.mark_conversations.disconnect(on_mark_conversations);
main_window.conversation_list_view.visible_conversations_changed.disconnect(on_visible_conversations_changed);
main_window.folder_list.folder_selected.disconnect(on_folder_selected);
main_window.folder_list.copy_conversation.disconnect(on_copy_conversation);
main_window.folder_list.move_conversation.disconnect(on_move_conversation);
main_window.main_toolbar.copy_folder_menu.folder_selected.disconnect(on_copy_conversation);
main_window.main_toolbar.move_folder_menu.folder_selected.disconnect(on_move_conversation);
main_window.conversation_viewer.conversation_added.disconnect(
on_conversation_view_added
);
if (this.main_window != null) {
// Disconnect from various UI signals.
this.main_window.conversation_list_view.conversations_selected.disconnect(on_conversations_selected);
this.main_window.conversation_list_view.conversation_activated.disconnect(on_conversation_activated);
this.main_window.conversation_list_view.load_more.disconnect(on_load_more);
this.main_window.conversation_list_view.mark_conversations.disconnect(on_mark_conversations);
this.main_window.conversation_list_view.visible_conversations_changed.disconnect(on_visible_conversations_changed);
this.main_window.folder_list.folder_selected.disconnect(on_folder_selected);
this.main_window.folder_list.copy_conversation.disconnect(on_copy_conversation);
this.main_window.folder_list.move_conversation.disconnect(on_move_conversation);
this.main_window.main_toolbar.copy_folder_menu.folder_selected.disconnect(on_copy_conversation);
this.main_window.main_toolbar.move_folder_menu.folder_selected.disconnect(on_move_conversation);
this.main_window.conversation_viewer.conversation_added.disconnect(
on_conversation_view_added
);
// hide window while shutting down, as this can take a few seconds under certain conditions
main_window.hide();
// hide window while shutting down, as this can take a few
// seconds under certain conditions
this.main_window.hide();
}
// Release monitoring early so held resources can be freed up
this.libnotify = null;
@ -533,9 +535,11 @@ public class GearyController : Geary.BaseObject {
);
this.account_manager = null;
this.application.remove_window(this.main_window);
this.main_window.destroy();
this.main_window = null;
if (this.main_window != null) {
this.application.remove_window(this.main_window);
this.main_window.destroy();
this.main_window = null;
}
this.upgrade_dialog = null;
@ -560,17 +564,10 @@ public class GearyController : Geary.BaseObject {
debug("Closed GearyController");
}
/**
* Opens a new, blank composer.
*/
public void compose() {
create_compose_widget(ComposerWidget.ComposeType.NEW_MESSAGE);
}
/**
* Opens or queues a new composer addressed to a specific email address.
*/
public void compose_mailto(string mailto) {
public void compose(string? mailto = null) {
if (current_account == null) {
// Schedule the send for after we have an account open.
pending_mailtos.add(mailto);
@ -861,7 +858,7 @@ public class GearyController : Geary.BaseObject {
Geary.ServiceInformation service,
Geary.Endpoint endpoint,
GLib.TlsConnection cx) {
if (Args.revoke_certs) {
if (this.application.config.revoke_certs) {
// XXX
}
@ -1062,8 +1059,7 @@ public class GearyController : Geary.BaseObject {
private void display_main_window_if_ready() {
if (did_attempt_open_all_accounts() &&
!upgrade_dialog.visible &&
!cancellable_open_account.is_cancelled() &&
!Args.hidden_startup)
!cancellable_open_account.is_cancelled())
main_window.show();
}
@ -1184,8 +1180,8 @@ public class GearyController : Geary.BaseObject {
// If we were waiting for an account to be selected before issuing mailtos, do that now.
if (pending_mailtos.size > 0) {
foreach(string mailto in pending_mailtos)
compose_mailto(mailto);
foreach(string? mailto in pending_mailtos)
compose(mailto);
pending_mailtos.clear();
}
@ -2530,12 +2526,14 @@ public class GearyController : Geary.BaseObject {
revokable.committed.connect(on_revokable_committed);
}
if (revokable != null && description != null)
this.main_window.main_toolbar.undo_tooltip = description;
else
this.main_window.main_toolbar.undo_tooltip = _("Undo (Ctrl+Z)");
if (this.main_window != null) {
if (revokable != null && description != null)
this.main_window.main_toolbar.undo_tooltip = description;
else
this.main_window.main_toolbar.undo_tooltip = _("Undo (Ctrl+Z)");
update_revokable_action();
update_revokable_action();
}
}
private void update_revokable_action() {
@ -3074,7 +3072,7 @@ public class GearyController : Geary.BaseObject {
private void on_link_activated(string uri) {
if (uri.down().has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
compose_mailto(uri);
compose(uri);
} else {
open_uri(uri);
}

View file

@ -73,8 +73,7 @@ public abstract class ClientWebView : WebKit.WebView, Geary.BaseInterface {
*/
public static void init_web_context(Configuration config,
File web_extension_dir,
File cache_dir,
bool enable_logging) {
File cache_dir) {
WebsiteDataManager data_manager = new WebsiteDataManager(cache_dir.get_path());
WebKit.WebContext context = new WebKit.WebContext.with_website_data_manager(data_manager);
// Use a shared process so we don't spawn N WebProcess instances
@ -101,7 +100,7 @@ public abstract class ClientWebView : WebKit.WebView, Geary.BaseInterface {
web_extension_dir.get_path()
);
context.set_web_extensions_initialization_user_data(
new Variant.boolean(enable_logging)
new Variant.boolean(config.enable_debug)
);
});
@ -300,7 +299,7 @@ public abstract class ClientWebView : WebKit.WebView, Geary.BaseInterface {
WebKit.Settings setts = new WebKit.Settings();
setts.allow_modal_dialogs = false;
setts.default_charset = "UTF-8";
setts.enable_developer_extras = Args.inspector;
setts.enable_developer_extras = config.enable_inspector;
setts.enable_fullscreen = false;
setts.enable_html5_database = false;
setts.enable_html5_local_storage = false;

View file

@ -998,7 +998,7 @@ public class ComposerWidget : Gtk.EventBox, Geary.BaseInterface {
}
// User-Agent
email.mailer = GearyApplication.PRGNAME + "/" + GearyApplication.VERSION;
email.mailer = Environment.get_prgname() + "/" + GearyApplication.VERSION;
return email;
}
@ -1968,7 +1968,7 @@ public class ComposerWidget : Gtk.EventBox, Geary.BaseInterface {
if (!this.editor.is_rich_text)
append_menu_section(context_menu, section);
} else if (section == this.context_menu_inspector) {
if (Args.inspector)
if (this.config.enable_inspector)
append_menu_section(context_menu, section);
} else {
append_menu_section(context_menu, section);

View file

@ -408,7 +408,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
add_action(ACTION_COPY_SELECTION, false).activate.connect(() => {
web_view.copy_clipboard();
});
add_action(ACTION_OPEN_INSPECTOR, Args.inspector).activate.connect(() => {
add_action(ACTION_OPEN_INSPECTOR, config.enable_inspector).activate.connect(() => {
this.web_view.get_inspector().show();
});
add_action(ACTION_OPEN_LINK, true, VariantType.STRING)
@ -429,7 +429,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
context_menu_email = (MenuModel) builder.get_object("context_menu_email");
context_menu_image = (MenuModel) builder.get_object("context_menu_image");
context_menu_main = (MenuModel) builder.get_object("context_menu_main");
if (Args.inspector) {
if (config.enable_inspector) {
context_menu_inspector =
(MenuModel) builder.get_object("context_menu_inspector");
}

View file

@ -26,7 +26,7 @@ public class Libnotify : Geary.BaseObject {
monitor.add_required_fields(REQUIRED_FIELDS);
if (!Notify.is_initted()) {
if (!Notify.init(GearyApplication.PRGNAME))
if (!Notify.init(Environment.get_prgname()))
message("Failed to initialize libnotify.");
}

View file

@ -16,11 +16,11 @@ public abstract class ClientWebViewTestCase<V> : TestCase {
protected ClientWebViewTestCase(string name) {
base(name);
this.config = new Configuration(GearyApplication.APP_ID);
this.config.enable_debug = true;
ClientWebView.init_web_context(
this.config,
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
File.new_for_path("/tmp"), // XXX use something better here
true
File.new_for_path("/tmp") // XXX use something better here
);
try {
ClientWebView.load_resources(GLib.File.new_for_path("/tmp"));

View file

@ -15,11 +15,11 @@ public class ClientWebViewTest : TestCase {
public void init_web_context() throws Error {
Configuration config = new Configuration(GearyApplication.APP_ID);
config.enable_debug = true;
ClientWebView.init_web_context(
config,
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
File.new_for_path("/tmp"), // XXX use something better here
true
File.new_for_path("/tmp") // XXX use something better here
);
}