Skip to content

Instantly share code, notes, and snippets.

@luigifab
Last active April 17, 2025 14:17
Show Gist options
  • Save luigifab/0fce786cdb93b5687069a82f490ea95e to your computer and use it in GitHub Desktop.
Save luigifab/0fce786cdb93b5687069a82f490ea95e to your computer and use it in GitHub Desktop.
gtk3-classic (GTK 3.24.49) & gtk4-classic (GTK 4.18.4) & gtk5-classic (xptdr) - for Debian Testing
# GtkWindow3: restore focus on application start (GTK_FOCUS_VISIBLE=1)
# https://github.com/GNOME/gtk/blob/3.24.37/gtk/gtkwindow.c
Index: b/gtk/gtkwindow.c
===================================================================
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -6357,7 +6357,9 @@ gtk_window_map
/* inherit from transient parent, so that a dialog that is
* opened via keynav shows focus initially
*/
- if (priv->transient_parent)
+ if (g_strcmp0 (g_getenv ("GTK_FOCUS_VISIBLE"), "1") == 0)
+ gtk_window_set_focus_visible (window, TRUE);
+ else if (priv->transient_parent)
gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
else
gtk_window_set_focus_visible (window, FALSE);
# GtkWindow4: restore focus on application start (GTK_FOCUS_VISIBLE=1)
# https://github.com/GNOME/gtk/blob/4.12.3/gtk/gtkwindow.c
# @todo: with awf-gtk4, compared to awf-gtk3, focus is not on the first toolbar button, why?
Index: b/gtk/gtkwindow.c
===================================================================
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -4013,7 +4013,9 @@ gtk_window_map
/* inherit from transient parent, so that a dialog that is
* opened via keynav shows focus initially
*/
- if (priv->transient_parent)
+ if (g_strcmp0 (g_getenv ("GTK_FOCUS_VISIBLE"), "1") == 0)
+ gtk_window_set_focus_visible (window, TRUE);
+ else if (priv->transient_parent)
gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
else
gtk_window_set_focus_visible (window, FALSE);
# GtkNotebook3: add classes for stack widget
# default way: notebook header.top.bottom.left.right + notebook stack
# updated way: notebook header.top.bottom.left.right + notebook stack.top.bottom.left.right
# https://github.com/GNOME/gtk/blob/3.24.37/gtk/gtknotebook.c
Index: b/gtk/gtknotebook.c
===================================================================
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -1351,6 +1351,7 @@ gtk_notebook_init
gtk_notebook_draw_stack,
NULL,
NULL);
+ gtk_css_gadget_add_class (priv->stack_gadget, GTK_STYLE_CLASS_TOP);
gtk_css_gadget_set_state (priv->stack_gadget, gtk_css_node_get_state (widget_node));
gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), -1, priv->stack_gadget, TRUE, GTK_ALIGN_FILL);
@@ -7074,9 +7075,15 @@ gtk_notebook_update_tab_pos
for (i = 0; i < G_N_ELEMENTS (tab_pos_names); i++)
{
if (tab_pos == i)
+ {
+ gtk_css_gadget_add_class (priv->stack_gadget, tab_pos_names[i]);
gtk_css_gadget_add_class (priv->header_gadget, tab_pos_names[i]);
+ }
else
+ {
+ gtk_css_gadget_remove_class (priv->stack_gadget, tab_pos_names[i]);
gtk_css_gadget_remove_class (priv->header_gadget, tab_pos_names[i]);
+ }
}
gtk_box_gadget_remove_gadget (GTK_BOX_GADGET (priv->gadget), priv->header_gadget);
# GtkNotebook4: add classes for stack widget (warning! left/right not inverted in rtl with gtk4)
# default way: notebook header.top.bottom.left.right + notebook stack
# updated way: notebook header.top.bottom.left.right + notebook stack.top.bottom.left.right
# https://github.com/GNOME/gtk/blob/4.12.3/gtk/gtknotebook.c
Index: b/gtk/gtknotebook.c
===================================================================
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -1492,6 +1492,7 @@ gtk_notebook_init
gtk_widget_set_hexpand (notebook->stack_widget, TRUE);
gtk_widget_set_vexpand (notebook->stack_widget, TRUE);
gtk_widget_set_parent (notebook->stack_widget, GTK_WIDGET (notebook));
+ gtk_widget_add_css_class (notebook->stack_widget, "top");
dest = gtk_drop_target_new (GTK_TYPE_NOTEBOOK_PAGE, GDK_ACTION_MOVE);
gtk_drop_target_set_preload (dest, TRUE);
@@ -6214,9 +6214,15 @@ gtk_notebook_update_tab_pos
for (i = 0; i < G_N_ELEMENTS (tab_pos_names); i++)
{
if (tab_pos == i)
+ {
+ gtk_widget_add_css_class (notebook->stack_widget, tab_pos_names[i]);
gtk_widget_add_css_class (notebook->header_widget, tab_pos_names[i]);
+ }
else
+ {
+ gtk_widget_remove_css_class (notebook->stack_widget, tab_pos_names[i]);
gtk_widget_remove_css_class (notebook->header_widget, tab_pos_names[i]);
+ }
}
layout = gtk_widget_get_layout_manager (GTK_WIDGET (notebook));
# GtkProgressBar3: restore the double color of the progress text with automatic min-width/min-height from text
# default way
# progressbar trough[.empty][.full]
# progressbar text OR progressbar > text
# updated way
# progressbar[.empty][.full] trough[.empty][.full]
# progressbar[.empty][.full] text OR progressbar[.empty][.full] > text
# and when GTK_PROGRESS_TEXT_INSIDE=1 (text is the last child node of progressbar)
# (start_clip) progressbar.classic text.progress
# (end_clip) progressbar.classic text.trough
# https://github.com/lah7/gtk3-classic/issues/58
# https://github.com/GNOME/gtk/blob/3.24.49/gtk/gtkprogressbar.c
Index: b/gtk/gtkprogressbar.c
===================================================================
--- a/gtk/gtkprogressbar.c
+++ b/gtk/gtkprogressbar.c
@@ -449,15 +449,21 @@ update_fraction_classes
full = TRUE;
}
- if (empty)
- gtk_css_gadget_add_class (priv->trough_gadget, "empty");
- else
- gtk_css_gadget_remove_class (priv->trough_gadget, "empty");
-
- if (full)
- gtk_css_gadget_add_class (priv->trough_gadget, "full");
- else
- gtk_css_gadget_remove_class (priv->trough_gadget, "full");
+ if (empty) {
+ gtk_css_gadget_add_class (priv->trough_gadget, "empty");
+ gtk_css_gadget_add_class (priv->gadget, "empty");
+ } else {
+ gtk_css_gadget_remove_class (priv->trough_gadget, "empty");
+ gtk_css_gadget_remove_class (priv->gadget, "empty");
+ }
+
+ if (full) {
+ gtk_css_gadget_add_class (priv->trough_gadget, "full");
+ gtk_css_gadget_add_class (priv->gadget, "full");
+ } else {
+ gtk_css_gadget_remove_class (priv->trough_gadget, "full");
+ gtk_css_gadget_remove_class (priv->gadget, "full");
+ }
}
static void
@@ -749,7 +755,7 @@ gtk_progress_bar_measure
pbar = GTK_PROGRESS_BAR (widget);
priv = pbar->priv;
- if (priv->show_text)
+ if (priv->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") != 0))
gtk_css_gadget_get_preferred_size (priv->text_gadget,
orientation,
-1,
@@ -932,6 +938,18 @@ gtk_progress_bar_measure_trough
gtk_widget_style_get (widget, "min-vertical-bar-height", minimum, NULL);
}
+ if (priv->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0))
+ {
+ if ( ((orientation == GTK_ORIENTATION_HORIZONTAL) && (priv->orientation == GTK_ORIENTATION_VERTICAL)) ||
+ ((orientation == GTK_ORIENTATION_VERTICAL) && (priv->orientation == GTK_ORIENTATION_HORIZONTAL)) )
+ {
+ gint text_minimum;
+ gtk_css_gadget_get_preferred_size (priv->text_gadget, orientation, -1, &text_minimum, NULL, NULL, NULL);
+ if (*minimum < text_minimum)
+ *minimum = text_minimum;
+ }
+ }
+
*natural = *minimum;
if (minimum_baseline)
@@ -987,6 +1005,18 @@ gtk_progress_bar_measure_progress
gtk_widget_style_get (widget, "min-horizontal-bar-height", minimum, NULL);
}
+ if (priv->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0))
+ {
+ if ( ((orientation == GTK_ORIENTATION_HORIZONTAL) && (priv->orientation == GTK_ORIENTATION_VERTICAL)) ||
+ ((orientation == GTK_ORIENTATION_VERTICAL) && (priv->orientation == GTK_ORIENTATION_HORIZONTAL)) )
+ {
+ gint text_minimum;
+ gtk_css_gadget_get_preferred_size (priv->text_gadget, orientation, -1, &text_minimum, NULL, NULL, NULL);
+ if (*minimum < text_minimum)
+ *minimum = text_minimum;
+ }
+ }
+
*natural = *minimum;
if (minimum_baseline)
@@ -1328,11 +1358,105 @@ gtk_progress_bar_render_text
if (priv->ellipsize)
pango_layout_set_width (layout, width * PANGO_SCALE);
- gtk_render_layout (context, cr, x, y, layout);
-
- g_object_unref (layout);
-
- gtk_style_context_restore (context);
+ if ((g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0) && (g_strcmp0 (g_getenv ("STOP3"), "1") != 0))
+ {
+ gint width, height;
+ GdkRectangle start_clip, end_clip;
+ gboolean ltr = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR, rtl = !ltr;
+
+ GtkAllocation allocation_total, allocation_progress;
+ gtk_css_gadget_get_preferred_size (priv->gadget, GTK_ORIENTATION_HORIZONTAL, -1, &width, NULL, NULL, NULL);
+ gtk_css_gadget_get_preferred_size (priv->gadget, GTK_ORIENTATION_VERTICAL, -1, &height, NULL, NULL, NULL);
+ allocation_total.width = width;
+ allocation_total.height = height;
+ gtk_css_gadget_get_preferred_size (priv->progress_gadget, GTK_ORIENTATION_HORIZONTAL, -1, &width, NULL, NULL, NULL);
+ gtk_css_gadget_get_preferred_size (priv->progress_gadget, GTK_ORIENTATION_VERTICAL, -1, &height, NULL, NULL, NULL);
+ allocation_progress.width = width;
+ allocation_progress.height = height;
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (ltr && !priv->inverted || rtl && priv->inverted)
+ {
+ start_clip.x = 0;
+ start_clip.y = 0;
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = allocation_progress.width;
+ end_clip.y = 0;
+ end_clip.width = allocation_total.width - allocation_progress.width;
+ end_clip.height = allocation_total.height;
+ }
+ else
+ {
+ start_clip.x = allocation_total.width - allocation_progress.width; // here
+ start_clip.y = 0;
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = 0; // here
+ end_clip.y = 0;
+ end_clip.width = allocation_total.width - allocation_progress.width;
+ end_clip.height = allocation_total.height;
+ }
+ }
+ else
+ {
+ if (!priv->ellipsize)
+ pango_layout_set_width (layout, allocation_total.width * PANGO_SCALE);
+ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+
+ if (ltr && !priv->inverted || rtl && !priv->inverted)
+ {
+ start_clip.x = 0;
+ start_clip.y = 0;
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = 0;
+ end_clip.y = allocation_progress.height;
+ end_clip.width = allocation_total.width;
+ end_clip.height = allocation_total.height - allocation_progress.height;
+ }
+ else
+ {
+ start_clip.x = 0;
+ start_clip.y = allocation_total.height - allocation_progress.height; // here
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = 0;
+ end_clip.y = 0; // here
+ end_clip.width = allocation_total.width;
+ end_clip.height = allocation_total.height - allocation_progress.height;
+ }
+ }
+
+ if (start_clip.width > 0 && start_clip.height > 0)
+ {
+ cairo_save (cr);
+ gdk_cairo_rectangle (cr, &start_clip);
+ cairo_clip (cr);
+ gtk_style_context_add_class (context, "progress");
+ gtk_render_layout (context, cr, x, y, layout);
+ gtk_style_context_remove_class (context, "progress");
+ cairo_restore (cr);
+ }
+ if (end_clip.width > 0 && end_clip.height > 0)
+ {
+ cairo_save (cr);
+ gdk_cairo_rectangle (cr, &end_clip);
+ cairo_clip (cr);
+ gtk_style_context_add_class (context, "trough");
+ gtk_render_layout (context, cr, x, y, layout);
+ gtk_style_context_remove_class (context, "trough");
+ cairo_restore (cr);
+ }
+ }
+ else
+ {
+ gtk_render_layout (context, cr, x, y, layout);
+ }
+
+ g_object_unref (layout);
+ gtk_style_context_restore (context); g_print("gtk_progress_bar_render_text\n");
return FALSE;
}
@@ -1565,22 +1689,40 @@ gtk_progress_bar_set_show_text
if (show_text)
{
- priv->text_gadget = gtk_css_custom_gadget_new ("text",
- GTK_WIDGET (pbar),
- priv->gadget,
- priv->trough_gadget,
- gtk_progress_bar_measure_text,
- NULL,
- gtk_progress_bar_render_text,
- NULL,
- NULL);
+ if (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0)
+ {
+ gtk_css_gadget_add_class (priv->gadget, "classic");
+ priv->text_gadget = gtk_css_custom_gadget_new ("text",
+ GTK_WIDGET (pbar),
+ priv->gadget,
+ NULL,
+ gtk_progress_bar_measure_text,
+ NULL,
+ gtk_progress_bar_render_text,
+ NULL,
+ NULL);
+ }
+ else
+ {
+ priv->text_gadget = gtk_css_custom_gadget_new ("text",
+ GTK_WIDGET (pbar),
+ priv->gadget,
+ priv->trough_gadget,
+ gtk_progress_bar_measure_text,
+ NULL,
+ gtk_progress_bar_render_text,
+ NULL,
+ NULL);
+ }
g_signal_connect (gtk_css_gadget_get_node (priv->text_gadget), "style-changed",
G_CALLBACK (gtk_progress_bar_text_style_changed), pbar);
update_node_state (pbar);
}
else
{
+ if (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0)
+ gtk_css_gadget_remove_class (priv->gadget, "classic");
if (priv->text_gadget)
gtk_css_node_set_parent (gtk_css_gadget_get_node (priv->text_gadget), NULL);
g_clear_object (&priv->text_gadget);
# GtkProgressBar4: experimental, restore the double color of the progress text WITHOUT automatic min-width/min-height from text
# default way
# progressbar trough[.empty][.full]
# progressbar text OR progressbar > text
# updated way
# progressbar[.empty][.full] trough[.empty][.full]
# progressbar[.empty][.full] text OR progressbar[.empty][.full] > text
# and when GTK_PROGRESS_TEXT_INSIDE=1 (text and .text are the last child nodes of progressbar)
# (original) progressbar.classic text
# (start_clip) progressbar.classic .text.progress
# (end_clip) progressbar.classic .text.trough
# a lot of deprecated things - but it works
# https://github.com/lah7/gtk3-classic/issues/58
# https://github.com/GNOME/gtk/blob/4.18.3/gtk/gtkprogressbar.c
Index: b/gtk/gtkprogressbar.c
===================================================================
--- a/gtk/gtkprogressbar.c
+++ b/gtk/gtkprogressbar.c
@@ -37,6 +37,11 @@
#include "gtkprivate.h"
#include "gtksnapshot.h"
#include "gtkwidgetprivate.h"
+#include "deprecated/gtkstylecontext.h"
+#include "deprecated/gtkrender.h"
+#include "gtkdrawingarea.h"
+#include "gtkcssprovider.h"
+#include <graphene.h>
#include <string.h>
@@ -161,6 +166,8 @@
GtkOrientation orientation);
static void gtk_progress_bar_direction_changed (GtkWidget *widget,
GtkTextDirection previous_dir);
+static void on_label_update (GObject *object, GParamSpec *pspec, gpointer user_data);
+static void draw_text (GtkProgressBar *pbar, GtkWidget *widget, cairo_t* cr, int width, int height);
G_DEFINE_TYPE_WITH_CODE (GtkProgressBar, gtk_progress_bar, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)
@@ -288,15 +295,21 @@ update_fraction_classes
full = TRUE;
}
- if (empty)
- gtk_widget_add_css_class (pbar->trough_widget, "empty");
- else
- gtk_widget_remove_css_class (pbar->trough_widget, "empty");
-
- if (full)
- gtk_widget_add_css_class (pbar->trough_widget, "full");
- else
- gtk_widget_remove_css_class (pbar->trough_widget, "full");
+ if (empty) {
+ gtk_widget_add_css_class (pbar->trough_widget, "empty");
+ gtk_widget_add_css_class (GTK_WIDGET (pbar), "empty");
+ } else {
+ gtk_widget_remove_css_class (pbar->trough_widget, "empty");
+ gtk_widget_remove_css_class (GTK_WIDGET (pbar), "empty");
+ }
+
+ if (full) {
+ gtk_widget_add_css_class (pbar->trough_widget, "full");
+ gtk_widget_add_css_class (GTK_WIDGET (pbar), "full");
+ } else {
+ gtk_widget_remove_css_class (pbar->trough_widget, "full");
+ gtk_widget_remove_css_class (GTK_WIDGET (pbar), "full");
+ }
}
static void
@@ -397,6 +410,24 @@ allocate_trough
&progress_width, NULL,
NULL, NULL);
+ g_print("allocate_trough\n"); if (pbar->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0))
+ { g_print("label = %s\n", gtk_label_get_labe (GTK_LABEL (pbar->label)));
+ if (pbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ int text_height;
+ gtk_widget_measure (pbar->label, GTK_ORIENTATION_VERTICAL, -1, &text_height, NULL, NULL, NULL);
+ if (progress_height < text_height)
+ progress_height = text_height;
+ }
+ else if (pbar->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ int text_width;
+ gtk_widget_measure (pbar->label, GTK_ORIENTATION_HORIZONTAL, -1, &text_width, NULL, NULL, NULL);
+ if (progress_width < text_width)
+ progress_width = text_width;
+ }
+ }
+
if (pbar->activity_mode)
{
if (pbar->orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -458,6 +489,16 @@ snapshot_trough
gtk_css_boxes_init (&boxes, GTK_WIDGET (gizmo));
gtk_snapshot_push_rounded_clip (snapshot, gtk_css_boxes_get_border_box (&boxes));
gtk_widget_snapshot_child (GTK_WIDGET (gizmo), pbar->progress_widget, snapshot);
+
+ GtkAllocation alloc;
+ gtk_widget_get_allocation (GTK_WIDGET (gizmo), &alloc);
+ graphene_rect_t bounds;
+ bounds = graphene_rect_init (0, 0, alloc.width, alloc.height);
+
+ cairo_t *cr = gtk_snapshot_append_cairo (snapshot, &bounds);
+ draw_text (pbar, GTK_WIDGET (gizmo), cr, alloc.width, alloc.height);
+ cairo_destroy (cr);
+
gtk_snapshot_pop (snapshot);
}
}
@@ -916,13 +957,26 @@ gtk_progress_bar_set_show_text
"label", text,
"ellipsize", pbar->ellipsize,
NULL);
- gtk_widget_insert_after (pbar->label, GTK_WIDGET (pbar), NULL);
+
+ if (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0)
+ {
+ gtk_widget_add_css_class (GTK_WIDGET (pbar), "classic");
+ gtk_widget_insert_before (pbar->label, GTK_WIDGET (pbar), NULL);
+ //gtk_widget_set_visible (pbar->label, FALSE);
+ //g_signal_connect (pbar->label, "notify::label", G_CALLBACK (on_label_update), pbar);
+ }
+ else
+ {
+ gtk_widget_insert_after (pbar->label, GTK_WIDGET (pbar), NULL);
+ }
g_free (text);
}
else
{
g_clear_pointer (&pbar->label, gtk_widget_unparent);
+ if (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0)
+ gtk_widget_remove_css_class (GTK_WIDGET (pbar), "classic");
}
g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_SHOW_TEXT]);
@@ -1156,3 +1210,112 @@
return pbar->ellipsize;
}
+
+static void on_label_update (GObject *object, GParamSpec *pspec, gpointer user_data) {
+ gtk_widget_queue_draw (GTK_WIDGET (user_data));
+}
+
+static void draw_text (GtkProgressBar *pbar, GtkWidget *widget, cairo_t* cr, int width, int height) {
+
+ int x, y, text_width, text_height;
+
+ // same idea as gtk3
+ GtkStyleContext *context = gtk_widget_get_style_context (widget);
+ gtk_style_context_save (context);
+ PangoLayout *layout = gtk_widget_create_pango_layout (widget, get_current_text (pbar));
+
+ // to center the text horizontal & vertical
+ pango_layout_get_pixel_size (layout, &text_width, &text_height);
+ x = (width - text_width) / 2;
+ y = (height - text_height) / 2;
+
+ // copied from gtk3 patch (except for gtk_widget_get_allocation)
+ // it's deprecated, but osef!
+
+ pango_layout_set_ellipsize (layout, pbar->ellipsize);
+ if (pbar->ellipsize)
+ pango_layout_set_width (layout, width * PANGO_SCALE);
+
+
+ GdkRectangle start_clip, end_clip;
+ gboolean ltr = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR, rtl = !ltr;
+
+ GtkAllocation allocation_total, allocation_progress;
+ gtk_widget_get_allocation (GTK_WIDGET (pbar), &allocation_total);
+ gtk_widget_get_allocation (pbar->progress_widget, &allocation_progress);
+
+ if (pbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (ltr && !pbar->inverted || rtl && pbar->inverted)
+ {
+ start_clip.x = 0;
+ start_clip.y = 0;
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = allocation_progress.width;
+ end_clip.y = 0;
+ end_clip.width = allocation_total.width - allocation_progress.width;
+ end_clip.height = allocation_total.height;
+ }
+ else
+ {
+ start_clip.x = allocation_total.width - allocation_progress.width; // here
+ start_clip.y = 0;
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = 0; // here
+ end_clip.y = 0;
+ end_clip.width = allocation_total.width - allocation_progress.width;
+ end_clip.height = allocation_total.height;
+ }
+ }
+ else
+ {
+ if (ltr && !pbar->inverted || rtl && !pbar->inverted)
+ {
+ start_clip.x = 0;
+ start_clip.y = 0;
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = 0;
+ end_clip.y = allocation_progress.height;
+ end_clip.width = allocation_total.width;
+ end_clip.height = allocation_total.height - allocation_progress.height;
+ }
+ else
+ {
+ start_clip.x = 0;
+ start_clip.y = allocation_total.height - allocation_progress.height; // here
+ start_clip.width = allocation_progress.width;
+ start_clip.height = allocation_progress.height;
+ end_clip.x = 0;
+ end_clip.y = 0; // here
+ end_clip.width = allocation_total.width;
+ end_clip.height = allocation_total.height - allocation_progress.height;
+ }
+ }
+
+ if (start_clip.width > 0 && start_clip.height > 0)
+ {
+ cairo_save (cr);
+ gdk_cairo_rectangle (cr, &start_clip);
+ cairo_clip (cr);
+ gtk_style_context_add_class (context, "progress");
+ gtk_render_layout (context, cr, x, y, layout);
+ gtk_style_context_remove_class (context, "progress");
+ cairo_restore (cr);
+ }
+ if (end_clip.width > 0 && end_clip.height > 0)
+ {
+ cairo_save (cr);
+ gdk_cairo_rectangle (cr, &end_clip);
+ cairo_clip (cr);
+ gtk_style_context_add_class (context, "trough");
+ gtk_render_layout (context, cr, x, y, layout);
+ gtk_style_context_remove_class (context, "trough");
+ cairo_restore (cr);
+ }
+
+ g_object_unref (layout);
+ gtk_style_context_restore (context);
+}
# GtkWindow3: toggle .csd/.solid-csd when compositor is enabled/disabled and do not add solid-csd for non CSD windows/dialogs
# default way
# compositor enabled + csd window/dialog: window.csd dialog.csd
# compositor disabled + csd window/dialog: window.solid-csd dialog.solid-csd
# standard window/dialog: window dialog.solid-csd
# updated way
# compositor enabled + csd window/dialog: window.csd dialog.csd
# compositor disabled + csd window/dialog: window.solid-csd.compositor-off dialog.solid-csd.compositor-off
# standard window/dialog: window dialog
# and when compositor is enabled -> disabled: .csd -> .solid-csd
# and when compositor is disabled -> enabled: .solid-csd -> .csd ONLY when .compositor-off is not defined
# https://github.com/GNOME/gtk/blob/3.24.49/gtk/gtkwindow.c
# https://github.com/lah7/gtk3-classic/issues/125
Index: b/gtk/gtkwindow.c
===================================================================
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -7407,6 +7407,16 @@ gtk_window_realize
create_decoration (widget);
_gtk_widget_get_allocation (widget, &allocation);
+ if (!priv->client_decorated)
+ {
+ GtkStyleContext *context = gtk_widget_get_style_context (widget);
+ gtk_style_context_remove_class (context, "solid-csd");
+ }
+ else if (!gdk_screen_is_composited (priv->screen))
+ {
+ GtkStyleContext *context = gtk_widget_get_style_context (widget);
+ gtk_style_context_add_class (context, "compositor-off");
+ }
if (gtk_widget_get_parent_window (widget))
{
@@ -11302,6 +11312,24 @@ gtk_window_on_composited_changed
{
GtkWidget *widget = GTK_WIDGET (window);
+ GtkStyleContext *context = gtk_widget_get_style_context (widget);
+ if (
+ !gtk_style_context_has_class (context, "compositor-off") &&
+ (gtk_style_context_has_class (context, "solid-csd") || gtk_style_context_has_class (context, "csd"))
+ )
+ {
+ if (gdk_screen_is_composited (screen))
+ {
+ gtk_style_context_remove_class (context, "solid-csd");
+ gtk_style_context_add_class (context, "csd");
+ }
+ else
+ {
+ gtk_style_context_remove_class (context, "csd");
+ gtk_style_context_add_class (context, "solid-csd");
+ }
+ }
+
gtk_widget_queue_draw (widget);
_gtk_widget_propagate_composited_changed (widget);
}
# GtkWindow4: toggle .csd/.solid-csd when compositor is enabled/disabled and do not add solid-csd for non CSD windows/dialogs
# default way
# compositor enabled + csd window/dialog: window.csd dialog.csd
# compositor disabled + csd window/dialog: window.solid-csd dialog.solid-csd
# standard window/dialog: window dialog
# updated way
# compositor enabled + csd window/dialog: window.csd dialog.csd
# compositor disabled + csd window/dialog: window.solid-csd.compositor-off dialog.solid-csd.compositor-off
# standard window/dialog: window dialog
# and when compositor is enabled -> disabled: .csd -> .solid-csd
# and when compositor is disabled -> enabled: .solid-csd -> .csd ONLY when .compositor-off is not defined
# https://github.com/GNOME/gtk/blob/4.18.3/gtk/gtkwindow.c
# https://github.com/lah7/gtk3-classic/issues/125
Index: b/gtk/gtkwindow.c
===================================================================
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -543,6 +543,26 @@
static GtkAccessibleInterface *parent_accessible_iface;
+static void gtk_window_on_composited_changed (GdkDisplay *display, GParamSpec *pspec, GtkWidget *widget)
+{
+ if (
+ !gtk_widget_has_css_class (widget, "compositor-off") &&
+ (gtk_widget_has_css_class (widget, "solid-csd") || gtk_widget_has_css_class (widget, "csd"))
+ )
+ {
+ if (gdk_display_is_composited (display))
+ {
+ gtk_widget_remove_css_class (widget, "solid-csd");
+ gtk_widget_add_css_class (widget, "csd");
+ }
+ else
+ {
+ gtk_widget_remove_css_class (widget, "csd");
+ gtk_widget_add_css_class (widget, "solid-csd");
+ }
+ } g_print("gtk_window_on_composited_changed\n");
+}
+
static gboolean
gtk_window_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
@@ -4398,7 +4418,10 @@ gtk_window_realize
update_window_actions (window);
}
else
- priv->use_client_shadow = FALSE;
+ {
+ priv->use_client_shadow = FALSE;
+ gtk_widget_add_css_class (widget, "compositor-off");
+ }
}
surface = gdk_surface_new_toplevel (gtk_widget_get_display (widget));
@@ -4413,6 +4436,7 @@ gtk_window_realize
g_signal_connect (surface, "render", G_CALLBACK (surface_render), widget);
g_signal_connect (surface, "event", G_CALLBACK (surface_event), widget);
g_signal_connect (surface, "compute-size", G_CALLBACK (toplevel_compute_size), widget);
+ g_signal_connect (gtk_widget_get_display (widget), "notify::composited", G_CALLBACK (on_composited_changed), widget);
frame_clock = gdk_surface_get_frame_clock (surface);
g_signal_connect (frame_clock, "after-paint", G_CALLBACK (after_paint), widget);
@@ -4519,6 +4543,7 @@ gtk_window_unrealize
g_signal_handlers_disconnect_by_func (surface, surface_render, widget);
g_signal_handlers_disconnect_by_func (surface, surface_event, widget);
g_signal_handlers_disconnect_by_func (surface, toplevel_compute_size, widget);
+ g_signal_handlers_disconnect_by_func (gtk_widget_get_display (widget), on_composited_changed, widget);
frame_clock = gdk_surface_get_frame_clock (surface);
# GtkFileChooserWidget3: allow to use IEC units in GTK (GTK_USE_IEC_UNITS=1)
# https://github.com/GNOME/gtk/blob/3.24.41/gtk/gtkfilechooserwidget.c
Index: b/gtk/gtkfilechooserwidget.c
===================================================================
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -5223,6 +5223,8 @@ file_system_model_set
case MODEL_COL_SIZE_TEXT:
if (info == NULL || _gtk_file_info_consider_as_directory (info))
g_value_set_string (value, NULL);
+ else if (g_strcmp0 (g_getenv ("GTK_USE_IEC_UNITS"), "1") == 0)
+ g_value_take_string (value, g_format_size_full (g_file_info_get_size (info), G_FORMAT_SIZE_IEC_UNITS));
else
g_value_take_string (value, g_format_size (g_file_info_get_size (info)));
break;
# GtkFileChooserWidget4: allow to use IEC units in GTK (GTK_USE_IEC_UNITS=1)
# https://github.com/GNOME/gtk/blob/4.12.5/gtk/gtkfilechooserwidget.c
Index: b/gtk/gtkfilechooserwidget.c
===================================================================
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -2087,7 +2087,12 @@ column_view_get_size
column_view_get_size (GFileInfo *info)
{
if (info && !_gtk_file_info_consider_as_directory (info))
+ {
+ if (g_strcmp0 (g_getenv ("GTK_USE_IEC_UNITS"), "1") == 0)
+ return g_format_size_full (g_file_info_get_size (info), G_FORMAT_SIZE_IEC_UNITS);
+
return g_format_size (g_file_info_get_size (info));
+ }
else
return NULL;
}
#!/bin/bash
# updated 15/04/2025 for Debian Testing (Trixie)
# gtk3-classic DEB packages: https://build.opensuse.org/package/show/home:luigifab/gtk3-classic
# classic desktop theme: https://github.com/luigifab/human-theme/releases
cd "$(dirname "$0")"
if [ ! -d gtk3-classic ]; then
git clone https://github.com/lah7/gtk3-classic.git
fi
if [ ! -d builder ]; then
mkdir builder
fi
cd builder/
numb=171
for serie in trixie; do
rm -rf ${serie}/*/ ${serie}/*.dsc ${serie}/*.buildinfo ${serie}/*.changes ${serie}/*-1*
if [ ! -d ${serie} ]; then
mkdir $serie
fi
cd ${serie}/
# https://packages.ubuntu.com/search?searchon=sourcenames&keywords=gtk%2B3.0
# https://packages.debian.org/search?searchon=sourcenames&keywords=gtk%2B3.0
# https://packages.debian.org/source/trixie/gtk+3.0
echo ""
echo "==== ${serie}/gtk3 =========================================="
echo ""
version=3.24.49
classic=${version}
wget -nc http://deb.debian.org/debian/pool/main/g/gtk+3.0/gtk+3.0_${version}.orig.tar.xz
wget -nc http://deb.debian.org/debian/pool/main/g/gtk+3.0/gtk+3.0_${version}-3.debian.tar.xz
# prepare gtk3-classic
cp -r ../../gtk3-classic/ .
cd gtk3-classic/
#git checkout -q $classic
git checkout -q master
git pull -q
cd ..
# extract and update data
tar xf gtk+3.0_${version}.orig.tar.xz
cd gtk-${version}
tar xf ../gtk*.debian.tar.xz
rm debian/changelog
echo "gtk+3.0 (2:${version}-${numb}+${serie}) ${serie}; urgency=medium" > debian/changelog
echo "" >> debian/changelog
echo " * Rebuild gtk3 ${version} with gtk3-classic patches" >> debian/changelog
echo "" >> debian/changelog
echo " -- Fabrice Creuzot <[email protected]> $(LC_TIME=C date -u +"%a, %d %b %Y %H:%M:%S") +0000" >> debian/changelog
echo "" >> debian/changelog
cp ../gtk3-classic/*.patch debian/patches/
cp ../gtk3-classic/*.css debian/patches/
sed -i 's/env -u LD_PRELOAD xvfb-run -a dh_auto_test/#env -u LD_PRELOAD xvfb-run -a dh_auto_test/' debian/rules
sed -i 's/APIVER := 3/APIVER := 3\nexport DEB_BUILD_OPTIONS := nocheck/' debian/rules
rm debian/*symbols
# add patches
rm -f debian/patches/appearance__focus-visible.gtk3.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__focus-visible.gtk3.patch -q --output-document=debian/patches/appearance__focus-visible.gtk3.patch
rm -f debian/patches/appearance__notebook_stack_class.gtk3.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__notebook_stack_class.gtk3.patch -q --output-document=debian/patches/appearance__notebook_stack_class.gtk3.patch
rm -f debian/patches/appearance__progress_text.gtk3.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__progress_text.gtk3.patch -q --output-document=debian/patches/appearance__progress_text.gtk3.patch
rm -f debian/patches/consistent_file_size_units.gtk3.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/consistent_file_size_units.gtk3.patch -q --output-document=debian/patches/consistent_file_size_units.gtk3.patch
rm -f debian/patches/appearance__toggle_csd.gtk3.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__toggle_csd.gtk3.patch -q --output-document=debian/patches/appearance__toggle_csd.gtk3.patch
# update patch list
rm debian/patches/series
for file in debian/patches/*.patch; do
echo $(basename $file) >> debian/patches/series
done
# @todo?
sed -i 's/evince /atril /' debian/patches/printing-Default-to-papers-previewer-and-fallback-to-evin.patch
# build packages
# dpkg-buildpackage -rfakeroot -b -uc -us
dpkg-buildpackage -us -uc -ui -d -S
cd ..
# sign packages
debsign *.changes
cd ..
done
cd ..
#!/bin/bash
# updated 17/04/2025 for Debian Testing (Trixie)
# gtk4-classic DEB packages: https://build.opensuse.org/package/show/home:luigifab/gtk4-classic
# classic desktop theme: https://github.com/luigifab/human-theme/releases
cd "$(dirname "$0")"
if [ ! -d builder ]; then
mkdir builder
fi
cd builder/
numb=171
for serie in trixie; do
rm -rf ${serie}/*/ ${serie}/*.dsc ${serie}/*.buildinfo ${serie}/*.changes ${serie}/*-1*
if [ ! -d ${serie} ]; then
mkdir $serie
fi
cd ${serie}/
# https://packages.ubuntu.com/search?searchon=sourcenames&keywords=gtk4
# https://packages.debian.org/search?searchon=sourcenames&keywords=gtk4
# https://packages.debian.org/source/trixie/gtk4
echo ""
echo "==== ${serie}/gtk4 =========================================="
echo ""
version=4.18.4
classic=${version}
wget -nc http://deb.debian.org/debian/pool/main/g/gtk4/gtk4_${version}+ds.orig.tar.xz
wget -nc http://deb.debian.org/debian/pool/main/g/gtk4/gtk4_${version}+ds-1.debian.tar.xz
cp gtk4_${version}+ds.orig.tar.xz gtk4_${version}.orig.tar.xz
# extract and update data
tar xf gtk4_${version}.orig.tar.xz
cd gtk-${version}
tar xf ../gtk*.debian.tar.xz
rm debian/changelog
echo "gtk4 (2:${version}-${numb}+${serie}) ${serie}; urgency=medium" > debian/changelog
echo "" >> debian/changelog
echo " * Rebuild gtk4 ${version} with gtk4-classic patches" >> debian/changelog
echo "" >> debian/changelog
echo " -- Fabrice Creuzot <[email protected]> $(LC_TIME=C date -u +"%a, %d %b %Y %H:%M:%S") +0000" >> debian/changelog
echo "" >> debian/changelog
sed -i 's/export SONAME := 1/export SONAME := 1\nexport DEB_BUILD_OPTIONS := nocheck/' debian/rules
# add patches
rm -f debian/patches/treeview__alternating_row_colours.gtk4.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/treeview__alternating_row_colours.gtk4.patch -q --output-document=debian/patches/treeview__alternating_row_colours.gtk4.patch
rm -f debian/patches/appearance__notebook_stack_class.gtk4.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__notebook_stack_class.gtk4.patch -q --output-document=debian/patches/appearance__notebook_stack_class.gtk4.patch
rm -f debian/patches/appearance__focus-visible.gtk4.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__focus-visible.gtk4.patch -q --output-document=debian/patches/appearance__focus-visible.gtk4.patch
rm -f debian/patches/appearance__progress_text.gtk4.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__progress_text.gtk4.patch -q --output-document=debian/patches/appearance__progress_text.gtk4.patch
rm -f debian/patches/consistent_file_size_units.gtk4.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/consistent_file_size_units.gtk4.patch -q --output-document=debian/patches/consistent_file_size_units.gtk4.patch
rm -f debian/patches/appearance__toggle_csd.gtk4.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__toggle_csd.gtk4.patch -q --output-document=debian/patches/appearance__toggle_csd.gtk4.patch
# update patch list
echo treeview__alternating_row_colours.gtk4.patch >> debian/patches/series
echo appearance__notebook_stack_class.gtk4.patch >> debian/patches/series
echo appearance__focus-visible.gtk4.patch >> debian/patches/series
echo appearance__progress_text.gtk4.patch >> debian/patches/series
echo consistent_file_size_units.gtk4.patch >> debian/patches/series
echo appearance__toggle_csd.gtk4.patch >> debian/patches/series
# build packages
# dpkg-buildpackage -rfakeroot -b -uc -us
dpkg-buildpackage -us -uc -ui -d -S
cd ..
# sign packages
debsign *.changes
cd ..
done
cd ..
#!/bin/bash
# updated 17/04/2025 for Debian Testing (Trixie)
# https://docs.gtk.org/gtk4/migrating-4to5.html
# @todo color_expressions.gtk5.patch (because color expressions are going away... lol)
#!/bin/bash
# updated 17/04/2025 for Debian Testing (Trixie)
# mate-notification-daemon DEB packages: https://build.opensuse.org/package/show/home:luigifab/mate-notification
# classic desktop theme: https://github.com/luigifab/human-theme/releases
cd "$(dirname "$0")"
if [ ! -d builder ]; then
mkdir builder
fi
cd builder/
numb=171
for serie in trixie; do
rm -rf ${serie}/*/ ${serie}/*.dsc ${serie}/*.buildinfo ${serie}/*.changes ${serie}/*-1*
if [ ! -d ${serie} ]; then
mkdir $serie
fi
cd ${serie}/
# https://packages.debian.org/source/trixie/mate-notification-daemon
echo ""
echo "==== ${serie}/mate-notification-daemon ======================"
echo ""
version=1.26.1
wget -nc http://deb.debian.org/debian/pool/main/m/mate-notification-daemon/mate-notification-daemon_${version}.orig.tar.xz
wget -nc http://deb.debian.org/debian/pool/main/m/mate-notification-daemon/mate-notification-daemon_${version}-1.debian.tar.xz
# extract and update data
tar xf mate-notification-daemon_${version}.orig.tar.xz
cd mate-notification-daemon-${version}
tar xf ../mate-notification-daemon*.debian.tar.xz
rm debian/changelog
echo "mate-notification-daemon (${version}-${numb}+${serie}) ${serie}; urgency=medium" > debian/changelog
echo "" >> debian/changelog
echo " * Rebuild with PR 232+233+234" >> debian/changelog
echo "" >> debian/changelog
echo " -- Fabrice Creuzot <[email protected]> $(LC_TIME=C date -u +"%a, %d %b %Y %H:%M:%S") +0000" >> debian/changelog
echo "" >> debian/changelog
rm -f debian/patches/notifs.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/notifs.patch -q --output-document=debian/patches/notifs.patch
echo notifs.patch >> debian/patches/series
# build packages
#dpkg-buildpackage -rfakeroot -b -uc -us
dpkg-buildpackage -us -uc -ui -d -S
cd ..
cd ..
done
cd ..
diff --git a/src/capplet/mate-notification-properties.c b/src/capplet/mate-notification-properties.c
index 10f99d5..d8a5eab 100644
--- a/src/capplet/mate-notification-properties.c
+++ b/src/capplet/mate-notification-properties.c
@@ -46,7 +46,8 @@ typedef struct {
GtkWidget* dnd_checkbox;
GtkWidget* monitor_label;
- NotifyNotification* preview;
+ NotifyNotification* preview1;
+ NotifyNotification* preview2;
} NotificationAppletDialog;
enum {
@@ -387,14 +388,19 @@ static void show_message(NotificationAppletDialog* dialog, const gchar* message)
static void notification_properties_dialog_preview_closed(NotifyNotification* preview, NotificationAppletDialog* dialog)
{
- if (preview == dialog->preview)
- {
- dialog->preview = NULL;
- }
+ if (preview == dialog->preview1)
+ dialog->preview1 = NULL;
+ else if (preview == dialog->preview2)
+ dialog->preview2 = NULL;
g_object_unref(preview);
}
+static gboolean notification_properties_dialog_preview_action(void *data) {
+ // @todo call notification_properties_dialog_preview_closed
+ return FALSE;
+}
+
static void notification_properties_dialog_preview(NotificationAppletDialog* dialog)
{
if (!notify_is_initted() && !notify_init("n-d"))
@@ -405,16 +411,23 @@ static void notification_properties_dialog_preview(NotificationAppletDialog* dia
GError* error = NULL;
- if (dialog->preview)
+ if (dialog->preview1)
{
- notify_notification_close(dialog->preview, NULL);
- g_object_unref(dialog->preview);
- dialog->preview = NULL;
+ notify_notification_close(dialog->preview1, NULL);
+ g_object_unref(dialog->preview1);
+ dialog->preview1 = NULL;
+ }
+ if (dialog->preview2)
+ {
+ notify_notification_close(dialog->preview2, NULL);
+ g_object_unref(dialog->preview2);
+ dialog->preview2 = NULL;
}
- dialog->preview = notify_notification_new(_("Notification Test"), _("Just a test"), "dialog-information");
+ dialog->preview1 = notify_notification_new(_("Notification Test"), _("Just a test"), "dialog-information");
+ notify_notification_set_timeout (dialog->preview1, 50000);
- if (!notify_notification_show(dialog->preview, &error))
+ if (!notify_notification_show(dialog->preview1, &error))
{
char* message = g_strdup_printf(_("Error while displaying notification: %s"), error->message);
show_message(dialog, message);
@@ -422,7 +435,20 @@ static void notification_properties_dialog_preview(NotificationAppletDialog* dia
g_free(message);
}
- g_signal_connect(dialog->preview, "closed", G_CALLBACK(notification_properties_dialog_preview_closed), dialog);
+ dialog->preview2 = notify_notification_new(_("Notification Test"), _("Just a test"), "dialog-information");
+ notify_notification_add_action (dialog->preview2, "nothing", _("Close"), NOTIFY_ACTION_CALLBACK (notification_properties_dialog_preview_action), NULL, NULL);
+ notify_notification_set_timeout (dialog->preview2, 50000);
+
+ if (!notify_notification_show(dialog->preview2, &error))
+ {
+ char* message = g_strdup_printf(_("Error while displaying notification: %s"), error->message);
+ show_message(dialog, message);
+ g_error_free(error);
+ g_free(message);
+ }
+
+ g_signal_connect(dialog->preview1, "closed", G_CALLBACK(notification_properties_dialog_preview_closed), dialog);
+ g_signal_connect(dialog->preview2, "closed", G_CALLBACK(notification_properties_dialog_preview_closed), dialog);
}
static void notification_properties_dialog_response(GtkWidget* widget, int response, NotificationAppletDialog* dialog)
@@ -491,7 +517,8 @@ static gboolean notification_properties_dialog_init(NotificationAppletDialog* di
gtk_widget_show_all(dialog->dialog);
- dialog->preview = NULL;
+ dialog->preview1 = NULL;
+ dialog->preview2 = NULL;
return TRUE;
}
@@ -504,16 +531,23 @@ static void notification_properties_dialog_finalize(NotificationAppletDialog* di
dialog->dialog = NULL;
}
- if (dialog->preview)
+ if (dialog->preview1)
+ {
+ notify_notification_close(dialog->preview1, NULL);
+ dialog->preview1 = NULL;
+ }
+ if (dialog->preview2)
{
- notify_notification_close(dialog->preview, NULL);
- dialog->preview = NULL;
+ notify_notification_close(dialog->preview2, NULL);
+ dialog->preview2 = NULL;
}
+
+ g_free (dialog);
}
int main(int argc, char** argv)
{
- NotificationAppletDialog dialog = {NULL, }; /* <- ? */
+ NotificationAppletDialog *dialog;
#ifdef ENABLE_NLS
bindtextdomain(GETTEXT_PACKAGE, NOTIFICATION_LOCALEDIR);
@@ -525,15 +559,16 @@ int main(int argc, char** argv)
notify_init("mate-notification-properties");
- if (!notification_properties_dialog_init(&dialog))
+ dialog = g_new0 (NotificationAppletDialog, 1);
+ if (!notification_properties_dialog_init (dialog))
{
- notification_properties_dialog_finalize(&dialog);
+ notification_properties_dialog_finalize (dialog);
return 1;
}
gtk_main();
- notification_properties_dialog_finalize(&dialog);
+ notification_properties_dialog_finalize (dialog);
return 0;
}
diff --git a/src/themes/coco/coco-theme.c b/src/themes/coco/coco-theme.c
index 741861f..89e8d11 100644
--- a/src/themes/coco/coco-theme.c
+++ b/src/themes/coco/coco-theme.c
@@ -1,11 +1,8 @@
/*
- * coco-theme.c
- * This file is part of notification-daemon-engine-coco
- *
* Copyright (C) 2012 - Stefano Karapetsas <[email protected]>
* Copyright (C) 2010 - Eduardo Grajeda
* Copyright (C) 2008 - Martin Sourada
- * Copyright (C) 2012-2021 MATE Developers
+ * Copyright (C) 2012-2025 MATE Developers
*
* notification-daemon-engine-coco is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
@@ -27,7 +24,8 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>
/* Define basic coco types */
@@ -62,11 +60,8 @@ typedef struct
glong remaining;
UrlClickedCb url_clicked;
-
- GtkTextDirection rtl;
} WindowData;
-
enum
{
URGENCY_LOW,
@@ -74,22 +69,22 @@ enum
URGENCY_CRITICAL
};
-gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver,
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver,
unsigned int micro_ver);
-void get_theme_info(char **theme_name, char **theme_ver, char **author,
+void get_theme_info (char **theme_name, char **theme_ver, char **author,
char **homepage);
-GtkWindow* create_notification(UrlClickedCb url_clicked);
-void set_notification_text(GtkWindow *nw, const char *summary,
+GtkWindow* create_notification (UrlClickedCb url_clicked);
+void set_notification_text (GtkWindow *nw, const char *summary,
const char *body);
-void set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf);
-void set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y);
-void add_notification_action(GtkWindow *nw, const char *text, const char *key,
+void set_notification_icon (GtkWindow *nw, GdkPixbuf *pixbuf);
+void set_notification_arrow (GtkWidget *nw, gboolean visible, int x, int y);
+void add_notification_action (GtkWindow *nw, const char *text, const char *key,
ActionInvokedCb cb);
-void clear_notification_actions(GtkWindow *nw);
-void move_notification(GtkWidget *nw, int x, int y);
-void set_notification_timeout(GtkWindow *nw, glong timeout);
-void set_notification_hints(GtkWindow *nw, GVariant *hints);
-void notification_tick(GtkWindow *nw, glong remaining);
+void clear_notification_actions (GtkWindow *nw);
+void move_notification (GtkWidget *nw, int x, int y);
+void set_notification_timeout (GtkWindow *nw, glong timeout);
+void set_notification_hints (GtkWindow *nw, GVariant *hints);
+void notification_tick (GtkWindow *nw, glong remaining);
#define STRIPE_WIDTH 32
#define WIDTH 300
@@ -107,28 +102,33 @@ void notification_tick(GtkWindow *nw, glong remaining);
#define BACKGROUND_OPACITY 0.9
#define GRADIENT_CENTER 0.7
-/* Support Nodoka Functions */
+static void get_background_color (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
+{
+ GdkRGBA *c;
+
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ gtk_style_context_get (context, state,
+ "background-color", &c,
+ NULL);
+
+ *color = *c;
+ gdk_rgba_free (c);
+}
-/* Handle clicking on link */
-static gboolean
-activate_link (GtkLabel *label, const char *url, WindowData *windata)
+static gboolean activate_link (GtkLabel *label, const char *url, WindowData *windata)
{
windata->url_clicked (GTK_WINDOW (windata->win), url);
return TRUE;
}
-static void
-destroy_windata(WindowData *windata)
+static void destroy_windata (WindowData *windata)
{
g_free(windata);
}
-/* Draw fuctions */
-/* Standard rounded rectangle */
-static void
-nodoka_rounded_rectangle (cairo_t * cr,
- double x, double y, double w, double h,
- int radius)
+static void nodoka_rounded_rectangle (cairo_t * cr, double x, double y, double w, double h, int radius)
{
cairo_move_to (cr, x + radius, y);
cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.5, G_PI * 2);
@@ -137,9 +137,7 @@ nodoka_rounded_rectangle (cairo_t * cr,
cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
}
-/* Fill background */
-static void
-fill_background(GtkWidget *widget, WindowData *windata, cairo_t *cr)
+static void fill_background (GtkWidget *widget, WindowData *windata, cairo_t *cr)
{
double alpha;
if (windata->composited)
@@ -164,14 +162,34 @@ fill_background(GtkWidget *widget, WindowData *windata, cairo_t *cr)
cairo_fill (cr);
}
-static void
-draw_pie(GtkWidget *pie, WindowData *windata, cairo_t *cr)
+static void draw_pie (GtkWidget *pie, WindowData *windata, cairo_t *cr)
{
if (windata->timeout == 0)
return;
gdouble arc_angle = 1.0 - (gdouble)windata->remaining / (gdouble)windata->timeout;
- cairo_set_source_rgba (cr, 1.0, 0.4, 0.0, 0.3);
+ GtkStyleContext *context;
+ GdkRGBA orig, bg;
+
+ // :selected { background-color:#aabbcc; } ignored -> 1.0, 1.0, 1.0, 0.3
+ context = gtk_widget_get_style_context (windata->win);
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED);
+ get_background_color (context, GTK_STATE_FLAG_SELECTED, &orig);
+ gtk_style_context_restore (context);
+
+ // .notification-box .countdown:selected { background-color:#aabbcc; }
+ context = gtk_widget_get_style_context (pie);
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED);
+ get_background_color (context, GTK_STATE_FLAG_SELECTED, &bg);
+ gtk_style_context_restore (context);
+
+ if (gdk_rgba_equal (&orig, &bg))
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3);
+ else
+ cairo_set_source_rgba (cr, bg.red, bg.green, bg.blue, bg.alpha);
+
cairo_move_to(cr, PIE_RADIUS, PIE_RADIUS);
cairo_arc_negative(cr, PIE_RADIUS, PIE_RADIUS, PIE_RADIUS,
-G_PI/2, (-0.25 + arc_angle)*2*G_PI);
@@ -180,71 +198,45 @@ draw_pie(GtkWidget *pie, WindowData *windata, cairo_t *cr)
cairo_fill (cr);
}
-static void
-update_shape_region (cairo_surface_t *surface,
- WindowData *windata)
+static void update_shape_region (cairo_surface_t *surface, WindowData *windata)
{
if (windata->width == windata->last_width && windata->height == windata->last_height)
- {
return;
- }
- if (windata->width == 0 || windata->height == 0)
- {
- GtkAllocation allocation;
- gtk_widget_get_allocation (windata->win, &allocation);
-
- windata->width = MAX (allocation.width, 1);
- windata->height = MAX (allocation.height, 1);
+ if (windata->composited) {
+ gtk_widget_shape_combine_region (windata->win, NULL);
}
-
- if (!windata->composited) {
+ else {
cairo_region_t *region;
-
region = gdk_cairo_region_create_from_surface (surface);
gtk_widget_shape_combine_region (windata->win, region);
cairo_region_destroy (region);
- } else {
- gtk_widget_shape_combine_region (windata->win, NULL);
- return;
+ windata->last_width = windata->width;
+ windata->last_height = windata->height;
+ gtk_widget_queue_draw (GTK_WIDGET (windata->win));
}
-
- windata->last_width = windata->width;
- windata->last_height = windata->height;
}
-static void
-paint_window (GtkWidget *widget,
- cairo_t *cr,
- WindowData *windata)
+static void paint_window (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
- cairo_surface_t *surface;
cairo_t *cr2;
+ cairo_surface_t *surface;
if (windata->width == 0 || windata->height == 0) {
GtkAllocation allocation;
-
- gtk_widget_get_allocation(windata->win, &allocation);
+ gtk_widget_get_allocation (windata->win, &allocation);
windata->width = allocation.width;
windata->height = allocation.height;
}
- surface = cairo_surface_create_similar(cairo_get_target(cr),
- CAIRO_CONTENT_COLOR_ALPHA,
- windata->width,
- windata->height);
-
+ surface = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, windata->width, windata->height);
cr2 = cairo_create (surface);
-
- /* transparent background */
cairo_rectangle (cr2, 0, 0, windata->width, windata->height);
- cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0);
- cairo_fill (cr2);
-
- nodoka_rounded_rectangle (cr2, 0, 0, windata->width , windata->height, 6);
- fill_background(widget, windata, cr2);
+ cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0); // transparent background color
cairo_fill (cr2);
+ nodoka_rounded_rectangle (cr2, 0, 0, windata->width, windata->height, 6);
+ fill_background (widget, windata, cr2);
cairo_destroy (cr2);
cairo_save (cr);
@@ -254,58 +246,38 @@ paint_window (GtkWidget *widget,
cairo_restore (cr);
update_shape_region (surface, windata);
-
cairo_surface_destroy (surface);
}
-static gboolean
-on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
+static gboolean on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
paint_window (widget, cr, windata);
-
return FALSE;
}
-/* Event handlers */
-static gboolean
-configure_event_cb(GtkWidget *nw,
- GdkEventConfigure *event,
- WindowData *windata)
+static gboolean on_configure_event (GtkWidget* widget, GdkEventConfigure* event, WindowData* windata)
{
windata->width = event->width;
windata->height = event->height;
-
- gtk_widget_queue_draw(nw);
-
+ gtk_widget_queue_draw (widget);
return FALSE;
}
-static gboolean
-countdown_expose_cb(GtkWidget *pie,
- cairo_t *cr,
- WindowData *windata)
+static gboolean countdown_expose_cb (GtkWidget *pie, cairo_t *cr, WindowData *windata)
{
cairo_t *cr2;
cairo_surface_t *surface;
GtkAllocation alloc;
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
gtk_widget_get_allocation (pie, &alloc);
- surface = cairo_surface_create_similar (cairo_get_target (cr),
- CAIRO_CONTENT_COLOR_ALPHA,
- alloc.width,
- alloc.height);
-
+ surface = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, alloc.width, alloc.height);
cr2 = cairo_create (surface);
-
- cairo_translate (cr2, -alloc.x, -alloc.y);
- fill_background (pie, windata, cr2);
- cairo_translate (cr2, alloc.x, alloc.y);
- draw_pie (pie, windata, cr2);
+ cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0); // transparent background color
+ cairo_paint (cr2);
+ draw_pie (pie, windata, cr2); // countdown
cairo_fill (cr2);
-
cairo_destroy (cr2);
cairo_save (cr);
@@ -317,26 +289,13 @@ countdown_expose_cb(GtkWidget *pie,
return TRUE;
}
-static gboolean on_configure_event (GtkWidget* widget, GdkEventConfigure* event, WindowData* windata)
-{
- windata->width = event->width;
- windata->height = event->height;
-
- gtk_widget_queue_draw (widget);
-
- return FALSE;
-}
-
static void on_composited_changed (GtkWidget* window, WindowData* windata)
{
windata->composited = gdk_screen_is_composited (gtk_widget_get_screen(window));
-
gtk_widget_queue_draw (window);
}
-static void
-action_clicked_cb(GtkWidget *w, GdkEventButton *event,
- ActionInvokedCb action_cb)
+static void action_clicked_cb (GtkWidget *w, GdkEventButton *event, ActionInvokedCb action_cb)
{
GtkWindow *nw = g_object_get_data(G_OBJECT(w), "_nw");
const char *key = g_object_get_data(G_OBJECT(w), "_action_key");
@@ -344,24 +303,16 @@ action_clicked_cb(GtkWidget *w, GdkEventButton *event,
action_cb(nw, key);
}
-
-
/* Required functions */
/* Checking if we support this notification daemon version */
-gboolean
-theme_check_init(unsigned int major_ver, unsigned int minor_ver,
- unsigned int micro_ver)
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver, unsigned int micro_ver)
{
return major_ver == NOTIFICATION_DAEMON_MAJOR_VERSION && minor_ver == NOTIFICATION_DAEMON_MINOR_VERSION && micro_ver == NOTIFICATION_DAEMON_MICRO_VERSION;
}
/* Sending theme info to the notification daemon */
-void
-get_theme_info(char **theme_name,
- char **theme_ver,
- char **author,
- char **homepage)
+void get_theme_info (char **theme_name, char **theme_ver, char **author, char **homepage)
{
*theme_name = g_strdup("Coco");
*theme_ver = g_strdup_printf("%d.%d.%d", NOTIFICATION_DAEMON_MAJOR_VERSION,
@@ -372,8 +323,7 @@ get_theme_info(char **theme_name,
}
/* Create new notification */
-GtkWindow *
-create_notification(UrlClickedCb url_clicked)
+GtkWindow* create_notification (UrlClickedCb url_clicked)
{
GtkWidget *win;
GtkWidget *main_vbox;
@@ -389,15 +339,13 @@ create_notification(UrlClickedCb url_clicked)
win = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
+ gtk_widget_set_app_paintable(win, TRUE);
windata->win = win;
-
- windata->rtl = gtk_widget_get_default_direction();
windata->composited = FALSE;
screen = gtk_window_get_screen(GTK_WINDOW(win));
visual = gdk_screen_get_rgba_visual(screen);
- if (visual != NULL)
- {
+ if (visual != NULL) {
gtk_widget_set_visual(win, visual);
if (gdk_screen_is_composited(screen))
windata->composited = TRUE;
@@ -406,25 +354,23 @@ create_notification(UrlClickedCb url_clicked)
gtk_window_set_title(GTK_WINDOW(win), "Notification");
gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_NOTIFICATION);
gtk_widget_add_events(win, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
- gtk_widget_realize(win);
+ gtk_widget_set_size_request(win, WIDTH, -1);
- g_object_set_data_full(G_OBJECT(win), "windata", windata,
- (GDestroyNotify)destroy_windata);
+ g_object_set_data_full(G_OBJECT(win), "windata", windata, (GDestroyNotify) destroy_windata);
atk_object_set_role(gtk_widget_get_accessible(win), ATK_ROLE_ALERT);
- g_signal_connect(G_OBJECT(win), "configure_event",
- G_CALLBACK(configure_event_cb), windata);
-
- main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_show(main_vbox);
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_show (main_vbox);
gtk_container_add (GTK_CONTAINER (win), main_vbox);
+ //gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
- g_signal_connect (G_OBJECT (main_vbox), "draw",
- G_CALLBACK (on_draw), windata);
-
- g_signal_connect (G_OBJECT (win), "configure-event", G_CALLBACK (on_configure_event), windata);
-
- g_signal_connect (G_OBJECT (win), "composited-changed", G_CALLBACK (on_composited_changed), windata);
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (main_vbox, "notification-box");
+ gtk_widget_add_css_class (main_vbox, "coco-theme");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "notification-box");
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "coco-theme");
+ #endif
windata->main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_halign (windata->main_hbox, GTK_ALIGN_START);
@@ -435,7 +381,7 @@ create_notification(UrlClickedCb url_clicked)
gtk_box_pack_start (GTK_BOX(main_vbox), windata->main_hbox, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(windata->main_hbox), 13);
- /* The icon goes at the left */
+ /* The icon goes at the left */
windata->iconbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_show(windata->iconbox);
gtk_box_pack_start(GTK_BOX(windata->main_hbox), windata->iconbox,
@@ -445,14 +391,13 @@ create_notification(UrlClickedCb url_clicked)
gtk_box_pack_start(GTK_BOX(windata->iconbox), windata->icon,
FALSE, FALSE, 0);
- /* The title and the text at the right */
+ /* The title and the text at the right */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (vbox, GTK_ALIGN_START);
gtk_widget_set_margin_start (vbox, 8);
gtk_widget_show (vbox);
gtk_box_pack_start (GTK_BOX (windata->main_hbox), vbox, TRUE, TRUE, 0);
-
windata->summary_label = gtk_label_new(NULL);
gtk_widget_show(windata->summary_label);
gtk_box_pack_start(GTK_BOX(vbox), windata->summary_label, FALSE, FALSE, 0);
@@ -470,7 +415,7 @@ create_notification(UrlClickedCb url_clicked)
gtk_label_set_yalign (GTK_LABEL (windata->body_label), 0.0);
gtk_label_set_line_wrap(GTK_LABEL(windata->body_label), TRUE);
gtk_label_set_line_wrap_mode (GTK_LABEL (windata->body_label), PANGO_WRAP_WORD_CHAR);
- gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
+ gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
g_signal_connect(G_OBJECT(windata->body_label), "activate-link",
G_CALLBACK(activate_link), windata);
@@ -480,15 +425,29 @@ create_notification(UrlClickedCb url_clicked)
windata->actions_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign(windata->actions_box, GTK_ALIGN_END);
+
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->summary_label, "summary");
+ gtk_widget_add_css_class (windata->body_label, "body");
+ gtk_widget_add_css_class (windata->actions_box, "actions-box");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->summary_label), "summary");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->body_label), "body");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->actions_box), "actions-box");
+ #endif
+
gtk_widget_show(windata->actions_box);
gtk_box_pack_start(GTK_BOX(vbox), windata->actions_box, FALSE, TRUE, 0);
+ g_signal_connect (G_OBJECT (win), "draw", G_CALLBACK (on_draw), windata);
+ g_signal_connect (G_OBJECT (win), "configure-event", G_CALLBACK (on_configure_event), windata);
+ g_signal_connect (G_OBJECT (win), "composited-changed", G_CALLBACK (on_composited_changed), windata);
+
return GTK_WINDOW(win);
}
/* Set the notification text */
-void
-set_notification_text(GtkWindow *nw, const char *summary, const char *body)
+void set_notification_text (GtkWindow *nw, const char *summary, const char *body)
{
char *str;
size_t str_len;
@@ -546,7 +505,7 @@ set_notification_text(GtkWindow *nw, const char *summary, const char *body)
if ((body_label_text == NULL) || (strlen (body_label_text) == 0)) {
goto render_fail;
}
- goto renrer_ok;
+ goto render_ok;
}
render_fail:
@@ -557,7 +516,7 @@ render_fail:
g_free (quoted);
g_free (str);
-renrer_ok:
+render_ok:
xmlCleanupParser ();
if (body == NULL || *body == '\0')
@@ -573,8 +532,7 @@ renrer_ok:
}
/* Set notification icon */
-void
-set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf)
+void set_notification_icon (GtkWindow *nw, GdkPixbuf *pixbuf)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
@@ -584,10 +542,8 @@ set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf)
if (pixbuf != NULL)
{
int pixbuf_width = gdk_pixbuf_get_width(pixbuf);
-
gtk_widget_show(windata->icon);
- gtk_widget_set_size_request(windata->iconbox,
- MAX(BODY_X_OFFSET, pixbuf_width), -1);
+ gtk_widget_set_size_request(windata->iconbox, MAX(BODY_X_OFFSET, pixbuf_width), -1);
}
else
{
@@ -597,16 +553,13 @@ set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf)
}
/* Set notification arrow */
-void
-set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y)
+void set_notification_arrow (GtkWidget *nw, gboolean visible, int x, int y)
{
/* nothing */
}
/* Add notification action */
-void
-add_notification_action(GtkWindow *nw, const char *text, const char *key,
- ActionInvokedCb cb)
+void add_notification_action (GtkWindow *nw, const char *text, const char *key, ActionInvokedCb cb)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
GtkWidget *label;
@@ -625,13 +578,18 @@ add_notification_action(GtkWindow *nw, const char *text, const char *key,
if (!windata->pie_countdown) {
windata->pie_countdown = gtk_drawing_area_new();
gtk_widget_set_halign (windata->pie_countdown, GTK_ALIGN_END);
+ gtk_widget_set_valign (windata->pie_countdown, GTK_ALIGN_CENTER);
gtk_widget_show(windata->pie_countdown);
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->pie_countdown, "countdown");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->pie_countdown), "countdown");
+ #endif
+
gtk_box_pack_end (GTK_BOX (windata->actions_box), windata->pie_countdown, FALSE, TRUE, 0);
- gtk_widget_set_size_request(windata->pie_countdown,
- PIE_WIDTH, PIE_HEIGHT);
- g_signal_connect(G_OBJECT(windata->pie_countdown), "draw",
- G_CALLBACK(countdown_expose_cb), windata);
+ gtk_widget_set_size_request(windata->pie_countdown, PIE_WIDTH, PIE_HEIGHT);
+ g_signal_connect(G_OBJECT(windata->pie_countdown), "draw", G_CALLBACK (countdown_expose_cb), windata);
}
}
@@ -686,8 +644,7 @@ add_button:
}
/* Clear notification actions */
-void
-clear_notification_actions(GtkWindow *nw)
+void clear_notification_actions (GtkWindow *nw)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -699,8 +656,7 @@ clear_notification_actions(GtkWindow *nw)
}
/* Move notification window */
-void
-move_notification(GtkWidget *nw, int x, int y)
+void move_notification (GtkWidget *nw, int x, int y)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
@@ -708,7 +664,6 @@ move_notification(GtkWidget *nw, int x, int y)
gtk_window_move(GTK_WINDOW(nw), x, y);
}
-
/* Optional Functions */
/* Destroy notification */
@@ -718,8 +673,7 @@ move_notification(GtkWidget *nw, int x, int y)
/* Hide notification */
/* Set notification timeout */
-void
-set_notification_timeout(GtkWindow *nw, glong timeout)
+void set_notification_timeout (GtkWindow *nw, glong timeout)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
@@ -728,7 +682,7 @@ set_notification_timeout(GtkWindow *nw, glong timeout)
}
/* Set notification hints */
-void set_notification_hints(GtkWindow *nw, GVariant *hints)
+void set_notification_hints (GtkWindow *nw, GVariant *hints)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
guint8 urgency;
@@ -755,8 +709,7 @@ void set_notification_hints(GtkWindow *nw, GVariant *hints)
}
/* Notification tick */
-void
-notification_tick(GtkWindow *nw, glong remaining)
+void notification_tick (GtkWindow *nw, glong remaining)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
windata->remaining = remaining;
diff --git a/src/themes/nodoka/nodoka-theme.c b/src/themes/nodoka/nodoka-theme.c
index 2ad102e..4dad2b2 100644
--- a/src/themes/nodoka/nodoka-theme.c
+++ b/src/themes/nodoka/nodoka-theme.c
@@ -1,10 +1,7 @@
/*
- * nodoka-theme.c
- * This file is part of notification-daemon-engine-nodoka
- *
* Copyright (C) 2012 - Stefano Karapetsas <[email protected]>
* Copyright (C) 2008 - Martin Sourada
- * Copyright (C) 2012-2021 MATE Developers
+ * Copyright (C) 2012-2025 MATE Developers
*
* notification-daemon-engine-nodoka is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
@@ -22,16 +19,14 @@
* Boston, MA 02110-1301 USA
*/
-
-
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>
-/* Define basic nodoka types */
typedef void (*ActionInvokedCb)(GtkWindow *nw, const char *key);
typedef void (*UrlClickedCb)(GtkWindow *nw, const char *url);
@@ -82,7 +77,6 @@ typedef struct
} WindowData;
-
enum
{
URGENCY_LOW,
@@ -90,22 +84,22 @@ enum
URGENCY_CRITICAL
};
-gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver,
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver,
unsigned int micro_ver);
-void get_theme_info(char **theme_name, char **theme_ver, char **author,
+void get_theme_info (char **theme_name, char **theme_ver, char **author,
char **homepage);
-GtkWindow* create_notification(UrlClickedCb url_clicked);
-void set_notification_text(GtkWindow *nw, const char *summary,
+GtkWindow* create_notification (UrlClickedCb url_clicked);
+void set_notification_text (GtkWindow *nw, const char *summary,
const char *body);
-void set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf);
-void set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y);
-void add_notification_action(GtkWindow *nw, const char *text, const char *key,
+void set_notification_icon (GtkWindow *nw, GdkPixbuf *pixbuf);
+void set_notification_arrow (GtkWidget *nw, gboolean visible, int x, int y);
+void add_notification_action (GtkWindow *nw, const char *text, const char *key,
ActionInvokedCb cb);
-void clear_notification_actions(GtkWindow *nw);
-void move_notification(GtkWidget *nw, int x, int y);
-void set_notification_timeout(GtkWindow *nw, glong timeout);
-void set_notification_hints(GtkWindow *nw, GVariant *hints);
-void notification_tick(GtkWindow *nw, glong remaining);
+void clear_notification_actions (GtkWindow *nw);
+void move_notification (GtkWidget *nw, int x, int y);
+void set_notification_timeout (GtkWindow *nw, glong timeout);
+void set_notification_hints (GtkWindow *nw, GVariant *hints);
+void notification_tick (GtkWindow *nw, glong remaining);
#define STRIPE_WIDTH 32
#define WIDTH 400
@@ -123,18 +117,28 @@ void notification_tick(GtkWindow *nw, glong remaining);
#define BACKGROUND_OPACITY 0.92
#define GRADIENT_CENTER 0.7
-/* Support Nodoka Functions */
+static void get_background_color (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
+{
+ GdkRGBA *c;
+
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-/* Handle clicking on link */
-static gboolean
-activate_link (GtkLabel *label, const char *url, WindowData *windata)
+ gtk_style_context_get (context, state,
+ "background-color", &c,
+ NULL);
+
+ *color = *c;
+ gdk_rgba_free (c);
+}
+
+static gboolean activate_link (GtkLabel *label, const char *url, WindowData *windata)
{
windata->url_clicked (GTK_WINDOW (windata->win), url);
return TRUE;
}
-static void
-get_size_of_widgets_monitor(GtkWidget *widget, int *width, int *height)
+static void get_size_of_widgets_monitor (GtkWidget *widget, int *width, int *height)
{
GdkWindow *window = gtk_widget_get_window (widget);
GdkMonitor *monitor = gdk_display_get_monitor_at_window (
@@ -147,8 +151,7 @@ get_size_of_widgets_monitor(GtkWidget *widget, int *width, int *height)
}
/* Set if we have arrow down or arrow up */
-static GtkArrowType
-get_notification_arrow_type(GtkWidget *nw)
+static GtkArrowType get_notification_arrow_type (GtkWidget *nw)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
int monitor_height;
@@ -167,8 +170,7 @@ get_notification_arrow_type(GtkWidget *nw)
}
/* Set arrow parameters like offset and position */
-static void
-set_arrow_parameters (WindowData *windata)
+static void set_arrow_parameters (WindowData *windata)
{
int monitor_width;
int x,y;
@@ -251,14 +253,12 @@ set_arrow_parameters (WindowData *windata)
gtk_window_move(GTK_WINDOW(windata->win), x, y);
}
-static void
-destroy_windata(WindowData *windata)
+static void destroy_windata (WindowData *windata)
{
g_free(windata);
}
-static void
-update_spacers(GtkWidget *nw)
+static void update_spacers (GtkWidget *nw)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -287,8 +287,7 @@ update_spacers(GtkWidget *nw)
}
}
-static void
-update_content_hbox_visibility(WindowData *windata)
+static void update_content_hbox_visibility (WindowData *windata)
{
/*
* This is all a hack, but until we have a libview-style ContentBox,
@@ -306,12 +305,7 @@ update_content_hbox_visibility(WindowData *windata)
}
}
-/* Draw fuctions */
-/* Standard rounded rectangle */
-static void
-nodoka_rounded_rectangle (cairo_t * cr,
- double x, double y, double w, double h,
- int radius)
+static void nodoka_rounded_rectangle (cairo_t * cr, double x, double y, double w, double h, int radius)
{
cairo_move_to (cr, x + radius, y);
cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.5, G_PI * 2);
@@ -320,11 +314,7 @@ nodoka_rounded_rectangle (cairo_t * cr,
cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
}
-/* Rounded rectangle with arrow */
-static void
-nodoka_rounded_rectangle_with_arrow (cairo_t * cr,
- double x, double y, double w, double h,
- int radius, ArrowParameters * arrow)
+static void nodoka_rounded_rectangle_with_arrow (cairo_t * cr, double x, double y, double w, double h, int radius, ArrowParameters * arrow)
{
gboolean arrow_up;
arrow_up = (arrow->point_begin.y > arrow->point_middle.y);
@@ -376,9 +366,7 @@ nodoka_rounded_rectangle_with_arrow (cairo_t * cr,
}
-/* Fill background */
-static void
-fill_background(GtkWidget *widget, WindowData *windata, cairo_t *cr)
+static void fill_background (GtkWidget *widget, WindowData *windata, cairo_t *cr)
{
double alpha;
if (windata->composited)
@@ -403,12 +391,14 @@ fill_background(GtkWidget *widget, WindowData *windata, cairo_t *cr)
cairo_fill (cr);
}
-
-static void
-draw_stripe(GtkWidget *widget, WindowData *windata, cairo_t *cr)
+static void draw_stripe (GtkWidget *widget, WindowData *windata, cairo_t *cr)
{
+ int stripe_x = 0;
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ stripe_x = windata->width - STRIPE_WIDTH - stripe_x;
+
cairo_save (cr);
- cairo_rectangle (cr, 0, 0, STRIPE_WIDTH, windata->height);
+ cairo_rectangle (cr, stripe_x, 0, STRIPE_WIDTH, windata->height);
cairo_clip (cr);
gdouble color_mult = 1.0;
@@ -463,7 +453,6 @@ draw_stripe(GtkWidget *widget, WindowData *windata, cairo_t *cr)
break;
}
-
cairo_pattern_t *pattern;
pattern = cairo_pattern_create_linear (0, 0, 0, windata->height);
cairo_pattern_add_color_stop_rgba (pattern, 0, top_color.red / color_mult, top_color.green / color_mult, top_color.blue / color_mult, alpha);
@@ -483,8 +472,7 @@ draw_stripe(GtkWidget *widget, WindowData *windata, cairo_t *cr)
cairo_restore (cr);
}
-static void
-draw_border(GtkWidget *widget, WindowData *windata, cairo_t *cr)
+static void draw_border (GtkWidget *widget, WindowData *windata, cairo_t *cr)
{
double alpha;
if (windata->composited)
@@ -510,14 +498,34 @@ draw_border(GtkWidget *widget, WindowData *windata, cairo_t *cr)
cairo_stroke (cr);
}
-static void
-draw_pie(GtkWidget *pie, WindowData *windata, cairo_t *cr)
+static void draw_pie (GtkWidget *pie, WindowData *windata, cairo_t *cr)
{
if (windata->timeout == 0)
return;
gdouble arc_angle = 1.0 - (gdouble)windata->remaining / (gdouble)windata->timeout;
- cairo_set_source_rgba (cr, 1.0, 0.4, 0.0, 0.3);
+ GtkStyleContext *context;
+ GdkRGBA orig, bg;
+
+ // :selected { background-color:#aabbcc; } ignored -> 1.0, 0.4, 0.0, 0.3
+ context = gtk_widget_get_style_context (windata->win);
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED);
+ get_background_color (context, GTK_STATE_FLAG_SELECTED, &orig);
+ gtk_style_context_restore (context);
+
+ // .notification-box .countdown:selected { background-color:#aabbcc; }
+ context = gtk_widget_get_style_context (pie);
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED);
+ get_background_color (context, GTK_STATE_FLAG_SELECTED, &bg);
+ gtk_style_context_restore (context);
+
+ if (gdk_rgba_equal (&orig, &bg))
+ cairo_set_source_rgba (cr, 1.0, 0.4, 0.0, 0.3);
+ else
+ cairo_set_source_rgba (cr, bg.red, bg.green, bg.blue, bg.alpha);
+
cairo_move_to(cr, PIE_RADIUS, PIE_RADIUS);
cairo_arc_negative(cr, PIE_RADIUS, PIE_RADIUS, PIE_RADIUS,
-G_PI/2, (-0.25 + arc_angle)*2*G_PI);
@@ -526,49 +534,32 @@ draw_pie(GtkWidget *pie, WindowData *windata, cairo_t *cr)
cairo_fill (cr);
}
-static void
-update_shape_region (cairo_surface_t *surface,
- WindowData *windata)
+static void update_shape_region (cairo_surface_t *surface, WindowData *windata)
{
if (windata->width == windata->last_width && windata->height == windata->last_height)
- {
return;
- }
-
- if (windata->width == 0 || windata->height == 0)
- {
- GtkAllocation allocation;
- gtk_widget_get_allocation (windata->win, &allocation);
- windata->width = MAX (allocation.width, 1);
- windata->height = MAX (allocation.height, 1);
+ if (windata->composited) {
+ gtk_widget_shape_combine_region (windata->win, NULL);
}
-
- if (!windata->composited) {
+ else {
cairo_region_t *region;
-
region = gdk_cairo_region_create_from_surface (surface);
gtk_widget_shape_combine_region (windata->win, region);
cairo_region_destroy (region);
- } else {
- gtk_widget_shape_combine_region (windata->win, NULL);
- return;
+ windata->last_width = windata->width;
+ windata->last_height = windata->height;
+ gtk_widget_queue_draw (GTK_WIDGET (windata->win));
}
-
- windata->last_width = windata->width;
- windata->last_height = windata->height;
}
-static void
-paint_window (GtkWidget *widget,
- cairo_t *cr,
- WindowData *windata)
+static void paint_window (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
cairo_t *cr2;
cairo_surface_t *surface;
- GtkAllocation allocation;
if (windata->width == 0 || windata->height == 0) {
+ GtkAllocation allocation;
gtk_widget_get_allocation (windata->win, &allocation);
windata->width = allocation.width;
windata->height = allocation.height;
@@ -577,17 +568,11 @@ paint_window (GtkWidget *widget,
if (windata->arrow.has_arrow)
set_arrow_parameters (windata);
- surface = cairo_surface_create_similar (cairo_get_target (cr),
- CAIRO_CONTENT_COLOR_ALPHA,
- windata->width,
- windata->height);
-
+ surface = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, windata->width, windata->height);
cr2 = cairo_create (surface);
-
- /* transparent background */
- cairo_rectangle (cr2, 0, 0, windata->width, windata->height);
- cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0);
- cairo_fill (cr2);
+ cairo_rectangle (cr2, 0, 0, windata->width, windata->height);
+ cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0); // transparent background color
+ cairo_fill (cr2);
if (windata->arrow.has_arrow) {
nodoka_rounded_rectangle_with_arrow (cr2, 0, 0,
@@ -602,12 +587,9 @@ paint_window (GtkWidget *widget,
6);
}
- cairo_fill (cr2);
-
- fill_background(widget, windata, cr2);
- draw_border(widget, windata, cr2);
- draw_stripe(widget, windata, cr2);
-
+ fill_background (widget, windata, cr2);
+ draw_border (widget, windata, cr2);
+ draw_stripe (widget, windata, cr2);
cairo_destroy (cr2);
cairo_save (cr);
@@ -617,29 +599,22 @@ paint_window (GtkWidget *widget,
cairo_restore (cr);
update_shape_region (surface, windata);
-
cairo_surface_destroy (surface);
}
-static gboolean
-on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
+static gboolean on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
paint_window (widget, cr, windata);
-
return FALSE;
}
-/* Event handlers */
-static gboolean
-configure_event_cb(GtkWidget *nw,
- GdkEventConfigure *event,
- WindowData *windata)
+static gboolean on_configure_event (GtkWidget* widget, GdkEventConfigure* event, WindowData* windata)
{
windata->width = event->width;
windata->height = event->height;
- update_spacers(nw);
- gtk_widget_queue_draw(nw);
+ update_spacers (widget);
+ gtk_widget_queue_draw (widget);
return FALSE;
}
@@ -647,35 +622,24 @@ configure_event_cb(GtkWidget *nw,
static void on_composited_changed (GtkWidget* window, WindowData* windata)
{
windata->composited = gdk_screen_is_composited (gtk_widget_get_screen(window));
-
gtk_widget_queue_draw (window);
}
-static gboolean
-countdown_expose_cb(GtkWidget *pie,
- cairo_t *cr,
- WindowData *windata)
+static gboolean countdown_expose_cb (GtkWidget *pie, cairo_t *cr, WindowData *windata)
{
cairo_t *cr2;
cairo_surface_t *surface;
GtkAllocation alloc;
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
gtk_widget_get_allocation (pie, &alloc);
- surface = cairo_surface_create_similar (cairo_get_target (cr),
- CAIRO_CONTENT_COLOR_ALPHA,
- alloc.width,
- alloc.height);
+ surface = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, alloc.width, alloc.height);
cr2 = cairo_create (surface);
-
- cairo_translate (cr2, -alloc.x, -alloc.y);
- fill_background (pie, windata, cr2);
- cairo_translate (cr2, alloc.x, alloc.y);
- draw_pie (pie, windata, cr2);
+ cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0); // transparent background color
+ cairo_paint (cr2);
+ draw_pie (pie, windata, cr2); // countdown
cairo_fill (cr2);
-
cairo_destroy (cr2);
cairo_save (cr);
@@ -687,9 +651,7 @@ countdown_expose_cb(GtkWidget *pie,
return TRUE;
}
-static void
-action_clicked_cb(GtkWidget *w, GdkEventButton *event,
- ActionInvokedCb action_cb)
+static void action_clicked_cb (GtkWidget *w, GdkEventButton *event, ActionInvokedCb action_cb)
{
GtkWindow *nw = g_object_get_data(G_OBJECT(w), "_nw");
const char *key = g_object_get_data(G_OBJECT(w), "_action_key");
@@ -697,24 +659,16 @@ action_clicked_cb(GtkWidget *w, GdkEventButton *event,
action_cb(nw, key);
}
-
-
/* Required functions */
/* Checking if we support this notification daemon version */
-gboolean
-theme_check_init(unsigned int major_ver, unsigned int minor_ver,
- unsigned int micro_ver)
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver, unsigned int micro_ver)
{
return major_ver == NOTIFICATION_DAEMON_MAJOR_VERSION && minor_ver == NOTIFICATION_DAEMON_MINOR_VERSION && micro_ver == NOTIFICATION_DAEMON_MICRO_VERSION;
}
/* Sending theme info to the notification daemon */
-void
-get_theme_info(char **theme_name,
- char **theme_ver,
- char **author,
- char **homepage)
+void get_theme_info (char **theme_name, char **theme_ver, char **author, char **homepage)
{
*theme_name = g_strdup("Nodoka");
*theme_ver = g_strdup_printf("%d.%d.%d", NOTIFICATION_DAEMON_MAJOR_VERSION,
@@ -725,8 +679,7 @@ get_theme_info(char **theme_name,
}
/* Create new notification */
-GtkWindow *
-create_notification(UrlClickedCb url_clicked)
+GtkWindow* create_notification (UrlClickedCb url_clicked)
{
GtkWidget *spacer;
GtkWidget *win;
@@ -746,14 +699,13 @@ create_notification(UrlClickedCb url_clicked)
win = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
+ gtk_widget_set_app_paintable(win, TRUE);
windata->win = win;
-
windata->composited = FALSE;
screen = gtk_window_get_screen(GTK_WINDOW(win));
visual = gdk_screen_get_rgba_visual(screen);
- if (visual != NULL)
- {
+ if (visual != NULL) {
gtk_widget_set_visual(win, visual);
if (gdk_screen_is_composited(screen))
windata->composited = TRUE;
@@ -762,24 +714,28 @@ create_notification(UrlClickedCb url_clicked)
gtk_window_set_title(GTK_WINDOW(win), "Notification");
gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_NOTIFICATION);
gtk_widget_add_events(win, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
- gtk_widget_realize(win);
gtk_widget_set_size_request(win, WIDTH, -1);
- g_object_set_data_full(G_OBJECT(win), "windata", windata,
- (GDestroyNotify)destroy_windata);
+ g_object_set_data_full(G_OBJECT(win), "windata", windata, (GDestroyNotify) destroy_windata);
atk_object_set_role(gtk_widget_get_accessible(win), ATK_ROLE_ALERT);
- g_signal_connect(G_OBJECT(win), "configure_event",
- G_CALLBACK(configure_event_cb), windata);
-
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_show (main_vbox);
+ gtk_container_add (GTK_CONTAINER (win), main_vbox);
+ //gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
+
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (main_vbox, "notification-box");
+ gtk_widget_add_css_class (main_vbox, "nodoka-theme");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "notification-box");
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "nodoka-theme");
+ #endif
+
+ g_signal_connect (G_OBJECT (win), "draw", G_CALLBACK (on_draw), windata);
+ g_signal_connect (G_OBJECT (win), "configure-event", G_CALLBACK (on_configure_event), windata);
g_signal_connect (G_OBJECT (win), "composited-changed", G_CALLBACK (on_composited_changed), windata);
- main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_show(main_vbox);
- gtk_container_add(GTK_CONTAINER(win), main_vbox);
-
- g_signal_connect (G_OBJECT (main_vbox), "draw", G_CALLBACK (on_draw), windata);
-
windata->top_spacer = gtk_image_new();
gtk_box_pack_start(GTK_BOX(main_vbox), windata->top_spacer,
FALSE, FALSE, 0);
@@ -866,7 +822,7 @@ create_notification(UrlClickedCb url_clicked)
gtk_label_set_yalign (GTK_LABEL (windata->body_label), 0.0);
gtk_label_set_line_wrap(GTK_LABEL(windata->body_label), TRUE);
gtk_label_set_line_wrap_mode (GTK_LABEL (windata->body_label), PANGO_WRAP_WORD_CHAR);
- gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
+ gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
g_signal_connect(G_OBJECT(windata->body_label), "activate-link",
G_CALLBACK(activate_link), windata);
@@ -876,6 +832,17 @@ create_notification(UrlClickedCb url_clicked)
windata->actions_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign (windata->actions_box, GTK_ALIGN_END);
+
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->summary_label, "summary");
+ gtk_widget_add_css_class (windata->body_label, "body");
+ gtk_widget_add_css_class (windata->actions_box, "actions-box");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->summary_label), "summary");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->body_label), "body");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->actions_box), "actions-box");
+ #endif
+
gtk_widget_show(windata->actions_box);
gtk_box_pack_start(GTK_BOX(vbox), windata->actions_box, FALSE, TRUE, 0);
@@ -883,8 +850,7 @@ create_notification(UrlClickedCb url_clicked)
}
/* Set the notification text */
-void
-set_notification_text(GtkWindow *nw, const char *summary, const char *body)
+void set_notification_text (GtkWindow *nw, const char *summary, const char *body)
{
char *str;
size_t str_len;
@@ -941,7 +907,7 @@ set_notification_text(GtkWindow *nw, const char *summary, const char *body)
if ((body_label_text == NULL) || (strlen (body_label_text) == 0)) {
goto render_fail;
}
- goto renrer_ok;
+ goto render_ok;
}
render_fail:
@@ -952,7 +918,7 @@ render_fail:
g_free (quoted);
g_free (str);
-renrer_ok:
+render_ok:
xmlCleanupParser ();
if (body == NULL || *body == '\0')
@@ -970,8 +936,7 @@ renrer_ok:
}
/* Set notification icon */
-void
-set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf)
+void set_notification_icon (GtkWindow *nw, GdkPixbuf *pixbuf)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
@@ -996,8 +961,7 @@ set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf)
}
/* Set notification arrow */
-void
-set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y)
+void set_notification_arrow (GtkWidget *nw, gboolean visible, int x, int y)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
@@ -1010,9 +974,7 @@ set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y)
}
/* Add notification action */
-void
-add_notification_action(GtkWindow *nw, const char *text, const char *key,
- ActionInvokedCb cb)
+void add_notification_action (GtkWindow *nw, const char *text, const char *key, ActionInvokedCb cb)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
GtkWidget *label;
@@ -1032,13 +994,18 @@ add_notification_action(GtkWindow *nw, const char *text, const char *key,
if (!windata->pie_countdown) {
windata->pie_countdown = gtk_drawing_area_new();
gtk_widget_set_halign (windata->pie_countdown, GTK_ALIGN_END);
+ gtk_widget_set_valign (windata->pie_countdown, GTK_ALIGN_CENTER);
gtk_widget_show(windata->pie_countdown);
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->pie_countdown, "countdown");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->pie_countdown), "countdown");
+ #endif
+
gtk_box_pack_end (GTK_BOX (windata->actions_box), windata->pie_countdown, FALSE, TRUE, 0);
- gtk_widget_set_size_request(windata->pie_countdown,
- PIE_WIDTH, PIE_HEIGHT);
- g_signal_connect(G_OBJECT(windata->pie_countdown), "draw",
- G_CALLBACK(countdown_expose_cb), windata);
+ gtk_widget_set_size_request(windata->pie_countdown, PIE_WIDTH, PIE_HEIGHT);
+ g_signal_connect(G_OBJECT(windata->pie_countdown), "draw", G_CALLBACK(countdown_expose_cb), windata);
}
}
@@ -1093,8 +1060,7 @@ add_button:
}
/* Clear notification actions */
-void
-clear_notification_actions(GtkWindow *nw)
+void clear_notification_actions (GtkWindow *nw)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -1106,8 +1072,7 @@ clear_notification_actions(GtkWindow *nw)
}
/* Move notification window */
-void
-move_notification(GtkWidget *nw, int x, int y)
+void move_notification (GtkWidget *nw, int x, int y)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
@@ -1122,7 +1087,6 @@ move_notification(GtkWidget *nw, int x, int y)
}
}
-
/* Optional Functions */
/* Destroy notification */
@@ -1132,8 +1096,7 @@ move_notification(GtkWidget *nw, int x, int y)
/* Hide notification */
/* Set notification timeout */
-void
-set_notification_timeout(GtkWindow *nw, glong timeout)
+void set_notification_timeout (GtkWindow *nw, glong timeout)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
@@ -1142,7 +1105,7 @@ set_notification_timeout(GtkWindow *nw, glong timeout)
}
/* Set notification hints */
-void set_notification_hints(GtkWindow *nw, GVariant *hints)
+void set_notification_hints (GtkWindow *nw, GVariant *hints)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
guint8 urgency;
@@ -1169,8 +1132,7 @@ void set_notification_hints(GtkWindow *nw, GVariant *hints)
}
/* Notification tick */
-void
-notification_tick(GtkWindow *nw, glong remaining)
+void notification_tick (GtkWindow *nw, glong remaining)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
windata->remaining = remaining;
diff --git a/src/themes/slider/theme.c b/src/themes/slider/theme.c
index 8cc203c..87c147f 100644
--- a/src/themes/slider/theme.c
+++ b/src/themes/slider/theme.c
@@ -1,9 +1,8 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
+/*
* Copyright (C) 2006-2007 Christian Hammond <[email protected]>
* Copyright (C) 2009 Red Hat, Inc.
* Copyright (C) 2011 Perberos <[email protected]>
- * Copyright (C) 2012-2021 MATE Developers
+ * Copyright (C) 2012-2025 MATE Developers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +24,8 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>
typedef void (*ActionInvokedCb) (GtkWindow* nw, const char* key);
@@ -65,22 +65,22 @@ enum {
URGENCY_CRITICAL
};
-gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver,
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver,
unsigned int micro_ver);
-void get_theme_info(char **theme_name, char **theme_ver, char **author,
+void get_theme_info (char **theme_name, char **theme_ver, char **author,
char **homepage);
-GtkWindow* create_notification(UrlClickedCb url_clicked);
-void set_notification_text(GtkWindow *nw, const char *summary,
+GtkWindow* create_notification (UrlClickedCb url_clicked);
+void set_notification_text (GtkWindow *nw, const char *summary,
const char *body);
-void set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf);
-void set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y);
-void add_notification_action(GtkWindow *nw, const char *text, const char *key,
+void set_notification_icon (GtkWindow *nw, GdkPixbuf *pixbuf);
+void set_notification_arrow (GtkWidget *nw, gboolean visible, int x, int y);
+void add_notification_action (GtkWindow *nw, const char *text, const char *key,
ActionInvokedCb cb);
-void clear_notification_actions(GtkWindow *nw);
-void move_notification(GtkWidget *nw, int x, int y);
-void set_notification_timeout(GtkWindow *nw, glong timeout);
-void set_notification_hints(GtkWindow *nw, GVariant *hints);
-void notification_tick(GtkWindow *nw, glong remaining);
+void clear_notification_actions (GtkWindow *nw);
+void move_notification (GtkWidget *nw, int x, int y);
+void set_notification_timeout (GtkWindow *nw, glong timeout);
+void set_notification_hints (GtkWindow *nw, GVariant *hints);
+void notification_tick (GtkWindow *nw, glong remaining);
gboolean get_always_stack(GtkWidget* nw);
#define WIDTH 400
@@ -96,7 +96,7 @@ gboolean get_always_stack(GtkWidget* nw);
#define MAX_ICON_SIZE IMAGE_SIZE
-static void draw_round_rect(cairo_t* cr, gdouble aspect, gdouble x, gdouble y, gdouble corner_radius, gdouble width, gdouble height)
+static void draw_round_rect (cairo_t* cr, gdouble aspect, gdouble x, gdouble y, gdouble corner_radius, gdouble width, gdouble height)
{
gdouble radius = corner_radius / aspect;
@@ -127,10 +127,7 @@ static void draw_round_rect(cairo_t* cr, gdouble aspect, gdouble x, gdouble y, g
cairo_arc(cr, x + radius, y + radius, radius, 180.0f * G_PI / 180.0f, 270.0f * G_PI / 180.0f);
}
-static void
-get_background_color (GtkStyleContext *context,
- GtkStateFlags state,
- GdkRGBA *color)
+static void get_background_color (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
{
GdkRGBA *c;
@@ -145,7 +142,7 @@ get_background_color (GtkStyleContext *context,
gdk_rgba_free (c);
}
-static void fill_background(GtkWidget* widget, WindowData* windata, cairo_t* cr)
+static void fill_background (GtkWidget* widget, WindowData* windata, cairo_t* cr)
{
GtkAllocation allocation;
GtkStyleContext *context;
@@ -177,102 +174,68 @@ static void fill_background(GtkWidget* widget, WindowData* windata, cairo_t* cr)
cairo_stroke(cr);
}
-static void
-update_shape_region (cairo_surface_t *surface,
- WindowData *windata)
+static void update_shape_region (cairo_surface_t *surface, WindowData *windata)
{
if (windata->width == windata->last_width && windata->height == windata->last_height)
- {
return;
- }
-
- if (windata->width == 0 || windata->height == 0)
- {
- GtkAllocation allocation;
- gtk_widget_get_allocation (windata->win, &allocation);
- windata->width = MAX (allocation.width, 1);
- windata->height = MAX (allocation.height, 1);
+ if (windata->composited) {
+ gtk_widget_shape_combine_region (windata->win, NULL);
}
-
- if (!windata->composited) {
+ else {
cairo_region_t *region;
-
region = gdk_cairo_region_create_from_surface (surface);
gtk_widget_shape_combine_region (windata->win, region);
cairo_region_destroy (region);
- } else {
- gtk_widget_shape_combine_region (windata->win, NULL);
- return;
+ windata->last_width = windata->width;
+ windata->last_height = windata->height;
+ gtk_widget_queue_draw (GTK_WIDGET (windata->win));
}
-
- windata->last_width = windata->width;
- windata->last_height = windata->height;
}
-static void paint_window (GtkWidget *widget,
- cairo_t *cr,
- WindowData *windata)
+static void paint_window (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
- cairo_surface_t *surface;
cairo_t *cr2;
- GtkAllocation allocation;
+ cairo_surface_t *surface;
+ if (windata->width == 0 || windata->height == 0) {
+ GtkAllocation allocation;
gtk_widget_get_allocation (windata->win, &allocation);
-
- if (windata->width == 0 || windata->height == 0)
- {
- windata->width = MAX (allocation.width, 1);
- windata->height = MAX (allocation.height, 1);
+ windata->width = allocation.width;
+ windata->height = allocation.height;
}
- surface = cairo_surface_create_similar (cairo_get_target (cr),
- CAIRO_CONTENT_COLOR_ALPHA,
- windata->width,
- windata->height);
-
+ surface = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, windata->width, windata->height);
cr2 = cairo_create (surface);
-
- /* transparent background */
cairo_rectangle (cr2, 0, 0, windata->width, windata->height);
- cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0);
+ cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0); // transparent background color
cairo_fill (cr2);
fill_background (widget, windata, cr2);
-
- cairo_destroy(cr2);
+ cairo_destroy (cr2);
cairo_save (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_surface(cr, surface, 0, 0);
- cairo_paint(cr);
- update_shape_region (surface, windata);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
cairo_restore (cr);
- cairo_surface_destroy(surface);
-}
-
-static gboolean on_window_map(GtkWidget* widget, GdkEvent* event, WindowData* windata)
-{
- return FALSE;
+ update_shape_region (surface, windata);
+ cairo_surface_destroy (surface);
}
-static gboolean
-on_draw (GtkWidget *widget,
- cairo_t *cr,
- WindowData *windata)
+static gboolean on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
paint_window (widget, cr, windata);
-
return FALSE;
}
-static void destroy_windata(WindowData* windata)
+static void destroy_windata (WindowData* windata)
{
g_free(windata);
}
-static void update_content_hbox_visibility(WindowData* windata)
+static void update_content_hbox_visibility (WindowData* windata)
{
if (gtk_widget_get_visible(windata->icon) || gtk_widget_get_visible(windata->body_label) || gtk_widget_get_visible(windata->actions_box))
{
@@ -289,24 +252,18 @@ static gboolean on_configure_event(GtkWidget* widget, GdkEventConfigure* event,
windata->width = event->width;
windata->height = event->height;
- gtk_widget_queue_draw(widget);
+ gtk_widget_queue_draw (widget);
return FALSE;
}
-static void on_window_realize(GtkWidget* widget, WindowData* windata)
-{
- /* Nothing */
-}
-
-static void on_composited_changed(GtkWidget* window, WindowData* windata)
+static void on_composited_changed (GtkWidget* window, WindowData* windata)
{
- windata->composited = gdk_screen_is_composited(gtk_widget_get_screen(window));
-
- gtk_widget_queue_draw (windata->win);
+ windata->composited = gdk_screen_is_composited (gtk_widget_get_screen(window));
+ gtk_widget_queue_draw (window);
}
-GtkWindow* create_notification(UrlClickedCb url_clicked)
+GtkWindow* create_notification (UrlClickedCb url_clicked)
{
GtkWidget* win;
GtkWidget* main_vbox;
@@ -325,42 +282,41 @@ GtkWindow* create_notification(UrlClickedCb url_clicked)
win = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
gtk_widget_set_app_paintable(win, TRUE);
- g_signal_connect(G_OBJECT(win), "map-event", G_CALLBACK(on_window_map), windata);
- g_signal_connect(G_OBJECT(win), "draw", G_CALLBACK(on_draw), windata);
- g_signal_connect(G_OBJECT(win), "realize", G_CALLBACK(on_window_realize), windata);
-
windata->win = win;
-
windata->composited = FALSE;
-
screen = gtk_window_get_screen(GTK_WINDOW(win));
-
visual = gdk_screen_get_rgba_visual(screen);
- if (visual != NULL)
- {
- gtk_widget_set_visual(win, visual);
+ if (visual != NULL) {
+ gtk_widget_set_visual(win, visual);
if (gdk_screen_is_composited(screen))
- {
windata->composited = TRUE;
- }
}
- g_signal_connect(win, "composited-changed", G_CALLBACK(on_composited_changed), windata);
-
gtk_window_set_title(GTK_WINDOW(win), "Notification");
gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_NOTIFICATION);
gtk_widget_add_events(win, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+ gtk_widget_set_size_request(win, WIDTH, -1);
g_object_set_data_full(G_OBJECT(win), "windata", windata, (GDestroyNotify) destroy_windata);
atk_object_set_role(gtk_widget_get_accessible(win), ATK_ROLE_ALERT);
- g_signal_connect(G_OBJECT(win), "configure-event", G_CALLBACK(on_configure_event), windata);
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_show (main_vbox);
+ gtk_container_add (GTK_CONTAINER (win), main_vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (main_vbox, "notification-box");
+ gtk_widget_add_css_class (main_vbox, "slider-theme");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "notification-box");
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "slider-theme");
+ #endif
- main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_show(main_vbox);
- gtk_container_add(GTK_CONTAINER(win), main_vbox);
- gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 12);
+ g_signal_connect (G_OBJECT (win), "draw", G_CALLBACK (on_draw), windata);
+ g_signal_connect (G_OBJECT (win), "configure-event", G_CALLBACK (on_configure_event), windata);
+ g_signal_connect (G_OBJECT (win), "composited-changed", G_CALLBACK (on_composited_changed), windata);
windata->main_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_show(windata->main_hbox);
@@ -431,7 +387,7 @@ GtkWindow* create_notification(UrlClickedCb url_clicked)
gtk_label_set_yalign (GTK_LABEL (windata->body_label), 0.0);
gtk_label_set_line_wrap(GTK_LABEL(windata->body_label), TRUE);
gtk_label_set_line_wrap_mode (GTK_LABEL (windata->body_label), PANGO_WRAP_WORD_CHAR);
- gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
+ gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
g_signal_connect_swapped(G_OBJECT(windata->body_label), "activate-link", G_CALLBACK(windata->url_clicked), win);
atkobj = gtk_widget_get_accessible(windata->body_label);
@@ -439,14 +395,24 @@ GtkWindow* create_notification(UrlClickedCb url_clicked)
windata->actions_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign (windata->actions_box, GTK_ALIGN_END);
- gtk_widget_show(windata->actions_box);
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->summary_label, "summary");
+ gtk_widget_add_css_class (windata->body_label, "body");
+ gtk_widget_add_css_class (windata->actions_box, "actions-box");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->summary_label), "summary");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->body_label), "body");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->actions_box), "actions-box");
+ #endif
+
+ gtk_widget_show(windata->actions_box);
gtk_box_pack_start (GTK_BOX (vbox), windata->actions_box, FALSE, TRUE, 0);
return GTK_WINDOW(win);
}
-void set_notification_hints(GtkWindow *nw, GVariant *hints)
+void set_notification_hints (GtkWindow *nw, GVariant *hints)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
guint8 urgency;
@@ -472,7 +438,7 @@ void set_notification_hints(GtkWindow *nw, GVariant *hints)
}
}
-void set_notification_timeout(GtkWindow *nw, glong timeout)
+void set_notification_timeout (GtkWindow *nw, glong timeout)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -481,7 +447,7 @@ void set_notification_timeout(GtkWindow *nw, glong timeout)
windata->timeout = timeout;
}
-void notification_tick(GtkWindow* nw, glong remaining)
+void notification_tick (GtkWindow* nw, glong remaining)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -493,7 +459,7 @@ void notification_tick(GtkWindow* nw, glong remaining)
}
}
-void set_notification_text(GtkWindow* nw, const char* summary, const char* body)
+void set_notification_text (GtkWindow* nw, const char* summary, const char* body)
{
char* str;
size_t str_len;
@@ -555,7 +521,7 @@ void set_notification_text(GtkWindow* nw, const char* summary, const char* body)
if ((body_label_text == NULL) || (strlen (body_label_text) == 0)) {
goto render_fail;
}
- goto renrer_ok;
+ goto render_ok;
}
render_fail:
@@ -564,7 +530,7 @@ render_fail:
gtk_label_set_markup (GTK_LABEL (windata->body_label), quoted);
g_free (quoted);
-renrer_ok:
+render_ok:
xmlCleanupParser ();
if (body == NULL || *body == '\0')
@@ -627,7 +593,7 @@ static GdkPixbuf* scale_pixbuf(GdkPixbuf* pixbuf, int max_width, int max_height,
}
}
-void set_notification_icon(GtkWindow* nw, GdkPixbuf* pixbuf)
+void set_notification_icon (GtkWindow* nw, GdkPixbuf* pixbuf)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -660,17 +626,14 @@ void set_notification_icon(GtkWindow* nw, GdkPixbuf* pixbuf)
update_content_hbox_visibility(windata);
}
-void set_notification_arrow(GtkWidget* nw, gboolean visible, int x, int y)
+void set_notification_arrow (GtkWidget* nw, gboolean visible, int x, int y)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
g_assert(windata != NULL);
}
-static void
-paint_countdown (GtkWidget *pie,
- cairo_t* cr,
- WindowData* windata)
+static void paint_countdown (GtkWidget *pie, cairo_t* cr, WindowData* windata)
{
GtkStyleContext* context;
GdkRGBA bg;
@@ -678,50 +641,41 @@ paint_countdown (GtkWidget *pie,
cairo_t* cr2;
cairo_surface_t* surface;
- context = gtk_widget_get_style_context(windata->win);
-
+ // :selected { background-color:#aabbcc; } or
+ // .notification-box .countdown:selected { background-color:#aabbcc; }
+ context = gtk_widget_get_style_context (pie);
gtk_style_context_save (context);
gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED);
-
get_background_color (context, GTK_STATE_FLAG_SELECTED, &bg);
-
gtk_style_context_restore (context);
gtk_widget_get_allocation(pie, &allocation);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
- surface = cairo_surface_create_similar(cairo_get_target(cr),
- CAIRO_CONTENT_COLOR_ALPHA,
- allocation.width,
- allocation.height);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ surface = cairo_surface_create_similar (cairo_get_target(cr),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ allocation.width,
+ allocation.height);
cr2 = cairo_create (surface);
-
- fill_background (pie, windata, cr2);
-
if (windata->timeout > 0)
{
gdouble pct = (gdouble) windata->remaining / (gdouble) windata->timeout;
-
gdk_cairo_set_source_rgba (cr2, &bg);
-
cairo_move_to (cr2, PIE_RADIUS, PIE_RADIUS);
cairo_arc_negative (cr2, PIE_RADIUS, PIE_RADIUS, PIE_RADIUS, -G_PI_2, -(pct * G_PI * 2) - G_PI_2);
cairo_line_to (cr2, PIE_RADIUS, PIE_RADIUS);
cairo_fill (cr2);
}
-
- cairo_destroy(cr2);
+ cairo_destroy (cr2);
cairo_save (cr);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
cairo_restore (cr);
-
cairo_surface_destroy(surface);
}
-static gboolean
-on_countdown_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
+static gboolean on_countdown_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
paint_countdown (widget, cr, windata);
@@ -736,7 +690,7 @@ static void on_action_clicked(GtkWidget* w, GdkEventButton *event, ActionInvoked
action_cb(nw, key);
}
-void add_notification_action(GtkWindow* nw, const char* text, const char* key, ActionInvokedCb cb)
+void add_notification_action (GtkWindow* nw, const char* text, const char* key, ActionInvokedCb cb)
{
WindowData* windata;
GtkWidget* label;
@@ -749,7 +703,7 @@ void add_notification_action(GtkWindow* nw, const char* text, const char* key, A
g_assert(windata != NULL);
- if (!gtk_widget_get_visible(windata->actions_box))
+ if (gtk_widget_get_visible(windata->actions_box))
{
gtk_widget_show(windata->actions_box);
update_content_hbox_visibility(windata);
@@ -761,11 +715,15 @@ void add_notification_action(GtkWindow* nw, const char* text, const char* key, A
gtk_widget_set_valign (windata->pie_countdown, GTK_ALIGN_CENTER);
gtk_widget_show(windata->pie_countdown);
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->pie_countdown, "countdown");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->pie_countdown), "countdown");
+ #endif
+
gtk_box_pack_end (GTK_BOX (windata->actions_box), windata->pie_countdown, FALSE, TRUE, 0);
- gtk_widget_set_size_request(windata->pie_countdown,
- PIE_WIDTH, PIE_HEIGHT);
- g_signal_connect(G_OBJECT(windata->pie_countdown), "draw",
- G_CALLBACK(on_countdown_draw), windata);
+ gtk_widget_set_size_request(windata->pie_countdown, PIE_WIDTH, PIE_HEIGHT);
+ g_signal_connect(G_OBJECT(windata->pie_countdown), "draw", G_CALLBACK(on_countdown_draw), windata);
}
}
@@ -817,7 +775,7 @@ add_button:
gtk_widget_show_all(windata->actions_box);
}
-void clear_notification_actions(GtkWindow* nw)
+void clear_notification_actions (GtkWindow* nw)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -827,7 +785,7 @@ void clear_notification_actions(GtkWindow* nw)
gtk_container_foreach(GTK_CONTAINER(windata->actions_box), (GtkCallback) gtk_widget_destroy, NULL);
}
-void move_notification(GtkWidget* widget, int x, int y)
+void move_notification (GtkWidget* widget, int x, int y)
{
WindowData* windata = g_object_get_data(G_OBJECT(widget), "windata");
@@ -836,7 +794,7 @@ void move_notification(GtkWidget* widget, int x, int y)
gtk_window_move(GTK_WINDOW(windata->win), x, y);
}
-void get_theme_info(char** theme_name, char** theme_ver, char** author, char** homepage)
+void get_theme_info (char** theme_name, char** theme_ver, char** author, char** homepage)
{
*theme_name = g_strdup("Slider");
*theme_ver = g_strdup_printf("%d.%d.%d", NOTIFICATION_DAEMON_MAJOR_VERSION, NOTIFICATION_DAEMON_MINOR_VERSION, NOTIFICATION_DAEMON_MICRO_VERSION);
@@ -849,7 +807,7 @@ gboolean get_always_stack(GtkWidget* nw)
return TRUE;
}
-gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver, unsigned int micro_ver)
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver, unsigned int micro_ver)
{
return major_ver == NOTIFICATION_DAEMON_MAJOR_VERSION && minor_ver == NOTIFICATION_DAEMON_MINOR_VERSION && micro_ver == NOTIFICATION_DAEMON_MICRO_VERSION;
}
diff --git a/src/themes/standard/theme.c b/src/themes/standard/theme.c
index ad44424..7a16559 100644
--- a/src/themes/standard/theme.c
+++ b/src/themes/standard/theme.c
@@ -1,9 +1,8 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
+/*
* Copyright (C) 2006-2007 Christian Hammond <[email protected]>
* Copyright (C) 2009 Red Hat, Inc.
* Copyright (C) 2011 Perberos <[email protected]>
- * Copyright (C) 2012-2021 MATE Developers
+ * Copyright (C) 2012-2025 MATE Developers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,11 +19,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
+
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>
typedef void (*ActionInvokedCb) (GtkWindow* nw, const char* key);
@@ -82,29 +83,28 @@ enum {
URGENCY_CRITICAL
};
-gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver,
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver,
unsigned int micro_ver);
-void get_theme_info(char **theme_name, char **theme_ver, char **author,
+void get_theme_info (char **theme_name, char **theme_ver, char **author,
char **homepage);
-GtkWindow* create_notification(UrlClickedCb url_clicked);
-void set_notification_text(GtkWindow *nw, const char *summary,
+GtkWindow* create_notification (UrlClickedCb url_clicked);
+void set_notification_text (GtkWindow *nw, const char *summary,
const char *body);
-void set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf);
-void set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y);
-void add_notification_action(GtkWindow *nw, const char *text, const char *key,
+void set_notification_icon (GtkWindow *nw, GdkPixbuf *pixbuf);
+void set_notification_arrow (GtkWidget *nw, gboolean visible, int x, int y);
+void add_notification_action (GtkWindow *nw, const char *text, const char *key,
ActionInvokedCb cb);
-void clear_notification_actions(GtkWindow *nw);
-void move_notification(GtkWidget *nw, int x, int y);
-void set_notification_timeout(GtkWindow *nw, glong timeout);
-void set_notification_hints(GtkWindow *nw, GVariant *hints);
-void notification_tick(GtkWindow *nw, glong remaining);
+void clear_notification_actions (GtkWindow *nw);
+void move_notification (GtkWidget *nw, int x, int y);
+void set_notification_timeout (GtkWindow *nw, glong timeout);
+void set_notification_hints (GtkWindow *nw, GVariant *hints);
+void notification_tick (GtkWindow *nw, glong remaining);
//#define ENABLE_GRADIENT_LOOK
-
#ifdef ENABLE_GRADIENT_LOOK
- #define STRIPE_WIDTH 45
+#define STRIPE_WIDTH 45
#else
- #define STRIPE_WIDTH 30
+#define STRIPE_WIDTH 30
#endif
#define WIDTH 400
@@ -121,10 +121,7 @@ void notification_tick(GtkWindow *nw, glong remaining);
#define BACKGROUND_OPACITY 0.92
#define BOTTOM_GRADIENT_HEIGHT 30
-static void
-get_background_color (GtkStyleContext *context,
- GtkStateFlags state,
- GdkRGBA *color)
+static void get_background_color (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
{
GdkRGBA *c;
@@ -139,7 +136,7 @@ get_background_color (GtkStyleContext *context,
gdk_rgba_free (c);
}
-static void fill_background(GtkWidget* widget, WindowData* windata, cairo_t* cr)
+static void fill_background (GtkWidget* widget, WindowData* windata, cairo_t* cr)
{
GtkStyleContext *context;
GdkRGBA bg;
@@ -148,14 +145,11 @@ static void fill_background(GtkWidget* widget, WindowData* windata, cairo_t* cr)
gtk_widget_get_allocation(widget, &allocation);
- #ifdef ENABLE_GRADIENT_LOOK
-
- cairo_pattern_t *gradient;
- int gradient_y;
-
- gradient_y = allocation.height - BOTTOM_GRADIENT_HEIGHT;
-
- #endif
+#ifdef ENABLE_GRADIENT_LOOK
+ cairo_pattern_t *gradient;
+ int gradient_y;
+ gradient_y = allocation.height - BOTTOM_GRADIENT_HEIGHT;
+#endif
context = gtk_widget_get_style_context (windata->win);
@@ -179,30 +173,30 @@ static void fill_background(GtkWidget* widget, WindowData* windata, cairo_t* cr)
cairo_fill(cr);
- #ifdef ENABLE_GRADIENT_LOOK
- /* Add a very subtle gradient to the bottom of the notification */
- gradient = cairo_pattern_create_linear(0, gradient_y, 0, allocation.height);
- cairo_pattern_add_color_stop_rgba(gradient, 0, 0, 0, 0, 0);
- cairo_pattern_add_color_stop_rgba(gradient, 1, 0, 0, 0, 0.15);
- cairo_rectangle(cr, 0, gradient_y, allocation.width, BOTTOM_GRADIENT_HEIGHT);
-
- cairo_set_source(cr, gradient);
- cairo_fill(cr);
- cairo_pattern_destroy(gradient);
- #endif
+#ifdef ENABLE_GRADIENT_LOOK
+ /* Add a very subtle gradient to the bottom of the notification */
+ gradient = cairo_pattern_create_linear(0, gradient_y, 0, allocation.height);
+ cairo_pattern_add_color_stop_rgba(gradient, 0, 0, 0, 0, 0);
+ cairo_pattern_add_color_stop_rgba(gradient, 1, 0, 0, 0, 0.15);
+ cairo_rectangle(cr, 0, gradient_y, allocation.width, BOTTOM_GRADIENT_HEIGHT);
+
+ cairo_set_source(cr, gradient);
+ cairo_fill(cr);
+ cairo_pattern_destroy(gradient);
+#endif
}
-static void draw_stripe(GtkWidget* widget, WindowData* windata, cairo_t* cr)
+static void draw_stripe (GtkWidget* widget, WindowData* windata, cairo_t* cr)
{
GtkStyleContext* context;
GdkRGBA bg;
int stripe_x;
int stripe_y;
int stripe_height;
- #ifdef ENABLE_GRADIENT_LOOK
- cairo_pattern_t* gradient;
- double r, g, b;
- #endif
+#ifdef ENABLE_GRADIENT_LOOK
+ cairo_pattern_t* gradient;
+ double r, g, b;
+#endif
context = gtk_widget_get_style_context (widget);
@@ -247,24 +241,24 @@ static void draw_stripe(GtkWidget* widget, WindowData* windata, cairo_t* cr)
cairo_rectangle(cr, stripe_x, stripe_y, STRIPE_WIDTH, stripe_height);
- #ifdef ENABLE_GRADIENT_LOOK
- r = color.red / 65535.0;
- g = color.green / 65535.0;
- b = color.blue / 65535.0;
-
- gradient = cairo_pattern_create_linear(stripe_x, 0, STRIPE_WIDTH, 0);
- cairo_pattern_add_color_stop_rgba(gradient, 0, r, g, b, 1);
- cairo_pattern_add_color_stop_rgba(gradient, 1, r, g, b, 0);
- cairo_set_source(cr, gradient);
- cairo_fill(cr);
- cairo_pattern_destroy(gradient);
- #else
- gdk_cairo_set_source_rgba (cr, &bg);
- cairo_fill(cr);
- #endif
+#ifdef ENABLE_GRADIENT_LOOK
+ r = color.red / 65535.0;
+ g = color.green / 65535.0;
+ b = color.blue / 65535.0;
+
+ gradient = cairo_pattern_create_linear(stripe_x, 0, STRIPE_WIDTH, 0);
+ cairo_pattern_add_color_stop_rgba(gradient, 0, r, g, b, 1);
+ cairo_pattern_add_color_stop_rgba(gradient, 1, r, g, b, 0);
+ cairo_set_source(cr, gradient);
+ cairo_fill(cr);
+ cairo_pattern_destroy(gradient);
+#else
+ gdk_cairo_set_source_rgba (cr, &bg);
+ cairo_fill(cr);
+#endif
}
-static GtkArrowType get_notification_arrow_type(GtkWidget* nw)
+static GtkArrowType get_notification_arrow_type (GtkWidget* nw)
{
WindowData* windata;
GdkScreen* screen;
@@ -298,7 +292,7 @@ static GtkArrowType get_notification_arrow_type(GtkWidget* nw)
i++;\
} G_STMT_END
-static void create_border_with_arrow(GtkWidget* nw, WindowData* windata)
+static void create_border_with_arrow (GtkWidget* nw, WindowData* windata)
{
int width;
int height;
@@ -487,7 +481,7 @@ static void create_border_with_arrow(GtkWidget* nw, WindowData* windata)
g_free(shape_points);
}
-static void draw_border(GtkWidget* widget, WindowData *windata, cairo_t* cr)
+static void draw_border (GtkWidget* widget, WindowData *windata, cairo_t* cr)
{
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
cairo_set_line_width(cr, 1.0);
@@ -519,54 +513,45 @@ static void draw_border(GtkWidget* widget, WindowData *windata, cairo_t* cr)
cairo_stroke(cr);
}
-static void
-paint_window (GtkWidget *widget,
- cairo_t *cr,
- WindowData *windata)
+static void paint_window (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
- cairo_t* cr2;
- cairo_surface_t* surface;
- GtkAllocation allocation;
-
- gtk_widget_get_allocation(windata->win, &allocation);
-
- if (windata->width == 0)
- {
- windata->width = allocation.width;
- windata->height = allocation.height;
+ cairo_t *cr2;
+ cairo_surface_t *surface;
+
+ if (windata->width == 0 || windata->height == 0) {
+ GtkAllocation allocation;
+ gtk_widget_get_allocation (windata->win, &allocation);
+ windata->width = allocation.width;
+ windata->height = allocation.height;
}
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-
- gtk_widget_get_allocation(widget, &allocation);
-
- surface = cairo_surface_create_similar (cairo_get_target (cr),
- CAIRO_CONTENT_COLOR_ALPHA,
- allocation.width,
- allocation.height);
-
+ surface = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, windata->width, windata->height);
cr2 = cairo_create (surface);
-
- fill_background(widget, windata, cr2);
- draw_border(widget, windata, cr2);
- draw_stripe(widget, windata, cr2);
+ cairo_rectangle (cr2, 0, 0, windata->width, windata->height);
+ cairo_set_source_rgba (cr2, 0.0, 0.0, 0.0, 0.0); // transparent background color
cairo_fill (cr2);
+
+ fill_background (widget, windata, cr2);
+ draw_border (widget, windata, cr2);
+ draw_stripe (widget, windata, cr2);
cairo_destroy (cr2);
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface (cr, surface, 0, 0);
- cairo_paint(cr);
- cairo_surface_destroy(surface);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ cairo_surface_destroy (surface);
}
-static gboolean
-on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
+static gboolean on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
paint_window (widget, cr, windata);
-
return FALSE;
}
-static void destroy_windata(WindowData* windata)
+static void destroy_windata (WindowData* windata)
{
if (windata->window_region != NULL)
{
@@ -576,7 +561,7 @@ static void destroy_windata(WindowData* windata)
g_free(windata);
}
-static void update_spacers(GtkWidget* nw)
+static void update_spacers (GtkWidget* nw)
{
WindowData* windata;
@@ -607,7 +592,7 @@ static void update_spacers(GtkWidget* nw)
}
}
-static void update_content_hbox_visibility(WindowData* windata)
+static void update_content_hbox_visibility (WindowData* windata)
{
/*
* This is all a hack, but until we have a libview-style ContentBox,
@@ -623,25 +608,31 @@ static void update_content_hbox_visibility(WindowData* windata)
}
}
-static gboolean configure_event_cb(GtkWidget* nw, GdkEventConfigure* event, WindowData* windata)
+static gboolean on_configure_event (GtkWidget* widget, GdkEventConfigure* event, WindowData* windata)
{
windata->width = event->width;
windata->height = event->height;
- update_spacers(nw);
- gtk_widget_queue_draw(nw);
+ update_spacers (widget);
+ gtk_widget_queue_draw (widget);
return FALSE;
}
-static gboolean activate_link(GtkLabel* label, const char* url, WindowData* windata)
+static void on_composited_changed (GtkWidget* window, WindowData* windata)
+{
+ windata->composited = gdk_screen_is_composited (gtk_widget_get_screen(window));
+ gtk_widget_queue_draw (window);
+}
+
+static gboolean activate_link (GtkLabel* label, const char* url, WindowData* windata)
{
windata->url_clicked(GTK_WINDOW(windata->win), url);
return TRUE;
}
-GtkWindow* create_notification(UrlClickedCb url_clicked)
+GtkWindow* create_notification (UrlClickedCb url_clicked)
{
GtkWidget* spacer;
GtkWidget* win;
@@ -662,42 +653,42 @@ GtkWindow* create_notification(UrlClickedCb url_clicked)
win = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
+ gtk_widget_set_app_paintable(win, TRUE);
windata->win = win;
-
windata->composited = FALSE;
-
-
screen = gtk_window_get_screen(GTK_WINDOW(win));
-
visual = gdk_screen_get_rgba_visual(screen);
- if (visual != NULL)
- {
+ if (visual != NULL) {
gtk_widget_set_visual(win, visual);
-
if (gdk_screen_is_composited(screen))
- {
windata->composited = TRUE;
- }
}
gtk_window_set_title(GTK_WINDOW(win), "Notification");
gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_NOTIFICATION);
gtk_widget_add_events(win, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
- gtk_widget_realize(win);
gtk_widget_set_size_request(win, WIDTH, -1);
g_object_set_data_full(G_OBJECT(win), "windata", windata, (GDestroyNotify) destroy_windata);
atk_object_set_role(gtk_widget_get_accessible(win), ATK_ROLE_ALERT);
- g_signal_connect(G_OBJECT(win), "configure_event", G_CALLBACK(configure_event_cb), windata);
-
- main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_show(main_vbox);
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_show (main_vbox);
gtk_container_add (GTK_CONTAINER (win), main_vbox);
- gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
- g_signal_connect (G_OBJECT (main_vbox), "draw", G_CALLBACK (on_draw), windata);
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (main_vbox, "notification-box");
+ gtk_widget_add_css_class (main_vbox, "default-theme");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "notification-box");
+ gtk_style_context_add_class (gtk_widget_get_style_context (main_vbox), "default-theme");
+ #endif
+
+ g_signal_connect (G_OBJECT (win), "draw", G_CALLBACK (on_draw), windata);
+ g_signal_connect (G_OBJECT (win), "configure-event", G_CALLBACK (on_configure_event), windata);
+ g_signal_connect (G_OBJECT (win), "composited-changed", G_CALLBACK (on_composited_changed), windata);
windata->top_spacer = gtk_image_new();
gtk_box_pack_start(GTK_BOX(main_vbox), windata->top_spacer, FALSE, FALSE, 0);
@@ -782,7 +773,7 @@ GtkWindow* create_notification(UrlClickedCb url_clicked)
gtk_label_set_yalign (GTK_LABEL (windata->body_label), 0.0);
gtk_label_set_line_wrap(GTK_LABEL(windata->body_label), TRUE);
gtk_label_set_line_wrap_mode (GTK_LABEL (windata->body_label), PANGO_WRAP_WORD_CHAR);
- gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
+ gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50);
g_signal_connect(G_OBJECT(windata->body_label), "activate-link", G_CALLBACK(activate_link), windata);
atkobj = gtk_widget_get_accessible(windata->body_label);
@@ -790,13 +781,24 @@ GtkWindow* create_notification(UrlClickedCb url_clicked)
windata->actions_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign (windata->actions_box, GTK_ALIGN_END);
+
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->summary_label, "summary");
+ gtk_widget_add_css_class (windata->body_label, "body");
+ gtk_widget_add_css_class (windata->actions_box, "actions-box");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->summary_label), "summary");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->body_label), "body");
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->actions_box), "actions-box");
+ #endif
+
gtk_widget_show(windata->actions_box);
gtk_box_pack_start(GTK_BOX(vbox), windata->actions_box, FALSE, TRUE, 0);
return GTK_WINDOW(win);
}
-void set_notification_hints(GtkWindow *nw, GVariant *hints)
+void set_notification_hints (GtkWindow *nw, GVariant *hints)
{
WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata");
guint8 urgency;
@@ -822,7 +824,7 @@ void set_notification_hints(GtkWindow *nw, GVariant *hints)
}
}
-void set_notification_timeout(GtkWindow* nw, glong timeout)
+void set_notification_timeout (GtkWindow* nw, glong timeout)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -831,7 +833,7 @@ void set_notification_timeout(GtkWindow* nw, glong timeout)
windata->timeout = timeout;
}
-void notification_tick(GtkWindow* nw, glong remaining)
+void notification_tick (GtkWindow* nw, glong remaining)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -843,7 +845,7 @@ void notification_tick(GtkWindow* nw, glong remaining)
}
}
-void set_notification_text(GtkWindow* nw, const char* summary, const char* body)
+void set_notification_text (GtkWindow* nw, const char* summary, const char* body)
{
char* str;
size_t str_len;
@@ -903,7 +905,7 @@ void set_notification_text(GtkWindow* nw, const char* summary, const char* body)
if ((body_label_text == NULL) || (strlen (body_label_text) == 0)) {
goto render_fail;
}
- goto renrer_ok;
+ goto render_ok;
}
render_fail:
@@ -912,7 +914,7 @@ render_fail:
gtk_label_set_markup (GTK_LABEL (windata->body_label), quoted);
g_free (quoted);
-renrer_ok:
+render_ok:
xmlCleanupParser ();
if (body == NULL || *body == '\0')
@@ -937,7 +939,7 @@ renrer_ok:
gtk_widget_set_size_request(windata->summary_label, WIDTH - (1 * 2) - (10 * 2) - SPACER_LEFT - req.width - (6 * 2), -1);
}
-void set_notification_icon(GtkWindow* nw, GdkPixbuf* pixbuf)
+void set_notification_icon (GtkWindow* nw, GdkPixbuf* pixbuf)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -961,7 +963,7 @@ void set_notification_icon(GtkWindow* nw, GdkPixbuf* pixbuf)
update_content_hbox_visibility(windata);
}
-void set_notification_arrow(GtkWidget* nw, gboolean visible, int x, int y)
+void set_notification_arrow (GtkWidget* nw, gboolean visible, int x, int y)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -974,10 +976,7 @@ void set_notification_arrow(GtkWidget* nw, gboolean visible, int x, int y)
update_spacers(nw);
}
-static void
-paint_countdown (GtkWidget *pie,
- cairo_t *cr,
- WindowData *windata)
+static void paint_countdown (GtkWidget *pie, cairo_t *cr, WindowData *windata)
{
GtkStyleContext *context;
GdkRGBA bg;
@@ -985,57 +984,48 @@ paint_countdown (GtkWidget *pie,
cairo_t* cr2;
cairo_surface_t* surface;
- context = gtk_widget_get_style_context (windata->win);
-
+ // :selected { background-color:#aabbcc; } or
+ // .notification-box .countdown:selected { background-color:#aabbcc; }
+ context = gtk_widget_get_style_context (pie);
gtk_style_context_save (context);
gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED);
-
get_background_color (context, GTK_STATE_FLAG_SELECTED, &bg);
-
gtk_style_context_restore (context);
gtk_widget_get_allocation(pie, &alloc);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
surface = cairo_surface_create_similar (cairo_get_target(cr),
CAIRO_CONTENT_COLOR_ALPHA,
alloc.width,
alloc.height);
cr2 = cairo_create (surface);
-
- fill_background (pie, windata, cr2);
-
if (windata->timeout > 0)
{
gdouble pct = (gdouble) windata->remaining / (gdouble) windata->timeout;
-
gdk_cairo_set_source_rgba (cr2, &bg);
-
cairo_move_to (cr2, PIE_RADIUS, PIE_RADIUS);
cairo_arc_negative (cr2, PIE_RADIUS, PIE_RADIUS, PIE_RADIUS, -G_PI_2, -(pct * G_PI * 2) - G_PI_2);
cairo_line_to (cr2, PIE_RADIUS, PIE_RADIUS);
cairo_fill (cr2);
}
-
- cairo_destroy(cr2);
+ cairo_destroy (cr2);
cairo_save (cr);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
cairo_restore (cr);
-
cairo_surface_destroy(surface);
}
-static gboolean
-on_countdown_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
+static gboolean on_countdown_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata)
{
paint_countdown (widget, cr, windata);
return FALSE;
}
-static void action_clicked_cb(GtkWidget* w, GdkEventButton* event, ActionInvokedCb action_cb)
+static void action_clicked_cb (GtkWidget* w, GdkEventButton* event, ActionInvokedCb action_cb)
{
GtkWindow* nw;
const char* key;
@@ -1044,7 +1034,7 @@ static void action_clicked_cb(GtkWidget* w, GdkEventButton* event, ActionInvoked
action_cb(nw, key);
}
-void add_notification_action(GtkWindow* nw, const char* text, const char* key, ActionInvokedCb cb)
+void add_notification_action (GtkWindow* nw, const char* text, const char* key, ActionInvokedCb cb)
{
WindowData* windata;
GtkWidget* label;
@@ -1066,13 +1056,18 @@ void add_notification_action(GtkWindow* nw, const char* text, const char* key, A
if (!windata->pie_countdown) {
windata->pie_countdown = gtk_drawing_area_new();
gtk_widget_set_halign (windata->pie_countdown, GTK_ALIGN_END);
+ gtk_widget_set_valign (windata->pie_countdown, GTK_ALIGN_CENTER);
gtk_widget_show(windata->pie_countdown);
+ #if GTK_CHECK_VERSION (4,0,0)
+ gtk_widget_add_css_class (windata->pie_countdown, "countdown");
+ #else
+ gtk_style_context_add_class (gtk_widget_get_style_context (windata->pie_countdown), "countdown");
+ #endif
+
gtk_box_pack_end (GTK_BOX (windata->actions_box), windata->pie_countdown, FALSE, TRUE, 0);
- gtk_widget_set_size_request(windata->pie_countdown,
- PIE_WIDTH, PIE_HEIGHT);
- g_signal_connect(G_OBJECT(windata->pie_countdown), "draw",
- G_CALLBACK(on_countdown_draw), windata);
+ gtk_widget_set_size_request(windata->pie_countdown, PIE_WIDTH, PIE_HEIGHT);
+ g_signal_connect(G_OBJECT(windata->pie_countdown), "draw", G_CALLBACK(on_countdown_draw), windata);
}
}
@@ -1121,7 +1116,7 @@ add_button:
gtk_widget_show_all(windata->actions_box);
}
-void clear_notification_actions(GtkWindow* nw)
+void clear_notification_actions (GtkWindow* nw)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -1131,7 +1126,7 @@ void clear_notification_actions(GtkWindow* nw)
gtk_container_foreach(GTK_CONTAINER(windata->actions_box), (GtkCallback) gtk_widget_destroy, NULL);
}
-void move_notification(GtkWidget* nw, int x, int y)
+void move_notification (GtkWidget* nw, int x, int y)
{
WindowData* windata = g_object_get_data(G_OBJECT(nw), "windata");
@@ -1147,7 +1142,7 @@ void move_notification(GtkWidget* nw, int x, int y)
}
}
-void get_theme_info(char** theme_name, char** theme_ver, char** author, char** homepage)
+void get_theme_info (char** theme_name, char** theme_ver, char** author, char** homepage)
{
*theme_name = g_strdup("Standard");
@@ -1157,7 +1152,7 @@ void get_theme_info(char** theme_name, char** theme_ver, char** author, char** h
*homepage = g_strdup("http://www.galago-project.org/");
}
-gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver, unsigned int micro_ver)
+gboolean theme_check_init (unsigned int major_ver, unsigned int minor_ver, unsigned int micro_ver)
{
return major_ver == NOTIFICATION_DAEMON_MAJOR_VERSION && minor_ver == NOTIFICATION_DAEMON_MINOR_VERSION && micro_ver == NOTIFICATION_DAEMON_MICRO_VERSION;
}
# GtkTreeView4: add classes (odd/even/sorted) to restore zebra striping
# https://github.com/GNOME/gtk/blob/4.12.3/gtk/deprecated/gtktreeview.c
Index: b/gtk/deprecated/gtktreeview.c
===================================================================
--- a/gtk/deprecated/gtktreeview.c
+++ b/gtk/deprecated/gtktreeview.c
@@ -4609,6 +4609,18 @@ gtk_tree_view_bin_snapshot
gtk_style_context_add_class (context, "cell");
+ if (list == first_column)
+ gtk_style_context_add_class (context, rtl ? "last" : "first");
+ if (list == last_column)
+ gtk_style_context_add_class (context, rtl ? "first" : "last");
+ if (gtk_tree_rbtree_node_get_index (tree, node) % 2 == 0)
+ gtk_style_context_add_class (context, "odd");
+ else
+ gtk_style_context_add_class (context, "even");
+
+ if (flags & GTK_CELL_RENDERER_SORTED)
+ gtk_style_context_add_class (context, "sorted");
+
if (node == priv->cursor_node && has_can_focus_cell
&& ((column == priv->focus_column
&& priv->draw_keyfocus &&
@luigifab
Copy link
Author

luigifab commented Apr 1, 2025

https://build.opensuse.org/package/show/home:luigifab/gtk3-classic & https://build.opensuse.org/package/show/home:luigifab/gtk4-classic

appearance__progress_text.gtk.3.patch : high cpu usage
appearance__progress_text.gtk.4.patch : some warnings (Gtk-CRITICAL gtk_widget_unparent: assertion GTK_IS_WIDGET (widget) failed) + no automatic min-width/height from text width/height

appearance__focus-visible.gtk4.patch : focus is not on the first toolbar button

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment