Single instance
This commit is contained in:
37
src/main.cpp
37
src/main.cpp
@@ -15,6 +15,7 @@
|
||||
#include "keyrow.h"
|
||||
#include "mapping.h"
|
||||
#include "mappings.h"
|
||||
#include "singleinstance.h"
|
||||
|
||||
#ifndef PACKAGE
|
||||
#define PACKAGE "gkeymapper"
|
||||
@@ -129,7 +130,9 @@ void on_capture_clicked(GtkButton* btn, gpointer userData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sel == 0) {
|
||||
// "Key" and "Key (hold)" capture the same thing: a hold mapping is a single
|
||||
// step that the daemon keeps down while the G key is held.
|
||||
if (sel == 0 || sel == 3) {
|
||||
gkeymapper::open_key_capture_dialog(row, window);
|
||||
}
|
||||
}
|
||||
@@ -144,6 +147,10 @@ static void update_row_state(KeyRow* row) {
|
||||
gtk_button_set_label(GTK_BUTTON(row->captureButton), _("Choose file..."));
|
||||
gtk_entry_set_placeholder_text(GTK_ENTRY(row->targetEntry),
|
||||
_("e.g. /usr/bin/firefox or custom command"));
|
||||
} else if (sel == 3) {
|
||||
gtk_button_set_label(GTK_BUTTON(row->captureButton), _("Capture"));
|
||||
gtk_entry_set_placeholder_text(GTK_ENTRY(row->targetEntry),
|
||||
_("e.g. ctrl+w (held while the G key is held)"));
|
||||
} else {
|
||||
gtk_button_set_label(GTK_BUTTON(row->captureButton), _("Capture"));
|
||||
gtk_entry_set_placeholder_text(GTK_ENTRY(row->targetEntry),
|
||||
@@ -302,6 +309,12 @@ static void action_about(GSimpleAction* /*action*/, GVariant* /*parameter*/, gpo
|
||||
}
|
||||
}
|
||||
|
||||
// Exported by GApplication as org.gtk.Actions, so a new start can close this
|
||||
// instance over D-Bus before it takes over (see singleinstance.h).
|
||||
static void action_quit(GSimpleAction* /*action*/, GVariant* /*parameter*/, gpointer userData) {
|
||||
g_application_quit(G_APPLICATION(userData));
|
||||
}
|
||||
|
||||
static std::string find_asset(const std::string& name) {
|
||||
const char* env = g_getenv("GKEYMAPPER_ASSETS_DIR");
|
||||
if (env && *env) {
|
||||
@@ -395,7 +408,8 @@ void build_ui(GtkApplication* app) {
|
||||
gtk_grid_attach(GTK_GRID(grid), h, c, 0, 1, 1);
|
||||
}
|
||||
|
||||
const char* typeOptions[] = { _("Key"), _("Command"), _("Disabled"), nullptr };
|
||||
const char* typeOptions[] = { _("Key"), _("Command"), _("Disabled"),
|
||||
_("Key (hold)"), nullptr };
|
||||
|
||||
rows.resize(kNumKeys);
|
||||
for (int i = 0; i < kNumKeys; ++i) {
|
||||
@@ -484,6 +498,15 @@ void build_ui(GtkApplication* app) {
|
||||
}
|
||||
|
||||
static void on_activate(GtkApplication* app, gpointer /*user_data*/) {
|
||||
// One window, always. A second "activate" (a desktop launch, or D-Bus
|
||||
// activation while the app is open) must not build another window - main()
|
||||
// replaces a running instance before this runs, so normally there is none.
|
||||
GList* windows = gtk_application_get_windows(app);
|
||||
if (windows != nullptr) {
|
||||
gtk_window_present(GTK_WINDOW(windows->data));
|
||||
return;
|
||||
}
|
||||
|
||||
GSimpleAction* exportAction = g_simple_action_new("export-config", NULL);
|
||||
g_signal_connect(exportAction, "activate", G_CALLBACK(action_export), app);
|
||||
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(exportAction));
|
||||
@@ -496,6 +519,10 @@ static void on_activate(GtkApplication* app, gpointer /*user_data*/) {
|
||||
g_signal_connect(aboutAction, "activate", G_CALLBACK(action_about), app);
|
||||
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(aboutAction));
|
||||
|
||||
GSimpleAction* quitAction = g_simple_action_new("quit", NULL);
|
||||
g_signal_connect(quitAction, "activate", G_CALLBACK(action_quit), app);
|
||||
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(quitAction));
|
||||
|
||||
build_ui(app);
|
||||
}
|
||||
} // namespace
|
||||
@@ -511,6 +538,12 @@ int main(int argc, char** argv) {
|
||||
bind_textdomain_codeset(PACKAGE, "UTF-8");
|
||||
textdomain(PACKAGE);
|
||||
|
||||
// One GUI only, and it is the one that was just started: close the instance
|
||||
// that already owns the app id (an older build, or the same one) before
|
||||
// becoming the primary instance. Without this the new process just hands over
|
||||
// to the old one and its stale window stays on screen.
|
||||
gkeymapper::replace_running_instance(gkeymapper::ipc::kAppId);
|
||||
|
||||
GtkApplication* app = gtk_application_new(gkeymapper::ipc::kAppId,
|
||||
G_APPLICATION_FLAGS_NONE);
|
||||
g_signal_connect(app, "activate", G_CALLBACK(on_activate), nullptr);
|
||||
|
||||
Reference in New Issue
Block a user