diff options
| author | Hannes Schulze <haschu0103@outlook.de> | 2025-06-19 23:17:58 +0200 |
|---|---|---|
| committer | Hannes Schulze <haschu0103@outlook.de> | 2025-06-19 23:17:58 +0200 |
| commit | 1af3d14f3f995645a0de08a54b244c19840709e9 (patch) | |
| tree | 3c4098863d8a8fd004a2acc8912a23b6036ab4dd /src/application.c | |
| parent | 40efcf60a5f39674b5137f11de7bcfe37fb121b5 (diff) | |
init hs project
Diffstat (limited to 'src/application.c')
| -rw-r--r-- | src/application.c | 691 |
1 files changed, 0 insertions, 691 deletions
diff --git a/src/application.c b/src/application.c deleted file mode 100644 index bad62b1..0000000 --- a/src/application.c +++ /dev/null @@ -1,691 +0,0 @@ -#include "application.h" -#include "panel.h" -#include "launcher.h" -#include "control-center.h" -#include "notification-area.h" -#include "dbus/server.h" -#include "services/battery-service.h" -#include "services/clock-service.h" -#include "services/brightness-service.h" -#include "services/quick-answer-service.h" -#include "services/workspace-service.h" -#include "services/notification-service.h" -#include "services/audio-service.h" -#include "services/network-service.h" -#include "services/bluetooth-service.h" -#include "services/application-service.h" -#include "services/configuration-service.h" - -// -// FoobarApplication: -// -// Entry point for the application. This class is responsible for parsing and handling command line arguments, creating -// services and presenting windows as needed. -// -// Only the panel windows are application windows -- when all panels are closed, the application quits. Because of this, -// the application can't own a reference to the panel windows but needs to store their window IDs. Since all other -// windows are not attached to the application object, the application can hold a reference on them. -// - -struct _FoobarApplication -{ - GtkApplication parent_instance; - FoobarBatteryService* battery_service; - FoobarClockService* clock_service; - FoobarBrightnessService* brightness_service; - FoobarWorkspaceService* workspace_service; - FoobarNotificationService* notification_service; - FoobarAudioService* audio_service; - FoobarNetworkService* network_service; - FoobarBluetoothService* bluetooth_service; - FoobarApplicationService* application_service; - FoobarQuickAnswerService* quick_answer_service; - FoobarConfigurationService* configuration_service; - gulong config_handler_id; - FoobarServer* server_skeleton; - GtkCssProvider* style_provider; - guint bus_owner_id; - GArray* panel_window_ids; - gboolean panel_is_multi_monitor; - GListModel* monitors; - gulong monitors_handler_id; - FoobarLauncher* launcher; - FoobarControlCenter* control_center; - FoobarNotificationArea* notification_area; - gboolean option_inspector; - gboolean option_quit; - gboolean option_toggle_launcher; - gboolean option_toggle_control_center; -}; - -static void foobar_application_class_init ( FoobarApplicationClass* klass ); -static void foobar_application_init ( FoobarApplication* self ); -static void foobar_application_activate ( GApplication* app ); -static int foobar_application_command_line ( GApplication* app, - GApplicationCommandLine* cmdline ); -static void foobar_application_finalize ( GObject* object ); -static void foobar_application_handle_bus_acquired ( GDBusConnection* connection, - gchar const* name, - gpointer userdata ); -static gboolean foobar_application_handle_inspector ( FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ); -static gboolean foobar_application_handle_quit ( FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ); -static gboolean foobar_application_handle_toggle_launcher ( FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ); -static gboolean foobar_application_handle_toggle_control_center( FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ); -static void foobar_application_handle_config_changed ( GObject* object, - GParamSpec* pspec, - gpointer userdata ); -static void foobar_application_handle_monitors_changed ( GListModel* list, - guint position, - guint removed, - guint added, - gpointer userdata ); -static void foobar_application_destroy_panels ( FoobarApplication* self ); -static void foobar_application_create_panels ( FoobarApplication* self ); -static guint foobar_application_create_panel ( FoobarApplication* self, - GdkMonitor* monitor ); - -G_DEFINE_FINAL_TYPE( FoobarApplication, foobar_application, GTK_TYPE_APPLICATION ) - -// --------------------------------------------------------------------------------------------------------------------- -// Application Implementation -// --------------------------------------------------------------------------------------------------------------------- - -// -// Static initialization for the application. -// -void foobar_application_class_init( FoobarApplicationClass* klass ) -{ - GApplicationClass* app_klass = G_APPLICATION_CLASS( klass ); - app_klass->activate = foobar_application_activate; - app_klass->command_line = foobar_application_command_line; - - GObjectClass* object_klass = G_OBJECT_CLASS( klass ); - object_klass->finalize = foobar_application_finalize; -} - -// -// Instance initialization for the application. -// -void foobar_application_init( FoobarApplication* self ) -{ - g_application_set_default( G_APPLICATION( self ) ); - g_application_set_option_context_summary( G_APPLICATION( self ), "A bar." ); - - GOptionEntry const options[] = - { - { - .long_name = "inspector", - .short_name = 'i', - .flags = G_OPTION_FLAG_NONE, - .arg = G_OPTION_ARG_NONE, - .arg_data = &self->option_inspector, - .description = "Open the GTK inspector for the active bar instance.", - .arg_description = NULL, - }, - { - .long_name = "quit", - .short_name = 'q', - .flags = G_OPTION_FLAG_NONE, - .arg = G_OPTION_ARG_NONE, - .arg_data = &self->option_quit, - .description = "Quit the active bar instance.", - .arg_description = NULL, - }, - { - .long_name = "toggle-launcher", - .short_name = 'l', - .flags = G_OPTION_FLAG_NONE, - .arg = G_OPTION_ARG_NONE, - .arg_data = &self->option_toggle_launcher, - .description = "Toggle the launcher visibility for the active bar instance.", - .arg_description = NULL, - }, - { - .long_name = "toggle-control-center", - .short_name = 'c', - .flags = G_OPTION_FLAG_NONE, - .arg = G_OPTION_ARG_NONE, - .arg_data = &self->option_toggle_control_center, - .description = "Toggle the control center visibility for the active bar instance.", - .arg_description = NULL, - }, - { 0 }, - }; - g_application_add_main_option_entries( G_APPLICATION( self ), options ); -} - -// -// Called by GTK when the application is activated (only for a single instance of the application). -// -// This is where the services are created and the windows are presented. -// -void foobar_application_activate( GApplication* app ) -{ - FoobarApplication* self = (FoobarApplication*)app; - - // Initialize services. - - self->battery_service = foobar_battery_service_new( ); - self->clock_service = foobar_clock_service_new( ); - self->brightness_service = foobar_brightness_service_new( ); - self->workspace_service = foobar_workspace_service_new( ); - self->notification_service = foobar_notification_service_new( ); - self->audio_service = foobar_audio_service_new( ); - self->network_service = foobar_network_service_new( ); - self->bluetooth_service = foobar_bluetooth_service_new( ); - self->application_service = foobar_application_service_new( ); - self->quick_answer_service = foobar_quick_answer_service_new( ); - self->configuration_service = foobar_configuration_service_new( ); - - // Enforce a uniform style by forcing Adwaita and shipping our own icons. - - GtkSettings* settings = gtk_settings_get_default( ); - g_object_set( settings, "gtk-theme-name", "Adwaita", NULL ); - - GtkIconTheme* icon_theme = gtk_icon_theme_get_for_display( gdk_display_get_default( ) ); - gtk_icon_theme_add_resource_path( icon_theme, "/foobar/icons" ); - - // This application instance now becomes the "server" process, listening for commands from clients (which can be - // invoked via the command line). - - self->bus_owner_id = g_bus_own_name( - G_BUS_TYPE_SESSION, - g_application_get_application_id( G_APPLICATION( self ) ), - G_BUS_NAME_OWNER_FLAGS_NONE, - foobar_application_handle_bus_acquired, - NULL, - NULL, - self, - NULL ); - - // React to configuration file changes. - - FoobarConfiguration const* config = foobar_configuration_service_get_current( self->configuration_service ); - foobar_application_apply_configuration( self, foobar_configuration_get_general( config ) ); - self->panel_is_multi_monitor = foobar_panel_configuration_get_multi_monitor( foobar_configuration_get_panel( config ) ); - self->config_handler_id = g_signal_connect( - self->configuration_service, - "notify::current", - G_CALLBACK( foobar_application_handle_config_changed ), - self ); - - // React to monitor configuration changes (for multi-monitor support in the panel). - - self->monitors = gdk_display_get_monitors( gdk_display_get_default( ) ); - g_object_ref( self->monitors ); - - self->monitors_handler_id = g_signal_connect( - self->monitors, - "items-changed", - G_CALLBACK( foobar_application_handle_monitors_changed ), - self ); - - // Create all the windows. - - foobar_application_create_panels( self ); - - self->launcher = foobar_launcher_new( - self->application_service, - self->quick_answer_service, - self->configuration_service ); - g_object_ref( self->launcher ); - - self->control_center = foobar_control_center_new( - self->brightness_service, - self->audio_service, - self->network_service, - self->bluetooth_service, - self->notification_service, - self->configuration_service ); - g_object_ref( self->control_center ); - - self->notification_area = foobar_notification_area_new( - self->notification_service, - self->configuration_service ); - g_object_ref( self->notification_area ); - - // Only present the notification area, all other windows start out as hidden windows. - - gtk_window_present( GTK_WINDOW( self->notification_area ) ); -} - -// -// Called before activating the application, when GTK has parsed the command line arguments. -// -// This method decides whether the application should be activated (if it is the first instance). Otherwise it will -// handle command line flags for controlling the application. -// -int foobar_application_command_line( - GApplication* app, - GApplicationCommandLine* cmdline ) -{ - (void)cmdline; - FoobarApplication* self = (FoobarApplication*)app; - - // Try to open a connection to the existing server. - - g_autoptr( GError ) error = NULL; - g_autoptr( FoobarServer ) proxy = foobar_server_proxy_new_for_bus_sync( - G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - g_application_get_application_id( G_APPLICATION( self ) ), - "/com/github/hannesschulze/foobar/server", - NULL, - &error ); - - if ( !proxy ) - { - g_printerr( "Unable to create proxy: %s\n", error->message ); - return 1; - } - - // If there is no existing server application, the "name owner" will not be set. - - g_autofree gchar* owner = g_dbus_proxy_get_name_owner( G_DBUS_PROXY( proxy ) ); - if ( owner ) - { - // There is an active instance -> this is a client. Handle all command line flags. - - if ( self->option_inspector && !foobar_server_call_inspector_sync( proxy, NULL, &error ) ) - { - g_printerr( "Unable to open inspector: %s\n", error->message ); - return 2; - } - - if ( self->option_toggle_launcher && !foobar_server_call_toggle_launcher_sync( proxy, NULL, &error ) ) - { - g_printerr( "Unable to toggle launcher: %s\n", error->message ); - return 2; - } - - if ( self->option_toggle_control_center && !foobar_server_call_toggle_control_center_sync( proxy, NULL, &error ) ) - { - g_printerr( "Unable to toggle control center: %s\n", error->message ); - return 2; - } - - if ( self->option_quit && !foobar_server_call_quit_sync( proxy, NULL, &error ) ) - { - g_printerr( "Unable to quit server: %s\n", error->message ); - return 2; - } - } - else if ( !self->option_quit ) - { - // This is the main application -> launch the server. - - g_application_activate( G_APPLICATION( self ) ); - } - - return 0; -} - -// -// Instance cleanup for the application. -// -void foobar_application_finalize( GObject* object ) -{ - FoobarApplication* self = (FoobarApplication*)object; - - // Destroy the DBus server. - - if ( self->server_skeleton ) - { - g_dbus_interface_skeleton_unexport( G_DBUS_INTERFACE_SKELETON( self->server_skeleton ) ); - } - - // Destroy non-application windows. - - if ( self->launcher ) { gtk_window_destroy( GTK_WINDOW( self->launcher ) ); } - if ( self->control_center ) { gtk_window_destroy( GTK_WINDOW( self->control_center ) ); } - if ( self->notification_area ) { gtk_window_destroy( GTK_WINDOW( self->notification_area ) ); } - - // Destroy all other objects. - - g_clear_handle_id( &self->bus_owner_id, g_bus_unown_name ); - g_clear_signal_handler( &self->config_handler_id, self->configuration_service ); - g_clear_signal_handler( &self->monitors_handler_id, self->monitors ); - g_clear_object( &self->battery_service ); - g_clear_object( &self->clock_service ); - g_clear_object( &self->brightness_service ); - g_clear_object( &self->workspace_service ); - g_clear_object( &self->notification_service ); - g_clear_object( &self->audio_service ); - g_clear_object( &self->network_service ); - g_clear_object( &self->bluetooth_service ); - g_clear_object( &self->application_service ); - g_clear_object( &self->quick_answer_service ); - g_clear_object( &self->configuration_service ); - g_clear_object( &self->style_provider ); - g_clear_object( &self->server_skeleton ); - g_clear_object( &self->launcher ); - g_clear_object( &self->control_center ); - g_clear_object( &self->notification_area ); - g_clear_object( &self->monitors ); - g_clear_pointer( &self->panel_window_ids, g_array_unref ); - - G_OBJECT_CLASS( foobar_application_parent_class )->finalize( object ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------------------------------------------------- - -// -// Create a new application instance. -// -FoobarApplication* foobar_application_new( void ) -{ - return g_object_new( - FOOBAR_TYPE_APPLICATION, - "application-id", - "com.github.hannesschulze.foobar", - "flags", - G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_NON_UNIQUE, - NULL ); -} - -// -// Toggle the launcher window's visibility. -// -void foobar_application_toggle_launcher( FoobarApplication* self ) -{ - g_return_if_fail( FOOBAR_IS_APPLICATION( self ) ); - - gboolean previously_visible = gtk_widget_is_visible( GTK_WIDGET( self->launcher ) ); - gtk_widget_set_visible( GTK_WIDGET( self->launcher ), !previously_visible ); -} - -// -// Toggle the control center window's visibility. -// -void foobar_application_toggle_control_center( FoobarApplication* self ) -{ - g_return_if_fail( FOOBAR_IS_APPLICATION( self ) ); - - gboolean previously_visible = gtk_widget_is_visible( GTK_WIDGET( self->control_center ) ); - gtk_widget_set_visible( GTK_WIDGET( self->control_center ), !previously_visible ); -} - -// -// Apply the general application configuration provided by the configuration service. -// -void foobar_application_apply_configuration( - FoobarApplication* self, - FoobarGeneralConfiguration const* config ) -{ - g_return_if_fail( FOOBAR_IS_APPLICATION( self ) ); - g_return_if_fail( config != NULL ); - - GdkDisplay* display = gdk_display_get_default( ); - - // Remove the old stylesheet from the application. - - if ( self->style_provider ) - { - gtk_style_context_remove_provider_for_display( display, GTK_STYLE_PROVIDER( self->style_provider ) ); - g_clear_object( &self->style_provider ); - } - - // Add the new stylesheet. - - g_autoptr( GFile ) file = g_file_new_for_uri( foobar_general_configuration_get_stylesheet( config ) ); - self->style_provider = gtk_css_provider_new( ); - gtk_css_provider_load_from_file( self->style_provider, file ); - gtk_style_context_add_provider_for_display( - display, - GTK_STYLE_PROVIDER( self->style_provider ), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Signal Handlers -// --------------------------------------------------------------------------------------------------------------------- - -// -// Called after the application server process has asynchronously acquired the bus. -// -// This is where we can export server functionality using the corresponding DBus skeleton object. -// -void foobar_application_handle_bus_acquired( - GDBusConnection* connection, - gchar const* name, - gpointer userdata ) -{ - (void)name; - FoobarApplication* self = (FoobarApplication*)userdata; - - self->server_skeleton = foobar_server_skeleton_new( ); - g_signal_connect( - self->server_skeleton, - "handle-inspector", - G_CALLBACK( foobar_application_handle_inspector ), - self ); - g_signal_connect( - self->server_skeleton, - "handle-quit", - G_CALLBACK( foobar_application_handle_quit ), - self ); - g_signal_connect( - self->server_skeleton, - "handle-toggle-launcher", - G_CALLBACK( foobar_application_handle_toggle_launcher ), - self ); - g_signal_connect( - self->server_skeleton, - "handle-toggle-control-center", - G_CALLBACK( foobar_application_handle_toggle_control_center ), - self ); - - g_autoptr( GError ) error = NULL; - if ( !g_dbus_interface_skeleton_export( - G_DBUS_INTERFACE_SKELETON( self->server_skeleton ), - connection, - "/com/github/hannesschulze/foobar/server", - &error ) ) - { - g_warning( "Unable to export server interface: %s", error->message ); - } -} - -// -// DBus skeleton callback for the "Inspector" method. -// -gboolean foobar_application_handle_inspector( - FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ) -{ - (void)userdata; - - gtk_window_set_interactive_debugging( TRUE ); - - foobar_server_complete_inspector( server, invocation ); - return G_DBUS_METHOD_INVOCATION_HANDLED; -} - -// -// DBus skeleton callback for the "Quit" method. -// -gboolean foobar_application_handle_quit( - FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ) -{ - FoobarApplication* self = (FoobarApplication*)userdata; - - foobar_application_destroy_panels( self ); - - foobar_server_complete_quit( server, invocation ); - return G_DBUS_METHOD_INVOCATION_HANDLED; -} - -// -// DBus skeleton callback for the "ToggleLauncher" method. -// -gboolean foobar_application_handle_toggle_launcher( - FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ) -{ - FoobarApplication* self = (FoobarApplication*)userdata; - - foobar_application_toggle_launcher( self ); - - foobar_server_complete_toggle_launcher( server, invocation ); - return G_DBUS_METHOD_INVOCATION_HANDLED; -} - -// -// DBus skeleton callback for the "ToggleControlCenter" method. -// -gboolean foobar_application_handle_toggle_control_center( - FoobarServer* server, - GDBusMethodInvocation* invocation, - gpointer userdata ) -{ - FoobarApplication* self = (FoobarApplication*)userdata; - - foobar_application_toggle_control_center( self ); - - foobar_server_complete_toggle_control_center( server, invocation ); - return G_DBUS_METHOD_INVOCATION_HANDLED; -} - -// -// Signal handler called when the global configuration file has changed. -// -void foobar_application_handle_config_changed( - GObject* object, - GParamSpec* pspec, - gpointer userdata ) -{ - (void)object; - (void)pspec; - FoobarApplication* self = (FoobarApplication*)userdata; - - // Apply general settings. - - FoobarConfiguration const* config = foobar_configuration_service_get_current( self->configuration_service ); - foobar_application_apply_configuration( self, foobar_configuration_get_general( config ) ); - - // Update panel instances depending on whether multi-monitor mode is enabled. - - FoobarPanelConfiguration const* panel_config = foobar_configuration_get_panel( config ); - gboolean panel_is_multi_monitor = foobar_panel_configuration_get_multi_monitor( panel_config ); - if ( self->panel_is_multi_monitor != panel_is_multi_monitor ) - { - self->panel_is_multi_monitor = panel_is_multi_monitor; - - // Panel windows keep the application alive, so we need to "hold" it while we re-create the panel windows. - - g_application_hold( G_APPLICATION( self ) ); - foobar_application_destroy_panels( self ); - foobar_application_create_panels( self ); - g_application_release( G_APPLICATION( self ) ); - } -} - -// -// Signal handler called when the list of GdkMonitor objects has changed, possibly requiring us to re-create the panel -// windows. -// -void foobar_application_handle_monitors_changed( - GListModel* list, - guint position, - guint removed, - guint added, - gpointer userdata ) -{ - (void)list; - (void)position; - (void)removed; - (void)added; - FoobarApplication* self = (FoobarApplication*)userdata; - - if ( self->panel_is_multi_monitor ) - { - // Panel windows keep the application alive, so we need to "hold" it while we re-create the panel windows. - - g_application_hold( G_APPLICATION( self ) ); - foobar_application_destroy_panels( self ); - foobar_application_create_panels( self ); - g_application_release( G_APPLICATION( self ) ); - } -} - -// --------------------------------------------------------------------------------------------------------------------- -// Helper Methods -// --------------------------------------------------------------------------------------------------------------------- - -// -// Destroy all currently active panel windows. -// -void foobar_application_destroy_panels( FoobarApplication* self ) -{ - for ( guint i = 0; i < self->panel_window_ids->len; ++i ) - { - guint window_id = g_array_index( self->panel_window_ids, guint, i ); - GtkWindow* window = gtk_application_get_window_by_id( GTK_APPLICATION( self ), window_id ); - if ( window ) { gtk_window_destroy( window ); } - } - - g_clear_pointer( &self->panel_window_ids, g_array_unref ); -} - -// -// Create and present panel windows for -// - each monitor, if multi-monitor mode is enabled -// - the current monitor, if multi-monitor mode is disabled. -// -void foobar_application_create_panels( FoobarApplication* self ) -{ - self->panel_window_ids = g_array_new( FALSE, FALSE, sizeof( guint ) ); - - if ( self->panel_is_multi_monitor ) - { - for ( guint i = 0; i < g_list_model_get_n_items( self->monitors ); ++i ) - { - GdkMonitor* monitor = g_list_model_get_item( self->monitors, i ); - guint id = foobar_application_create_panel( self, monitor ); - g_array_append_val( self->panel_window_ids, id ); - } - } - else - { - guint id = foobar_application_create_panel( self, NULL ); - g_array_append_val( self->panel_window_ids, id ); - } -} - -// -// Create and present a panel for a single monitor (or NULL to use the current monitor). -// -guint foobar_application_create_panel( - FoobarApplication* self, - GdkMonitor* monitor ) -{ - FoobarPanel* panel = foobar_panel_new( - GTK_APPLICATION( self ), - monitor, - self->battery_service, - self->clock_service, - self->brightness_service, - self->workspace_service, - self->audio_service, - self->network_service, - self->bluetooth_service, - self->notification_service, - self->configuration_service ); - gtk_window_present( GTK_WINDOW( panel ) ); - - return gtk_application_window_get_id( GTK_APPLICATION_WINDOW( panel ) ); -} |
