Skip to content

Instantly share code, notes, and snippets.

@ivanstepanovftw
Last active November 13, 2022 16:20
Show Gist options
  • Select an option

  • Save ivanstepanovftw/8a257f40acd4cb4a532569c88be545b2 to your computer and use it in GitHub Desktop.

Select an option

Save ivanstepanovftw/8a257f40acd4cb4a532569c88be545b2 to your computer and use it in GitHub Desktop.
Gtk3 on theme change event example for GNOME DE C++
...
if (LINUX)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED IMPORTED_TARGET gtk+-3.0)
endif()
...
add_executable(scratch_theme
test/scratch_theme.cpp
)
target_link_libraries(scratch_theme PRIVATE
PkgConfig::GTK3
)
///
/// Listen for Gtk theme changer events
///
#include <gio/gio.h>
#include <thread>
#include <atomic>
#include <iostream>
namespace {
using namespace std::chrono_literals;
GApplication *app = nullptr;
gulong activate_sh; // signal handler
gulong shutdown_sh; // signal handler
gulong interface_changed_sh; // signal handler
GSettings *settings = nullptr;
// GMutex running_mutex;
std::atomic<int> tries_till_exit = 1;
std::atomic<bool> is_activated = false;
std::atomic<bool> is_shutdown = false;
}
void interface_changed_cb(GSettings *settings, gchar *name, gpointer user_data) {
gchar *theme = g_settings_get_string(settings, name);
if (strcmp(name, "color-scheme") == 0) {
tries_till_exit.fetch_sub(1, std::memory_order_relaxed);
}
g_print("theme_changed: %s:%s\n", name, theme);
g_free(theme);
}
/// Main loop
gpointer app_runner(gpointer data) {
g_print("app_runner!!!\n");
int status = g_application_run(app, 0, nullptr);
return reinterpret_cast<void *>(status);
}
void activate_cb(GApplication *app, gpointer user_data) {
g_print("activate_cb\n");
settings = g_settings_new("org.gnome.desktop.interface");
interface_changed_sh = g_signal_connect(settings, "changed", G_CALLBACK(interface_changed_cb), NULL);
is_activated.store(true, std::memory_order_relaxed);
}
void shutdown_cb(GApplication *app, gpointer user_data) {
g_print("shutdown_cb\n");
g_signal_handler_disconnect(settings, interface_changed_sh);
g_object_unref(settings);
settings = nullptr;
is_shutdown.store(true, std::memory_order_relaxed);
}
int main(int argc, char *argv[]) {
// Create app
app = g_application_new("com.wowcube.editor.test", G_APPLICATION_FLAGS_NONE);
g_application_set_inactivity_timeout(app, 1000);
g_application_hold(app); // Hold! Do not exit immediately.
activate_sh = g_signal_connect(app, "activate", G_CALLBACK(activate_cb), NULL);
shutdown_sh = g_signal_connect(app, "shutdown", G_CALLBACK(shutdown_cb), NULL);
GThread *thread = g_thread_new("gio_theme_listener", app_runner, nullptr);
// Wait max 5000 ms until started
auto activate_next_check = std::chrono::steady_clock::now();
auto activate_time_out = activate_next_check + 5000ms;
bool activate_timed_out = false;
while (true) {
if (is_activated.load(std::memory_order_relaxed)) {
break;
}
if (activate_next_check >= activate_time_out) {
activate_timed_out = true;
break;
}
activate_next_check += 100ms;
std::this_thread::sleep_until(activate_next_check);
}
if (activate_timed_out) {
g_print("activate_timed_out\n");
// g_application_quit(app);
return 1;
}
// Do some work on this thread...
while (tries_till_exit != 0) {
#define WAIT_AND_DEBUG
#ifdef WAIT_AND_DEBUG
static int i = 0;
if (i % 10 == 0) {
std::cout << "waiting: tries_till_exit: " << tries_till_exit << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
i++;
#endif
}
// Free connection and exit application
g_application_release(app); // Unhold!
// g_application_quit(app); // FIXME: should I call it?
// // Wait max 5000 ms till shutdown
// auto shutdown_next_check = std::chrono::steady_clock::now();
// auto shutdown_time_out = shutdown_next_check + 5000ms;
// bool shutdown_timed_out = false;
// while (true) {
// if (is_shutdown.load(std::memory_order_relaxed)) {
// break;
// }
// if (shutdown_next_check < shutdown_time_out) {
// shutdown_next_check += 100ms;
// std::this_thread::sleep_until(shutdown_next_check);
// } else {
// shutdown_timed_out = true;
// break;
// }
// }
// if (shutdown_timed_out) {
// g_print("shutdown_timed_out\n");
// return 2;
// }
std::cout << "Joining..." << std::endl;
int result = (int)(uintptr_t)(g_thread_join(thread));
// Cleanup
// g_object_unref(app);
std::cout << "return " << result << std::endl;
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment