From 1af3d14f3f995645a0de08a54b244c19840709e9 Mon Sep 17 00:00:00 2001 From: Hannes Schulze Date: Thu, 19 Jun 2025 23:17:58 +0200 Subject: init hs project --- src/widgets/panel/meson.build | 7 - src/widgets/panel/panel-item-clock.c | 152 ----- src/widgets/panel/panel-item-clock.h | 15 - src/widgets/panel/panel-item-icon.c | 92 --- src/widgets/panel/panel-item-icon.h | 13 - src/widgets/panel/panel-item-status.c | 955 ------------------------------ src/widgets/panel/panel-item-status.h | 25 - src/widgets/panel/panel-item-workspaces.c | 327 ---------- src/widgets/panel/panel-item-workspaces.h | 16 - src/widgets/panel/panel-item.c | 195 ------ src/widgets/panel/panel-item.h | 23 - 11 files changed, 1820 deletions(-) delete mode 100644 src/widgets/panel/meson.build delete mode 100644 src/widgets/panel/panel-item-clock.c delete mode 100644 src/widgets/panel/panel-item-clock.h delete mode 100644 src/widgets/panel/panel-item-icon.c delete mode 100644 src/widgets/panel/panel-item-icon.h delete mode 100644 src/widgets/panel/panel-item-status.c delete mode 100644 src/widgets/panel/panel-item-status.h delete mode 100644 src/widgets/panel/panel-item-workspaces.c delete mode 100644 src/widgets/panel/panel-item-workspaces.h delete mode 100644 src/widgets/panel/panel-item.c delete mode 100644 src/widgets/panel/panel-item.h (limited to 'src/widgets/panel') diff --git a/src/widgets/panel/meson.build b/src/widgets/panel/meson.build deleted file mode 100644 index 10afc94..0000000 --- a/src/widgets/panel/meson.build +++ /dev/null @@ -1,7 +0,0 @@ -foobar_sources += files( - 'panel-item.c', - 'panel-item-icon.c', - 'panel-item-clock.c', - 'panel-item-workspaces.c', - 'panel-item-status.c', -) diff --git a/src/widgets/panel/panel-item-clock.c b/src/widgets/panel/panel-item-clock.c deleted file mode 100644 index 00b2cc5..0000000 --- a/src/widgets/panel/panel-item-clock.c +++ /dev/null @@ -1,152 +0,0 @@ -#include "widgets/panel/panel-item-clock.h" - -// -// FoobarPanelItemClock: -// -// A panel item displaying the current time in the format configured by the user. -// - -struct _FoobarPanelItemClock -{ - FoobarPanelItem parent_instance; - gchar* format; - FoobarPanelItemAction action; - GtkWidget* label; - GtkWidget* button; - FoobarClockService* clock_service; -}; - -static void foobar_panel_item_clock_class_init ( FoobarPanelItemClockClass* klass ); -static void foobar_panel_item_clock_init ( FoobarPanelItemClock* self ); -static void foobar_panel_item_clock_finalize ( GObject* object ); -static void foobar_panel_item_clock_handle_clicked( GtkButton* button, - gpointer userdata ); -static gchar* foobar_panel_item_clock_compute_label ( GtkExpression* expression, - GDateTime* time, - gpointer userdata ); - -G_DEFINE_FINAL_TYPE( FoobarPanelItemClock, foobar_panel_item_clock, FOOBAR_TYPE_PANEL_ITEM ) - -// --------------------------------------------------------------------------------------------------------------------- -// Panel Item Implementation -// --------------------------------------------------------------------------------------------------------------------- - -// -// Static initialization for clock panel items. -// -void foobar_panel_item_clock_class_init( FoobarPanelItemClockClass* klass ) -{ - GObjectClass* object_klass = G_OBJECT_CLASS( klass ); - object_klass->finalize = foobar_panel_item_clock_finalize; -} - -// -// Instance initialization for clock panel items. -// -void foobar_panel_item_clock_init( FoobarPanelItemClock* self ) -{ - self->label = gtk_label_new( NULL ); - gtk_label_set_justify( GTK_LABEL( self->label ), GTK_JUSTIFY_CENTER ); - - self->button = gtk_button_new( ); - gtk_button_set_has_frame( GTK_BUTTON( self->button ), FALSE ); - gtk_button_set_child( GTK_BUTTON( self->button ), self->label ); - gtk_widget_set_halign( self->button, GTK_ALIGN_CENTER ); - gtk_widget_set_valign( self->button, GTK_ALIGN_CENTER ); - g_signal_connect( - self->button, - "clicked", - G_CALLBACK( foobar_panel_item_clock_handle_clicked ), - self ); - - gtk_widget_add_css_class( GTK_WIDGET( self ), "clock" ); - foobar_panel_item_set_child( FOOBAR_PANEL_ITEM( self ), self->button ); -} - -// -// Instance cleanup for clock panel items. -// -void foobar_panel_item_clock_finalize( GObject* object ) -{ - FoobarPanelItemClock* self = (FoobarPanelItemClock*)object; - - g_clear_pointer( &self->format, g_free ); - g_clear_object( &self->clock_service ); - - G_OBJECT_CLASS( foobar_panel_item_clock_parent_class )->finalize( object ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------------------------------------------------- - -// -// Create a new clock panel item with the given configuration. -// -FoobarPanelItem* foobar_panel_item_clock_new( - FoobarPanelItemConfiguration const* config, - FoobarClockService* clock_service ) -{ - g_return_val_if_fail( config != NULL, NULL ); - g_return_val_if_fail( foobar_panel_item_configuration_get_kind( config ) == FOOBAR_PANEL_ITEM_KIND_CLOCK, NULL ); - g_return_val_if_fail( FOOBAR_IS_CLOCK_SERVICE( clock_service ), NULL ); - - FoobarPanelItemClock* self = g_object_new( FOOBAR_TYPE_PANEL_ITEM_CLOCK, NULL ); - self->format = g_strdup( foobar_panel_item_clock_configuration_get_format( config ) ); - self->action = foobar_panel_item_configuration_get_action( config ); - self->clock_service = g_object_ref( clock_service ); - - gtk_widget_set_sensitive( self->button, self->action != FOOBAR_PANEL_ITEM_ACTION_NONE ); - - { - GtkExpression* service_expr = gtk_constant_expression_new( FOOBAR_TYPE_CLOCK_SERVICE, self->clock_service ); - GtkExpression* time_expr = gtk_property_expression_new( FOOBAR_TYPE_CLOCK_SERVICE, service_expr, "time" ); - GtkExpression* label_params[] = { time_expr }; - GtkExpression* label_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( label_params ), - label_params, - G_CALLBACK( foobar_panel_item_clock_compute_label ), - self, - NULL ); - gtk_expression_bind( label_expr, self->label, "label", NULL ); - } - - return FOOBAR_PANEL_ITEM( self ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Signal Handlers -// --------------------------------------------------------------------------------------------------------------------- - -// -// Called when the button was clicked. -// -void foobar_panel_item_clock_handle_clicked( - GtkButton* button, - gpointer userdata ) -{ - (void)button; - FoobarPanelItemClock* self = (FoobarPanelItemClock*)userdata; - - foobar_panel_item_invoke_action( FOOBAR_PANEL_ITEM( self ), self->action ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Value Converters -// --------------------------------------------------------------------------------------------------------------------- - -// -// Derive the label from a timestamp, depending on the configured time format. -// -gchar* foobar_panel_item_clock_compute_label( - GtkExpression* expression, - GDateTime* time, - gpointer userdata ) -{ - (void)expression; - FoobarPanelItemClock* self = (FoobarPanelItemClock*)userdata; - - return g_date_time_format( time, self->format ); -} diff --git a/src/widgets/panel/panel-item-clock.h b/src/widgets/panel/panel-item-clock.h deleted file mode 100644 index 5ff7e5b..0000000 --- a/src/widgets/panel/panel-item-clock.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "widgets/panel/panel-item.h" -#include "services/clock-service.h" - -G_BEGIN_DECLS - -#define FOOBAR_TYPE_PANEL_ITEM_CLOCK foobar_panel_item_clock_get_type( ) - -G_DECLARE_FINAL_TYPE( FoobarPanelItemClock, foobar_panel_item_clock, FOOBAR, PANEL_ITEM_CLOCK, FoobarPanelItem ) - -FoobarPanelItem* foobar_panel_item_clock_new( FoobarPanelItemConfiguration const* config, - FoobarClockService* clock_service ); - -G_END_DECLS diff --git a/src/widgets/panel/panel-item-icon.c b/src/widgets/panel/panel-item-icon.c deleted file mode 100644 index 0a3b4e9..0000000 --- a/src/widgets/panel/panel-item-icon.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "widgets/panel/panel-item-icon.h" - -// -// FoobarPanelItemIcon: -// -// Simple item implementation displaying an icon. -// - -struct _FoobarPanelItemIcon -{ - FoobarPanelItem parent_instance; - GtkWidget* button; - FoobarPanelItemAction action; -}; - -static void foobar_panel_item_icon_class_init ( FoobarPanelItemIconClass* klass ); -static void foobar_panel_item_icon_init ( FoobarPanelItemIcon* self ); -static void foobar_panel_item_icon_handle_clicked( GtkButton* button, - gpointer userdata ); - -G_DEFINE_FINAL_TYPE( FoobarPanelItemIcon, foobar_panel_item_icon, FOOBAR_TYPE_PANEL_ITEM ) - -// --------------------------------------------------------------------------------------------------------------------- -// Panel Item Implementation -// --------------------------------------------------------------------------------------------------------------------- - -// -// Static initialization for icon panel items. -// -void foobar_panel_item_icon_class_init( FoobarPanelItemIconClass* klass ) -{ - (void)klass; -} - -// -// Instance initialization for icon panel items. -// -void foobar_panel_item_icon_init( FoobarPanelItemIcon* self ) -{ - self->button = gtk_button_new( ); - gtk_button_set_has_frame( GTK_BUTTON( self->button ), FALSE ); - gtk_widget_set_halign( self->button, GTK_ALIGN_CENTER ); - gtk_widget_set_valign( self->button, GTK_ALIGN_CENTER ); - g_signal_connect( - self->button, - "clicked", - G_CALLBACK( foobar_panel_item_icon_handle_clicked ), - self ); - - gtk_widget_add_css_class( GTK_WIDGET( self ), "icon" ); - foobar_panel_item_set_child( FOOBAR_PANEL_ITEM( self ), self->button ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------------------------------------------------- - -// -// Create a new icon panel item with the given configuration. -// -FoobarPanelItem* foobar_panel_item_icon_new( FoobarPanelItemConfiguration const* config ) -{ - g_return_val_if_fail( config != NULL, NULL ); - g_return_val_if_fail( foobar_panel_item_configuration_get_kind( config ) == FOOBAR_PANEL_ITEM_KIND_ICON, NULL ); - - FoobarPanelItemIcon* self = g_object_new( FOOBAR_TYPE_PANEL_ITEM_ICON, NULL ); - self->action = foobar_panel_item_configuration_get_action( config ); - - gtk_widget_set_sensitive( self->button, self->action != FOOBAR_PANEL_ITEM_ACTION_NONE ); - gtk_button_set_icon_name( - GTK_BUTTON( self->button ), - foobar_panel_item_icon_configuration_get_icon_name( config ) ); - - return FOOBAR_PANEL_ITEM( self ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Signal Handlers -// --------------------------------------------------------------------------------------------------------------------- - -// -// Called when the button was clicked. -// -void foobar_panel_item_icon_handle_clicked( - GtkButton* button, - gpointer userdata ) -{ - (void)button; - FoobarPanelItemIcon* self = (FoobarPanelItemIcon*)userdata; - - foobar_panel_item_invoke_action( FOOBAR_PANEL_ITEM( self ), self->action ); -} diff --git a/src/widgets/panel/panel-item-icon.h b/src/widgets/panel/panel-item-icon.h deleted file mode 100644 index 2b4ac1f..0000000 --- a/src/widgets/panel/panel-item-icon.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "widgets/panel/panel-item.h" - -G_BEGIN_DECLS - -#define FOOBAR_TYPE_PANEL_ITEM_ICON foobar_panel_item_icon_get_type( ) - -G_DECLARE_FINAL_TYPE( FoobarPanelItemIcon, foobar_panel_item_icon, FOOBAR, PANEL_ITEM_ICON, FoobarPanelItem ) - -FoobarPanelItem* foobar_panel_item_icon_new( FoobarPanelItemConfiguration const* config ); - -G_END_DECLS diff --git a/src/widgets/panel/panel-item-status.c b/src/widgets/panel/panel-item-status.c deleted file mode 100644 index f06bb68..0000000 --- a/src/widgets/panel/panel-item-status.c +++ /dev/null @@ -1,955 +0,0 @@ -#include "widgets/panel/panel-item-status.h" - -// -// FoobarPanelItemStatus: -// -// A panel item showing status indicators for various things such as network state, audio volume, screen brightness, -// battery level, etc. -// - -struct _FoobarPanelItemStatus -{ - FoobarPanelItem parent_instance; - FoobarPanelItemAction action; - GtkWidget* button; - GtkWidget* layout; - FoobarBatteryService* battery_service; - FoobarBrightnessService* brightness_service; - FoobarAudioService* audio_service; - FoobarNetworkService* network_service; - FoobarBluetoothService* bluetooth_service; - FoobarNotificationService* notification_service; - GtkWidget* network_icon; - GtkWidget* network_label; - GtkExpression* network_icon_expr; - FoobarNetwork* network; - gulong network_handler_id; - gulong network_strength_handler_id; -}; - -enum -{ - PROP_ORIENTATION = 1, - N_PROPS, -}; - -static GParamSpec* props[N_PROPS] = { 0 }; - -static void foobar_panel_item_status_class_init ( FoobarPanelItemStatusClass* klass ); -static void foobar_panel_item_status_init ( FoobarPanelItemStatus* self ); -static void foobar_panel_item_status_get_property ( GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ); -static void foobar_panel_item_status_set_property ( GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ); -static void foobar_panel_item_status_finalize ( GObject* object ); -static void foobar_panel_item_status_handle_network_change ( FoobarNetworkAdapterWifi* adapter, - GParamSpec* pspec, - gpointer userdata ); -static void foobar_panel_item_status_handle_network_strength_change( GObject* object, - GParamSpec* pspec, - gpointer userdata ); -static void foobar_panel_item_status_handle_clicked ( GtkButton* button, - gpointer userdata ); -static gboolean foobar_panel_item_status_handle_brightness_scroll ( GtkEventControllerScroll* controller, - gdouble dx, - gdouble dy, - gpointer userdata ); -static gboolean foobar_panel_item_status_handle_audio_scroll ( GtkEventControllerScroll* controller, - gdouble dx, - gdouble dy, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_network_icon ( GtkExpression* expression, - FoobarNetworkAdapter* adapter, - FoobarNetworkAdapterState state, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_bluetooth_icon ( GtkExpression* expression, - gboolean is_enabled, - guint connected_device_count, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_battery_icon ( GtkExpression* expression, - FoobarBatteryState const* state, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_battery_label ( GtkExpression* expression, - FoobarBatteryState const* state, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_brightness_icon ( GtkExpression* expression, - gint percentage, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_brightness_label ( GtkExpression* expression, - gint percentage, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_audio_icon ( GtkExpression* expression, - gboolean is_available, - gint volume, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_audio_label ( GtkExpression* expression, - gboolean is_available, - gint volume, - gpointer userdata ); -static gchar* foobar_panel_item_status_compute_notifications_icon ( GtkExpression* expression, - guint count, - gpointer userdata ); -static GtkWidget* foobar_panel_item_status_create_item ( FoobarPanelItemStatus* self, - FoobarStatusItem item, - gboolean show_labels, - gboolean enable_scrolling ); -static void foobar_panel_item_status_reevaluate_network ( FoobarPanelItemStatus* self ); - -G_DEFINE_FINAL_TYPE_WITH_CODE( - FoobarPanelItemStatus, - foobar_panel_item_status, - FOOBAR_TYPE_PANEL_ITEM, - G_IMPLEMENT_INTERFACE( GTK_TYPE_ORIENTABLE, NULL ) ) - -// --------------------------------------------------------------------------------------------------------------------- -// Panel Item Implementation -// --------------------------------------------------------------------------------------------------------------------- - -// -// Static initialization for status panel items. -// -void foobar_panel_item_status_class_init( FoobarPanelItemStatusClass* klass ) -{ - GObjectClass* object_klass = G_OBJECT_CLASS( klass ); - object_klass->get_property = foobar_panel_item_status_get_property; - object_klass->set_property = foobar_panel_item_status_set_property; - object_klass->finalize = foobar_panel_item_status_finalize; - - gpointer orientable_iface = g_type_default_interface_peek( GTK_TYPE_ORIENTABLE ); - props[PROP_ORIENTATION] = g_param_spec_override( - "orientation", - g_object_interface_find_property( orientable_iface, "orientation" ) ); - g_object_class_install_properties( object_klass, N_PROPS, props ); -} - -// -// Instance initialization for status panel items. -// -void foobar_panel_item_status_init( FoobarPanelItemStatus* self ) -{ - self->layout = gtk_box_new( GTK_ORIENTATION_VERTICAL, 0 ); - - self->button = gtk_button_new( ); - gtk_button_set_has_frame( GTK_BUTTON( self->button ), FALSE ); - gtk_button_set_child( GTK_BUTTON( self->button ), self->layout ); - gtk_widget_set_halign( self->button, GTK_ALIGN_CENTER ); - gtk_widget_set_valign( self->button, GTK_ALIGN_CENTER ); - g_signal_connect( - self->button, - "clicked", - G_CALLBACK( foobar_panel_item_status_handle_clicked ), - self ); - - gtk_widget_add_css_class( GTK_WIDGET( self ), "status" ); - foobar_panel_item_set_child( FOOBAR_PANEL_ITEM( self ), self->button ); -} - -// -// Property getter implementation, mapping a property id to a method. -// -void foobar_panel_item_status_get_property( - GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ) -{ - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)object; - - switch ( prop_id ) - { - case PROP_ORIENTATION: - g_value_set_enum( value, gtk_orientable_get_orientation( GTK_ORIENTABLE( self->layout ) ) ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); - break; - } -} - -// -// Property setter implementation, mapping a property id to a method. -// -void foobar_panel_item_status_set_property( - GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ) -{ - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)object; - - switch ( prop_id ) - { - case PROP_ORIENTATION: - gtk_orientable_set_orientation( GTK_ORIENTABLE( self->layout ), g_value_get_enum( value ) ); - g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_ORIENTATION] ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); - break; - } -} - -// -// Instance cleanup for status panel items. -// -void foobar_panel_item_status_finalize( GObject* object ) -{ - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)object; - - FoobarNetworkAdapterWifi* adapter = foobar_network_service_get_wifi( self->network_service ); - g_clear_signal_handler( &self->network_handler_id, adapter ); - g_clear_signal_handler( &self->network_strength_handler_id, self->network ); - g_clear_object( &self->network ); - g_clear_object( &self->battery_service ); - g_clear_object( &self->brightness_service ); - g_clear_object( &self->audio_service ); - g_clear_object( &self->network_service ); - g_clear_object( &self->bluetooth_service ); - g_clear_object( &self->notification_service ); - g_clear_pointer( &self->network_icon_expr, gtk_expression_unref ); - - G_OBJECT_CLASS( foobar_panel_item_status_parent_class )->finalize( object ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------------------------------------------------- - -// -// Create a new status panel item with the given configuration. -// -FoobarPanelItem* foobar_panel_item_status_new( - FoobarPanelItemConfiguration const* config, - FoobarBatteryService* battery_service, - FoobarBrightnessService* brightness_service, - FoobarAudioService* audio_service, - FoobarNetworkService* network_service, - FoobarBluetoothService* bluetooth_service, - FoobarNotificationService* notification_service ) -{ - g_return_val_if_fail( config != NULL, NULL ); - g_return_val_if_fail( foobar_panel_item_configuration_get_kind( config ) == FOOBAR_PANEL_ITEM_KIND_STATUS, NULL ); - g_return_val_if_fail( FOOBAR_IS_BATTERY_SERVICE( battery_service ), NULL ); - g_return_val_if_fail( FOOBAR_IS_BRIGHTNESS_SERVICE( brightness_service ), NULL ); - g_return_val_if_fail( FOOBAR_IS_AUDIO_SERVICE( audio_service ), NULL ); - g_return_val_if_fail( FOOBAR_IS_NETWORK_SERVICE( network_service ), NULL ); - g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( bluetooth_service ), NULL ); - g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_SERVICE( notification_service ), NULL ); - - FoobarPanelItemStatus* self = g_object_new( FOOBAR_TYPE_PANEL_ITEM_STATUS, NULL ); - self->action = foobar_panel_item_configuration_get_action( config ); - self->battery_service = g_object_ref( battery_service ); - self->brightness_service = g_object_ref( brightness_service ); - self->audio_service = g_object_ref( audio_service ); - self->network_service = g_object_ref( network_service ); - self->bluetooth_service = g_object_ref( bluetooth_service ); - self->notification_service = g_object_ref( notification_service ); - - gtk_widget_set_sensitive( self->button, self->action != FOOBAR_PANEL_ITEM_ACTION_NONE ); - - gtk_box_set_spacing( GTK_BOX( self->layout ), foobar_panel_item_status_configuration_get_spacing( config ) ); - gboolean show_labels = foobar_panel_item_status_configuration_get_show_labels( config ); - gboolean enable_scrolling = foobar_panel_item_status_configuration_get_enable_scrolling( config ); - gsize items_count; - FoobarStatusItem const* items = foobar_panel_item_status_configuration_get_items( config, &items_count ); - for ( gsize i = 0; i < items_count; ++i ) - { - GtkWidget* widget = foobar_panel_item_status_create_item( self, items[i], show_labels, enable_scrolling ); - if ( widget ) - { - gtk_widget_set_halign( widget, GTK_ALIGN_CENTER ); - gtk_box_append( GTK_BOX( self->layout ), widget ); - } - } - - return FOOBAR_PANEL_ITEM( self ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Signal Handlers -// --------------------------------------------------------------------------------------------------------------------- - -// -// Called when the wi-fi adapter's active network changes. -// -// This is used to then subscribe to changes to the active network's strength. Unfortunately, we can't just use -// GtkExpressions here because the active network may be NULL in which case the strength expression would fail. If one -// expression fails to evaluate, then the closure expression used to derive the network icon/label also does not get -// updated. -// -// In addition, this method also updates the network label to show the active network's name or become invisible. -// -void foobar_panel_item_status_handle_network_change( - FoobarNetworkAdapterWifi* adapter, - GParamSpec* pspec, - gpointer userdata ) -{ - (void)pspec; - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)userdata; - - FoobarNetwork* network = foobar_network_adapter_wifi_get_active( adapter ); - if ( self->network != network ) - { - g_clear_signal_handler( &self->network_strength_handler_id, self->network ); - g_clear_object( &self->network ); - - if ( network ) - { - self->network = g_object_ref( network ); - self->network_strength_handler_id = g_signal_connect( - self->network, - "notify::strength", - G_CALLBACK( foobar_panel_item_status_handle_network_strength_change ), - self ); - } - - if ( self->network_label ) - { - gtk_label_set_label( - GTK_LABEL( self->network_label ), self->network ? foobar_network_get_name( self->network ) : NULL ); - gtk_widget_set_visible( GTK_WIDGET( self->network_label ), self->network != NULL ); - } - - foobar_panel_item_status_reevaluate_network( self ); - } -} - -// -// Called when the wi-fi adapter's active network strength changes. -// -// This just forces re-evaluation of the network icon expression for reasons mentioned in -// foobar_panel_item_status_handle_network_change. -// -void foobar_panel_item_status_handle_network_strength_change( - GObject* object, - GParamSpec* pspec, - gpointer userdata ) -{ - (void)object; - (void)pspec; - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)userdata; - foobar_panel_item_status_reevaluate_network( self ); -} - -// -// Called when the button was clicked. -// -void foobar_panel_item_status_handle_clicked( - GtkButton* button, - gpointer userdata ) -{ - (void)button; - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)userdata; - - foobar_panel_item_invoke_action( FOOBAR_PANEL_ITEM( self ), self->action ); -} - -// -// Called when the user has scrolled over the brightness item, used to adjust the brightness level. -// -gboolean foobar_panel_item_status_handle_brightness_scroll( - GtkEventControllerScroll* controller, - gdouble dx, - gdouble dy, - gpointer userdata ) -{ - (void)controller; - (void)dx; - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)userdata; - - gint new_brightness = foobar_brightness_service_get_percentage( self->brightness_service ) + (gint)dy; - foobar_brightness_service_set_percentage( self->brightness_service, new_brightness ); - - return TRUE; -} - -// -// Called when the user has scrolled over the audio item, used to adjust the volume. -// -gboolean foobar_panel_item_status_handle_audio_scroll( - GtkEventControllerScroll* controller, - gdouble dx, - gdouble dy, - gpointer userdata ) -{ - (void)controller; - (void)dx; - FoobarPanelItemStatus* self = (FoobarPanelItemStatus*)userdata; - - FoobarAudioDevice* device = foobar_audio_service_get_default_output( self->audio_service ); - gint new_volume = foobar_audio_device_get_volume( device ) + (gint)dy; - foobar_audio_device_set_volume( device, new_volume ); - - return TRUE; -} - -// --------------------------------------------------------------------------------------------------------------------- -// Value Converters -// --------------------------------------------------------------------------------------------------------------------- - -// -// Derive the network icon from the active network adapter and its state. -// -// In addition, this also uses the wi-fi adapter's active network strength which is monitored separately (see -// foobar_panel_item_status_handle_network_change). -// -gchar* foobar_panel_item_status_compute_network_icon( - GtkExpression* expression, - FoobarNetworkAdapter* adapter, - FoobarNetworkAdapterState state, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - if ( FOOBAR_IS_NETWORK_ADAPTER_WIFI( adapter ) ) - { - if ( state == FOOBAR_NETWORK_ADAPTER_STATE_DISCONNECTED ) { return g_strdup( "fluent-wifi-off-symbolic" ); } - if ( state != FOOBAR_NETWORK_ADAPTER_STATE_CONNECTED ) { return g_strdup( "fluent-wifi-warning-symbolic" ); } - - FoobarNetwork* network = foobar_network_adapter_wifi_get_active( FOOBAR_NETWORK_ADAPTER_WIFI( adapter ) ); - gint strength = network ? foobar_network_get_strength( network ) : 0; - if ( strength <= 25 ) { return g_strdup( "fluent-wifi-4-symbolic" ); } - if ( strength <= 50 ) { return g_strdup( "fluent-wifi-3-symbolic" ); } - if ( strength <= 75 ) { return g_strdup( "fluent-wifi-2-symbolic" ); } - return g_strdup( "fluent-wifi-1-symbolic" ); - } - else - { - return g_strdup( "fluent-virtual-network-symbolic" ); - } -} - -// -// Derive the bluetooth icon from the bluetooth adapter's state and the number of currently connected devices. -// -gchar* foobar_panel_item_status_compute_bluetooth_icon( - GtkExpression* expression, - gboolean is_enabled, - guint connected_device_count, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - if (is_enabled) - { - return ( connected_device_count > 0 ) - ? g_strdup( "fluent-bluetooth-connected-symbolic" ) - : g_strdup( "fluent-bluetooth-symbolic" ); - } - else - { - return g_strdup( "fluent-bluetooth-off-symbolic" ); - } -} - -// -// Derive the battery icon from the current state structure. -// -gchar* foobar_panel_item_status_compute_battery_icon( - GtkExpression* expression, - FoobarBatteryState const* state, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - if ( state ) - { - gint percentage = foobar_battery_state_get_percentage( state ); - if ( foobar_battery_state_is_charging( state ) ) { return g_strdup( "fluent-battery-charge-symbolic" ); } - if ( percentage <= 5 ) { return g_strdup( "fluent-battery-0-symbolic" ); } - if ( percentage <= 15 ) { return g_strdup( "fluent-battery-1-symbolic" ); } - if ( percentage <= 25 ) { return g_strdup( "fluent-battery-2-symbolic" ); } - if ( percentage <= 35 ) { return g_strdup( "fluent-battery-3-symbolic" ); } - if ( percentage <= 45 ) { return g_strdup( "fluent-battery-4-symbolic" ); } - if ( percentage <= 55 ) { return g_strdup( "fluent-battery-5-symbolic" ); } - if ( percentage <= 65 ) { return g_strdup( "fluent-battery-6-symbolic" ); } - if ( percentage <= 75 ) { return g_strdup( "fluent-battery-7-symbolic" ); } - if ( percentage <= 85 ) { return g_strdup( "fluent-battery-8-symbolic" ); } - if ( percentage <= 95 ) { return g_strdup( "fluent-battery-9-symbolic" ); } - return g_strdup( "fluent-battery-10-symbolic" ); - } - else - { - return g_strdup( "fluent-plug-connected-symbolic" ); - } -} - -// -// Derive the battery label from the current state structure, showing the percentage if available. -// -gchar* foobar_panel_item_status_compute_battery_label( - GtkExpression* expression, - FoobarBatteryState const* state, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - if ( state ) - { - return g_strdup_printf( "%d%%", foobar_battery_state_get_percentage( state ) ); - } - else - { - return g_strdup( "n/a" ); - } -} - -// -// Derive the brightness icon from the current percentage value. -// -gchar* foobar_panel_item_status_compute_brightness_icon( - GtkExpression* expression, - gint percentage, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - if ( percentage <= 50 ) - { - return g_strdup( "fluent-brightness-low-symbolic" ); - } - else - { - return g_strdup( "fluent-brightness-high-symbolic" ); - } -} - -// -// Derive the brightness label from the current percentage value. -// -gchar* foobar_panel_item_status_compute_brightness_label( - GtkExpression* expression, - gint percentage, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - return g_strdup_printf( "%d%%", percentage ); -} - -// -// Derive the audio icon from the current state and volume of the default output device. -// -gchar* foobar_panel_item_status_compute_audio_icon( - GtkExpression* expression, - gboolean is_available, - gint volume, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - if ( is_available ) - { - if ( volume == 0 ) { return g_strdup( "fluent-speaker-mute-symbolic" ); } - if ( volume <= 33 ) { return g_strdup( "fluent-speaker-0-symbolic" ); } - if ( volume <= 67 ) { return g_strdup( "fluent-speaker-1-symbolic" ); } - return g_strdup( "fluent-speaker-2-symbolic" ); - } - else - { - return g_strdup( "fluent-speaker-off-symbolic" ); - } -} - -// -// Derive the audio label from the current state and volume of the default output device. -// -gchar* foobar_panel_item_status_compute_audio_label( - GtkExpression* expression, - gboolean is_available, - gint volume, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - if ( is_available ) - { - return g_strdup_printf( "%d%%", volume ); - } - else - { - return g_strdup( "n/a" ); - } -} - -// -// Derive the notification icon from the current number of notifications. -// -gchar* foobar_panel_item_status_compute_notifications_icon( - GtkExpression* expression, - guint count, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - switch ( count ) - { - case 0: - return g_strdup( "fluent-checkmark-circle-symbolic" ); - case 1: - return g_strdup( "fluent-number-circle-1-symbolic" ); - case 2: - return g_strdup( "fluent-number-circle-2-symbolic" ); - case 3: - return g_strdup( "fluent-number-circle-3-symbolic" ); - case 4: - return g_strdup( "fluent-number-circle-4-symbolic" ); - case 5: - return g_strdup( "fluent-number-circle-5-symbolic" ); - case 6: - return g_strdup( "fluent-number-circle-6-symbolic" ); - case 7: - return g_strdup( "fluent-number-circle-7-symbolic" ); - case 8: - return g_strdup( "fluent-number-circle-8-symbolic" ); - case 9: - return g_strdup( "fluent-number-circle-9-symbolic" ); - default: - return g_strdup( "fluent-more-circle-symbolic" ); - } -} - -// --------------------------------------------------------------------------------------------------------------------- -// Helper Methods -// --------------------------------------------------------------------------------------------------------------------- - -// -// Create a new icon displaying the specified status item, optionally adding a label to it (if supported). -// -GtkWidget* foobar_panel_item_status_create_item( - FoobarPanelItemStatus* self, - FoobarStatusItem item, - gboolean show_labels, - gboolean enable_scrolling ) -{ - switch ( item ) - { - case FOOBAR_STATUS_ITEM_NETWORK: - { - GtkWidget* box = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 ); - gtk_widget_set_valign( box, GTK_ALIGN_FILL ); - - GtkExpression* service_expr = gtk_constant_expression_new( - FOOBAR_TYPE_NETWORK_SERVICE, - self->network_service ); - GtkExpression* active_expr = gtk_property_expression_new( - FOOBAR_TYPE_NETWORK_SERVICE, - service_expr, - "active" ); - GtkExpression* state_expr = gtk_property_expression_new( - FOOBAR_TYPE_NETWORK_ADAPTER, - gtk_expression_ref( active_expr ), - "state" ); - GtkExpression* icon_params[] = { active_expr, state_expr }; - self->network_icon_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( icon_params ), - icon_params, - G_CALLBACK( foobar_panel_item_status_compute_network_icon ), - self, - NULL ); - self->network_icon = gtk_image_new( ); - gtk_widget_set_valign( self->network_icon, GTK_ALIGN_CENTER ); - gtk_expression_bind( gtk_expression_ref( self->network_icon_expr ), self->network_icon, "icon-name", NULL ); - gtk_box_append( GTK_BOX( box ), self->network_icon ); - - if ( show_labels ) - { - self->network_label = gtk_label_new( NULL ); - gtk_widget_set_valign( self->network_label, GTK_ALIGN_CENTER ); - gtk_label_set_max_width_chars( GTK_LABEL( self->network_label ), 16 ); - gtk_label_set_ellipsize( GTK_LABEL( self->network_label ), PANGO_ELLIPSIZE_END ); - gtk_box_append( GTK_BOX( box ), self->network_label ); - } - - // Manually subscribe to network (/strength) because evaluation might fail. - - FoobarNetworkAdapterWifi* adapter = foobar_network_service_get_wifi( self->network_service ); - if ( adapter ) - { - self->network_handler_id = g_signal_connect( - adapter, - "notify::active", - G_CALLBACK( foobar_panel_item_status_handle_network_change ), - self ); - if ( foobar_network_adapter_wifi_get_active( adapter ) ) - { - self->network = g_object_ref( foobar_network_adapter_wifi_get_active( adapter ) ); - self->network_strength_handler_id = g_signal_connect( - self->network, - "notify::strength", - G_CALLBACK( foobar_panel_item_status_handle_network_strength_change ), - self ); - } - if ( self->network_label ) - { - gtk_label_set_label( - GTK_LABEL( self->network_label ), - self->network ? foobar_network_get_name( self->network ) : NULL ); - gtk_widget_set_visible( GTK_WIDGET( self->network_label ), self->network != NULL ); - } - } - - return box; - } - case FOOBAR_STATUS_ITEM_BLUETOOTH: - { - GtkWidget* icon = gtk_image_new( ); - gtk_widget_set_valign( icon, GTK_ALIGN_CENTER ); - - GtkExpression* service_expr = gtk_constant_expression_new( - FOOBAR_TYPE_BLUETOOTH_SERVICE, - self->bluetooth_service ); - GtkExpression* enabled_expr = gtk_property_expression_new( - FOOBAR_TYPE_BLUETOOTH_SERVICE, - gtk_expression_ref( service_expr ), - "is-enabled" ); - GtkExpression* connected_devices_expr = gtk_property_expression_new( - FOOBAR_TYPE_BLUETOOTH_SERVICE, - service_expr, - "connected-devices" ); - GtkExpression* connected_device_count_expr = gtk_property_expression_new( - GTK_TYPE_FILTER_LIST_MODEL, - connected_devices_expr, - "n-items" ); - GtkExpression* icon_params[] = { enabled_expr, connected_device_count_expr }; - GtkExpression* icon_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( icon_params ), - icon_params, - G_CALLBACK( foobar_panel_item_status_compute_bluetooth_icon ), - NULL, - NULL ); - gtk_expression_bind( icon_expr, icon, "icon-name", NULL ); - - return icon; - } - case FOOBAR_STATUS_ITEM_BATTERY: - { - GtkWidget* box = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 ); - gtk_widget_set_valign( box, GTK_ALIGN_FILL ); - - GtkExpression* service_expr = gtk_constant_expression_new( - FOOBAR_TYPE_BATTERY_SERVICE, - self->battery_service ); - GtkExpression* state_expr = gtk_property_expression_new( - FOOBAR_TYPE_BATTERY_SERVICE, - service_expr, - "state" ); - - GtkExpression* icon_params[] = { state_expr }; - GtkExpression* icon_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( icon_params ), - icon_params, - G_CALLBACK( foobar_panel_item_status_compute_battery_icon ), - NULL, - NULL ); - GtkWidget* icon = gtk_image_new( ); - gtk_widget_set_valign( icon, GTK_ALIGN_CENTER ); - gtk_expression_bind( icon_expr, icon, "icon-name", NULL ); - gtk_box_append( GTK_BOX( box ), icon ); - - if ( show_labels ) - { - GtkExpression* label_params[] = { gtk_expression_ref( state_expr ) }; - GtkExpression* label_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( label_params ), - label_params, - G_CALLBACK( foobar_panel_item_status_compute_battery_label ), - NULL, - NULL ); - GtkWidget* label = gtk_label_new( NULL ); - gtk_widget_set_valign( label, GTK_ALIGN_CENTER ); - gtk_expression_bind( label_expr, label, "label", NULL ); - gtk_box_append( GTK_BOX( box ), label ); - } - - return box; - } - case FOOBAR_STATUS_ITEM_BRIGHTNESS: - { - GtkWidget* box = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 ); - gtk_widget_set_valign( box, GTK_ALIGN_FILL ); - - if ( enable_scrolling ) - { - GtkEventController* scroll_controller = gtk_event_controller_scroll_new( - GTK_EVENT_CONTROLLER_SCROLL_VERTICAL | GTK_EVENT_CONTROLLER_SCROLL_DISCRETE ); - g_signal_connect( - scroll_controller, - "scroll", - G_CALLBACK( foobar_panel_item_status_handle_brightness_scroll ), - self ); - gtk_widget_add_controller( box, scroll_controller ); - } - - GtkExpression* service_expr = gtk_constant_expression_new( - FOOBAR_TYPE_BRIGHTNESS_SERVICE, - self->brightness_service ); - GtkExpression* percentage_expr = gtk_property_expression_new( - FOOBAR_TYPE_BRIGHTNESS_SERVICE, - service_expr, - "percentage" ); - - GtkExpression* icon_params[] = { percentage_expr }; - GtkExpression* icon_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( icon_params ), - icon_params, - G_CALLBACK( foobar_panel_item_status_compute_brightness_icon ), - NULL, - NULL ); - GtkWidget* icon = gtk_image_new( ); - gtk_widget_set_valign( icon, GTK_ALIGN_CENTER ); - gtk_expression_bind( icon_expr, icon, "icon-name", NULL ); - gtk_box_append( GTK_BOX( box ), icon ); - - if ( show_labels ) - { - GtkExpression* label_params[] = { gtk_expression_ref( percentage_expr ) }; - GtkExpression* label_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( label_params ), - label_params, - G_CALLBACK( foobar_panel_item_status_compute_brightness_label ), - NULL, - NULL ); - GtkWidget* label = gtk_label_new( NULL ); - gtk_widget_set_valign( label, GTK_ALIGN_CENTER ); - gtk_expression_bind( label_expr, label, "label", NULL ); - gtk_box_append( GTK_BOX( box ), label ); - } - - return box; - } - case FOOBAR_STATUS_ITEM_AUDIO: - { - GtkWidget* box = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 ); - gtk_widget_set_valign( box, GTK_ALIGN_FILL ); - - if ( enable_scrolling ) - { - GtkEventController* scroll_controller = gtk_event_controller_scroll_new( - GTK_EVENT_CONTROLLER_SCROLL_VERTICAL | GTK_EVENT_CONTROLLER_SCROLL_DISCRETE ); - g_signal_connect( - scroll_controller, - "scroll", - G_CALLBACK( foobar_panel_item_status_handle_audio_scroll ), - self ); - gtk_widget_add_controller( box, scroll_controller ); - } - - GtkExpression* device_expr = gtk_constant_expression_new( - FOOBAR_TYPE_AUDIO_DEVICE, - foobar_audio_service_get_default_output( self->audio_service ) ); - GtkExpression* available_expr = gtk_property_expression_new( - FOOBAR_TYPE_AUDIO_DEVICE, - gtk_expression_ref( device_expr ), - "is-available" ); - GtkExpression* volume_expr = gtk_property_expression_new( - FOOBAR_TYPE_AUDIO_DEVICE, - gtk_expression_ref( device_expr ), - "volume" ); - - GtkExpression* icon_params[] = { available_expr, volume_expr }; - GtkExpression* icon_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( icon_params ), - icon_params, - G_CALLBACK( foobar_panel_item_status_compute_audio_icon ), - NULL, - NULL ); - GtkWidget* icon = gtk_image_new( ); - gtk_widget_set_valign( icon, GTK_ALIGN_CENTER ); - gtk_expression_bind( icon_expr, icon, "icon-name", NULL ); - gtk_box_append( GTK_BOX( box ), icon ); - - if ( show_labels ) - { - GtkExpression* label_params[] = { gtk_expression_ref( available_expr ), gtk_expression_ref( volume_expr ) }; - GtkExpression* label_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( label_params ), - label_params, - G_CALLBACK( foobar_panel_item_status_compute_audio_label ), - NULL, - NULL ); - GtkWidget* label = gtk_label_new( NULL ); - gtk_widget_set_valign( label, GTK_ALIGN_CENTER ); - gtk_expression_bind( label_expr, label, "label", NULL ); - gtk_box_append( GTK_BOX( box ), label ); - } - - return box; - } - case FOOBAR_STATUS_ITEM_NOTIFICATIONS: - { - GtkWidget* icon = gtk_image_new( ); - gtk_widget_set_valign( icon, GTK_ALIGN_CENTER ); - - GtkExpression* list_expr = gtk_constant_expression_new( - G_TYPE_LIST_MODEL, - foobar_notification_service_get_notifications( self->notification_service ) ); - GtkExpression* count_expr = gtk_property_expression_new( - GTK_TYPE_SORT_LIST_MODEL, - list_expr, - "n-items" ); - GtkExpression* icon_params[] = { count_expr }; - GtkExpression* icon_expr = gtk_cclosure_expression_new( - G_TYPE_STRING, - NULL, - G_N_ELEMENTS( icon_params ), - icon_params, - G_CALLBACK( foobar_panel_item_status_compute_notifications_icon ), - NULL, - NULL ); - gtk_expression_bind( icon_expr, icon, "icon-name", NULL ); - - return icon; - } - default: - g_warn_if_reached( ); - return NULL; - } -} - -// -// Force re-evaluation of the network icon expression. -// -// This is used whenever the active network or its strength changes. -// -void foobar_panel_item_status_reevaluate_network( FoobarPanelItemStatus* self ) -{ - if ( self->network_icon && self->network_icon_expr ) - { - GValue value = G_VALUE_INIT; - if ( gtk_expression_evaluate( self->network_icon_expr, NULL, &value ) ) - { - gtk_image_set_from_icon_name( GTK_IMAGE( self->network_icon ), g_value_get_string( &value ) ); - } - g_value_unset( &value ); - } -} diff --git a/src/widgets/panel/panel-item-status.h b/src/widgets/panel/panel-item-status.h deleted file mode 100644 index 0f1cfdb..0000000 --- a/src/widgets/panel/panel-item-status.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "widgets/panel/panel-item.h" -#include "services/battery-service.h" -#include "services/brightness-service.h" -#include "services/audio-service.h" -#include "services/network-service.h" -#include "services/bluetooth-service.h" -#include "services/notification-service.h" - -G_BEGIN_DECLS - -#define FOOBAR_TYPE_PANEL_ITEM_STATUS foobar_panel_item_status_get_type( ) - -G_DECLARE_FINAL_TYPE( FoobarPanelItemStatus, foobar_panel_item_status, FOOBAR, PANEL_ITEM_STATUS, FoobarPanelItem ) - -FoobarPanelItem* foobar_panel_item_status_new( FoobarPanelItemConfiguration const* config, - FoobarBatteryService* battery_service, - FoobarBrightnessService* brightness_service, - FoobarAudioService* audio_service, - FoobarNetworkService* network_service, - FoobarBluetoothService* bluetooth_service, - FoobarNotificationService* notification_service ); - -G_END_DECLS diff --git a/src/widgets/panel/panel-item-workspaces.c b/src/widgets/panel/panel-item-workspaces.c deleted file mode 100644 index dff629b..0000000 --- a/src/widgets/panel/panel-item-workspaces.c +++ /dev/null @@ -1,327 +0,0 @@ -#include "widgets/panel/panel-item-workspaces.h" -#include "widgets/inset-container.h" - -// -// FoobarPanelItemWorkspaces: -// -// A panel item showing all workspaces for the current monitor (if multi-monitor mode is enabled) as buttons, indicating -// the current state of the workspace (i.e., whether it's active, visible, special, etc.). -// - -struct _FoobarPanelItemWorkspaces -{ - FoobarPanelItem parent_instance; - GtkWidget* list_view; - GtkWidget* inset_container; - FoobarWorkspaceService* workspace_service; - gint button_size; - gint spacing; - GtkFilter* monitor_filter; - gulong monitor_configuration_handler_id; -}; - -enum -{ - PROP_ORIENTATION = 1, - N_PROPS, -}; - -static GParamSpec* props[N_PROPS] = { 0 }; - -static void foobar_panel_item_workspaces_class_init ( FoobarPanelItemWorkspacesClass* klass ); -static void foobar_panel_item_workspaces_init ( FoobarPanelItemWorkspaces* self ); -static void foobar_panel_item_workspaces_get_property ( GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ); -static void foobar_panel_item_workspaces_set_property ( GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ); -static void foobar_panel_item_workspaces_finalize ( GObject* object ); -static void foobar_panel_item_workspaces_handle_item_setup ( GtkListItemFactory* factory, - GtkListItem* list_item, - gpointer userdata ); -static void foobar_panel_item_workspaces_handle_item_clicked ( GtkButton* button, - gpointer userdata ); -static void foobar_panel_item_workspaces_handle_monitor_configuration_changed( FoobarWorkspaceService* service, - gpointer userdata ); -static gchar** foobar_panel_item_workspaces_compute_css_classes ( GtkExpression* expression, - FoobarWorkspaceFlags flags, - gpointer userdata ); -static gboolean foobar_panel_item_workspaces_monitor_filter_func ( gpointer item, - gpointer userdata ); - -G_DEFINE_FINAL_TYPE_WITH_CODE( - FoobarPanelItemWorkspaces, - foobar_panel_item_workspaces, - FOOBAR_TYPE_PANEL_ITEM, - G_IMPLEMENT_INTERFACE( GTK_TYPE_ORIENTABLE, NULL ) ) - -// --------------------------------------------------------------------------------------------------------------------- -// Panel Item Implementation -// --------------------------------------------------------------------------------------------------------------------- - -// -// Static initialization for workspace panel items. -// -void foobar_panel_item_workspaces_class_init( FoobarPanelItemWorkspacesClass* klass ) -{ - GObjectClass* object_klass = G_OBJECT_CLASS( klass ); - object_klass->get_property = foobar_panel_item_workspaces_get_property; - object_klass->set_property = foobar_panel_item_workspaces_set_property; - object_klass->finalize = foobar_panel_item_workspaces_finalize; - - gpointer orientable_iface = g_type_default_interface_peek( GTK_TYPE_ORIENTABLE ); - props[PROP_ORIENTATION] = g_param_spec_override( - "orientation", - g_object_interface_find_property( orientable_iface, "orientation" ) ); - g_object_class_install_properties( object_klass, N_PROPS, props ); -} - -// -// Instance initialization for workspace panel items. -// -void foobar_panel_item_workspaces_init( FoobarPanelItemWorkspaces* self ) -{ - GtkListItemFactory* item_factory = gtk_signal_list_item_factory_new( ); - g_signal_connect( item_factory, "setup", G_CALLBACK( foobar_panel_item_workspaces_handle_item_setup ), self ); - - self->list_view = gtk_list_view_new( NULL, item_factory ); - gtk_widget_set_halign( self->list_view, GTK_ALIGN_CENTER ); - gtk_widget_set_valign( self->list_view, GTK_ALIGN_CENTER ); - gtk_list_view_set_single_click_activate( GTK_LIST_VIEW( self->list_view ), TRUE ); - - self->inset_container = foobar_inset_container_new( ); - foobar_inset_container_set_child( FOOBAR_INSET_CONTAINER( self->inset_container ), GTK_WIDGET( self->list_view ) ); - - gtk_widget_add_css_class( GTK_WIDGET( self ), "workspaces" ); - foobar_panel_item_set_child( FOOBAR_PANEL_ITEM( self ), GTK_WIDGET( self->inset_container ) ); -} - -// -// Property getter implementation, mapping a property id to a method. -// -void foobar_panel_item_workspaces_get_property( - GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ) -{ - FoobarPanelItemWorkspaces* self = (FoobarPanelItemWorkspaces*)object; - - switch ( prop_id ) - { - case PROP_ORIENTATION: - g_value_set_enum( value, gtk_orientable_get_orientation( GTK_ORIENTABLE( self->list_view ) ) ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); - break; - } -} - -// -// Property setter implementation, mapping a property id to a method. -// -void foobar_panel_item_workspaces_set_property( - GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ) -{ - FoobarPanelItemWorkspaces* self = (FoobarPanelItemWorkspaces*)object; - - switch ( prop_id ) - { - case PROP_ORIENTATION: - gtk_orientable_set_orientation( GTK_ORIENTABLE( self->list_view ), g_value_get_enum( value ) ); - g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_ORIENTATION] ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); - break; - } -} - -// -// Instance cleanup for workspace panel items. -// -void foobar_panel_item_workspaces_finalize( GObject* object ) -{ - FoobarPanelItemWorkspaces* self = (FoobarPanelItemWorkspaces*)object; - - g_clear_signal_handler( &self->monitor_configuration_handler_id, self->workspace_service ); - g_clear_object( &self->workspace_service ); - g_clear_object( &self->monitor_filter ); - - G_OBJECT_CLASS( foobar_panel_item_workspaces_parent_class )->finalize( object ); -} - - -// --------------------------------------------------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------------------------------------------------- - -// -// Create a new workspaces panel item with the given configuration. -// -// If monitor is not NULL, only workspaces on this monitor will be shown. -// -FoobarPanelItem* foobar_panel_item_workspaces_new( - FoobarPanelItemConfiguration const* config, - GdkMonitor* monitor, - FoobarWorkspaceService* workspace_service ) -{ - g_return_val_if_fail( config != NULL, NULL ); - g_return_val_if_fail( foobar_panel_item_configuration_get_kind( config ) == FOOBAR_PANEL_ITEM_KIND_WORKSPACES, NULL ); - g_return_val_if_fail( monitor == NULL || GDK_IS_MONITOR( monitor ), NULL ); - g_return_val_if_fail( FOOBAR_IS_WORKSPACE_SERVICE( workspace_service ), NULL ); - - FoobarPanelItemWorkspaces* self = g_object_new( FOOBAR_TYPE_PANEL_ITEM_WORKSPACES, NULL ); - self->button_size = foobar_panel_item_workspaces_configuration_get_button_size( config ); - self->spacing = foobar_panel_item_workspaces_configuration_get_spacing( config ); - self->workspace_service = g_object_ref( workspace_service ); - - // Set up the source model, optionally enabling filtering. - - GListModel* source_model = g_object_ref( foobar_workspace_service_get_workspaces( self->workspace_service ) ); - if ( monitor ) - { - GtkCustomFilter* filter = gtk_custom_filter_new( - foobar_panel_item_workspaces_monitor_filter_func, - g_object_ref( monitor ), - g_object_unref ); - self->monitor_filter = GTK_FILTER( filter ); - source_model = G_LIST_MODEL( gtk_filter_list_model_new( source_model, g_object_ref( self->monitor_filter ) ) ); - - self->monitor_configuration_handler_id = g_signal_connect( - self->workspace_service, - "monitor-configuration-changed", - G_CALLBACK( foobar_panel_item_workspaces_handle_monitor_configuration_changed ), - self ); - } - GtkNoSelection* selection_model = gtk_no_selection_new( source_model ); - gtk_list_view_set_model( GTK_LIST_VIEW( self->list_view ), GTK_SELECTION_MODEL( selection_model ) ); - - // Wrap the list in an inset container to remove the outer margin from the items. - - foobar_inset_container_set_inset_horizontal( FOOBAR_INSET_CONTAINER( self->inset_container ), -self->spacing / 2 ); - foobar_inset_container_set_inset_vertical( FOOBAR_INSET_CONTAINER( self->inset_container ), -self->spacing / 2 ); - - return FOOBAR_PANEL_ITEM( self ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Signal Handlers -// --------------------------------------------------------------------------------------------------------------------- - -// -// Called by the list view to create a widget for displaying a workspace. -// -void foobar_panel_item_workspaces_handle_item_setup( - GtkListItemFactory* factory, - GtkListItem* list_item, - gpointer userdata ) -{ - (void)factory; - FoobarPanelItemWorkspaces* self = (FoobarPanelItemWorkspaces*)userdata; - - GtkWidget* button = gtk_button_new( ); - gtk_widget_set_size_request( button, self->button_size, self->button_size ); - gtk_widget_set_margin_top( button, self->spacing / 2 ); - gtk_widget_set_margin_bottom( button, self->spacing / 2 ); - gtk_widget_set_margin_start( button, self->spacing / 2 ); - gtk_widget_set_margin_end( button, self->spacing / 2 ); - g_signal_connect( - button, - "clicked", - G_CALLBACK( foobar_panel_item_workspaces_handle_item_clicked ), - list_item ); - - gtk_list_item_set_child( list_item, button ); - - { - GtkExpression* item_expr = gtk_property_expression_new( GTK_TYPE_LIST_ITEM, NULL, "item" ); - GtkExpression* active_expr = gtk_property_expression_new( FOOBAR_TYPE_WORKSPACE, item_expr, "flags" ); - GtkExpression* params[] = { active_expr }; - GtkExpression* css_expr = gtk_cclosure_expression_new( - G_TYPE_STRV, - NULL, - G_N_ELEMENTS( params ), - params, - G_CALLBACK( foobar_panel_item_workspaces_compute_css_classes ), - NULL, - NULL ); - gtk_expression_bind( css_expr, button, "css-classes", list_item ); - } -} - -// -// Called by the workspace service when the monitor for any workspace has changed. -// -// This is needed because the GtkFilterListModel does not track changes to the item properties and needs to be -// re-evaluated manually. -// -void foobar_panel_item_workspaces_handle_monitor_configuration_changed( - FoobarWorkspaceService* service, - gpointer userdata ) -{ - (void)service; - FoobarPanelItemWorkspaces* self = (FoobarPanelItemWorkspaces*)userdata; - - gtk_filter_changed( self->monitor_filter, GTK_FILTER_CHANGE_DIFFERENT ); -} - -// -// Called when a workspace button was clicked, activating that workspace. -// -void foobar_panel_item_workspaces_handle_item_clicked( GtkButton* button, gpointer userdata ) -{ - (void)button; - GtkListItem* item = (GtkListItem*)userdata; - - FoobarWorkspace* workspace = gtk_list_item_get_item( item ); - if ( workspace ) { foobar_workspace_activate( workspace ); } -} - -// --------------------------------------------------------------------------------------------------------------------- -// Value Converters -// --------------------------------------------------------------------------------------------------------------------- - -// -// Derive the list of CSS classes for a workspace button from the workspace's current flags. -// -gchar** foobar_panel_item_workspaces_compute_css_classes( - GtkExpression* expression, - FoobarWorkspaceFlags flags, - gpointer userdata ) -{ - (void)expression; - (void)userdata; - - GStrvBuilder* builder = g_strv_builder_new( ); - if ( flags & FOOBAR_WORKSPACE_FLAGS_ACTIVE ) { g_strv_builder_add( builder, "active" ); } - if ( flags & FOOBAR_WORKSPACE_FLAGS_VISIBLE ) { g_strv_builder_add( builder, "visible" ); } - if ( flags & FOOBAR_WORKSPACE_FLAGS_SPECIAL ) { g_strv_builder_add( builder, "special" ); } - if ( flags & FOOBAR_WORKSPACE_FLAGS_URGENT ) { g_strv_builder_add( builder, "urgent" ); } - if ( flags & FOOBAR_WORKSPACE_FLAGS_PERSISTENT ) { g_strv_builder_add( builder, "persistent" ); } - return g_strv_builder_end( builder ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Helper Methods -// --------------------------------------------------------------------------------------------------------------------- - -// -// Check if a workspace is on the panel's monitor. -// -gboolean foobar_panel_item_workspaces_monitor_filter_func( gpointer item, gpointer userdata ) -{ - FoobarWorkspace* workspace = (FoobarWorkspace*)item; - GdkMonitor* monitor = (GdkMonitor*)userdata; - - gchar const* expected = gdk_monitor_get_connector( monitor ); - gchar const* actual = foobar_workspace_get_monitor( workspace ); - return !expected || !g_strcmp0( expected, actual ); -} diff --git a/src/widgets/panel/panel-item-workspaces.h b/src/widgets/panel/panel-item-workspaces.h deleted file mode 100644 index d179217..0000000 --- a/src/widgets/panel/panel-item-workspaces.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "widgets/panel/panel-item.h" -#include "services/workspace-service.h" - -G_BEGIN_DECLS - -#define FOOBAR_TYPE_PANEL_ITEM_WORKSPACES foobar_panel_item_workspaces_get_type( ) - -G_DECLARE_FINAL_TYPE( FoobarPanelItemWorkspaces, foobar_panel_item_workspaces, FOOBAR, PANEL_ITEM_WORKSPACES, FoobarPanelItem ) - -FoobarPanelItem* foobar_panel_item_workspaces_new( FoobarPanelItemConfiguration const* config, - GdkMonitor* monitor, - FoobarWorkspaceService* workspace_service ); - -G_END_DECLS diff --git a/src/widgets/panel/panel-item.c b/src/widgets/panel/panel-item.c deleted file mode 100644 index 918d9f5..0000000 --- a/src/widgets/panel/panel-item.c +++ /dev/null @@ -1,195 +0,0 @@ -#include "widgets/panel/panel-item.h" -#include "application.h" - -// -// FoobarPanelItem: -// -// Base class for all panel items. This is basically a bin layout where the subclass usually sets the child widget. -// - -typedef struct _FoobarPanelItemPrivate -{ - GtkWidget* child; -} FoobarPanelItemPrivate; - -enum -{ - PROP_CHILD = 1, - N_PROPS, -}; - -static GParamSpec* props[N_PROPS] = { 0 }; - -static void foobar_panel_item_class_init ( FoobarPanelItemClass* klass ); -static void foobar_panel_item_init ( FoobarPanelItem* self ); -static void foobar_panel_item_get_property( GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ); -static void foobar_panel_item_set_property( GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ); -static void foobar_panel_item_dispose ( GObject* object ); - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE( FoobarPanelItem, foobar_panel_item, GTK_TYPE_WIDGET ) - -// --------------------------------------------------------------------------------------------------------------------- -// Widget Implementation -// --------------------------------------------------------------------------------------------------------------------- - -// -// Static initialization for panel items. -// -void foobar_panel_item_class_init( FoobarPanelItemClass* klass ) -{ - GtkWidgetClass* widget_klass = GTK_WIDGET_CLASS( klass ); - gtk_widget_class_set_css_name( widget_klass, "panel-item" ); - gtk_widget_class_set_layout_manager_type( widget_klass, GTK_TYPE_BIN_LAYOUT ); - - GObjectClass* object_klass = G_OBJECT_CLASS( klass ); - object_klass->get_property = foobar_panel_item_get_property; - object_klass->set_property = foobar_panel_item_set_property; - object_klass->dispose = foobar_panel_item_dispose; - - props[PROP_CHILD] = g_param_spec_object( - "child", - "Child", - "Child widget for the panel item.", - GTK_TYPE_WIDGET, - G_PARAM_READWRITE ); - g_object_class_install_properties( object_klass, N_PROPS, props ); -} - -// -// Instance initialization for panel items. -// -void foobar_panel_item_init( FoobarPanelItem* self ) -{ - (void)self; -} - -// -// Property getter implementation, mapping a property id to a method. -// -void foobar_panel_item_get_property( - GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ) -{ - FoobarPanelItem* self = (FoobarPanelItem*)object; - - switch ( prop_id ) - { - case PROP_CHILD: - g_value_set_object( value, foobar_panel_item_get_child( self ) ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); - break; - } -} - -// -// Property setter implementation, mapping a property id to a method. -// -void foobar_panel_item_set_property( - GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ) -{ - FoobarPanelItem* self = (FoobarPanelItem*)object; - - switch ( prop_id ) - { - case PROP_CHILD: - foobar_panel_item_set_child( self, g_value_get_object( value ) ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); - break; - } -} - -// -// Instance de-initialization for panel items. -// -void foobar_panel_item_dispose( GObject* object ) -{ - FoobarPanelItem* self = (FoobarPanelItem*)object; - FoobarPanelItemPrivate* priv = foobar_panel_item_get_instance_private( self ); - - g_clear_pointer( &priv->child, gtk_widget_unparent ); - - G_OBJECT_CLASS( foobar_panel_item_parent_class )->dispose( object ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------------------------------------------------- - -// -// Get the child widget for the panel item. -// -GtkWidget* foobar_panel_item_get_child( FoobarPanelItem* self ) -{ - g_return_val_if_fail( FOOBAR_IS_PANEL_ITEM( self ), NULL ); - FoobarPanelItemPrivate* priv = foobar_panel_item_get_instance_private( self ); - - return priv->child; -} - -// -// Update the child widget for the panel item. -// -void foobar_panel_item_set_child( - FoobarPanelItem* self, - GtkWidget* child ) -{ - g_return_if_fail( FOOBAR_IS_PANEL_ITEM( self ) ); - FoobarPanelItemPrivate* priv = foobar_panel_item_get_instance_private( self ); - g_return_if_fail( child == NULL || priv->child == child || gtk_widget_get_parent( child ) == NULL ); - - if ( priv->child != child ) - { - g_clear_pointer( &priv->child, gtk_widget_unparent ); - - if ( child ) - { - priv->child = child; - gtk_widget_set_parent( child, GTK_WIDGET( self ) ); - } - - g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_CHILD] ); - } -} - -// -// Invoke the action for the panel item. -// -// This needs to be triggered by a subclass, for example by adding a button to the item. Support for panel item actions -// is opt-in and subclasses have to explicitly implement it. This is just a helper for implementing the action. -// -void foobar_panel_item_invoke_action( - FoobarPanelItem* self, - FoobarPanelItemAction action ) -{ - g_return_if_fail( FOOBAR_IS_PANEL_ITEM( self ) ); - - switch ( action ) - { - case FOOBAR_PANEL_ITEM_ACTION_NONE: - break; - case FOOBAR_PANEL_ITEM_ACTION_LAUNCHER: - foobar_application_toggle_launcher( FOOBAR_APPLICATION_DEFAULT ); - break; - case FOOBAR_PANEL_ITEM_ACTION_CONTROL_CENTER: - foobar_application_toggle_control_center( FOOBAR_APPLICATION_DEFAULT ); - break; - default: - g_warn_if_reached( ); - break; - } -} diff --git a/src/widgets/panel/panel-item.h b/src/widgets/panel/panel-item.h deleted file mode 100644 index 12a7e35..0000000 --- a/src/widgets/panel/panel-item.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include "services/configuration-service.h" - -G_BEGIN_DECLS - -#define FOOBAR_TYPE_PANEL_ITEM foobar_panel_item_get_type( ) - -G_DECLARE_DERIVABLE_TYPE( FoobarPanelItem, foobar_panel_item, FOOBAR, PANEL_ITEM, GtkWidget ) - -struct _FoobarPanelItemClass -{ - GtkWidgetClass parent_class; -}; - -GtkWidget* foobar_panel_item_get_child ( FoobarPanelItem* self ); -void foobar_panel_item_set_child ( FoobarPanelItem* self, - GtkWidget* child ); -void foobar_panel_item_invoke_action( FoobarPanelItem* self, - FoobarPanelItemAction action ); - -G_END_DECLS -- cgit v1.3.1