diff options
author | kotontrion <[email protected]> | 2024-06-09 20:27:00 +0200 |
---|---|---|
committer | kotontrion <[email protected]> | 2024-06-09 20:27:00 +0200 |
commit | 29b1060c6fc2614dcbfe6edc177944a31f4decd6 (patch) | |
tree | 5e0b0305206f6499edeffe5152267e4ad96b88b0 /src/river-output.c |
initial commit
Diffstat (limited to 'src/river-output.c')
-rw-r--r-- | src/river-output.c | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/src/river-output.c b/src/river-output.c new file mode 100644 index 0000000..4a7398e --- /dev/null +++ b/src/river-output.c @@ -0,0 +1,329 @@ + +#include "river-private.h" +#include <gio/gio.h> +#include "river-status-unstable-v1-client.h" + +struct _AstalRiverOutput { + GObject parent_instance; + guint focused_tags; + guint occupied_tags; + guint urgent_tags; + gchar *layout_name; + gchar *focused_view; + guint id; + gchar* name; +}; + +typedef struct { + struct zriver_status_manager_v1 *river_status_manager; + struct zriver_output_status_v1 *river_output_status; + struct wl_display *wl_display; + struct wl_output *wl_output; +} AstalRiverOutputPrivate; + +G_DEFINE_FINAL_TYPE_WITH_PRIVATE(AstalRiverOutput, astal_river_output, G_TYPE_OBJECT); + +typedef enum { + ASTAL_RIVER_OUTPUT_PROP_FOCUSED_TAGS = 1, + ASTAL_RIVER_OUTPUT_PROP_OCCUPIED_TAGS, + ASTAL_RIVER_OUTPUT_PROP_URGENT_TAGS, + ASTAL_RIVER_OUTPUT_PROP_LAYOUT_NAME, + ASTAL_RIVER_OUTPUT_PROP_NAME, + ASTAL_RIVER_OUTPUT_PROP_FOCUSED_VIEW, + ASTAL_RIVER_OUTPUT_PROP_ID, + ASTAL_RIVER_OUTPUT_N_PROPERTIES +} AstalRiverOutputProperties; + +typedef enum { + ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED, + ASTAL_RIVER_OUTPUT_N_SIGNALS +} AstalRiverOutputSignals; + +static guint astal_river_output_signals[ASTAL_RIVER_OUTPUT_N_SIGNALS] = {0,}; +static GParamSpec *astal_river_output_properties[ASTAL_RIVER_OUTPUT_N_PROPERTIES] = {NULL,}; + +guint astal_river_output_get_id(AstalRiverOutput *self) { + return self->id; +} + +gchar* astal_river_output_get_name(AstalRiverOutput *self) { + return self->name; +} + +gchar* astal_river_output_get_layout_name(AstalRiverOutput *self) { + return self->layout_name; +} + +gchar* astal_river_output_get_focused_view(AstalRiverOutput *self) { + return self->focused_view; +} + +void astal_river_output_set_focused_view(AstalRiverOutput *self, gchar* focused_view) { + g_free(self->focused_view); + self->focused_view = g_strdup(focused_view); + g_object_notify (G_OBJECT(self), "focused-view"); + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +guint astal_river_output_get_focused_tags(AstalRiverOutput *self) { + return self->focused_tags; +} + +guint astal_river_output_get_urgent_tags(AstalRiverOutput *self) { + return self->urgent_tags; +} + +guint astal_river_output_get_occupied_tags(AstalRiverOutput *self) { + return self->occupied_tags; +} + + +struct wl_output* astal_river_output_get_wl_output(AstalRiverOutput *self) { + AstalRiverOutputPrivate *priv = astal_river_output_get_instance_private(self); + return priv->wl_output; +} + +static void astal_river_output_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT(object); + + switch (property_id) { + case ASTAL_RIVER_OUTPUT_PROP_FOCUSED_TAGS: + g_value_set_uint (value, self->focused_tags); + break; + case ASTAL_RIVER_OUTPUT_PROP_OCCUPIED_TAGS: + g_value_set_uint (value, self->occupied_tags); + break; + case ASTAL_RIVER_OUTPUT_PROP_URGENT_TAGS: + g_value_set_uint (value, self->urgent_tags); + break; + case ASTAL_RIVER_OUTPUT_PROP_ID: + g_value_set_uint (value, self->id); + break; + case ASTAL_RIVER_OUTPUT_PROP_NAME: + g_value_set_string (value, self->name); + break; + case ASTAL_RIVER_OUTPUT_PROP_LAYOUT_NAME: + g_value_set_string (value, self->layout_name); + break; + case ASTAL_RIVER_OUTPUT_PROP_FOCUSED_VIEW: + g_value_set_string (value, self->focused_view); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void astal_river_output_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT(object); + + switch (property_id) { + case ASTAL_RIVER_OUTPUT_PROP_ID: + self->id = g_value_get_uint (value); + g_object_notify(G_OBJECT(self), "id"); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +static void noop() {} + +static void astal_river_handle_focused_tags(void *data, + struct zriver_output_status_v1 *status, + uint32_t tags) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT (data); + self->focused_tags = tags; + g_object_notify (G_OBJECT(self), "focused-tags"); + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +static void astal_river_handle_urgent_tags(void *data, + struct zriver_output_status_v1 *status, + uint32_t tags) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT (data); + self->urgent_tags = tags; + g_object_notify (G_OBJECT(self), "urgent-tags"); + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +static void astal_river_handle_occupied_tags(void *data, + struct zriver_output_status_v1 *status, + struct wl_array *view_tags) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT (data); + guint tags = 0; + guint *view; + wl_array_for_each (view, view_tags) { + tags |= *view; + } + + self->occupied_tags = tags; + g_object_notify (G_OBJECT(self), "occupied-tags"); + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +static void astal_river_handle_layout_name(void *data, + struct zriver_output_status_v1 *status, + const char* name) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT (data); + g_free(self->layout_name); + self->layout_name = g_strdup (name); + g_object_notify (G_OBJECT(self), "layout-name"); + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +static void astal_river_handle_layout_name_clear(void *data, + struct zriver_output_status_v1 *status) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT (data); + g_free(self->layout_name); + g_object_notify (G_OBJECT(self), "layout-name"); + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +static void astal_river_wl_output_handle_name(void *data, + struct wl_output *output, + const char* name) { + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT (data); + g_free(self->name); + self->name = g_strdup(name); + g_object_notify (G_OBJECT(self), "name"); + g_signal_emit (self, astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED], 0); +} + +static const struct zriver_output_status_v1_listener output_status_listener = { + .focused_tags = astal_river_handle_focused_tags, + .view_tags = astal_river_handle_occupied_tags, + .urgent_tags = astal_river_handle_urgent_tags, + .layout_name = astal_river_handle_layout_name, + .layout_name_clear = astal_river_handle_layout_name_clear, +}; + +static const struct wl_output_listener wl_output_listener = { + .name = astal_river_wl_output_handle_name, + .geometry = noop, + .mode = noop, + .scale = noop, + .description = noop, + .done = noop, +}; + +static void astal_river_output_finalize(GObject *object) { + + AstalRiverOutput *self = ASTAL_RIVER_OUTPUT(object); + AstalRiverOutputPrivate *priv = astal_river_output_get_instance_private (self); + + zriver_output_status_v1_destroy (priv->river_output_status); + wl_output_destroy (priv->wl_output); + + wl_display_roundtrip (priv->wl_display); + + g_free(self->layout_name); + g_free(self->name); + + G_OBJECT_CLASS (astal_river_output_parent_class)->finalize(object); +} + +static void astal_river_output_init(AstalRiverOutput *self) { +} + +AstalRiverOutput *astal_river_output_new(guint id, + struct wl_output *wl_output, + struct zriver_status_manager_v1 *status_manager, + struct wl_display *wl_display) { + + AstalRiverOutput *self = g_object_new (ASTAL_RIVER_TYPE_OUTPUT, NULL); + AstalRiverOutputPrivate *priv = astal_river_output_get_instance_private (self); + + self->id = id; + priv->wl_display = wl_display; + priv->wl_output = wl_output; + priv->river_status_manager = status_manager; + + priv->river_output_status = zriver_status_manager_v1_get_river_output_status( + priv->river_status_manager, wl_output); + + zriver_output_status_v1_add_listener( + priv->river_output_status, &output_status_listener, self); + + wl_output_add_listener (wl_output, &wl_output_listener, self); + + wl_display_roundtrip(priv->wl_display); + + return self; +} + +static void astal_river_output_class_init(AstalRiverOutputClass *class) { + + GObjectClass *object_class = G_OBJECT_CLASS (class); + object_class->get_property = astal_river_output_get_property; + object_class->set_property = astal_river_output_set_property; + object_class->finalize = astal_river_output_finalize; + + + astal_river_output_properties[ASTAL_RIVER_OUTPUT_PROP_FOCUSED_TAGS] = + g_param_spec_uint("focused-tags", + "focused-tags", + "currently focused tags", + 0, + INT_MAX, + 0, + G_PARAM_READABLE); + astal_river_output_properties[ASTAL_RIVER_OUTPUT_PROP_OCCUPIED_TAGS] = + g_param_spec_uint("occupied-tags", + "occupied-tags", + "currently occupied tags", + 0, + INT_MAX, + 0, + G_PARAM_READABLE); + astal_river_output_properties[ASTAL_RIVER_OUTPUT_PROP_URGENT_TAGS] = + g_param_spec_uint("urgent-tags", + "urgent-tags", + "currently urgent tags", + 0, + INT_MAX, + 0, + G_PARAM_READABLE); + astal_river_output_properties[ASTAL_RIVER_OUTPUT_PROP_ID] = + g_param_spec_uint("id", + "id", + "id of the output object", + 0, + INT_MAX, + 0, + G_PARAM_READABLE); + astal_river_output_properties[ASTAL_RIVER_OUTPUT_PROP_LAYOUT_NAME] = + g_param_spec_string("layout-name", + "layout-name", + "name of the current layout", + NULL, + G_PARAM_READABLE); + astal_river_output_properties[ASTAL_RIVER_OUTPUT_PROP_NAME] = + g_param_spec_string("name", + "name", + "name of the output", + NULL, + G_PARAM_READABLE); + astal_river_output_properties[ASTAL_RIVER_OUTPUT_PROP_FOCUSED_VIEW] = + g_param_spec_string("focused-view", + "focused-view", + "name of last focused view on this output", + NULL, + G_PARAM_READABLE); + + g_object_class_install_properties(object_class, + ASTAL_RIVER_OUTPUT_N_PROPERTIES, + astal_river_output_properties); + astal_river_output_signals[ASTAL_RIVER_OUTPUT_SIGNAL_CHANGED] = + g_signal_new("changed", + G_TYPE_FROM_CLASS(class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); +} |