Skip to content

Instantly share code, notes, and snippets.

@luigifab
Last active December 28, 2025 10:13
Show Gist options
  • Select an option

  • Save luigifab/0fce786cdb93b5687069a82f490ea95e to your computer and use it in GitHub Desktop.

Select an option

Save luigifab/0fce786cdb93b5687069a82f490ea95e to your computer and use it in GitHub Desktop.
gtk3-classic+ (GTK 3.24.51) & gtk4-classic (GTK 4.20.2) & gtk5-classic (xptdr) - for Debian Testing and Ubuntu
# GtkCellRendererToggle4: add classes to check and radio elements
# https://github.com/GNOME/gtk/blob/4.21.3/gtk/deprecated/gtkcellrenderertoggle.c
Index: b/gtk/deprecated/gtkcellrenderertoggle.c
===================================================================
--- a/gtk/deprecated/gtkcellrenderertoggle.c
+++ b/gtk/deprecated/gtkcellrenderertoggle.c
@@ -482,6 +482,7 @@ gtk_cell_renderer_toggle_snapshot
context = gtk_cell_renderer_toggle_save_context (celltoggle, widget);
gtk_style_context_set_state (context, state);
+ gtk_style_context_add_class (context, priv->radio ? "radio" : "check");
gtk_snapshot_render_background (snapshot, context,
cell_area->x + x_offset + xpad,
# 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);
# GtkTreeview3: disable treeview lines (for example vertical treeview lines in GtkInspector)
# https://github.com/GNOME/gtk/blob/3.24.49/gtk/gtktreeview.c
Index: b/gtk/gtktreeview.c
===================================================================
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -16013,6 +16013,9 @@ gtk_tree_view_set_grid_lines
GtkTreeViewPrivate *priv;
GtkWidget *widget;
GtkTreeViewGridLines old_grid_lines;
+
+ if (g_strcmp0 (g_getenv ("GTK_TREEVIEW_LINES"), "0") == 0)
+ grid_lines = GTK_TREE_VIEW_GRID_LINES_NONE;
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
priv = tree_view->priv;
# 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)
# (original) progressbar.classic text -> add opacity:0; or color:transparent;
# (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
@@ -770,7 +776,12 @@ gtk_progress_bar_measure
&trough_minimum, &trough_natural,
NULL, NULL);
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ if (priv->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0))
+ {
+ *minimum = MAX (text_minimum, trough_minimum);
+ *natural = MAX (text_natural, trough_natural);
+ }
+ else if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
@@ -932,6 +943,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 +1010,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 +1373,134 @@ 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)
+ {
+ // without copiedContext, infinite loop of gtk_progress_bar_render_text when using context only
+ // it's used only to apply text color from CSS theme
+ GtkStyleContext *copiedContextProgress, *copiedContextTrough;
+ GtkWidgetPath *path;
+
+ copiedContextProgress = g_object_get_data (G_OBJECT (widget), "style-context-progress");
+ if (!copiedContextProgress)
+ {
+ path = gtk_widget_path_copy (gtk_style_context_get_path (context));
+ gtk_widget_path_append_type (path, GTK_TYPE_LABEL);
+ gtk_widget_path_iter_set_object_name (path, -1, "text");
+
+ copiedContextProgress = gtk_style_context_new ();
+ gtk_style_context_set_path (copiedContextProgress, path);
+ gtk_style_context_add_class (copiedContextProgress, "progress");
+ gtk_style_context_set_screen (copiedContextProgress, gtk_style_context_get_screen (context));
+ gtk_style_context_set_parent (copiedContextProgress, context);
+
+ gtk_widget_path_unref (path);
+ g_object_set_data_full (G_OBJECT (widget), "style-context-progress", copiedContextProgress, g_object_unref);
+ }
+
+ copiedContextTrough = g_object_get_data (G_OBJECT (widget), "style-context-trough");
+ if (!copiedContextTrough)
+ {
+ path = gtk_widget_path_copy (gtk_style_context_get_path (context));
+ gtk_widget_path_append_type (path, GTK_TYPE_LABEL);
+ gtk_widget_path_iter_set_object_name (path, -1, "text");
+
+ copiedContextTrough = gtk_style_context_new ();
+ gtk_style_context_set_path (copiedContextTrough, path);
+ gtk_style_context_add_class (copiedContextTrough, "trough");
+ gtk_style_context_set_screen (copiedContextTrough, gtk_style_context_get_screen (context));
+ gtk_style_context_set_parent (copiedContextTrough, context);
+
+ gtk_widget_path_unref (path);
+ g_object_set_data_full (G_OBJECT (widget), "style-context-trough", copiedContextTrough, g_object_unref);
+ }
+
+ GdkRectangle start_clip, end_clip;
+ gboolean ltr = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR, rtl = !ltr; // widget=progressbar_widget
+
+ int *baseline_total, *baseline_progress;
+ GtkAllocation allocation_total, allocation_progress;
+ gtk_css_gadget_get_border_allocation (priv->gadget, &allocation_total, baseline_total);
+ gtk_css_gadget_get_border_allocation (priv->progress_gadget, &allocation_progress, baseline_progress);
+
+ 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_render_layout (g_object_get_data (G_OBJECT (widget), "style-context-progress"), cr, x, y, layout);
+ 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_render_layout (g_object_get_data (G_OBJECT (widget), "style-context-trough"), cr, x, y, layout);
+ cairo_restore (cr);
+ }
+ }
+ else
+ {
+ gtk_render_layout (context, cr, x, y, layout);
+ }
+
+ g_object_unref (layout);
+ gtk_style_context_restore (context);
return FALSE;
}
@@ -1442,9 +1600,16 @@ gtk_progress_bar_set_fraction
priv = pbar->priv;
+ gdouble old = priv->fraction;
priv->fraction = CLAMP (fraction, 0.0, 1.0);
gtk_progress_bar_set_activity_mode (pbar, FALSE);
gtk_widget_queue_allocate (GTK_WIDGET (pbar));
+ if ((g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0) && (
+ (old < 0.1 && priv->fraction >= 0.1) || // 0-9% => 10%+
+ (old >= 1.0 && priv->fraction < 1.0) || // 100% => 99%-
+ (old >= 0.1 && old < 1.0 && (priv->fraction < 1.0 || priv->fraction >= 1.0)) // 10-99% => 9%- or 100%
+ ))
+ gtk_widget_queue_resize (GTK_WIDGET (pbar));
update_fraction_classes (pbar);
g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_FRACTION]);
@@ -1565,22 +1730,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: 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)
# (original) progressbar.classic text -> add opacity:0; or color:transparent;
# (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,10 @@
#include "gtkprivate.h"
#include "gtksnapshot.h"
#include "gtkwidgetprivate.h"
+#include "deprecated/gtkstylecontext.h"
+#include "deprecated/gtkrender.h"
+#include "gtkdrawingarea.h"
+#include "gtkcssprovider.h"
#include <string.h>
@@ -288,15 +292,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 +407,26 @@ allocate_trough
&progress_width, NULL,
NULL, NULL);
+ if (pbar->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0))
+ {
+ if (!gtk_widget_get_visible (pbar->label))
+ gtk_widget_set_visible (pbar->label, TRUE);
+
+ int text_minimum;
+ if (pbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gtk_widget_measure (pbar->label, GTK_ORIENTATION_VERTICAL, -1, &text_minimum, NULL, NULL, NULL);
+ if (progress_height < text_minimum)
+ progress_height = text_minimum;
+ }
+ else
+ {
+ gtk_widget_measure (pbar->label, GTK_ORIENTATION_HORIZONTAL, -1, &text_minimum, NULL, NULL, NULL);
+ if (progress_width < text_minimum)
+ progress_width = text_minimum;
+ }
+ }
+
if (pbar->activity_mode)
{
if (pbar->orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -473,6 +503,15 @@ allocate_trough
}
gtk_widget_size_allocate (pbar->progress_widget, &alloc, -1);
+
+ if (pbar->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0))
+ {
+ alloc.width = gtk_widget_get_width (GTK_WIDGET (pbar));
+ alloc.height = gtk_widget_get_height (GTK_WIDGET (pbar));
+ alloc.x = 0;
+ alloc.y = 0;
+ gtk_widget_size_allocate (pbar->trough_widget, &alloc, -1);
+ }
}
static void
@@ -458,6 +497,135 @@ 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);
+
+ if (pbar->show_text && (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0))
+ {
+ GtkWidget *trough_widget = GTK_WIDGET (gizmo);
+ int x, y, width, height, text_width, text_height;
+
+ GtkAllocation alloc;
+ gtk_widget_get_allocation (trough_widget, &alloc); // -> gtk_widget_compute_bounds
+ width = alloc.width;
+ height = alloc.height;
+
+ graphene_rect_t bounds;
+ graphene_rect_init (&bounds, 0, 0, alloc.width, alloc.height);
+ cairo_t *cr = gtk_snapshot_append_cairo (snapshot, &bounds);
+
+ // g_strdup/g_strdup_printf it's get_current_text (not callable here from snapshot_trough)
+ PangoLayout *layout;
+ if (pbar->text)
+ layout = gtk_widget_create_pango_layout (trough_widget, g_strdup (pbar->text));
+ else
+ layout = gtk_widget_create_pango_layout (trough_widget, g_strdup_printf (C_("progress bar label", "%.0f %%"), pbar->fraction * 100.0));
+
+ // copied from gtk3 patch (except for gtk_widget_get_allocation, and center text)
+ // it's deprecated, but osef!
+ GtkStyleContext *context = gtk_widget_get_style_context (pbar->label);
+ gtk_style_context_save (context);
+
+ pango_layout_set_ellipsize (layout, pbar->ellipsize);
+ if (pbar->ellipsize)
+ pango_layout_set_width (layout, width * PANGO_SCALE);
+
+ // to center the text horizontal & vertical
+ // ceil and floor only to get same position between gtk3 and gtk4
+ pango_layout_get_pixel_size (layout, &text_width, &text_height);
+ if (pbar->orientation == GTK_ORIENTATION_HORIZONTAL) {
+ x = (int) floor((float) (width - text_width) / 2);
+ y = (int) ceil((float) (height - text_height) / 2);
+ } else {
+ x = (int) ceil((float) (width - text_width) / 2);
+ y = (int) floor((float) (height - text_height) / 2);
+ }
+
+ //if (...)
+ //{
+ GdkRectangle start_clip, end_clip;
+ gboolean ltr = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR, rtl = !ltr; // widget=progressbar_widget
+
+ GtkAllocation allocation_total, allocation_progress;
+ gtk_widget_get_allocation (widget, &allocation_total); // widget=progressbar_widget // -> gtk_widget_compute_bounds
+ 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);
+ cairo_destroy (cr);
+ }
+
gtk_snapshot_pop (snapshot);
}
}
@@ -916,13 +1084,43 @@ 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)
+ {
+ GtkWidget *widget = GTK_WIDGET (pbar);
+
+ // without this... there is a delay, and layout is wrong during 0.01s
+ GtkStyleContext *context = gtk_widget_get_style_context (widget);
+ GtkBorder padding;
+ gtk_style_context_get_padding (context, &padding);
+ GtkBorder border;
+ gtk_style_context_get_border (context, &border);
+ GtkAllocation alloc;
+ gtk_widget_get_allocation (widget, &alloc);
+ alloc.width = alloc.width + padding.left + padding.right + border.left + border.right;
+ alloc.height = alloc.height + padding.top + padding.bottom + border.top + border.bottom;
+ gtk_widget_set_size_request (widget, alloc.width, alloc.height);
+ if (pbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_widget_set_size_request (pbar->progress_widget, -1, alloc.height);
+ else
+ gtk_widget_set_size_request (pbar->progress_widget, alloc.width, -1);
+
+ gtk_widget_add_css_class (widget, "classic");
+ gtk_widget_set_visible (pbar->label, FALSE);
+ gtk_widget_insert_before (pbar->label, widget, NULL);
+ }
+ else
+ {
+ gtk_widget_insert_after (pbar->label, GTK_WIDGET (pbar), NULL);
+ }
g_free (text);
}
else
{
+ if (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0)
+ gtk_widget_remove_css_class (GTK_WIDGET (pbar), "classic");
g_clear_pointer (&pbar->label, gtk_widget_unparent);
}
g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_SHOW_TEXT]);
@@ -1056,7 +1254,14 @@ gtk_progress_bar_set_orientation
pbar->orientation = orientation;
+ if (g_strcmp0 (g_getenv ("GTK_PROGRESS_TEXT_INSIDE"), "1") == 0)
+ {
+ gtk_widget_set_vexpand (pbar->trough_widget, TRUE);
+ gtk_widget_set_hexpand (pbar->trough_widget, TRUE);
+ gtk_widget_set_halign (pbar->trough_widget, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (pbar->trough_widget, GTK_ALIGN_FILL);
+ }
+ else if (orientation == GTK_ORIENTATION_HORIZONTAL)
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_widget_set_vexpand (pbar->trough_widget, FALSE);
gtk_widget_set_hexpand (pbar->trough_widget, TRUE);
# 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);
}
# 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))
- return g_format_size (g_file_info_get_size (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 14/12/2025 for Debian Testing (forky) and Ubuntu (resolute questing plucky noble)
# gtk3-classic DEB packages for DEBIAN -> https://build.opensuse.org/package/show/home:luigifab/gtk3-classic
# gtk3-classic DEB packages for UBUNTU -> https://launchpad.net/~luigifab/+archive/ubuntu/gtk-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
else
cd gtk3-classic/
git checkout master
git pull
cd ..
fi
if [ ! -d builder ]; then
mkdir builder
fi
cd builder/
numb=181
for serie in forky resolute questing plucky noble; do
# jammy ko: dh: error: Unknown sequence /usr/share/gnome-pkg-tools/1/rules/uploaders.mk
# (choose from: binary binary-arch binary-indep build build-arch build-indep clean install install-arch install-indep)
rm -rf ${serie}
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/forky/gtk+3.0
echo ""
echo "==== ${serie}/gtk3 =========================================="
echo ""
if [ $serie = "forky" ]; then
version=3.24.51
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}-2.debian.tar.xz
elif [ $serie = "resolute" ]; then
version=3.24.50
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}-1ubuntu2.debian.tar.xz
elif [ $serie = "questing" ]; then
version=3.24.50
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}-1ubuntu2.debian.tar.xz
elif [ $serie = "plucky" ]; then
version=3.24.49
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}-2ubuntu1.debian.tar.xz
elif [ $serie = "noble" ]; then
version=3.24.41
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}-4ubuntu1.3.debian.tar.xz
elif [ $serie = "jammy" ]; then
version=3.24.33
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk+3.0/gtk+3.0_${version}-1ubuntu2.2.debian.tar.xz
fi
# 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 <code@luigifab.fr> $(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__hide_treeview_lines.gtk3.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__hide_treeview_lines.gtk3.patch -q --output-document=debian/patches/appearance__hide_treeview_lines.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/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
# fix patch
sed -i 's/if (g_strcmp0 (g_getenv ("GTK_CSD"), "1") != 0)/if (g_getenv("GTK_CSD") == FALSE)/' debian/patches/csd__server-side-shadow.patch
# disable ubuntu patches
if [ $serie = "resolute" ]; then
sed -i "s/^message-dialog-restore-traditional-look-on-unity.patch/#message-dialog-restore-traditional-look-on-unity.patch/g" debian/patches/series
sed -i "s/^unity-border-radius.patch/#unity-border-radius.patch/g" debian/patches/series
sed -i "s/^unity-headerbar-maximized-mode.patch/#unity-headerbar-maximized-mode.patch/g" debian/patches/series
elif [ $serie = "questing" ]; then
sed -i "s/^message-dialog-restore-traditional-look-on-unity.patch/#message-dialog-restore-traditional-look-on-unity.patch/g" debian/patches/series
sed -i "s/^unity-border-radius.patch/#unity-border-radius.patch/g" debian/patches/series
sed -i "s/^unity-headerbar-maximized-mode.patch/#unity-headerbar-maximized-mode.patch/g" debian/patches/series
elif [ $serie = "plucky" ]; then
sed -i "s/^message-dialog-restore-traditional-look-on-unity.patch/#message-dialog-restore-traditional-look-on-unity.patch/g" debian/patches/series
sed -i "s/^unity-border-radius.patch/#unity-border-radius.patch/g" debian/patches/series
sed -i "s/^unity-headerbar-maximized-mode.patch/#unity-headerbar-maximized-mode.patch/g" debian/patches/series
elif [ $serie = "noble" ]; then
wget https://raw.githubusercontent.com/lah7/gtk3-classic/refs/tags/3.24.41/appearance__message-dialogs.patch -q --output-document=debian/patches/appearance__message-dialogs.patch
sed -i "s/^message-dialog-restore-traditional-look-on-unity.patch/#message-dialog-restore-traditional-look-on-unity.patch/g" debian/patches/series
sed -i "s/^unity-border-radius.patch/#unity-border-radius.patch/g" debian/patches/series
sed -i "s/^unity-headerbar-maximized-mode.patch/#unity-headerbar-maximized-mode.patch/g" debian/patches/series
elif [ $serie = "jammy" ]; then
wget https://raw.githubusercontent.com/lah7/gtk3-classic/refs/tags/3.24.33/appearance__message-dialogs.patch -q --output-document=debian/patches/appearance__message-dialogs.patch
sed -i "s/^message-dialog-restore-traditional-look-on-unity.patch/#message-dialog-restore-traditional-look-on-unity.patch/g" debian/patches/series
sed -i "s/^unity-border-radius.patch/#unity-border-radius.patch/g" debian/patches/series
sed -i "s/^unity-headerbar-maximized-mode.patch/#unity-headerbar-maximized-mode.patch/g" debian/patches/series
fi
# build packages
dpkg-buildpackage -us -uc -ui -d -S
cd ..
# sign packages
debsign *.changes
cd ..
done
cd ..
#!/bin/bash
# updated 28/12/2025 for Debian Testing (forky) and Ubuntu (resolute questing plucky)
# gtk3-classic DEB packages for DEBIAN -> https://build.opensuse.org/package/show/home:luigifab/gtk4-classic
# gtk3-classic DEB packages for UBUNTU -> https://launchpad.net/~luigifab/+archive/ubuntu/gtk-classic
# classic desktop theme: https://github.com/luigifab/human-theme/releases
cd "$(dirname "$0")"
if [ ! -d builder ]; then
mkdir builder
fi
cd builder/
numb=102
for serie in forky resolute questing plucky; do
rm -rf ${serie}
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/forky/gtk4
echo ""
echo "==== ${serie}/gtk4 =========================================="
echo ""
if [ $serie = "forky" ]; then
version=4.20.3
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-3.debian.tar.xz
elif [ $serie = "resolute" ]; then
version=4.20.3
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk4/gtk4_${version}+ds.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk4/gtk4_${version}+ds-3.debian.tar.xz
elif [ $serie = "questing" ]; then
version=4.20.1
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk4/gtk4_${version}+ds.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk4/gtk4_${version}+ds-2.debian.tar.xz
elif [ $serie = "plucky" ]; then
version=4.18.5
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk4/gtk4_${version}+ds.orig.tar.xz
wget -nc http://archive.ubuntu.com/ubuntu/pool/main/g/gtk4/gtk4_${version}+ds-0ubuntu0.1.debian.tar.xz
fi
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 <code@luigifab.fr> $(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 and update patch list
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
echo treeview__alternating_row_colours.gtk4.patch >> debian/patches/series
rm -f debian/patches/appearance__checkradio.gtk4.patch
wget https://gist.githubusercontent.com/luigifab/0fce786cdb93b5687069a82f490ea95e/raw/appearance__checkradio.gtk4.patch -q --output-document=debian/patches/appearance__checkradio.gtk4.patch
echo appearance__checkradio.gtk4.patch >> debian/patches/series
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
echo appearance__focus_visible.gtk4.patch >> debian/patches/series
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
echo appearance__notebook_stack_class.gtk4.patch >> debian/patches/series
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
echo appearance__progress_text.gtk4.patch >> debian/patches/series
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
echo consistent_file_size_units.gtk4.patch >> debian/patches/series
# build packages
dpkg-buildpackage -us -uc -ui -d -S
cd ..
# sign packages
debsign *.changes
cd ..
done
cd ..
#!/bin/bash
# updated 09/09/2025 for Debian Testing (forky)
# 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=175
for serie in forky; 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/forky/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 & 235" >> debian/changelog
echo "" >> debian/changelog
echo " -- Fabrice Creuzot <code@luigifab.fr> $(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
rm -f debian/patches/235.diff
wget https://github.com/mate-desktop/mate-notification-daemon/pull/235.diff -q --output-document=debian/patches/235.diff
echo 235.diff >> debian/patches/series
# build packages
dpkg-buildpackage -us -uc -ui -d -S
cd ..
# sign packages
debsign *.changes
cd ..
done
cd ..
# fix pseudo transparency for notifications, add some css classes, reformat code, try to do same between all themes
# https://github.com/mate-desktop/mate-notification-daemon
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 <stefano@karapetsas.com>
* 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 <stefano@karapetsas.com>
* 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 <chipx86@chipx86.com>
* Copyright (C) 2009 Red Hat, Inc.
* Copyright (C) 2011 Perberos <perberos@gmail.com>
- * 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 <chipx86@chipx86.com>
* Copyright (C) 2009 Red Hat, Inc.
* Copyright (C) 2011 Perberos <perberos@gmail.com>
- * 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

@mid-kid
Copy link

mid-kid commented Dec 20, 2025

Does it really make sense to keep this in a gist, and not move it into a proper github repo, like gtk3-classic is?

@luigifab
Copy link
Author

Yes, it works for me, and it's the fastest.

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