Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 406a32d825 | |||
| beabe8c33b | |||
| 90500519d6 | |||
| 06921674a9 | |||
| a91fa9a680 | |||
| ead40dc834 | |||
| 2be928b569 | |||
| 621ba6d67c | |||
| af929a8787 | |||
| ef986f4256 | |||
| ab36c275cf | |||
| 720327bc00 | |||
| 679d510059 | |||
| 0c2b437643 | |||
| 0764cf0c9c | |||
| 557a1ed879 | |||
| c28b6a3ee6 | |||
| dd22e2aea9 | |||
| 7f3ea15d80 | |||
| d3dfdd214f | |||
| b6c3cf4eee | |||
| 157ef1d395 | |||
| d0263f563a | |||
| 83b48bb25f | |||
| 81e9eca256 | |||
| 44c2d585b8 | |||
| 348803af7d | |||
| c8bfea7aa1 | |||
| 8f47e885f0 | |||
| a9f50f1f7a | |||
| 0d58e5365d | |||
| d00d4c4475 | |||
| a6e7c38236 | |||
| eee7e59265 | |||
| c2cb1ffe9e | |||
| d918a77d34 | |||
| 2285ef3824 | |||
| b2a2bf819d | |||
| dd9433b50e | |||
| 67c53e46f9 | |||
| 238e7ec351 | |||
| d916659781 | |||
| 82c02574f1 | |||
| 26e6d2106b | |||
| 625ffa2d96 | |||
| dd3eedd510 | |||
| dc3a72cf38 | |||
| b937c19dd4 | |||
| 04c3af537c | |||
| cc43f5dcde | |||
| c74d7afce5 | |||
| 52e18eb7fb | |||
| c0b5b4b8c1 | |||
| d497e721c9 | |||
| a7fb9a6865 | |||
| 2365d9be18 | |||
| 41b60bbd6c | |||
| f0d3d011ea | |||
| 48e141a42c | |||
| 6215b38e64 | |||
| 41490f9624 | |||
| 45e6e9a7d1 | |||
| 9991d6834d | |||
| ddf8c4dd1a | |||
| 970072ef65 | |||
| f8321029fc | |||
| f83cab01ec | |||
| 8a74770ec1 | |||
| 39c503c108 | |||
| fc32b8242b | |||
| 7c2b4eb0e7 | |||
| d8b0aea6b7 | |||
| 190d8ef8ff | |||
| 15e9194b59 | |||
| 0257da6cc0 | |||
| 3fc7c97979 |
+2
-1
@@ -21,7 +21,7 @@ many things that we value:
|
||||
Please, do not use the issue tracker for support questions. If you have
|
||||
questions on how to use GTK effectively, you can use:
|
||||
|
||||
- the `#gtk` IRC channel on irc.gnome.org
|
||||
- the `gtk` [room on matrix](https://matrix.to/#/#gtk:gnome.org)
|
||||
- the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk)
|
||||
|
||||
You can also look at the GTK tag on [Stack
|
||||
@@ -44,6 +44,7 @@ If you're reporting a bug make sure to list:
|
||||
|
||||
0. which version of GTK are you using?
|
||||
0. which operating system are you using?
|
||||
0. what display and graphics driver are you using?
|
||||
0. the necessary steps to reproduce the issue
|
||||
0. the expected outcome
|
||||
0. a description of the behavior; screenshots are also welcome
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
Overview of Changes in 4.9.4, xx-xx-xxxx
|
||||
========================================
|
||||
|
||||
* Printing:
|
||||
- Add a CPDB print backend
|
||||
|
||||
* GtkFileDialog:
|
||||
- Robustness fixes
|
||||
|
||||
* GtkScaleButton:
|
||||
- Add an 'active' property
|
||||
|
||||
* Fix conflicting type names between gtk and gio
|
||||
|
||||
* Gsk:
|
||||
- Settable filtering for scaled textures
|
||||
- Add mask nodes
|
||||
|
||||
* Wayland:
|
||||
- Handle dispatch failing in more places
|
||||
|
||||
* Translation updates:
|
||||
Belarusian
|
||||
Chinese (Taiwan)
|
||||
Georgian
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.9.3, 04-02-2023
|
||||
========================================
|
||||
|
||||
|
||||
@@ -215,6 +215,12 @@
|
||||
<file>demo3widget.h</file>
|
||||
<file>demo3widget.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/mask">
|
||||
<file>demo4widget.c</file>
|
||||
<file>demo4widget.h</file>
|
||||
<file>hsla.h</file>
|
||||
<file>hsla.c</file>
|
||||
</gresource>
|
||||
<gresource prefix="/paintable_svg">
|
||||
<file>svgpaintable.h</file>
|
||||
<file>svgpaintable.c</file>
|
||||
@@ -311,6 +317,7 @@
|
||||
<file>list_store.c</file>
|
||||
<file>main.c</file>
|
||||
<file>markup.c</file>
|
||||
<file>mask.c</file>
|
||||
<file>menu.c</file>
|
||||
<file>overlay.c</file>
|
||||
<file>overlay_decorative.c</file>
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_PAINTABLE = 1,
|
||||
PROP_TEXTURE = 1,
|
||||
PROP_FILTER,
|
||||
PROP_SCALE
|
||||
};
|
||||
|
||||
@@ -11,8 +12,9 @@ struct _Demo3Widget
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GdkPaintable *paintable;
|
||||
GdkTexture *texture;
|
||||
float scale;
|
||||
GskScalingFilter filter;
|
||||
|
||||
GtkWidget *menu;
|
||||
};
|
||||
@@ -28,6 +30,7 @@ static void
|
||||
demo3_widget_init (Demo3Widget *self)
|
||||
{
|
||||
self->scale = 1.f;
|
||||
self->filter = GSK_SCALING_FILTER_LINEAR;
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
@@ -36,7 +39,7 @@ demo3_widget_dispose (GObject *object)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (object);
|
||||
|
||||
g_clear_object (&self->paintable);
|
||||
g_clear_object (&self->texture);
|
||||
|
||||
gtk_widget_dispose_template (GTK_WIDGET (self), DEMO3_TYPE_WIDGET);
|
||||
|
||||
@@ -50,12 +53,13 @@ demo3_widget_snapshot (GtkWidget *widget,
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
int x, y, width, height;
|
||||
double w, h;
|
||||
GskRenderNode *node;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
w = self->scale * gdk_paintable_get_intrinsic_width (self->paintable);
|
||||
h = self->scale * gdk_paintable_get_intrinsic_height (self->paintable);
|
||||
w = self->scale * gdk_texture_get_width (self->texture);
|
||||
h = self->scale * gdk_texture_get_height (self->texture);
|
||||
|
||||
x = MAX (0, (width - ceil (w)) / 2);
|
||||
y = MAX (0, (height - ceil (h)) / 2);
|
||||
@@ -63,7 +67,11 @@ demo3_widget_snapshot (GtkWidget *widget,
|
||||
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gdk_paintable_snapshot (self->paintable, snapshot, w, h);
|
||||
node = gsk_texture_scale_node_new (self->texture,
|
||||
&GRAPHENE_RECT_INIT (0, 0, w, h),
|
||||
self->filter);
|
||||
gtk_snapshot_append_node (snapshot, node);
|
||||
gsk_render_node_unref (node);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
@@ -81,9 +89,9 @@ demo3_widget_measure (GtkWidget *widget,
|
||||
int size;
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
size = gdk_paintable_get_intrinsic_width (self->paintable);
|
||||
size = gdk_texture_get_width (self->texture);
|
||||
else
|
||||
size = gdk_paintable_get_intrinsic_height (self->paintable);
|
||||
size = gdk_texture_get_height (self->texture);
|
||||
|
||||
*minimum = *natural = self->scale * size;
|
||||
}
|
||||
@@ -113,9 +121,9 @@ demo3_widget_set_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PAINTABLE:
|
||||
g_clear_object (&self->paintable);
|
||||
self->paintable = g_value_dup_object (value);
|
||||
case PROP_TEXTURE:
|
||||
g_clear_object (&self->texture);
|
||||
self->texture = g_value_dup_object (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
@@ -124,6 +132,11 @@ demo3_widget_set_property (GObject *object,
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
case PROP_FILTER:
|
||||
self->filter = g_value_get_enum (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -140,14 +153,18 @@ demo3_widget_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PAINTABLE:
|
||||
g_value_set_object (value, self->paintable);
|
||||
case PROP_TEXTURE:
|
||||
g_value_set_object (value, self->texture);
|
||||
break;
|
||||
|
||||
case PROP_SCALE:
|
||||
g_value_set_float (value, self->scale);
|
||||
break;
|
||||
|
||||
case PROP_FILTER:
|
||||
g_value_set_enum (value, self->filter);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -205,16 +222,21 @@ demo3_widget_class_init (Demo3WidgetClass *class)
|
||||
widget_class->measure = demo3_widget_measure;
|
||||
widget_class->size_allocate = demo3_widget_size_allocate;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PAINTABLE,
|
||||
g_param_spec_object ("paintable", "Paintable", "Paintable",
|
||||
GDK_TYPE_PAINTABLE,
|
||||
g_object_class_install_property (object_class, PROP_TEXTURE,
|
||||
g_param_spec_object ("texture", NULL, NULL,
|
||||
GDK_TYPE_TEXTURE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SCALE,
|
||||
g_param_spec_float ("scale", "Scale", "Scale",
|
||||
g_param_spec_float ("scale", NULL, NULL,
|
||||
0.0, 10.0, 1.0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_FILTER,
|
||||
g_param_spec_enum ("filter", NULL, NULL,
|
||||
GSK_TYPE_SCALING_FILTER, GSK_SCALING_FILTER_LINEAR,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
/* These are the actions that we are using in the menu */
|
||||
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
|
||||
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
|
||||
@@ -229,16 +251,13 @@ GtkWidget *
|
||||
demo3_widget_new (const char *resource)
|
||||
{
|
||||
Demo3Widget *self;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPaintable *paintable;
|
||||
GdkTexture *texture;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_resource (resource, NULL);
|
||||
paintable = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
|
||||
texture = gdk_texture_new_from_resource (resource);
|
||||
|
||||
self = g_object_new (DEMO3_TYPE_WIDGET, "paintable", paintable, NULL);
|
||||
self = g_object_new (DEMO3_TYPE_WIDGET, "texture", texture, NULL);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
g_object_unref (paintable);
|
||||
g_object_unref (texture);
|
||||
|
||||
return GTK_WIDGET (self);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
#include <math.h>
|
||||
#include "demo4widget.h"
|
||||
#include "hsla.h"
|
||||
|
||||
struct _Demo4Widget
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
PangoLayout *layout;
|
||||
GskColorStop stops[8];
|
||||
gsize n_stops;
|
||||
|
||||
guint tick;
|
||||
};
|
||||
|
||||
struct _Demo4WidgetClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (Demo4Widget, demo4_widget, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
rotate_color (GdkRGBA *rgba)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
|
||||
_gdk_hsla_init_from_rgba (&hsla, rgba);
|
||||
hsla.hue -= 1;
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rotate_colors (GtkWidget *widget,
|
||||
GdkFrameClock *clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
Demo4Widget *self = DEMO4_WIDGET (widget);
|
||||
|
||||
for (unsigned int i = 0; i < self->n_stops; i++)
|
||||
rotate_color (&self->stops[i].color);
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_init (Demo4Widget *self)
|
||||
{
|
||||
PangoFontDescription *desc;
|
||||
|
||||
self->n_stops = 8;
|
||||
self->stops[0].offset = 0;
|
||||
self->stops[0].color = (GdkRGBA) { 1, 0, 0, 1 };
|
||||
|
||||
for (unsigned int i = 1; i < self->n_stops; i++)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
|
||||
self->stops[i].offset = i / (double)(self->n_stops - 1);
|
||||
_gdk_hsla_init_from_rgba (&hsla, &self->stops[i - 1].color);
|
||||
hsla.hue += 360.0 / (double)(self->n_stops - 1);
|
||||
_gdk_rgba_init_from_hsla (&self->stops[i].color, &hsla);
|
||||
}
|
||||
|
||||
self->layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "123");
|
||||
desc = pango_font_description_from_string ("Cantarell Bold 210");
|
||||
pango_layout_set_font_description (self->layout, desc);
|
||||
pango_font_description_free (desc);
|
||||
|
||||
self->tick = gtk_widget_add_tick_callback (GTK_WIDGET (self), rotate_colors, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_dispose (GObject *object)
|
||||
{
|
||||
Demo4Widget *self = DEMO4_WIDGET (object);
|
||||
|
||||
g_clear_object (&self->layout);
|
||||
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick);
|
||||
|
||||
G_OBJECT_CLASS (demo4_widget_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
Demo4Widget *self = DEMO4_WIDGET (widget);
|
||||
int width, height;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
gtk_snapshot_push_mask (snapshot);
|
||||
gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
|
||||
gtk_snapshot_pop (snapshot);
|
||||
|
||||
gtk_snapshot_append_linear_gradient (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height),
|
||||
&GRAPHENE_POINT_INIT (0, 0),
|
||||
&GRAPHENE_POINT_INIT (width, height),
|
||||
self->stops,
|
||||
self->n_stops);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_class_init (Demo4WidgetClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->dispose = demo4_widget_dispose;
|
||||
|
||||
widget_class->snapshot = demo4_widget_snapshot;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
demo4_widget_new (void)
|
||||
{
|
||||
return g_object_new (DEMO4_TYPE_WIDGET, NULL);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define DEMO4_TYPE_WIDGET (demo4_widget_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (Demo4Widget, demo4_widget, DEMO4, WIDGET, GtkWidget)
|
||||
|
||||
GtkWidget * demo4_widget_new (void);
|
||||
@@ -0,0 +1,146 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include "hsla.h"
|
||||
|
||||
void
|
||||
_gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
float min;
|
||||
float max;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float delta;
|
||||
|
||||
g_return_if_fail (hsla != NULL);
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
red = rgba->red;
|
||||
green = rgba->green;
|
||||
blue = rgba->blue;
|
||||
|
||||
if (red > green)
|
||||
{
|
||||
if (red > blue)
|
||||
max = red;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
if (green < blue)
|
||||
min = green;
|
||||
else
|
||||
min = blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (green > blue)
|
||||
max = green;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
if (red < blue)
|
||||
min = red;
|
||||
else
|
||||
min = blue;
|
||||
}
|
||||
|
||||
hsla->lightness = (max + min) / 2;
|
||||
hsla->saturation = 0;
|
||||
hsla->hue = 0;
|
||||
hsla->alpha = rgba->alpha;
|
||||
|
||||
if (max != min)
|
||||
{
|
||||
if (hsla->lightness <= 0.5)
|
||||
hsla->saturation = (max - min) / (max + min);
|
||||
else
|
||||
hsla->saturation = (max - min) / (2 - max - min);
|
||||
|
||||
delta = max -min;
|
||||
if (red == max)
|
||||
hsla->hue = (green - blue) / delta;
|
||||
else if (green == max)
|
||||
hsla->hue = 2 + (blue - red) / delta;
|
||||
else if (blue == max)
|
||||
hsla->hue = 4 + (red - green) / delta;
|
||||
|
||||
hsla->hue *= 60;
|
||||
if (hsla->hue < 0.0)
|
||||
hsla->hue += 360;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GdkHSLA *hsla)
|
||||
{
|
||||
float hue;
|
||||
float lightness;
|
||||
float saturation;
|
||||
float m1, m2;
|
||||
|
||||
lightness = hsla->lightness;
|
||||
saturation = hsla->saturation;
|
||||
|
||||
if (lightness <= 0.5)
|
||||
m2 = lightness * (1 + saturation);
|
||||
else
|
||||
m2 = lightness + saturation - lightness * saturation;
|
||||
m1 = 2 * lightness - m2;
|
||||
|
||||
rgba->alpha = hsla->alpha;
|
||||
|
||||
if (saturation == 0)
|
||||
{
|
||||
rgba->red = lightness;
|
||||
rgba->green = lightness;
|
||||
rgba->blue = lightness;
|
||||
}
|
||||
else
|
||||
{
|
||||
hue = hsla->hue + 120;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
if (hue < 60)
|
||||
rgba->red = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
rgba->red = m2;
|
||||
else if (hue < 240)
|
||||
rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->red = m1;
|
||||
|
||||
hue = hsla->hue;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
if (hue < 60)
|
||||
rgba->green = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
rgba->green = m2;
|
||||
else if (hue < 240)
|
||||
rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->green = m1;
|
||||
|
||||
hue = hsla->hue - 120;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
if (hue < 60)
|
||||
rgba->blue = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
rgba->blue = m2;
|
||||
else if (hue < 240)
|
||||
rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->blue = m1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct _GdkHSLA GdkHSLA;
|
||||
|
||||
struct _GdkHSLA {
|
||||
float hue;
|
||||
float saturation;
|
||||
float lightness;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
void _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba);
|
||||
void _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GdkHSLA *hsla);
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Masking
|
||||
*
|
||||
* Demonstrates mask nodes.
|
||||
*
|
||||
* This demo uses a text node as mask for
|
||||
* an animated linear gradient.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "demo4widget.h"
|
||||
|
||||
|
||||
GtkWidget *
|
||||
do_mask (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *widget;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Mask Nodes");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
widget = demo4_widget_new ();
|
||||
gtk_widget_set_hexpand (widget, TRUE);
|
||||
gtk_widget_set_vexpand (widget, TRUE);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), widget);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
+12
-1
@@ -22,9 +22,11 @@ do_menu (GtkWidget *do_widget)
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *box2;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *dropdown;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Menu");
|
||||
@@ -43,10 +45,19 @@ do_menu (GtkWidget *do_widget)
|
||||
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), box2);
|
||||
|
||||
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
|
||||
gtk_range_set_value (GTK_RANGE (scale), 1.0);
|
||||
gtk_box_append (GTK_BOX (box), scale);
|
||||
gtk_widget_set_hexpand (scale, TRUE);
|
||||
gtk_box_append (GTK_BOX (box2), scale);
|
||||
|
||||
dropdown = gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new ((const char *[]){ "Linear", "Nearest", "Trilinear", NULL })), NULL);
|
||||
gtk_box_append (GTK_BOX (box2), dropdown);
|
||||
|
||||
g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT);
|
||||
|
||||
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
|
||||
widget, "scale",
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
|
||||
@@ -46,6 +46,7 @@ demos = files([
|
||||
'links.c',
|
||||
'listbox.c',
|
||||
'listbox_controls.c',
|
||||
'mask.c',
|
||||
'menu.c',
|
||||
'flowbox.c',
|
||||
'list_store.c',
|
||||
@@ -114,6 +115,7 @@ extra_demo_sources = files([
|
||||
'gtkshadertoy.c',
|
||||
'gtkshaderstack.c',
|
||||
'gskshaderpaintable.c',
|
||||
'hsla.c',
|
||||
'puzzlepiece.c',
|
||||
'bluroverlay.c',
|
||||
'demoimage.c',
|
||||
@@ -126,6 +128,7 @@ extra_demo_sources = files([
|
||||
'four_point_transform.c',
|
||||
'demo2widget.c',
|
||||
'demo3widget.c',
|
||||
'demo4widget.c',
|
||||
'pixbufpaintable.c',
|
||||
'script-names.c',
|
||||
'unicode-names.c',
|
||||
|
||||
@@ -297,6 +297,21 @@ The default texture is a 10x10 checkerboard with the top left and bottom right
|
||||
representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQXY0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=")
|
||||
`.
|
||||
|
||||
### texture-scale
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| texture | `<url>` | *see below* | always |
|
||||
| filter | `filter` | *see below* | non-default |
|
||||
|
||||
Creates a node like `gsk_texture_scale_node_new()` with the given properties.
|
||||
|
||||
The default texture is a 10x10 checkerboard, just like for texture.
|
||||
|
||||
The possible filter values are `linear`, `nearest` and `trilinear`, with
|
||||
`linear` being the default.
|
||||
|
||||
### transform
|
||||
|
||||
| property | syntax | default | printed |
|
||||
|
||||
@@ -115,7 +115,7 @@ Instead of gtk_show_uri(), you should use GtkUriLauncher or GtkFileLauncher.
|
||||
This is an oldfashioned widget that does not do all that much anymore, since
|
||||
it no longer has a resize handle for the window.
|
||||
|
||||
## GtkLockButton is going away
|
||||
## GtkLockButton and GtkVolumeButton are going away
|
||||
|
||||
This is an very specialized widget that should better live with the application
|
||||
where it is used.
|
||||
These are very specialized widgets that should better live with the application
|
||||
where they are used.
|
||||
|
||||
+2
-12
@@ -1511,7 +1511,6 @@ gdk_button_event_get_button (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkKeyEvent */
|
||||
|
||||
/**
|
||||
@@ -1972,7 +1971,6 @@ gdk_key_event_get_match (GdkEvent *event,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkTouchEvent */
|
||||
|
||||
/**
|
||||
@@ -2109,7 +2107,6 @@ gdk_touch_event_get_emulating_pointer (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkCrossingEvent */
|
||||
|
||||
/**
|
||||
@@ -2253,7 +2250,6 @@ gdk_crossing_event_get_detail (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkDeleteEvent */
|
||||
|
||||
/**
|
||||
@@ -2284,7 +2280,6 @@ gdk_delete_event_new (GdkSurface *surface)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkFocusEvent */
|
||||
|
||||
/**
|
||||
@@ -2341,7 +2336,6 @@ gdk_focus_event_get_in (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkScrollEvent */
|
||||
|
||||
/**
|
||||
@@ -2600,7 +2594,6 @@ gdk_scroll_event_get_unit (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkTouchpadEvent */
|
||||
|
||||
/**
|
||||
@@ -2859,7 +2852,6 @@ gdk_touchpad_event_get_pinch_scale (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkPadEvent */
|
||||
|
||||
/**
|
||||
@@ -3033,7 +3025,6 @@ gdk_pad_event_get_group_mode (GdkEvent *event,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkMotionEvent */
|
||||
|
||||
/**
|
||||
@@ -3195,7 +3186,6 @@ gdk_event_get_history (GdkEvent *event,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkProximityEvent */
|
||||
|
||||
/**
|
||||
@@ -3258,7 +3248,6 @@ gdk_proximity_event_new (GdkEventType type,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkDNDEvent */
|
||||
|
||||
/**
|
||||
@@ -3364,7 +3353,6 @@ gdk_dnd_event_get_drop (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkGrabBrokenEvent */
|
||||
|
||||
/**
|
||||
@@ -3442,3 +3430,5 @@ gdk_grab_broken_event_get_implicit (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
||||
@@ -39,6 +39,7 @@ struct _GdkGLTexture {
|
||||
|
||||
GdkGLContext *context;
|
||||
guint id;
|
||||
GLsync sync;
|
||||
|
||||
GdkTexture *saved;
|
||||
|
||||
@@ -64,6 +65,7 @@ drop_gl_resources (GdkGLTexture *self)
|
||||
|
||||
g_clear_object (&self->context);
|
||||
self->id = 0;
|
||||
self->sync = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -99,6 +101,10 @@ gdk_gl_texture_invoke_callback (gpointer data)
|
||||
context = gdk_display_get_gl_context (gdk_gl_context_get_display (invoke->self->context));
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
if (invoke->self->sync && context != invoke->self->context)
|
||||
glWaitSync (invoke->self->sync, 0, GL_TIMEOUT_IGNORED);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, invoke->self->id);
|
||||
|
||||
invoke->func (invoke->self, context, invoke->data);
|
||||
@@ -440,6 +446,46 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
int height,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (id != 0, NULL);
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
|
||||
return gdk_gl_texture_new_with_sync (context, id, NULL, width, height, destroy, data);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_gl_texture_new_with_sync:
|
||||
* @context: a `GdkGLContext`
|
||||
* @id: the ID of a texture that was created with @context
|
||||
* @sync: (nullable): an optional GLsync object
|
||||
* @width: the nominal width of the texture
|
||||
* @height: the nominal height of the texture
|
||||
* @destroy: a destroy notify that will be called when the GL resources
|
||||
* are released
|
||||
* @data: data that gets passed to @destroy
|
||||
*
|
||||
* Creates a new texture for an existing GL texture.
|
||||
*
|
||||
* If @sync is given, consumers of the texture are required to wait on
|
||||
* it before attempting to use the GL texture.
|
||||
*
|
||||
* The GL texture and the sync object must stay alive unmodified until
|
||||
* @destroy is called, which will happen when the GdkTexture object is
|
||||
* finalized, or due to an explicit call of [method@Gdk.GLTexture.release].
|
||||
*
|
||||
* Return value: (transfer full) (type GdkGLTexture): A newly-created
|
||||
* `GdkTexture`
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_gl_texture_new_with_sync (GdkGLContext *context,
|
||||
guint id,
|
||||
gpointer sync,
|
||||
int width,
|
||||
int height,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data)
|
||||
{
|
||||
GdkGLTexture *self;
|
||||
|
||||
@@ -455,6 +501,7 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
|
||||
self->context = g_object_ref (context);
|
||||
self->id = id;
|
||||
self->sync = sync;
|
||||
self->destroy = destroy;
|
||||
self->data = data;
|
||||
|
||||
@@ -463,3 +510,8 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
return GDK_TEXTURE (self);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gdk_gl_texture_get_sync (GdkGLTexture *self)
|
||||
{
|
||||
return self->sync;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,16 @@ G_BEGIN_DECLS
|
||||
|
||||
GdkGLContext * gdk_gl_texture_get_context (GdkGLTexture *self);
|
||||
guint gdk_gl_texture_get_id (GdkGLTexture *self);
|
||||
gpointer gdk_gl_texture_get_sync (GdkGLTexture *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkTexture * gdk_gl_texture_new_with_sync (GdkGLContext *context,
|
||||
guint id,
|
||||
gpointer sync,
|
||||
int width,
|
||||
int height,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context
|
||||
xdg_activation_token_v1_commit (token);
|
||||
|
||||
while (app_launch_data.token == NULL)
|
||||
wl_display_dispatch_queue (display->wl_display, event_queue);
|
||||
gdk_wayland_display_dispatch_queue (GDK_DISPLAY (display), event_queue);
|
||||
|
||||
xdg_activation_token_v1_destroy (token);
|
||||
id = app_launch_data.token;
|
||||
|
||||
@@ -2694,3 +2694,17 @@ gdk_wayland_display_query_registry (GdkDisplay *display,
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_display_dispatch_queue (GdkDisplay *display,
|
||||
struct wl_event_queue *event_queue)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
if (wl_display_dispatch_queue (display_wayland->wl_display, event_queue) == -1)
|
||||
{
|
||||
g_message ("Error %d (%s) dispatching to Wayland display.",
|
||||
errno, g_strerror (errno));
|
||||
_exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,9 @@ struct _GdkWaylandDisplayClass
|
||||
|
||||
gboolean gdk_wayland_display_prefers_ssd (GdkDisplay *display);
|
||||
|
||||
void gdk_wayland_display_dispatch_queue (GdkDisplay *display,
|
||||
struct wl_event_queue *event_queue);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WAYLAND_DISPLAY__ */
|
||||
|
||||
@@ -1334,8 +1334,6 @@ gdk_wayland_surface_present_popup (GdkWaylandPopup *wayland_popup,
|
||||
GdkPopupLayout *layout)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (wayland_popup);
|
||||
GdkWaylandDisplay *display_wayland =
|
||||
GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkWaylandSurface *wayland_surface = GDK_WAYLAND_SURFACE (wayland_popup);
|
||||
|
||||
if (!wayland_surface->mapped)
|
||||
@@ -1388,7 +1386,10 @@ gdk_wayland_surface_present_popup (GdkWaylandPopup *wayland_popup,
|
||||
}
|
||||
|
||||
while (wayland_popup->display_server.xdg_popup && !is_relayout_finished (surface))
|
||||
wl_display_dispatch_queue (display_wayland->wl_display, wayland_surface->event_queue);
|
||||
{
|
||||
gdk_wayland_display_dispatch_queue (surface->display,
|
||||
wayland_surface->event_queue);
|
||||
}
|
||||
|
||||
if (wayland_popup->display_server.xdg_popup)
|
||||
{
|
||||
|
||||
@@ -2119,7 +2119,10 @@ gdk_wayland_toplevel_focus (GdkToplevel *toplevel,
|
||||
xdg_activation_token_v1_commit (token);
|
||||
|
||||
while (startup_id == NULL)
|
||||
wl_display_dispatch_queue (display_wayland->wl_display, event_queue);
|
||||
{
|
||||
gdk_wayland_display_dispatch_queue (GDK_DISPLAY (display_wayland),
|
||||
event_queue);
|
||||
}
|
||||
|
||||
xdg_activation_token_v1_destroy (token);
|
||||
wl_event_queue_destroy (event_queue);
|
||||
|
||||
@@ -250,6 +250,7 @@ collect_reused_child_nodes (GskRenderer *renderer,
|
||||
/* Leaf nodes */
|
||||
|
||||
case GSK_TEXTURE_NODE:
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_BORDER_NODE:
|
||||
@@ -269,6 +270,7 @@ collect_reused_child_nodes (GskRenderer *renderer,
|
||||
case GSK_BLEND_NODE:
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
case GSK_BLUR_NODE:
|
||||
case GSK_MASK_NODE:
|
||||
|
||||
default:
|
||||
|
||||
@@ -845,6 +847,8 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
||||
}
|
||||
break; /* Fallback */
|
||||
|
||||
case GSK_MASK_NODE:
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
|
||||
@@ -403,6 +403,7 @@ gsk_gl_command_queue_dispose (GObject *object)
|
||||
gsk_gl_command_batches_clear (&self->batches);
|
||||
gsk_gl_command_binds_clear (&self->batch_binds);
|
||||
gsk_gl_command_uniforms_clear (&self->batch_uniforms);
|
||||
gsk_gl_syncs_clear (&self->syncs);
|
||||
|
||||
gsk_gl_buffer_destroy (&self->vertices);
|
||||
|
||||
@@ -425,6 +426,7 @@ gsk_gl_command_queue_init (GskGLCommandQueue *self)
|
||||
gsk_gl_command_batches_init (&self->batches, 128);
|
||||
gsk_gl_command_binds_init (&self->batch_binds, 1024);
|
||||
gsk_gl_command_uniforms_init (&self->batch_uniforms, 2048);
|
||||
gsk_gl_syncs_init (&self->syncs, 10);
|
||||
|
||||
gsk_gl_buffer_init (&self->vertices, GL_ARRAY_BUFFER, sizeof (GskGLDrawVertex));
|
||||
}
|
||||
@@ -570,7 +572,10 @@ gsk_gl_command_queue_end_draw (GskGLCommandQueue *self)
|
||||
g_assert (self->batches.len > 0);
|
||||
|
||||
if (will_ignore_batch (self))
|
||||
return;
|
||||
{
|
||||
self->in_draw = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
batch = gsk_gl_command_batches_tail (&self->batches);
|
||||
|
||||
@@ -1095,17 +1100,25 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
|
||||
if G_UNLIKELY (batch->draw.bind_count > 0)
|
||||
{
|
||||
const GskGLCommandBind *bind = &self->batch_binds.items[batch->draw.bind_offset];
|
||||
|
||||
for (guint i = 0; i < batch->draw.bind_count; i++)
|
||||
{
|
||||
if (textures[bind->texture] != bind->id)
|
||||
{
|
||||
GskGLSync *s;
|
||||
|
||||
if (active != bind->texture)
|
||||
{
|
||||
active = bind->texture;
|
||||
glActiveTexture (GL_TEXTURE0 + bind->texture);
|
||||
}
|
||||
|
||||
s = gsk_gl_syncs_get_sync (&self->syncs, bind->id);
|
||||
if (s && s->sync)
|
||||
{
|
||||
glWaitSync ((GLsync) s->sync, 0, GL_TIMEOUT_IGNORED);
|
||||
s->sync = NULL;
|
||||
}
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, bind->id);
|
||||
textures[bind->texture] = bind->id;
|
||||
}
|
||||
@@ -1233,6 +1246,7 @@ gsk_gl_command_queue_end_frame (GskGLCommandQueue *self)
|
||||
self->batches.len = 0;
|
||||
self->batch_binds.len = 0;
|
||||
self->batch_uniforms.len = 0;
|
||||
self->syncs.len = 0;
|
||||
self->n_uploads = 0;
|
||||
self->tail_batch_index = -1;
|
||||
self->in_frame = FALSE;
|
||||
@@ -1439,8 +1453,7 @@ gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
|
||||
|
||||
g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
|
||||
g_assert (!GDK_IS_GL_TEXTURE (texture));
|
||||
g_assert (min_filter == GL_LINEAR || min_filter == GL_NEAREST);
|
||||
g_assert (mag_filter == GL_LINEAR || min_filter == GL_NEAREST);
|
||||
g_assert (mag_filter == GL_LINEAR || mag_filter == GL_NEAREST);
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
@@ -1464,6 +1477,9 @@ gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
|
||||
|
||||
gsk_gl_command_queue_do_upload_texture (self, texture);
|
||||
|
||||
if (min_filter == GL_LINEAR_MIPMAP_LINEAR)
|
||||
glGenerateMipmap (GL_TEXTURE_2D);
|
||||
|
||||
/* Restore previous texture state if any */
|
||||
if (self->attachments->textures[0].id > 0)
|
||||
glBindTexture (self->attachments->textures[0].target,
|
||||
|
||||
@@ -167,9 +167,15 @@ typedef union _GskGLCommandBatch
|
||||
|
||||
G_STATIC_ASSERT (sizeof (GskGLCommandBatch) == 32);
|
||||
|
||||
typedef struct _GskGLSync {
|
||||
guint id;
|
||||
gpointer sync;
|
||||
} GskGLSync;
|
||||
|
||||
DEFINE_INLINE_ARRAY (GskGLCommandBatches, gsk_gl_command_batches, GskGLCommandBatch)
|
||||
DEFINE_INLINE_ARRAY (GskGLCommandBinds, gsk_gl_command_binds, GskGLCommandBind)
|
||||
DEFINE_INLINE_ARRAY (GskGLCommandUniforms, gsk_gl_command_uniforms, GskGLCommandUniform)
|
||||
DEFINE_INLINE_ARRAY (GskGLSyncs, gsk_gl_syncs, GskGLSync)
|
||||
|
||||
struct _GskGLCommandQueue
|
||||
{
|
||||
@@ -225,6 +231,8 @@ struct _GskGLCommandQueue
|
||||
*/
|
||||
GskGLCommandUniforms batch_uniforms;
|
||||
|
||||
GskGLSyncs syncs;
|
||||
|
||||
/* Discovered max texture size when loading the command queue so that we
|
||||
* can either scale down or slice textures to fit within this size. Assumed
|
||||
* to be both height and width.
|
||||
@@ -354,6 +362,37 @@ gsk_gl_command_queue_bind_framebuffer (GskGLCommandQueue *self,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline GskGLSync *
|
||||
gsk_gl_syncs_get_sync (GskGLSyncs *syncs,
|
||||
guint id)
|
||||
{
|
||||
for (unsigned int i = 0; i < syncs->len; i++)
|
||||
{
|
||||
GskGLSync *sync = &syncs->items[i];
|
||||
if (sync->id == id)
|
||||
return sync;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_syncs_add_sync (GskGLSyncs *syncs,
|
||||
guint id,
|
||||
gpointer sync)
|
||||
{
|
||||
GskGLSync *s;
|
||||
|
||||
s = gsk_gl_syncs_get_sync (syncs, id);
|
||||
if (s)
|
||||
g_assert (s->sync == sync);
|
||||
else
|
||||
{
|
||||
s = gsk_gl_syncs_append (syncs);
|
||||
s->id = id;
|
||||
s->sync = sync;
|
||||
}
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_GL_COMMAND_QUEUE_PRIVATE_H__ */
|
||||
|
||||
+34
-19
@@ -753,7 +753,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
{
|
||||
if ((t = gdk_texture_get_render_data (texture, self)))
|
||||
{
|
||||
if (t->min_filter == min_filter && t->mag_filter == mag_filter)
|
||||
if (t->min_filter == min_filter && t->mag_filter == mag_filter && t->texture_id)
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
@@ -1195,6 +1195,10 @@ gsk_gl_driver_create_command_queue (GskGLDriver *self,
|
||||
void
|
||||
gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
guint min_cols,
|
||||
guint min_rows,
|
||||
GskGLTextureSlice **out_slices,
|
||||
guint *out_n_slices)
|
||||
{
|
||||
@@ -1216,31 +1220,37 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
|
||||
/* XXX: Too much? */
|
||||
max_texture_size = self->command_queue->max_texture_size / 4;
|
||||
|
||||
tex_width = texture->width;
|
||||
tex_height = texture->height;
|
||||
cols = (texture->width / max_texture_size) + 1;
|
||||
rows = (texture->height / max_texture_size) + 1;
|
||||
|
||||
cols = MAX ((texture->width / max_texture_size) + 1, min_cols);
|
||||
rows = MAX ((texture->height / max_texture_size) + 1, min_rows);
|
||||
|
||||
n_slices = cols * rows;
|
||||
|
||||
if ((t = gdk_texture_get_render_data (texture, self)))
|
||||
{
|
||||
*out_slices = t->slices;
|
||||
*out_n_slices = t->n_slices;
|
||||
return;
|
||||
if (t->n_slices == n_slices)
|
||||
{
|
||||
*out_slices = t->slices;
|
||||
*out_n_slices = t->n_slices;
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_texture_clear_render_data (texture);
|
||||
}
|
||||
|
||||
n_slices = cols * rows;
|
||||
slices = g_new0 (GskGLTextureSlice, n_slices);
|
||||
memtex = gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture));
|
||||
|
||||
for (guint col = 0; col < cols; col ++)
|
||||
for (guint col = 0; col < cols; col++)
|
||||
{
|
||||
int slice_width = MIN (max_texture_size, texture->width - x);
|
||||
int slice_width = col + 1 < cols ? tex_width / cols : tex_width - x;
|
||||
|
||||
for (guint row = 0; row < rows; row ++)
|
||||
for (guint row = 0; row < rows; row++)
|
||||
{
|
||||
int slice_height = MIN (max_texture_size, texture->height - y);
|
||||
int slice_height = row + 1 < rows ? tex_height / rows : tex_height - y;
|
||||
int slice_index = (col * rows) + row;
|
||||
GdkTexture *subtex;
|
||||
guint texture_id;
|
||||
@@ -1250,7 +1260,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
slice_width, slice_height);
|
||||
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue,
|
||||
subtex,
|
||||
GL_NEAREST, GL_NEAREST);
|
||||
min_filter, mag_filter);
|
||||
g_object_unref (subtex);
|
||||
|
||||
slices[slice_index].rect.x = x;
|
||||
@@ -1319,6 +1329,7 @@ typedef struct _GskGLTextureState
|
||||
{
|
||||
GdkGLContext *context;
|
||||
GLuint texture_id;
|
||||
GLsync sync;
|
||||
} GskGLTextureState;
|
||||
|
||||
static void
|
||||
@@ -1331,6 +1342,7 @@ create_texture_from_texture_destroy (gpointer data)
|
||||
|
||||
gdk_gl_context_make_current (state->context);
|
||||
glDeleteTextures (1, &state->texture_id);
|
||||
glDeleteSync (state->sync);
|
||||
g_clear_object (&state->context);
|
||||
g_slice_free (GskGLTextureState, state);
|
||||
}
|
||||
@@ -1365,10 +1377,13 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
|
||||
texture->texture_id = 0;
|
||||
gsk_gl_texture_free (texture);
|
||||
|
||||
return gdk_gl_texture_new (self->command_queue->context,
|
||||
texture_id,
|
||||
width,
|
||||
height,
|
||||
create_texture_from_texture_destroy,
|
||||
state);
|
||||
state->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
return gdk_gl_texture_new_with_sync (self->command_queue->context,
|
||||
texture_id,
|
||||
state->sync,
|
||||
width,
|
||||
height,
|
||||
create_texture_from_texture_destroy,
|
||||
state);
|
||||
}
|
||||
|
||||
@@ -177,6 +177,10 @@ GskGLTexture * gsk_gl_driver_mark_texture_permanent (GskGLDriver *s
|
||||
guint texture_id);
|
||||
void gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
guint min_cols,
|
||||
guint min_rows,
|
||||
GskGLTextureSlice **out_slices,
|
||||
guint *out_n_slices);
|
||||
GskGLProgram * gsk_gl_driver_lookup_shader (GskGLDriver *self,
|
||||
@@ -228,6 +232,10 @@ gsk_gl_driver_lookup_texture (GskGLDriver *self,
|
||||
static inline void
|
||||
gsk_gl_driver_slice_texture (GskGLDriver *self,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
guint min_cols,
|
||||
guint min_rows,
|
||||
GskGLTextureSlice **out_slices,
|
||||
guint *out_n_slices)
|
||||
{
|
||||
@@ -235,12 +243,15 @@ gsk_gl_driver_slice_texture (GskGLDriver *self,
|
||||
|
||||
if ((t = gdk_texture_get_render_data (texture, self)))
|
||||
{
|
||||
*out_slices = t->slices;
|
||||
*out_n_slices = t->n_slices;
|
||||
return;
|
||||
if (min_cols == 0 && min_rows == 0)
|
||||
{
|
||||
*out_slices = t->slices;
|
||||
*out_n_slices = t->n_slices;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gsk_gl_driver_add_texture_slices (self, texture, out_slices, out_n_slices);
|
||||
gsk_gl_driver_add_texture_slices (self, texture, min_filter, mag_filter, min_cols, min_rows, out_slices, out_n_slices);
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -264,6 +264,27 @@ gsk_gl_program_set_uniform_texture (GskGLProgram *self,
|
||||
texture_slot);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_program_set_uniform_texture_with_sync (GskGLProgram *self,
|
||||
guint key,
|
||||
guint stamp,
|
||||
GLenum texture_target,
|
||||
GLenum texture_slot,
|
||||
guint texture_id,
|
||||
gpointer sync)
|
||||
{
|
||||
gsk_gl_attachment_state_bind_texture (self->driver->command_queue->attachments,
|
||||
texture_target,
|
||||
texture_slot,
|
||||
texture_id);
|
||||
gsk_gl_uniform_state_set_texture (self->uniforms,
|
||||
self->program_info,
|
||||
key,
|
||||
stamp,
|
||||
texture_slot);
|
||||
gsk_gl_syncs_add_sync (&self->driver->command_queue->syncs, texture_id, sync);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_program_set_uniform_matrix (GskGLProgram *self,
|
||||
guint key,
|
||||
|
||||
@@ -60,6 +60,10 @@ GSK_GL_DEFINE_PROGRAM (linear_gradient,
|
||||
GSK_GL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points)
|
||||
GSK_GL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat))
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM (mask,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("mask.glsl")),
|
||||
GSK_GL_ADD_UNIFORM (1, MASK_SOURCE, u_mask))
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM (outset_shadow,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("outset_shadow.glsl")),
|
||||
GSK_GL_ADD_UNIFORM (1, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
||||
|
||||
+236
-19
@@ -190,6 +190,7 @@ typedef struct _GskGLRenderOffscreen
|
||||
|
||||
/* Return location for texture ID */
|
||||
guint texture_id;
|
||||
gpointer sync;
|
||||
|
||||
/* Whether to force creating a new texture, even if the
|
||||
* input already is a texture
|
||||
@@ -3277,6 +3278,56 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
{
|
||||
const GskRenderNode *source = gsk_mask_node_get_source (node);
|
||||
const GskRenderNode *mask = gsk_mask_node_get_mask (node);
|
||||
GskGLRenderOffscreen source_offscreen = {0};
|
||||
GskGLRenderOffscreen mask_offscreen = {0};
|
||||
|
||||
source_offscreen.bounds = &node->bounds;
|
||||
source_offscreen.force_offscreen = TRUE;
|
||||
source_offscreen.reset_clip = TRUE;
|
||||
|
||||
mask_offscreen.bounds = &node->bounds;
|
||||
mask_offscreen.force_offscreen = TRUE;
|
||||
mask_offscreen.reset_clip = TRUE;
|
||||
|
||||
/* TODO: We create 2 textures here as big as the mask node, but both
|
||||
* nodes might be a lot smaller than that.
|
||||
*/
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, source, &source_offscreen))
|
||||
{
|
||||
gsk_gl_render_job_visit_node (job, source);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (source_offscreen.was_offscreen);
|
||||
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, mask, &mask_offscreen))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (mask_offscreen.was_offscreen);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, mask));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
source_offscreen.texture_id);
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_MASK_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE1,
|
||||
mask_offscreen.texture_id);
|
||||
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_color_matrix_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
@@ -3443,12 +3494,21 @@ gsk_gl_render_job_visit_gl_shader_node (GskGLRenderJob *job,
|
||||
static void
|
||||
gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
GskGLRenderOffscreen *offscreen)
|
||||
{
|
||||
if (gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
|
||||
GdkGLTexture *gl_texture = NULL;
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
gl_texture = (GdkGLTexture *) texture;
|
||||
|
||||
if (min_filter == GL_LINEAR &&
|
||||
mag_filter == GL_LINEAR &&
|
||||
gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
|
||||
texture->width,
|
||||
texture->height) &&
|
||||
!GDK_IS_GL_TEXTURE (texture))
|
||||
!gl_texture)
|
||||
{
|
||||
const GskGLIconData *icon_data;
|
||||
|
||||
@@ -3458,16 +3518,19 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
|
||||
}
|
||||
else
|
||||
{
|
||||
offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, GL_LINEAR, GL_LINEAR);
|
||||
offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, min_filter, mag_filter);
|
||||
init_full_texture_region (offscreen);
|
||||
if (gl_texture && offscreen->texture_id == gdk_gl_texture_get_id (gl_texture) &&
|
||||
gdk_gl_texture_get_context (gl_texture) != gsk_gl_command_queue_get_context (job->command_queue))
|
||||
offscreen->sync = gdk_gl_texture_get_sync (gl_texture);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_texture_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *bounds)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
int max_texture_size = job->command_queue->max_texture_size;
|
||||
|
||||
if G_LIKELY (texture->width <= max_texture_size &&
|
||||
@@ -3475,32 +3538,33 @@ gsk_gl_render_job_visit_texture_node (GskGLRenderJob *job,
|
||||
{
|
||||
GskGLRenderOffscreen offscreen = {0};
|
||||
|
||||
gsk_gl_render_job_upload_texture (job, texture, &offscreen);
|
||||
gsk_gl_render_job_upload_texture (job, texture, GL_LINEAR, GL_LINEAR, &offscreen);
|
||||
|
||||
g_assert (offscreen.texture_id);
|
||||
g_assert (offscreen.was_offscreen == FALSE);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
offscreen.texture_id);
|
||||
gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen);
|
||||
gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
offscreen.texture_id,
|
||||
offscreen.sync);
|
||||
gsk_gl_render_job_draw_offscreen (job, bounds, &offscreen);
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
}
|
||||
else
|
||||
{
|
||||
float min_x = job->offset_x + node->bounds.origin.x;
|
||||
float min_y = job->offset_y + node->bounds.origin.y;
|
||||
float max_x = min_x + node->bounds.size.width;
|
||||
float max_y = min_y + node->bounds.size.height;
|
||||
float min_x = job->offset_x + bounds->origin.x;
|
||||
float min_y = job->offset_y + bounds->origin.y;
|
||||
float max_x = min_x + bounds->size.width;
|
||||
float max_y = min_y + bounds->size.height;
|
||||
float scale_x = (max_x - min_x) / texture->width;
|
||||
float scale_y = (max_y - min_y) / texture->height;
|
||||
GskGLTextureSlice *slices = NULL;
|
||||
guint n_slices = 0;
|
||||
|
||||
gsk_gl_driver_slice_texture (job->driver, texture, &slices, &n_slices);
|
||||
gsk_gl_driver_slice_texture (job->driver, texture, GL_NEAREST, GL_NEAREST, 0, 0, &slices, &n_slices);
|
||||
|
||||
g_assert (slices != NULL);
|
||||
g_assert (n_slices > 0);
|
||||
@@ -3535,6 +3599,151 @@ gsk_gl_render_job_visit_texture_node (GskGLRenderJob *job,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_texture_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
const graphene_rect_t *bounds = &node->bounds;
|
||||
|
||||
gsk_gl_render_job_visit_texture (job, texture, bounds);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_scale_node_get_texture (node);
|
||||
const graphene_rect_t *bounds = &node->bounds;
|
||||
GskScalingFilter scaling_filter = gsk_texture_scale_node_get_filter (node);
|
||||
int min_filters[] = { GL_LINEAR, GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR };
|
||||
int mag_filters[] = { GL_LINEAR, GL_NEAREST, GL_LINEAR };
|
||||
int min_filter = min_filters[scaling_filter];
|
||||
int mag_filter = mag_filters[scaling_filter];
|
||||
int max_texture_size = job->command_queue->max_texture_size;
|
||||
|
||||
if (scaling_filter == GSK_SCALING_FILTER_LINEAR)
|
||||
{
|
||||
gsk_gl_render_job_visit_texture (job, texture, bounds);
|
||||
return;
|
||||
}
|
||||
|
||||
if G_LIKELY (texture->width <= max_texture_size &&
|
||||
texture->height <= max_texture_size)
|
||||
{
|
||||
GskGLRenderTarget *render_target;
|
||||
GskGLRenderOffscreen offscreen = {0};
|
||||
graphene_rect_t viewport;
|
||||
graphene_rect_t prev_viewport;
|
||||
graphene_matrix_t prev_projection;
|
||||
float prev_alpha;
|
||||
guint prev_fbo;
|
||||
guint texture_id;
|
||||
|
||||
viewport = GRAPHENE_RECT_INIT (0, 0,
|
||||
bounds->size.width,
|
||||
bounds->size.height);
|
||||
|
||||
if (!gsk_gl_driver_create_render_target (job->driver,
|
||||
(int) ceilf (viewport.size.width),
|
||||
(int) ceilf (viewport.size.height),
|
||||
get_target_format (job, node),
|
||||
GL_LINEAR, GL_LINEAR,
|
||||
&render_target))
|
||||
{
|
||||
/* viewport is too big, slice the texture and try again */
|
||||
goto slice;
|
||||
}
|
||||
|
||||
gsk_gl_render_job_upload_texture (job, texture, min_filter, mag_filter, &offscreen);
|
||||
|
||||
g_assert (offscreen.texture_id);
|
||||
g_assert (offscreen.was_offscreen == FALSE);
|
||||
|
||||
gsk_gl_render_job_set_viewport (job, &viewport, &prev_viewport);
|
||||
gsk_gl_render_job_set_projection_from_rect (job, &viewport, &prev_projection);
|
||||
gsk_gl_render_job_set_modelview (job, NULL);
|
||||
prev_alpha = gsk_gl_render_job_set_alpha (job, 1.0f);
|
||||
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (viewport));
|
||||
|
||||
prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
|
||||
gsk_gl_command_queue_clear (job->command_queue, 0, &viewport);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
offscreen.texture_id);
|
||||
gsk_gl_render_job_draw_offscreen (job, &viewport, &offscreen);
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
|
||||
gsk_gl_render_job_pop_clip (job);
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL);
|
||||
gsk_gl_render_job_set_projection (job, &prev_projection);
|
||||
gsk_gl_render_job_set_alpha (job, prev_alpha);
|
||||
gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo);
|
||||
|
||||
texture_id = gsk_gl_driver_release_render_target (job->driver, render_target, FALSE);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
texture_id);
|
||||
gsk_gl_render_job_draw_offscreen_rect (job, bounds);
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
}
|
||||
else
|
||||
{
|
||||
slice:
|
||||
float min_x = bounds->origin.x;
|
||||
float min_y = bounds->origin.y;
|
||||
float max_x = min_x + bounds->size.width;
|
||||
float max_y = min_y + bounds->size.height;
|
||||
float scale_x = (max_x - min_x) / texture->width;
|
||||
float scale_y = (max_y - min_y) / texture->height;
|
||||
GskGLTextureSlice *slices = NULL;
|
||||
guint n_slices = 0;
|
||||
GdkGLContext *context = gsk_gl_driver_get_context (job->driver);
|
||||
guint rows, cols;
|
||||
|
||||
/* Slice enough that neither the original texture nor the scaled texture
|
||||
* exceed the texture size limit
|
||||
*/
|
||||
cols = (int)(MAX (bounds->size.width, texture->width) / (max_texture_size / 4)) + 1;
|
||||
rows = (int)(MAX (bounds->size.height, texture->height) / (max_texture_size / 4)) + 1;
|
||||
|
||||
gsk_gl_driver_slice_texture (job->driver, texture, GL_NEAREST, GL_NEAREST, cols, rows, &slices, &n_slices);
|
||||
|
||||
g_assert (slices != NULL);
|
||||
g_assert (n_slices > 0);
|
||||
|
||||
for (guint i = 0; i < n_slices; i ++)
|
||||
{
|
||||
const GskGLTextureSlice *slice = &slices[i];
|
||||
float x1, x2, y1, y2;
|
||||
GdkTexture *sub_texture;
|
||||
GskRenderNode *sub_node;
|
||||
|
||||
x1 = min_x + (scale_x * slice->rect.x);
|
||||
x2 = x1 + (slice->rect.width * scale_x);
|
||||
y1 = min_y + (scale_y * slice->rect.y);
|
||||
y2 = y1 + (slice->rect.height * scale_y);
|
||||
|
||||
sub_texture = gdk_gl_texture_new (context, slice->texture_id, slice->rect.width, slice->rect.height, NULL, NULL);
|
||||
|
||||
sub_node = gsk_texture_scale_node_new (sub_texture, &GRAPHENE_RECT_INIT (x1, y1, x2 - x1, y2 - y1), scaling_filter);
|
||||
|
||||
gsk_gl_render_job_visit_node (job, sub_node);
|
||||
gsk_render_node_unref (sub_node);
|
||||
g_object_unref (sub_texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_repeat_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
@@ -3720,6 +3929,10 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_visit_as_fallback (job, node);
|
||||
break;
|
||||
|
||||
case GSK_MASK_NODE:
|
||||
gsk_gl_render_job_visit_mask_node (job, node);
|
||||
break;
|
||||
|
||||
case GSK_OPACITY_NODE:
|
||||
gsk_gl_render_job_visit_opacity_node (job, node);
|
||||
break;
|
||||
@@ -3762,6 +3975,10 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_visit_texture_node (job, node);
|
||||
break;
|
||||
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
gsk_gl_render_job_visit_texture_scale_node (job, node);
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_NODE:
|
||||
gsk_gl_render_job_visit_transform_node (job, node);
|
||||
break;
|
||||
@@ -3808,7 +4025,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
offscreen->force_offscreen == FALSE)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
gsk_gl_render_job_upload_texture (job, texture, offscreen);
|
||||
gsk_gl_render_job_upload_texture (job, texture, GL_LINEAR, GL_LINEAR, offscreen);
|
||||
g_assert (offscreen->was_offscreen == FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,8 @@ gsk_gl_texture_library_real_compact (GskGLTextureLibrary *self,
|
||||
{
|
||||
if (!entry->accessed)
|
||||
{
|
||||
gsk_gl_driver_release_texture (self->driver, entry->texture);
|
||||
if (entry->texture)
|
||||
gsk_gl_driver_release_texture (self->driver, entry->texture);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
dropped++;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// VERTEX_SHADER:
|
||||
// mask.glsl
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
// mask.glsl
|
||||
|
||||
uniform sampler2D u_mask;
|
||||
|
||||
void main() {
|
||||
vec4 source = GskTexture(u_source, vUv);
|
||||
vec4 mask = GskTexture(u_mask, vUv);
|
||||
gskSetOutputColor(vec4 (source * mask.a));
|
||||
}
|
||||
@@ -35,6 +35,7 @@
|
||||
* @GSK_CONIC_GRADIENT_NODE: A node drawing a conic gradient
|
||||
* @GSK_BORDER_NODE: A node stroking a border around an area
|
||||
* @GSK_TEXTURE_NODE: A node drawing a `GdkTexture`
|
||||
* @GSK_TEXTURE_SCALE_NODE: A node drawing a `GdkTexture` scaled and filtered
|
||||
* @GSK_INSET_SHADOW_NODE: A node drawing an inset shadow
|
||||
* @GSK_OUTSET_SHADOW_NODE: A node drawing an outset shadow
|
||||
* @GSK_TRANSFORM_NODE: A node that renders its child after applying a matrix transform
|
||||
@@ -45,6 +46,7 @@
|
||||
* @GSK_ROUNDED_CLIP_NODE: A node that clips its child to a rounded rectangle
|
||||
* @GSK_SHADOW_NODE: A node that draws a shadow below its child
|
||||
* @GSK_BLEND_NODE: A node that blends two children together
|
||||
* @GSK_MASK_NODE: A node that masks one child with another
|
||||
* @GSK_CROSS_FADE_NODE: A node that cross-fades between two children
|
||||
* @GSK_TEXT_NODE: A node containing a glyph string
|
||||
* @GSK_BLUR_NODE: A node that applies a blur
|
||||
@@ -65,6 +67,7 @@ typedef enum {
|
||||
GSK_CONIC_GRADIENT_NODE,
|
||||
GSK_BORDER_NODE,
|
||||
GSK_TEXTURE_NODE,
|
||||
GSK_TEXTURE_SCALE_NODE,
|
||||
GSK_INSET_SHADOW_NODE,
|
||||
GSK_OUTSET_SHADOW_NODE,
|
||||
GSK_TRANSFORM_NODE,
|
||||
@@ -75,6 +78,7 @@ typedef enum {
|
||||
GSK_ROUNDED_CLIP_NODE,
|
||||
GSK_SHADOW_NODE,
|
||||
GSK_BLEND_NODE,
|
||||
GSK_MASK_NODE,
|
||||
GSK_CROSS_FADE_NODE,
|
||||
GSK_TEXT_NODE,
|
||||
GSK_BLUR_NODE,
|
||||
|
||||
+26
-1
@@ -142,6 +142,7 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
|
||||
#define GSK_TYPE_DEBUG_NODE (gsk_debug_node_get_type())
|
||||
#define GSK_TYPE_COLOR_NODE (gsk_color_node_get_type())
|
||||
#define GSK_TYPE_TEXTURE_NODE (gsk_texture_node_get_type())
|
||||
#define GSK_TYPE_TEXTURE_SCALE_NODE (gsk_texture_scale_node_get_type())
|
||||
#define GSK_TYPE_LINEAR_GRADIENT_NODE (gsk_linear_gradient_node_get_type())
|
||||
#define GSK_TYPE_REPEATING_LINEAR_GRADIENT_NODE (gsk_repeating_linear_gradient_node_get_type())
|
||||
#define GSK_TYPE_RADIAL_GRADIENT_NODE (gsk_radial_gradient_node_get_type())
|
||||
@@ -163,11 +164,13 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
|
||||
#define GSK_TYPE_CROSS_FADE_NODE (gsk_cross_fade_node_get_type())
|
||||
#define GSK_TYPE_TEXT_NODE (gsk_text_node_get_type())
|
||||
#define GSK_TYPE_BLUR_NODE (gsk_blur_node_get_type())
|
||||
#define GSK_TYPE_MASK_NODE (gsk_mask_node_get_type())
|
||||
#define GSK_TYPE_GL_SHADER_NODE (gsk_gl_shader_node_get_type())
|
||||
|
||||
typedef struct _GskDebugNode GskDebugNode;
|
||||
typedef struct _GskColorNode GskColorNode;
|
||||
typedef struct _GskTextureNode GskTextureNode;
|
||||
typedef struct _GskTextureScaleNode GskTextureScaleNode;
|
||||
typedef struct _GskLinearGradientNode GskLinearGradientNode;
|
||||
typedef struct _GskRepeatingLinearGradientNode GskRepeatingLinearGradientNode;
|
||||
typedef struct _GskRadialGradientNode GskRadialGradientNode;
|
||||
@@ -189,6 +192,7 @@ typedef struct _GskBlendNode GskBlendNode;
|
||||
typedef struct _GskCrossFadeNode GskCrossFadeNode;
|
||||
typedef struct _GskTextNode GskTextNode;
|
||||
typedef struct _GskBlurNode GskBlurNode;
|
||||
typedef struct _GskMaskNode GskMaskNode;
|
||||
typedef struct _GskGLShaderNode GskGLShaderNode;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -217,6 +221,17 @@ GskRenderNode * gsk_texture_node_new (GdkTexture
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gsk_texture_node_get_texture (const GskRenderNode *node) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GType gsk_texture_scale_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GskRenderNode * gsk_texture_scale_node_new (GdkTexture *texture,
|
||||
const graphene_rect_t *bounds,
|
||||
GskScalingFilter filter);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkTexture * gsk_texture_scale_node_get_texture (const GskRenderNode *node) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GskScalingFilter gsk_texture_scale_node_get_filter (const GskRenderNode *node) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_linear_gradient_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -516,8 +531,18 @@ GskRenderNode * gsk_blur_node_get_child (const GskRender
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_blur_node_get_radius (const GskRenderNode *node) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GType gsk_mask_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GskRenderNode * gsk_mask_node_new (GskRenderNode *source,
|
||||
GskRenderNode *mask);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GskRenderNode * gsk_mask_node_get_source (const GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GskRenderNode * gsk_mask_node_get_mask (const GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_gl_shader_node_get_type (void) G_GNUC_CONST;
|
||||
GType gsk_gl_shader_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskRenderNode * gsk_gl_shader_node_new (GskGLShader *shader,
|
||||
const graphene_rect_t *bounds,
|
||||
|
||||
+397
-23
@@ -58,7 +58,7 @@ rectangle_init_from_graphene (cairo_rectangle_int_t *cairo,
|
||||
cairo->height = ceilf (graphene->origin.y + graphene->size.height) - cairo->y;
|
||||
}
|
||||
|
||||
/*** GSK_COLOR_NODE ***/
|
||||
/* {{{ GSK_COLOR_NODE */
|
||||
|
||||
/**
|
||||
* GskColorNode:
|
||||
@@ -147,7 +147,8 @@ gsk_color_node_new (const GdkRGBA *rgba,
|
||||
return node;
|
||||
}
|
||||
|
||||
/*** GSK_LINEAR_GRADIENT_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_LINEAR_GRADIENT_NODE */
|
||||
|
||||
/**
|
||||
* GskRepeatingLinearGradientNode:
|
||||
@@ -420,7 +421,8 @@ gsk_linear_gradient_node_get_color_stops (const GskRenderNode *node,
|
||||
return self->stops;
|
||||
}
|
||||
|
||||
/*** GSK_RADIAL_GRADIENT_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_RADIAL_GRADIENT_NODE */
|
||||
|
||||
/**
|
||||
* GskRepeatingRadialGradientNode:
|
||||
@@ -790,7 +792,8 @@ gsk_radial_gradient_node_get_end (const GskRenderNode *node)
|
||||
return self->end;
|
||||
}
|
||||
|
||||
/*** GSK_CONIC_GRADIENT_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_CONIC_GRADIENT_NODE */
|
||||
|
||||
/**
|
||||
* GskConicGradientNode:
|
||||
@@ -1147,7 +1150,8 @@ gsk_conic_gradient_node_get_angle (const GskRenderNode *node)
|
||||
return self->angle;
|
||||
}
|
||||
|
||||
/*** GSK_BORDER_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_BORDER_NODE */
|
||||
|
||||
/**
|
||||
* GskBorderNode:
|
||||
@@ -1459,7 +1463,8 @@ gsk_border_node_get_uniform_color (const GskRenderNode *self)
|
||||
return node->uniform_color;
|
||||
}
|
||||
|
||||
/*** GSK_TEXTURE_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_TEXTURE_NODE */
|
||||
|
||||
/**
|
||||
* GskTextureNode:
|
||||
@@ -1576,7 +1581,193 @@ gsk_texture_node_new (GdkTexture *texture,
|
||||
return node;
|
||||
}
|
||||
|
||||
/*** GSK_INSET_SHADOW_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_TEXTURE_SCALE_NODE */
|
||||
|
||||
/**
|
||||
* GskTextureScaleNode:
|
||||
*
|
||||
* A render node for a `GdkTexture`.
|
||||
*/
|
||||
struct _GskTextureScaleNode
|
||||
{
|
||||
GskRenderNode render_node;
|
||||
|
||||
GdkTexture *texture;
|
||||
GskScalingFilter filter;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_texture_scale_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskTextureScaleNode *self = (GskTextureScaleNode *) node;
|
||||
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_TEXTURE_SCALE_NODE));
|
||||
|
||||
g_clear_object (&self->texture);
|
||||
|
||||
parent_class->finalize (node);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_scale_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskTextureScaleNode *self = (GskTextureScaleNode *) node;
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
cairo_filter_t filters[] = {
|
||||
CAIRO_FILTER_BILINEAR,
|
||||
CAIRO_FILTER_NEAREST,
|
||||
CAIRO_FILTER_GOOD,
|
||||
};
|
||||
cairo_t *cr2;
|
||||
cairo_surface_t *surface2;
|
||||
|
||||
surface2 = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
(int) ceilf (node->bounds.size.width),
|
||||
(int) ceilf (node->bounds.size.height));
|
||||
cr2 = cairo_create (surface2);
|
||||
|
||||
cairo_set_source_rgba (cr2, 0, 0, 0, 0);
|
||||
cairo_paint (cr2);
|
||||
|
||||
surface = gdk_texture_download_surface (self->texture);
|
||||
pattern = cairo_pattern_create_for_surface (surface);
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||
|
||||
cairo_matrix_init_scale (&matrix,
|
||||
gdk_texture_get_width (self->texture) / node->bounds.size.width,
|
||||
gdk_texture_get_height (self->texture) / node->bounds.size.height);
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
cairo_pattern_set_filter (pattern, filters[self->filter]);
|
||||
|
||||
cairo_set_source (cr2, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
cairo_rectangle (cr2, 0, 0, node->bounds.size.width, node->bounds.size.height);
|
||||
cairo_fill (cr2);
|
||||
|
||||
cairo_destroy (cr2);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
pattern = cairo_pattern_create_for_surface (surface2);
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||
|
||||
cairo_matrix_init_identity (&matrix);
|
||||
cairo_matrix_translate (&matrix,
|
||||
-node->bounds.origin.x,
|
||||
-node->bounds.origin.y);
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
cairo_surface_destroy (surface2);
|
||||
|
||||
gsk_cairo_rectangle (cr, &node->bounds);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_scale_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GskTextureScaleNode *self1 = (GskTextureScaleNode *) node1;
|
||||
GskTextureScaleNode *self2 = (GskTextureScaleNode *) node2;
|
||||
|
||||
if (graphene_rect_equal (&node1->bounds, &node2->bounds) &&
|
||||
self1->texture == self2->texture &&
|
||||
self1->filter == self2->filter)
|
||||
return;
|
||||
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_texture_scale_node_get_texture:
|
||||
* @node: (type GskTextureNode): a `GskRenderNode` of type %GSK_TEXTURE_SCALE_NODE
|
||||
*
|
||||
* Retrieves the `GdkTexture` used when creating this `GskRenderNode`.
|
||||
*
|
||||
* Returns: (transfer none): the `GdkTexture`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GdkTexture *
|
||||
gsk_texture_scale_node_get_texture (const GskRenderNode *node)
|
||||
{
|
||||
const GskTextureScaleNode *self = (const GskTextureScaleNode *) node;
|
||||
|
||||
return self->texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_texture_scale_node_get_filter:
|
||||
* @node: (type GskTextureNode): a `GskRenderNode` of type %GSK_TEXTURE_SCALE_NODE
|
||||
*
|
||||
* Retrieves the `GskScalingFilter` used when creating this `GskRenderNode`.
|
||||
*
|
||||
* Returns: (transfer none): the `GskScalingFilter`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GskScalingFilter
|
||||
gsk_texture_scale_node_get_filter (const GskRenderNode *node)
|
||||
{
|
||||
const GskTextureScaleNode *self = (const GskTextureScaleNode *) node;
|
||||
|
||||
return self->filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_texture_scale_node_new:
|
||||
* @texture: the texture to scale
|
||||
* @bounds: the size of the texture to scale to
|
||||
* @filter: how to scale the texture
|
||||
*
|
||||
* Creates a node that scales the texture to the size given by the
|
||||
* bounds and the filter and then places it at the bounds' position.
|
||||
*
|
||||
* This node is intended for tight control over scaling applied
|
||||
* to a texture, such as in image editors and requires the
|
||||
* application to be aware of the whole render tree as further
|
||||
* transforms may be applied that conflict with the desired effect
|
||||
* of this node.
|
||||
*
|
||||
* Returns: (transfer full) (type GskTextureScaleNode): A new `GskRenderNode`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_texture_scale_node_new (GdkTexture *texture,
|
||||
const graphene_rect_t *bounds,
|
||||
GskScalingFilter filter)
|
||||
{
|
||||
GskTextureScaleNode *self;
|
||||
GskRenderNode *node;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
g_return_val_if_fail (bounds != NULL, NULL);
|
||||
|
||||
self = gsk_render_node_alloc (GSK_TEXTURE_SCALE_NODE);
|
||||
node = (GskRenderNode *) self;
|
||||
node->offscreen_for_opacity = FALSE;
|
||||
|
||||
self->texture = g_object_ref (texture);
|
||||
graphene_rect_init_from_rect (&node->bounds, bounds);
|
||||
self->filter = filter;
|
||||
|
||||
node->prefers_high_depth = gdk_memory_format_prefers_high_depth (gdk_texture_get_format (texture));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ GSK_INSET_SHADOW_NODE */
|
||||
|
||||
/**
|
||||
* GskInsetShadowNode:
|
||||
@@ -2132,7 +2323,8 @@ gsk_inset_shadow_node_get_blur_radius (const GskRenderNode *node)
|
||||
return self->blur_radius;
|
||||
}
|
||||
|
||||
/*** GSK_OUTSET_SHADOW_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_OUTSET_SHADOW_NODE */
|
||||
|
||||
/**
|
||||
* GskOutsetShadowNode:
|
||||
@@ -2438,7 +2630,8 @@ gsk_outset_shadow_node_get_blur_radius (const GskRenderNode *node)
|
||||
return self->blur_radius;
|
||||
}
|
||||
|
||||
/*** GSK_CAIRO_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_CAIRO_NODE */
|
||||
|
||||
/**
|
||||
* GskCairoNode:
|
||||
@@ -2576,7 +2769,8 @@ gsk_cairo_node_get_draw_context (GskRenderNode *node)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**** GSK_CONTAINER_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_CONTAINER_NODE */
|
||||
|
||||
/**
|
||||
* GskContainerNode:
|
||||
@@ -2835,7 +3029,8 @@ gsk_container_node_is_disjoint (const GskRenderNode *node)
|
||||
return self->disjoint;
|
||||
}
|
||||
|
||||
/*** GSK_TRANSFORM_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_TRANSFORM_NODE */
|
||||
|
||||
/**
|
||||
* GskTransformNode:
|
||||
@@ -3058,7 +3253,8 @@ gsk_transform_node_get_translate (const GskRenderNode *node,
|
||||
*dy = self->dy;
|
||||
}
|
||||
|
||||
/*** GSK_OPACITY_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_OPACITY_NODE */
|
||||
|
||||
/**
|
||||
* GskOpacityNode:
|
||||
@@ -3185,7 +3381,8 @@ gsk_opacity_node_get_opacity (const GskRenderNode *node)
|
||||
return self->opacity;
|
||||
}
|
||||
|
||||
/*** GSK_COLOR_MATRIX_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_COLOR_MATRIX_NODE */
|
||||
|
||||
/**
|
||||
* GskColorMatrixNode:
|
||||
@@ -3406,7 +3603,8 @@ gsk_color_matrix_node_get_color_offset (const GskRenderNode *node)
|
||||
return &self->color_offset;
|
||||
}
|
||||
|
||||
/*** GSK_REPEAT_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_REPEAT_NODE */
|
||||
|
||||
/**
|
||||
* GskRepeatNode:
|
||||
@@ -3542,7 +3740,8 @@ gsk_repeat_node_get_child_bounds (const GskRenderNode *node)
|
||||
return &self->child_bounds;
|
||||
}
|
||||
|
||||
/*** GSK_CLIP_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_CLIP_NODE */
|
||||
|
||||
/**
|
||||
* GskClipNode:
|
||||
@@ -3676,7 +3875,8 @@ gsk_clip_node_get_clip (const GskRenderNode *node)
|
||||
return &self->clip;
|
||||
}
|
||||
|
||||
/*** GSK_ROUNDED_CLIP_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_ROUNDED_CLIP_NODE */
|
||||
|
||||
/**
|
||||
* GskRoundedClipNode:
|
||||
@@ -3810,7 +4010,8 @@ gsk_rounded_clip_node_get_clip (const GskRenderNode *node)
|
||||
return &self->clip;
|
||||
}
|
||||
|
||||
/*** GSK_SHADOW_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_SHADOW_NODE */
|
||||
|
||||
/**
|
||||
* GskShadowNode:
|
||||
@@ -4050,7 +4251,8 @@ gsk_shadow_node_get_n_shadows (const GskRenderNode *node)
|
||||
return self->n_shadows;
|
||||
}
|
||||
|
||||
/*** GSK_BLEND_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_BLEND_NODE */
|
||||
|
||||
/**
|
||||
* GskBlendNode:
|
||||
@@ -4244,7 +4446,8 @@ gsk_blend_node_get_blend_mode (const GskRenderNode *node)
|
||||
return self->blend_mode;
|
||||
}
|
||||
|
||||
/*** GSK_CROSS_FADE_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_CROSS_FADE_NODE */
|
||||
|
||||
/**
|
||||
* GskCrossFadeNode:
|
||||
@@ -4395,7 +4598,8 @@ gsk_cross_fade_node_get_progress (const GskRenderNode *node)
|
||||
return self->progress;
|
||||
}
|
||||
|
||||
/*** GSK_TEXT_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_TEXT_NODE */
|
||||
|
||||
/**
|
||||
* GskTextNode:
|
||||
@@ -4660,7 +4864,8 @@ gsk_text_node_get_offset (const GskRenderNode *node)
|
||||
return &self->offset;
|
||||
}
|
||||
|
||||
/*** GSK_BLUR_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_BLUR_NODE */
|
||||
|
||||
/**
|
||||
* GskBlurNode:
|
||||
@@ -4979,7 +5184,137 @@ gsk_blur_node_get_radius (const GskRenderNode *node)
|
||||
return self->radius;
|
||||
}
|
||||
|
||||
/*** GSK_DEBUG_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_MASK_NODE */
|
||||
|
||||
/**
|
||||
* GskMaskNode:
|
||||
*
|
||||
* A render node masking one child node with another.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
typedef struct _GskMaskNode GskMaskNode;
|
||||
|
||||
struct _GskMaskNode
|
||||
{
|
||||
GskRenderNode render_node;
|
||||
|
||||
GskRenderNode *mask;
|
||||
GskRenderNode *source;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_mask_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskMaskNode *self = (GskMaskNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->source);
|
||||
gsk_render_node_unref (self->mask);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_mask_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskMaskNode *self = (GskMaskNode *) node;
|
||||
cairo_pattern_t *mask_pattern;
|
||||
|
||||
cairo_push_group (cr);
|
||||
gsk_render_node_draw (self->source, cr);
|
||||
cairo_pop_group_to_source (cr);
|
||||
|
||||
cairo_push_group (cr);
|
||||
gsk_render_node_draw (self->mask, cr);
|
||||
mask_pattern = cairo_pop_group (cr);
|
||||
|
||||
cairo_mask (cr, mask_pattern);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_mask_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GskMaskNode *self1 = (GskMaskNode *) node1;
|
||||
GskMaskNode *self2 = (GskMaskNode *) node2;
|
||||
|
||||
gsk_render_node_diff (self1->source, self2->source, region);
|
||||
gsk_render_node_diff (self1->mask, self2->mask, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_mask_node_new:
|
||||
* @source: The bottom node to be drawn
|
||||
* @mask: The node to be blended onto the @bottom node
|
||||
*
|
||||
* Creates a `GskRenderNode` that will use @blend_mode to blend the @top
|
||||
* node onto the @bottom node.
|
||||
*
|
||||
* Returns: (transfer full) (type GskMaskNode): A new `GskRenderNode`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_mask_node_new (GskRenderNode *source,
|
||||
GskRenderNode *mask)
|
||||
{
|
||||
GskMaskNode *self;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE (source), NULL);
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE (mask), NULL);
|
||||
|
||||
self = gsk_render_node_alloc (GSK_MASK_NODE);
|
||||
self->source = gsk_render_node_ref (source);
|
||||
self->mask = gsk_render_node_ref (mask);
|
||||
|
||||
graphene_rect_union (&source->bounds, &mask->bounds, &self->render_node.bounds);
|
||||
|
||||
return &self->render_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_mask_node_get_source:
|
||||
* @node: (type GskBlendNode): a mask `GskRenderNode`
|
||||
*
|
||||
* Retrieves the source `GskRenderNode` child of the @node.
|
||||
*
|
||||
* Returns: (transfer none): the source child node
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_mask_node_get_source (const GskRenderNode *node)
|
||||
{
|
||||
const GskMaskNode *self = (const GskMaskNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_MASK_NODE), NULL);
|
||||
|
||||
return self->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_mask_node_get_mask:
|
||||
* @node: (type GskBlendNode): a mask `GskRenderNode`
|
||||
*
|
||||
* Retrieves the mask `GskRenderNode` child of the @node.
|
||||
*
|
||||
* Returns: (transfer none): the mask child node
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_mask_node_get_mask (const GskRenderNode *node)
|
||||
{
|
||||
const GskMaskNode *self = (const GskMaskNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_MASK_NODE), NULL);
|
||||
|
||||
return self->mask;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ GSK_DEBUG_NODE */
|
||||
|
||||
/**
|
||||
* GskDebugNode:
|
||||
@@ -5104,7 +5439,8 @@ gsk_debug_node_get_message (const GskRenderNode *node)
|
||||
return self->message;
|
||||
}
|
||||
|
||||
/*** GSK_GL_SHADER_NODE ***/
|
||||
/* }}} */
|
||||
/* {{{ GSK_GL_SHADER_NODE */
|
||||
|
||||
/**
|
||||
* GskGLShaderNode:
|
||||
@@ -5309,6 +5645,8 @@ gsk_gl_shader_node_get_args (const GskRenderNode *node)
|
||||
return self->args;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
GType gsk_render_node_types[GSK_RENDER_NODE_TYPE_N_TYPES];
|
||||
|
||||
#ifndef I_
|
||||
@@ -5333,6 +5671,7 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeating_radial_gradient_node, GSK_REPEATING_R
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_conic_gradient_node, GSK_CONIC_GRADIENT_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_border_node, GSK_BORDER_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_texture_node, GSK_TEXTURE_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_texture_scale_node, GSK_TEXTURE_SCALE_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_inset_shadow_node, GSK_INSET_SHADOW_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_outset_shadow_node, GSK_OUTSET_SHADOW_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_transform_node, GSK_TRANSFORM_NODE)
|
||||
@@ -5346,6 +5685,7 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_blend_node, GSK_BLEND_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_cross_fade_node, GSK_CROSS_FADE_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_text_node, GSK_TEXT_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_blur_node, GSK_BLUR_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_mask_node, GSK_MASK_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_gl_shader_node, GSK_GL_SHADER_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_debug_node, GSK_DEBUG_NODE)
|
||||
|
||||
@@ -5512,6 +5852,22 @@ gsk_render_node_init_types_once (void)
|
||||
gsk_render_node_types[GSK_TEXTURE_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
GSK_TEXTURE_SCALE_NODE,
|
||||
sizeof (GskTextureScaleNode),
|
||||
NULL,
|
||||
gsk_texture_scale_node_finalize,
|
||||
gsk_texture_scale_node_draw,
|
||||
NULL,
|
||||
gsk_texture_scale_node_diff,
|
||||
};
|
||||
|
||||
GType node_type = gsk_render_node_type_register_static (I_("GskTextureScaleNode"), &node_info);
|
||||
gsk_render_node_types[GSK_TEXTURE_SCALE_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
@@ -5720,6 +6076,22 @@ gsk_render_node_init_types_once (void)
|
||||
gsk_render_node_types[GSK_BLUR_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
GSK_MASK_NODE,
|
||||
sizeof (GskMaskNode),
|
||||
NULL,
|
||||
gsk_mask_node_finalize,
|
||||
gsk_mask_node_draw,
|
||||
NULL,
|
||||
gsk_mask_node_diff,
|
||||
};
|
||||
|
||||
GType node_type = gsk_render_node_type_register_static (I_("GskMaskNode"), &node_info);
|
||||
gsk_render_node_types[GSK_MASK_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
@@ -5884,3 +6256,5 @@ gsk_render_node_init_types (void)
|
||||
g_once_init_leave (®ister_types__volatile, initialized);
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
||||
@@ -600,6 +600,32 @@ clear_shadows (gpointer inout_shadows)
|
||||
g_array_set_size (*(GArray **) inout_shadows, 0);
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
GskScalingFilter filter;
|
||||
const char *name;
|
||||
} scaling_filters[] = {
|
||||
{ GSK_SCALING_FILTER_LINEAR, "linear" },
|
||||
{ GSK_SCALING_FILTER_NEAREST, "nearest" },
|
||||
{ GSK_SCALING_FILTER_TRILINEAR, "trilinear" },
|
||||
};
|
||||
|
||||
static gboolean
|
||||
parse_scaling_filter (GtkCssParser *parser,
|
||||
gpointer out_filter)
|
||||
{
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS (scaling_filters); i++)
|
||||
{
|
||||
if (gtk_css_parser_try_ident (parser, scaling_filters[i].name))
|
||||
{
|
||||
*(GskScalingFilter *) out_filter = scaling_filters[i].filter;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
GskBlendMode mode;
|
||||
@@ -1350,6 +1376,31 @@ parse_glshader_node (GtkCssParser *parser)
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_mask_node (GtkCssParser *parser)
|
||||
{
|
||||
GskRenderNode *source = NULL;
|
||||
GskRenderNode *mask = NULL;
|
||||
const Declaration declarations[] = {
|
||||
{ "source", parse_node, clear_node, &source },
|
||||
{ "mask", parse_node, clear_node, &mask },
|
||||
};
|
||||
GskRenderNode *result;
|
||||
|
||||
parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
|
||||
if (source == NULL)
|
||||
source = create_default_render_node ();
|
||||
if (mask == NULL)
|
||||
mask = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
|
||||
|
||||
result = gsk_mask_node_new (source, mask);
|
||||
|
||||
gsk_render_node_unref (source);
|
||||
gsk_render_node_unref (mask);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_border_node (GtkCssParser *parser)
|
||||
{
|
||||
@@ -1389,6 +1440,30 @@ parse_texture_node (GtkCssParser *parser)
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_texture_scale_node (GtkCssParser *parser)
|
||||
{
|
||||
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
|
||||
GdkTexture *texture = NULL;
|
||||
GskScalingFilter filter = GSK_SCALING_FILTER_LINEAR;
|
||||
const Declaration declarations[] = {
|
||||
{ "bounds", parse_rect, NULL, &bounds },
|
||||
{ "texture", parse_texture, clear_texture, &texture },
|
||||
{ "filter", parse_scaling_filter, NULL, &filter }
|
||||
};
|
||||
GskRenderNode *node;
|
||||
|
||||
parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
|
||||
|
||||
if (texture == NULL)
|
||||
texture = create_default_texture ();
|
||||
|
||||
node = gsk_texture_scale_node_new (texture, &bounds, filter);
|
||||
g_object_unref (texture);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_cairo_node (GtkCssParser *parser)
|
||||
{
|
||||
@@ -1861,8 +1936,10 @@ parse_node (GtkCssParser *parser,
|
||||
{ "shadow", parse_shadow_node },
|
||||
{ "text", parse_text_node },
|
||||
{ "texture", parse_texture_node },
|
||||
{ "texture-scale", parse_texture_scale_node },
|
||||
{ "transform", parse_transform_node },
|
||||
{ "glshader", parse_glshader_node },
|
||||
{ "mask", parse_mask_node },
|
||||
};
|
||||
GskRenderNode **node_p = out_node;
|
||||
guint i;
|
||||
@@ -2757,6 +2834,73 @@ render_node_print (Printer *p,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_scale_node_get_texture (node);
|
||||
GskScalingFilter filter = gsk_texture_scale_node_get_filter (node);
|
||||
GBytes *bytes;
|
||||
|
||||
start_node (p, "texture-scale");
|
||||
append_rect_param (p, "bounds", &node->bounds);
|
||||
|
||||
if (filter != GSK_SCALING_FILTER_LINEAR)
|
||||
{
|
||||
_indent (p);
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS (scaling_filters); i++)
|
||||
{
|
||||
if (scaling_filters[i].filter == filter)
|
||||
{
|
||||
g_string_append_printf (p->str, "filter: %s;\n", scaling_filters[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_indent (p);
|
||||
|
||||
switch (gdk_texture_get_format (texture))
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
g_string_append (p->str, "texture: url(\"data:image/png;base64,");
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||
bytes = gdk_texture_save_to_tiff_bytes (texture);
|
||||
g_string_append (p->str, "texture: url(\"data:image/tiff;base64,");
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
b64 = base64_encode_with_linebreaks (g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
append_escaping_newlines (p->str, b64);
|
||||
g_free (b64);
|
||||
g_string_append (p->str, "\");\n");
|
||||
end_node (p);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TEXT_NODE:
|
||||
{
|
||||
const graphene_point_t *offset = gsk_text_node_get_offset (node);
|
||||
@@ -2982,6 +3126,17 @@ render_node_print (Printer *p,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_MASK_NODE:
|
||||
{
|
||||
start_node (p, "mask");
|
||||
|
||||
append_node_param (p, "source", gsk_mask_node_get_source (node));
|
||||
append_node_param (p, "mask", gsk_mask_node_get_mask (node));
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_NOT_A_RENDER_NODE:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
|
||||
@@ -19,6 +19,7 @@ gsk_private_gl_shaders = [
|
||||
'gl/resources/repeat.glsl',
|
||||
'gl/resources/custom.glsl',
|
||||
'gl/resources/filled_border.glsl',
|
||||
'gl/resources/mask.glsl',
|
||||
]
|
||||
|
||||
gsk_public_sources = files([
|
||||
|
||||
@@ -440,6 +440,9 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
g_array_append_val (self->render_ops, op);
|
||||
return;
|
||||
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
goto fallback;
|
||||
|
||||
case GSK_COLOR_NODE:
|
||||
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_COLOR;
|
||||
@@ -501,6 +504,9 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
g_array_append_val (self->render_ops, op);
|
||||
return;
|
||||
|
||||
case GSK_MASK_NODE:
|
||||
goto fallback;
|
||||
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "gtkprivate.h"
|
||||
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
/**
|
||||
* GtkVolumeButton:
|
||||
*
|
||||
@@ -49,7 +49,7 @@ struct _GtkVolumeButton
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_volume_button_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10
|
||||
GtkWidget* gtk_volume_button_new (void);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkVolumeButton, g_object_unref)
|
||||
@@ -49,6 +49,7 @@ gtk_deprecated_sources = [
|
||||
'deprecated/gtktreepopover.c',
|
||||
'deprecated/gtktreeview.c',
|
||||
'deprecated/gtktreeviewcolumn.c',
|
||||
'deprecated/gtkvolumebutton.c',
|
||||
]
|
||||
|
||||
gtk_deprecated_headers = [
|
||||
@@ -106,4 +107,5 @@ gtk_deprecated_headers = [
|
||||
'deprecated/gtktreestore.h',
|
||||
'deprecated/gtktreeview.h',
|
||||
'deprecated/gtktreeviewcolumn.h',
|
||||
'deprecated/gtkvolumebutton.h',
|
||||
]
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright 2017 Red Hat, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __G_OPEN_URI_PORTAL_H__
|
||||
|
||||
#include "gtkwindow.h"
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean g_openuri_portal_is_available (void);
|
||||
|
||||
void g_openuri_portal_open_async (GFile *file,
|
||||
gboolean open_folder,
|
||||
GtkWindow *window,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean g_openuri_portal_open_finish (GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
void g_openuri_portal_open_uri_async (const char *uri,
|
||||
GtkWindow *window,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean g_openuri_portal_open_uri_finish (GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -290,7 +290,7 @@
|
||||
#include <gtk/gtkversion.h>
|
||||
#include <gtk/gtkvideo.h>
|
||||
#include <gtk/gtkviewport.h>
|
||||
#include <gtk/gtkvolumebutton.h>
|
||||
#include <gtk/deprecated/gtkvolumebutton.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gtk/gtkwidgetpaintable.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
+10
-3
@@ -72,6 +72,8 @@ struct _GtkEditableLabel
|
||||
GtkWidget *stack;
|
||||
GtkWidget *label;
|
||||
GtkWidget *entry;
|
||||
|
||||
guint stop_editing_soon_id;
|
||||
};
|
||||
|
||||
struct _GtkEditableLabelClass
|
||||
@@ -196,10 +198,12 @@ static gboolean
|
||||
stop_editing_soon (gpointer data)
|
||||
{
|
||||
GtkEventController *controller = data;
|
||||
GtkWidget *widget = gtk_event_controller_get_widget (controller);
|
||||
GtkEditableLabel *self = GTK_EDITABLE_LABEL (gtk_event_controller_get_widget (controller));
|
||||
|
||||
if (!gtk_event_controller_focus_contains_focus (GTK_EVENT_CONTROLLER_FOCUS (controller)))
|
||||
gtk_editable_label_stop_editing (GTK_EDITABLE_LABEL (widget), TRUE);
|
||||
gtk_editable_label_stop_editing (self, TRUE);
|
||||
|
||||
self->stop_editing_soon_id = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -208,7 +212,8 @@ static void
|
||||
gtk_editable_label_focus_out (GtkEventController *controller,
|
||||
GtkEditableLabel *self)
|
||||
{
|
||||
g_timeout_add (100, stop_editing_soon, controller);
|
||||
if (self->stop_editing_soon_id == 0)
|
||||
self->stop_editing_soon_id = g_timeout_add (100, stop_editing_soon, controller);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -361,6 +366,8 @@ gtk_editable_label_dispose (GObject *object)
|
||||
self->entry = NULL;
|
||||
self->label = NULL;
|
||||
|
||||
g_clear_handle_id (&self->stop_editing_soon_id, g_source_remove);
|
||||
|
||||
G_OBJECT_CLASS (gtk_editable_label_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ send_close (FilechooserPortalData *data)
|
||||
|
||||
message = g_dbus_message_new_method_call (PORTAL_BUS_NAME,
|
||||
PORTAL_OBJECT_PATH,
|
||||
PORTAL_FILECHOOSER_INTERFACE,
|
||||
PORTAL_REQUEST_INTERFACE,
|
||||
"Close");
|
||||
g_dbus_message_set_body (message,
|
||||
g_variant_new ("(o)", data->portal_handle));
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
#include "gtkexpression.h"
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
#include "gopenuriportal.h"
|
||||
#include "gtkopenuriportal.h"
|
||||
#endif
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
+3
-3
@@ -694,7 +694,7 @@ gtk_file_dialog_set_initial_file (GtkFileDialog *self,
|
||||
GFile *folder;
|
||||
GFileInfo *info;
|
||||
|
||||
if (g_file_equal (self->initial_file, file))
|
||||
if (self->initial_file && g_file_equal (self->initial_file, file))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INITIAL_FILE]);
|
||||
@@ -707,7 +707,7 @@ gtk_file_dialog_set_initial_file (GtkFileDialog *self,
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INITIAL_FOLDER]);
|
||||
|
||||
info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, 0, NULL, NULL);
|
||||
if (g_file_info_get_edit_name (info) != NULL)
|
||||
if (info && g_file_info_get_edit_name (info) != NULL)
|
||||
{
|
||||
if (g_set_str (&self->initial_name, g_file_info_get_edit_name (info)))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INITIAL_NAME]);
|
||||
@@ -724,7 +724,7 @@ gtk_file_dialog_set_initial_file (GtkFileDialog *self,
|
||||
g_free (name);
|
||||
g_free (relative);
|
||||
}
|
||||
g_object_unref (info);
|
||||
g_clear_object (&info);
|
||||
g_object_unref (folder);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "gtkfilelauncher.h"
|
||||
|
||||
#include "gtkdialogerror.h"
|
||||
#include "gopenuriportal.h"
|
||||
#include "gtkopenuriportal.h"
|
||||
#include "deprecated/gtkshow.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
@@ -219,7 +219,7 @@ open_done (GObject *source,
|
||||
GTask *task = G_TASK (data);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_openuri_portal_open_finish (result, &error))
|
||||
if (!gtk_openuri_portal_open_finish (result, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
@@ -367,9 +367,9 @@ gtk_file_launcher_launch (GtkFileLauncher *self,
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (g_openuri_portal_is_available ())
|
||||
if (gtk_openuri_portal_is_available ())
|
||||
{
|
||||
g_openuri_portal_open_async (self->file, FALSE, parent, cancellable, open_done, task);
|
||||
gtk_openuri_portal_open_async (self->file, FALSE, parent, cancellable, open_done, task);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -461,9 +461,9 @@ gtk_file_launcher_open_containing_folder (GtkFileLauncher *self,
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (g_openuri_portal_is_available ())
|
||||
if (gtk_openuri_portal_is_available ())
|
||||
{
|
||||
g_openuri_portal_open_async (self->file, TRUE, parent, cancellable, open_done, task);
|
||||
gtk_openuri_portal_open_async (self->file, TRUE, parent, cancellable, open_done, task);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
+12
-5
@@ -32,6 +32,7 @@
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkrenderlayoutprivate.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gdk/gdkgltextureprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
@@ -144,6 +145,7 @@
|
||||
|
||||
typedef struct {
|
||||
guint id;
|
||||
GLsync sync;
|
||||
int width;
|
||||
int height;
|
||||
GdkTexture *holder;
|
||||
@@ -394,6 +396,8 @@ delete_one_texture (gpointer data)
|
||||
texture->id = 0;
|
||||
}
|
||||
|
||||
g_clear_pointer (&texture->sync, glDeleteSync);
|
||||
|
||||
g_free (texture);
|
||||
}
|
||||
|
||||
@@ -673,6 +677,7 @@ release_texture (gpointer data)
|
||||
{
|
||||
Texture *texture = data;
|
||||
texture->holder = NULL;
|
||||
g_clear_pointer (&texture->sync, glDeleteSync);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -735,11 +740,13 @@ gtk_gl_area_snapshot (GtkWidget *widget,
|
||||
priv->texture = NULL;
|
||||
priv->textures = g_list_prepend (priv->textures, texture);
|
||||
|
||||
texture->holder = gdk_gl_texture_new (priv->context,
|
||||
texture->id,
|
||||
texture->width,
|
||||
texture->height,
|
||||
release_texture, texture);
|
||||
texture->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
texture->holder = gdk_gl_texture_new_with_sync (priv->context,
|
||||
texture->id,
|
||||
texture->sync,
|
||||
texture->width,
|
||||
texture->height,
|
||||
release_texture, texture);
|
||||
|
||||
/* Our texture is rendered by OpenGL, so it is upside down,
|
||||
* compared to what GSK expects, so flip it back.
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <string.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "gopenuriportal.h"
|
||||
#include "gtkopenuriportal.h"
|
||||
#include "xdp-dbus.h"
|
||||
#include "gtkwindowprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
@@ -43,7 +43,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
static GXdpOpenURI *openuri;
|
||||
static GtkXdpOpenURI *openuri;
|
||||
|
||||
static gboolean
|
||||
init_openuri_portal (void)
|
||||
@@ -57,10 +57,10 @@ init_openuri_portal (void)
|
||||
|
||||
if (connection != NULL)
|
||||
{
|
||||
openuri = gxdp_open_uri_proxy_new_sync (connection, 0,
|
||||
PORTAL_BUS_NAME,
|
||||
PORTAL_OBJECT_PATH,
|
||||
NULL, &error);
|
||||
openuri = gtk_xdp_open_uri_proxy_new_sync (connection, 0,
|
||||
PORTAL_BUS_NAME,
|
||||
PORTAL_OBJECT_PATH,
|
||||
NULL, &error);
|
||||
if (openuri == NULL)
|
||||
{
|
||||
g_warning ("Cannot create OpenURI portal proxy: %s", error->message);
|
||||
@@ -83,7 +83,7 @@ init_openuri_portal (void)
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_openuri_portal_is_available (void)
|
||||
gtk_openuri_portal_is_available (void)
|
||||
{
|
||||
return init_openuri_portal ();
|
||||
}
|
||||
@@ -169,7 +169,7 @@ open_call_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GXdpOpenURI *portal = GXDP_OPEN_URI (source);
|
||||
GtkXdpOpenURI *portal = GTK_XDP_OPEN_URI (source);
|
||||
GTask *task = user_data;
|
||||
OpenUriData *data = g_task_get_task_data (task);
|
||||
GError *error = NULL;
|
||||
@@ -179,13 +179,13 @@ open_call_done (GObject *source,
|
||||
switch (data->call)
|
||||
{
|
||||
case OPEN_FILE:
|
||||
res = gxdp_open_uri_call_open_file_finish (portal, &path, NULL, result, &error);
|
||||
res = gtk_xdp_open_uri_call_open_file_finish (portal, &path, NULL, result, &error);
|
||||
break;
|
||||
case OPEN_FOLDER:
|
||||
res = gxdp_open_uri_call_open_directory_finish (portal, &path, NULL, result, &error);
|
||||
res = gtk_xdp_open_uri_call_open_directory_finish (portal, &path, NULL, result, &error);
|
||||
break;
|
||||
case OPEN_URI:
|
||||
res = gxdp_open_uri_call_open_uri_finish (portal, &path, result, &error);
|
||||
res = gtk_xdp_open_uri_call_open_uri_finish (portal, &path, result, &error);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -341,7 +341,7 @@ open_uri (OpenUriData *data,
|
||||
if (open_folder)
|
||||
{
|
||||
data->call = OPEN_FOLDER;
|
||||
gxdp_open_uri_call_open_directory (openuri,
|
||||
gtk_xdp_open_uri_call_open_directory (openuri,
|
||||
parent_window ? parent_window : "",
|
||||
g_variant_new ("h", fd_id),
|
||||
opts,
|
||||
@@ -353,7 +353,7 @@ open_uri (OpenUriData *data,
|
||||
else
|
||||
{
|
||||
data->call = OPEN_FILE;
|
||||
gxdp_open_uri_call_open_file (openuri,
|
||||
gtk_xdp_open_uri_call_open_file (openuri,
|
||||
parent_window ? parent_window : "",
|
||||
g_variant_new ("h", fd_id),
|
||||
opts,
|
||||
@@ -373,7 +373,7 @@ open_uri (OpenUriData *data,
|
||||
uri = g_file_get_uri (file);
|
||||
|
||||
data->call = OPEN_URI;
|
||||
gxdp_open_uri_call_open_uri (openuri,
|
||||
gtk_xdp_open_uri_call_open_uri (openuri,
|
||||
parent_window ? parent_window : "",
|
||||
uri ? uri : data->uri,
|
||||
opts,
|
||||
@@ -441,12 +441,12 @@ window_handle_exported (GtkWindow *window,
|
||||
}
|
||||
|
||||
void
|
||||
g_openuri_portal_open_async (GFile *file,
|
||||
gboolean open_folder,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
gtk_openuri_portal_open_async (GFile *file,
|
||||
gboolean open_folder,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
OpenUriData *data;
|
||||
|
||||
@@ -465,27 +465,27 @@ g_openuri_portal_open_async (GFile *file,
|
||||
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||
data->task = g_task_new (parent, cancellable, callback, user_data);
|
||||
g_task_set_check_cancellable (data->task, FALSE);
|
||||
g_task_set_source_tag (data->task, g_openuri_portal_open_async);
|
||||
g_task_set_source_tag (data->task, gtk_openuri_portal_open_async);
|
||||
|
||||
if (!parent || !gtk_window_export_handle (parent, window_handle_exported, data))
|
||||
window_handle_exported (parent, NULL, data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_openuri_portal_open_finish (GAsyncResult *result,
|
||||
GError **error)
|
||||
gtk_openuri_portal_open_finish (GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == g_openuri_portal_open_async, FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_openuri_portal_open_async, FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
void
|
||||
g_openuri_portal_open_uri_async (const char *uri,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
gtk_openuri_portal_open_uri_async (const char *uri,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
OpenUriData *data;
|
||||
|
||||
@@ -503,17 +503,17 @@ g_openuri_portal_open_uri_async (const char *uri,
|
||||
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||
data->task = g_task_new (parent, cancellable, callback, user_data);
|
||||
g_task_set_check_cancellable (data->task, FALSE);
|
||||
g_task_set_source_tag (data->task, g_openuri_portal_open_uri_async);
|
||||
g_task_set_source_tag (data->task, gtk_openuri_portal_open_uri_async);
|
||||
|
||||
if (!parent || !gtk_window_export_handle (parent, window_handle_exported, data))
|
||||
window_handle_exported (parent, NULL, data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_openuri_portal_open_uri_finish (GAsyncResult *result,
|
||||
GError **error)
|
||||
gtk_openuri_portal_open_uri_finish (GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == g_openuri_portal_open_uri_async, FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_openuri_portal_open_uri_async, FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright 2017 Red Hat, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __G_OPEN_URI_PORTAL_H__
|
||||
|
||||
#include "gtkwindow.h"
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean gtk_openuri_portal_is_available (void);
|
||||
|
||||
void gtk_openuri_portal_open_async (GFile *file,
|
||||
gboolean open_folder,
|
||||
GtkWindow *window,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean gtk_openuri_portal_open_finish (GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
void gtk_openuri_portal_open_uri_async (const char *uri,
|
||||
GtkWindow *window,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean gtk_openuri_portal_open_uri_finish (GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -36,6 +36,13 @@
|
||||
*
|
||||
* `GtkOrientable` is more flexible in that it allows the orientation to be
|
||||
* changed at runtime, allowing the widgets to “flip”.
|
||||
*
|
||||
* ## CSS nodes
|
||||
*
|
||||
* `GtkWidget` types implementing the `GtkOrientable` interface will
|
||||
* automatically acquire the `horizontal` or `vertical` CSS class depending on
|
||||
* the value of the [property@Gtk.Orientable:orientation] property.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
+41
-1
@@ -95,7 +95,8 @@ enum
|
||||
PROP_VALUE,
|
||||
PROP_SIZE,
|
||||
PROP_ADJUSTMENT,
|
||||
PROP_ICONS
|
||||
PROP_ICONS,
|
||||
PROP_ACTIVE
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@@ -256,6 +257,17 @@ gtk_scale_button_class_init (GtkScaleButtonClass *klass)
|
||||
G_TYPE_STRV,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GtkScaleButton:active: (attributes org.gtk.Property.get=gtk_scale_button_get_active)
|
||||
*
|
||||
* If the scale button should be pressed in.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ACTIVE,
|
||||
g_param_spec_boolean ("active", NULL, NULL,
|
||||
FALSE,
|
||||
GTK_PARAM_READABLE));
|
||||
|
||||
/**
|
||||
* GtkScaleButton::value-changed:
|
||||
* @button: the object which received the signal
|
||||
@@ -394,6 +406,8 @@ gtk_scale_button_toggled (GtkScaleButton *button)
|
||||
GtkScaleButtonPrivate *priv = gtk_scale_button_get_instance_private (button);
|
||||
gboolean active;
|
||||
|
||||
g_object_notify (G_OBJECT (button), "active");
|
||||
|
||||
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button));
|
||||
|
||||
if (active)
|
||||
@@ -515,6 +529,9 @@ gtk_scale_button_get_property (GObject *object,
|
||||
case PROP_ICONS:
|
||||
g_value_set_boxed (value, priv->icon_list);
|
||||
break;
|
||||
case PROP_ACTIVE:
|
||||
g_value_set_boolean (value, gtk_scale_button_get_active (button));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -768,6 +785,29 @@ gtk_scale_button_get_popup (GtkScaleButton *button)
|
||||
return priv->dock;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_scale_button_get_active: (attributes org.gtk.Method.get_property=active)
|
||||
* @button: a `GtkScaleButton`
|
||||
*
|
||||
* Queries a `GtkScaleButton` and returns its current state.
|
||||
*
|
||||
* Returns %TRUE if the scale button is pressed in and %FALSE
|
||||
* if it is raised.
|
||||
*
|
||||
* Returns: whether the button is pressed
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_scale_button_get_active (GtkScaleButton *button)
|
||||
{
|
||||
GtkScaleButtonPrivate *priv = gtk_scale_button_get_instance_private (button);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_SCALE_BUTTON (button), FALSE);
|
||||
|
||||
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scale_button_set_orientation_private (GtkScaleButton *button,
|
||||
GtkOrientation orientation)
|
||||
|
||||
@@ -96,6 +96,8 @@ GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_scale_button_get_minus_button (GtkScaleButton *button);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_scale_button_get_popup (GtkScaleButton *button);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_scale_button_get_active (GtkScaleButton *button);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkScaleButton, g_object_unref)
|
||||
|
||||
|
||||
@@ -97,8 +97,11 @@ finalize (GObject *object)
|
||||
|
||||
g_clear_object (&engine->search_query);
|
||||
g_clear_object (&engine->search_location_query);
|
||||
tracker_sparql_connection_close (engine->sparql_conn);
|
||||
g_clear_object (&engine->sparql_conn);
|
||||
if (engine->sparql_conn != NULL)
|
||||
{
|
||||
tracker_sparql_connection_close (engine->sparql_conn);
|
||||
g_clear_object (&engine->sparql_conn);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gtk_search_engine_tracker3_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -369,8 +372,8 @@ gtk_search_engine_tracker3_new (void)
|
||||
NULL, &error, NULL);
|
||||
if (!engine)
|
||||
{
|
||||
g_critical ("Could not init tracker3 search engine: %s",
|
||||
error->message);
|
||||
g_warning ("Could not init tracker3 search engine: %s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,9 @@ struct _GtkSnapshotState {
|
||||
struct {
|
||||
char *message;
|
||||
} debug;
|
||||
struct {
|
||||
GskRenderNode *mask_node;
|
||||
} mask;
|
||||
} data;
|
||||
};
|
||||
|
||||
@@ -1241,6 +1244,79 @@ gtk_snapshot_push_blend (GtkSnapshot *snapshot,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
gtk_snapshot_collect_mask_source (GtkSnapshot *snapshot,
|
||||
GtkSnapshotState *state,
|
||||
GskRenderNode **nodes,
|
||||
guint n_nodes)
|
||||
{
|
||||
GskRenderNode *source_child, *mask_child, *mask_node;
|
||||
|
||||
mask_child = gsk_render_node_ref (state->data.mask.mask_node);
|
||||
source_child = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
|
||||
|
||||
if (source_child == NULL || mask_child == NULL)
|
||||
return NULL;
|
||||
|
||||
mask_node = gsk_mask_node_new (source_child, mask_child);
|
||||
|
||||
gsk_render_node_unref (source_child);
|
||||
gsk_render_node_unref (mask_child);
|
||||
|
||||
return mask_node;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_snapshot_clear_mask_source (GtkSnapshotState *state)
|
||||
{
|
||||
g_clear_pointer (&(state->data.mask.mask_node), gsk_render_node_unref);
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
gtk_snapshot_collect_mask_mask (GtkSnapshot *snapshot,
|
||||
GtkSnapshotState *state,
|
||||
GskRenderNode **nodes,
|
||||
guint n_nodes)
|
||||
{
|
||||
GtkSnapshotState *prev_state = gtk_snapshot_get_previous_state (snapshot);
|
||||
|
||||
g_assert (prev_state->collect_func == gtk_snapshot_collect_mask_source);
|
||||
|
||||
prev_state->data.mask.mask_node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_snapshot_push_mask:
|
||||
* @snapshot: a #GtkSnapshot
|
||||
*
|
||||
* Until the first call to [method@Gtk.Snapshot.pop], the
|
||||
* mask image for the mask operation will be recorded.
|
||||
* After that call, the source image will be recorded until
|
||||
* the second call to [method@Gtk.Snapshot.pop].
|
||||
*
|
||||
* Calling this function requires 2 subsequent calls to gtk_snapshot_pop().
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_snapshot_push_mask (GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
|
||||
GtkSnapshotState *source_state;
|
||||
|
||||
source_state = gtk_snapshot_push_state (snapshot,
|
||||
current_state->transform,
|
||||
gtk_snapshot_collect_mask_source,
|
||||
gtk_snapshot_clear_mask_source);
|
||||
|
||||
gtk_snapshot_push_state (snapshot,
|
||||
source_state->transform,
|
||||
gtk_snapshot_collect_mask_mask,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
gtk_snapshot_collect_cross_fade_end (GtkSnapshot *snapshot,
|
||||
GtkSnapshotState *state,
|
||||
@@ -1918,6 +1994,10 @@ gtk_snapshot_append_cairo (GtkSnapshot *snapshot,
|
||||
* Creates a new render node drawing the @texture
|
||||
* into the given @bounds and appends it to the
|
||||
* current render node of @snapshot.
|
||||
*
|
||||
* If the texture needs to be scaled to fill @bounds,
|
||||
* linear filtering is used. See [method@Gtk.Snapshot.append_scaled_texture]
|
||||
* if you need other filtering, such as nearest-neighbour.
|
||||
*/
|
||||
void
|
||||
gtk_snapshot_append_texture (GtkSnapshot *snapshot,
|
||||
@@ -1939,6 +2019,44 @@ gtk_snapshot_append_texture (GtkSnapshot *snapshot,
|
||||
gtk_snapshot_append_node_internal (snapshot, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_snapshot_append_scaled_texture:
|
||||
* @snapshot: a `GtkSnapshot`
|
||||
* @texture: the texture to render
|
||||
* @filter: the filter to use
|
||||
* @bounds: the bounds for the new node
|
||||
*
|
||||
* Creates a new render node drawing the @texture
|
||||
* into the given @bounds and appends it to the
|
||||
* current render node of @snapshot.
|
||||
*
|
||||
* In contrast to [method@Gtk.Snapshot.append_texture],
|
||||
* this function provides control about how the filter
|
||||
* that is used when scaling.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_snapshot_append_scaled_texture (GtkSnapshot *snapshot,
|
||||
GdkTexture *texture,
|
||||
GskScalingFilter filter,
|
||||
const graphene_rect_t *bounds)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
graphene_rect_t real_bounds;
|
||||
float scale_x, scale_y, dx, dy;
|
||||
|
||||
g_return_if_fail (snapshot != NULL);
|
||||
g_return_if_fail (GDK_IS_TEXTURE (texture));
|
||||
g_return_if_fail (bounds != NULL);
|
||||
|
||||
gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
|
||||
gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
|
||||
node = gsk_texture_scale_node_new (texture, &real_bounds, filter);
|
||||
|
||||
gtk_snapshot_append_node_internal (snapshot, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_snapshot_append_color:
|
||||
* @snapshot: a `GtkSnapshot`
|
||||
|
||||
@@ -95,6 +95,9 @@ void gtk_snapshot_push_shadow (GtkSnapshot
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_snapshot_push_blend (GtkSnapshot *snapshot,
|
||||
GskBlendMode blend_mode);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_snapshot_push_mask (GtkSnapshot *snapshot);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
|
||||
double progress);
|
||||
@@ -152,6 +155,11 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gtk_snapshot_append_texture (GtkSnapshot *snapshot,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *bounds);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_snapshot_append_scaled_texture (GtkSnapshot *snapshot,
|
||||
GdkTexture *texture,
|
||||
GskScalingFilter filter,
|
||||
const graphene_rect_t *bounds);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_snapshot_append_color (GtkSnapshot *snapshot,
|
||||
const GdkRGBA *color,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "gtkurilauncher.h"
|
||||
|
||||
#include "gtkdialogerror.h"
|
||||
#include "gopenuriportal.h"
|
||||
#include "gtkopenuriportal.h"
|
||||
#include "deprecated/gtkshow.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
@@ -221,7 +221,7 @@ open_done (GObject *source,
|
||||
GTask *task = G_TASK (data);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_openuri_portal_open_uri_finish (result, &error))
|
||||
if (!gtk_openuri_portal_open_uri_finish (result, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
@@ -300,8 +300,8 @@ gtk_uri_launcher_launch (GtkUriLauncher *self,
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (g_openuri_portal_is_available ())
|
||||
g_openuri_portal_open_uri_async (self->uri, parent, cancellable, open_done, task);
|
||||
if (gtk_openuri_portal_is_available ())
|
||||
gtk_openuri_portal_open_uri_async (self->uri, parent, cancellable, open_done, task);
|
||||
else
|
||||
#endif
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
+47
-25
@@ -7442,6 +7442,7 @@ gtk_widget_real_destroy (GtkWidget *object)
|
||||
{
|
||||
GtkWidgetClass *class;
|
||||
GSList *l;
|
||||
GHashTable *auto_children;
|
||||
|
||||
#ifdef G_ENABLE_CONSISTENCY_CHECKS
|
||||
GSList *assertions = NULL;
|
||||
@@ -7490,8 +7491,52 @@ gtk_widget_real_destroy (GtkWidget *object)
|
||||
}
|
||||
#endif /* G_ENABLE_CONSISTENCY_CHECKS */
|
||||
|
||||
/* Release references to all automated children */
|
||||
g_object_set_qdata (G_OBJECT (widget), quark_auto_children, NULL);
|
||||
/* Prepare to release references to all automated children */
|
||||
auto_children = g_object_steal_qdata (G_OBJECT (widget), quark_auto_children);
|
||||
|
||||
/* Set any automatic private data pointers to NULL and release child references */
|
||||
for (class = GTK_WIDGET_GET_CLASS (widget);
|
||||
GTK_IS_WIDGET_CLASS (class);
|
||||
class = g_type_class_peek_parent (class))
|
||||
{
|
||||
GHashTable *auto_child_hash = NULL;
|
||||
|
||||
if (!class->priv->template)
|
||||
continue;
|
||||
|
||||
if (auto_children)
|
||||
{
|
||||
GType type = G_TYPE_FROM_CLASS (class);
|
||||
|
||||
g_hash_table_steal_extended (auto_children,
|
||||
GSIZE_TO_POINTER (type),
|
||||
NULL,
|
||||
(gpointer *) &auto_child_hash);
|
||||
}
|
||||
|
||||
for (l = class->priv->template->children; l; l = l->next)
|
||||
{
|
||||
AutomaticChildClass *child_class = l->data;
|
||||
|
||||
if (child_class->offset != 0)
|
||||
{
|
||||
gpointer field_p;
|
||||
|
||||
/* Nullify instance private data for internal children */
|
||||
field_p = G_STRUCT_MEMBER_P (widget, child_class->offset);
|
||||
(* (gpointer *) field_p) = NULL;
|
||||
}
|
||||
|
||||
/* Release the references in order after setting the pointer to NULL */
|
||||
if (auto_child_hash)
|
||||
g_hash_table_remove (auto_child_hash, child_class->name);
|
||||
}
|
||||
|
||||
g_clear_pointer (&auto_child_hash, g_hash_table_unref);
|
||||
}
|
||||
|
||||
/* Free the child reference hash table */
|
||||
g_clear_pointer (&auto_children, g_hash_table_unref);
|
||||
|
||||
#ifdef G_ENABLE_CONSISTENCY_CHECKS
|
||||
for (l = assertions; l; l = l->next)
|
||||
@@ -7509,29 +7554,6 @@ gtk_widget_real_destroy (GtkWidget *object)
|
||||
}
|
||||
g_slist_free (assertions);
|
||||
#endif /* G_ENABLE_CONSISTENCY_CHECKS */
|
||||
|
||||
/* Set any automatic private data pointers to NULL */
|
||||
for (class = GTK_WIDGET_GET_CLASS (widget);
|
||||
GTK_IS_WIDGET_CLASS (class);
|
||||
class = g_type_class_peek_parent (class))
|
||||
{
|
||||
if (!class->priv->template)
|
||||
continue;
|
||||
|
||||
for (l = class->priv->template->children; l; l = l->next)
|
||||
{
|
||||
AutomaticChildClass *child_class = l->data;
|
||||
|
||||
if (child_class->offset != 0)
|
||||
{
|
||||
gpointer field_p;
|
||||
|
||||
/* Nullify instance private data for internal children */
|
||||
field_p = G_STRUCT_MEMBER_P (widget, child_class->offset);
|
||||
(* (gpointer *) field_p) = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Callers of add_mnemonic_label() should disconnect on ::destroy */
|
||||
|
||||
@@ -264,6 +264,7 @@ create_list_model_for_render_node (GskRenderNode *node)
|
||||
case GSK_CAIRO_NODE:
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_TEXTURE_NODE:
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
@@ -304,6 +305,10 @@ create_list_model_for_render_node (GskRenderNode *node)
|
||||
return create_render_node_list_model ((GskRenderNode *[2]) { gsk_blend_node_get_bottom_child (node),
|
||||
gsk_blend_node_get_top_child (node) }, 2);
|
||||
|
||||
case GSK_MASK_NODE:
|
||||
return create_render_node_list_model ((GskRenderNode *[2]) { gsk_mask_node_get_source (node),
|
||||
gsk_mask_node_get_mask (node) }, 2);
|
||||
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
return create_render_node_list_model ((GskRenderNode *[2]) { gsk_cross_fade_node_get_start_child (node),
|
||||
gsk_cross_fade_node_get_end_child (node) }, 2);
|
||||
@@ -402,6 +407,8 @@ node_type_name (GskRenderNodeType type)
|
||||
return "Border";
|
||||
case GSK_TEXTURE_NODE:
|
||||
return "Texture";
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
return "Scaled Texture";
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
return "Inset Shadow";
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
@@ -422,6 +429,8 @@ node_type_name (GskRenderNodeType type)
|
||||
return "Shadow";
|
||||
case GSK_BLEND_NODE:
|
||||
return "Blend";
|
||||
case GSK_MASK_NODE:
|
||||
return "Mask";
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
return "CrossFade";
|
||||
case GSK_TEXT_NODE:
|
||||
@@ -459,6 +468,7 @@ node_name (GskRenderNode *node)
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
case GSK_SHADOW_NODE:
|
||||
case GSK_BLEND_NODE:
|
||||
case GSK_MASK_NODE:
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_BLUR_NODE:
|
||||
@@ -476,6 +486,11 @@ node_name (GskRenderNode *node)
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
return g_strdup_printf ("%dx%d Texture", gdk_texture_get_width (texture), gdk_texture_get_height (texture));
|
||||
}
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
return g_strdup_printf ("%dx%d Texture, Filter %d", gdk_texture_get_width (texture), gdk_texture_get_height (texture), gsk_texture_scale_node_get_filter (node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,6 +948,18 @@ populate_render_node_properties (GListStore *store,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
{
|
||||
GdkTexture *texture = g_object_ref (gsk_texture_scale_node_get_texture (node));
|
||||
GskScalingFilter filter = gsk_texture_scale_node_get_filter (node);
|
||||
g_list_store_append (store, object_property_new ("Texture", "", texture));
|
||||
|
||||
tmp = g_enum_to_string (GSK_TYPE_SCALING_FILTER, filter);
|
||||
add_text_row (store, "Filter", tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_COLOR_NODE:
|
||||
add_color_row (store, "Color", gsk_color_node_get_color (node));
|
||||
break;
|
||||
@@ -1112,6 +1139,9 @@ populate_render_node_properties (GListStore *store,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_MASK_NODE:
|
||||
break;
|
||||
|
||||
case GSK_BLUR_NODE:
|
||||
add_float_row (store, "Radius", gsk_blur_node_get_radius (node));
|
||||
break;
|
||||
|
||||
+2
-4
@@ -391,7 +391,6 @@ gtk_public_sources = files([
|
||||
'gtkversion.c',
|
||||
'gtkvideo.c',
|
||||
'gtkviewport.c',
|
||||
'gtkvolumebutton.c',
|
||||
'gtkwidget.c',
|
||||
'gtkwidgetfocus.c',
|
||||
'gtkwidgetpaintable.c',
|
||||
@@ -613,7 +612,6 @@ gtk_public_headers = files([
|
||||
'gtkurilauncher.h',
|
||||
'gtkvideo.h',
|
||||
'gtkviewport.h',
|
||||
'gtkvolumebutton.h',
|
||||
'gtkwidget.h',
|
||||
'gtkwidgetpaintable.h',
|
||||
'gtkwindow.h',
|
||||
@@ -758,7 +756,7 @@ if not (x11_enabled or win32_enabled)
|
||||
endif
|
||||
|
||||
if not os_win32
|
||||
gtk_sources += ['gopenuriportal.c', ]
|
||||
gtk_sources += ['gtkopenuriportal.c', ]
|
||||
endif
|
||||
|
||||
gen_gtk_gresources_xml = find_program('gen-gtk-gresources-xml.py')
|
||||
@@ -991,7 +989,7 @@ else
|
||||
xdp_dbus_generated = gnome.gdbus_codegen('xdp-dbus',
|
||||
sources : 'org.freedesktop.portal.OpenURI.xml',
|
||||
interface_prefix : 'org.freedesktop.portal.',
|
||||
namespace : 'GXdp',
|
||||
namespace : 'GtkXdp',
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
project('gtk', 'c',
|
||||
version: '4.9.3',
|
||||
version: '4.9.4',
|
||||
default_options: [
|
||||
'buildtype=debugoptimized',
|
||||
'warning_level=1',
|
||||
|
||||
@@ -41,6 +41,11 @@ option('media-gstreamer',
|
||||
|
||||
# Print backends
|
||||
|
||||
option('print-cpdb',
|
||||
type: 'feature',
|
||||
value: 'disabled',
|
||||
description : 'Build the cpdb print backend')
|
||||
|
||||
option('print-cups',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkgstsinkprivate.h"
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include "gtkgstpaintableprivate.h"
|
||||
|
||||
@@ -290,17 +291,22 @@ gtk_gst_sink_texture_from_buffer (GtkGstSink *self,
|
||||
GstGLSyncMeta *sync_meta;
|
||||
|
||||
sync_meta = gst_buffer_get_gl_sync_meta (buffer);
|
||||
if (sync_meta) {
|
||||
if (sync_meta)
|
||||
gst_gl_sync_meta_set_sync_point (sync_meta, self->gst_context);
|
||||
gst_gl_sync_meta_wait (sync_meta, self->gst_gdk_context);
|
||||
}
|
||||
|
||||
texture = gdk_gl_texture_new (self->gdk_context,
|
||||
*(guint *) frame->data[0],
|
||||
frame->info.width,
|
||||
frame->info.height,
|
||||
(GDestroyNotify) video_frame_free,
|
||||
frame);
|
||||
/* Note: using the gdk_context here is a (harmless) lie,
|
||||
* since the texture really originates in the gst_context.
|
||||
* But that is not a GdkGLContext. It is harmless, because
|
||||
* we are never using the texture in the gdk_context, so we
|
||||
* never make the (erroneous) decision to ignore the sync.
|
||||
*/
|
||||
texture = gdk_gl_texture_new_with_sync (self->gdk_context,
|
||||
*(guint *) frame->data[0],
|
||||
sync_meta ? sync_meta->data : NULL,
|
||||
frame->info.width,
|
||||
frame->info.height,
|
||||
(GDestroyNotify) video_frame_free,
|
||||
frame);
|
||||
|
||||
*pixel_aspect_ratio = ((double) frame->info.par_n) / ((double) frame->info.par_d);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtkprintbackendcpdb.h: Default implementation of GtkPrintBackend
|
||||
* for the Common Print Dialog Backends (CPDB)
|
||||
* Copyright (C) 2022, 2023 TinyTrebuchet <tinytrebuchet@protonmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GTK_PRINT_BACKEND_CPDB_H__
|
||||
#define __GTK_PRINT_BACKEND_CPDB_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkprintbackendprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_PRINT_BACKEND_CPDB (gtk_print_backend_cpdb_get_type ())
|
||||
#define GTK_PRINT_BACKEND_CPDB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND_CPDB, GtkPrintBackendCpdb))
|
||||
#define GTK_IS_PRINT_BACKEND_CPDB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND_CPDB))
|
||||
|
||||
typedef struct _GtkPrintBackendCpdbClass GtkPrintBackendCpdbClass;
|
||||
typedef struct _GtkPrintBackendCpdb GtkPrintBackendCpdb;
|
||||
|
||||
GtkPrintBackend *gtk_print_backend_cpdb_new (void);
|
||||
GType gtk_print_backend_cpdb_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_PRINT_BACKEND_CPDB_H__ */
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
|
||||
#include "gtkcupsutils.h"
|
||||
#include "gtkcupssecretsutils.h"
|
||||
#include "gtkprintbackendutils.h"
|
||||
|
||||
#include <gtkprintutils.h>
|
||||
#include "gtkprivate.h"
|
||||
@@ -6483,87 +6484,6 @@ foreach_option_get_settings (GtkPrinterOption *option,
|
||||
gtk_print_settings_set (settings, option->name, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supports_am_pm (void)
|
||||
{
|
||||
struct tm tmp_tm = { 0 };
|
||||
char time[8];
|
||||
int length;
|
||||
|
||||
length = strftime (time, sizeof (time), "%p", &tmp_tm);
|
||||
|
||||
return length != 0;
|
||||
}
|
||||
|
||||
/* Converts local time to UTC time. Local time has to be in one of these
|
||||
* formats: HH:MM:SS, HH:MM, HH:MM:SS {am, pm}, HH:MM {am, pm}, HH {am, pm},
|
||||
* {am, pm} HH:MM:SS, {am, pm} HH:MM, {am, pm} HH.
|
||||
* Returns a newly allocated string holding UTC time in HH:MM:SS format
|
||||
* or NULL.
|
||||
*/
|
||||
static char *
|
||||
localtime_to_utctime (const char *local_time)
|
||||
{
|
||||
const char *formats_0[] = {" %I : %M : %S %p ", " %p %I : %M : %S ",
|
||||
" %H : %M : %S ",
|
||||
" %I : %M %p ", " %p %I : %M ",
|
||||
" %H : %M ",
|
||||
" %I %p ", " %p %I "};
|
||||
const char *formats_1[] = {" %H : %M : %S ", " %H : %M "};
|
||||
const char *end = NULL;
|
||||
struct tm *actual_local_time;
|
||||
struct tm *actual_utc_time;
|
||||
struct tm local_print_time;
|
||||
struct tm utc_print_time;
|
||||
struct tm diff_time;
|
||||
char *utc_time = NULL;
|
||||
int i, n;
|
||||
|
||||
if (local_time == NULL || local_time[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
n = supports_am_pm () ? G_N_ELEMENTS (formats_0) : G_N_ELEMENTS (formats_1);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
local_print_time.tm_hour = 0;
|
||||
local_print_time.tm_min = 0;
|
||||
local_print_time.tm_sec = 0;
|
||||
|
||||
if (supports_am_pm ())
|
||||
end = strptime (local_time, formats_0[i], &local_print_time);
|
||||
else
|
||||
end = strptime (local_time, formats_1[i], &local_print_time);
|
||||
|
||||
if (end != NULL && end[0] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (end != NULL && end[0] == '\0')
|
||||
{
|
||||
time_t rawtime;
|
||||
time (&rawtime);
|
||||
|
||||
actual_utc_time = g_memdup2 (gmtime (&rawtime), sizeof (struct tm));
|
||||
actual_local_time = g_memdup2 (localtime (&rawtime), sizeof (struct tm));
|
||||
|
||||
diff_time.tm_hour = actual_utc_time->tm_hour - actual_local_time->tm_hour;
|
||||
diff_time.tm_min = actual_utc_time->tm_min - actual_local_time->tm_min;
|
||||
diff_time.tm_sec = actual_utc_time->tm_sec - actual_local_time->tm_sec;
|
||||
|
||||
utc_print_time.tm_hour = ((local_print_time.tm_hour + diff_time.tm_hour) + 24) % 24;
|
||||
utc_print_time.tm_min = ((local_print_time.tm_min + diff_time.tm_min) + 60) % 60;
|
||||
utc_print_time.tm_sec = ((local_print_time.tm_sec + diff_time.tm_sec) + 60) % 60;
|
||||
|
||||
utc_time = g_strdup_printf ("%02d:%02d:%02d",
|
||||
utc_print_time.tm_hour,
|
||||
utc_print_time.tm_min,
|
||||
utc_print_time.tm_sec);
|
||||
}
|
||||
|
||||
return utc_time;
|
||||
}
|
||||
|
||||
static void
|
||||
cups_printer_get_settings_from_options (GtkPrinter *printer,
|
||||
GtkPrinterOptionSet *options,
|
||||
|
||||
@@ -1,478 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtkprintbackendlpr.c: LPR implementation of GtkPrintBackend
|
||||
* for printing to lpr
|
||||
* Copyright (C) 2006, 2007 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <cairo.h>
|
||||
#include <cairo-ps.h>
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkprinterprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
#include "gtkprintbackendlpr.h"
|
||||
|
||||
typedef struct _GtkPrintBackendLprClass GtkPrintBackendLprClass;
|
||||
|
||||
#define GTK_PRINT_BACKEND_LPR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_LPR, GtkPrintBackendLprClass))
|
||||
#define GTK_IS_PRINT_BACKEND_LPR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_LPR))
|
||||
#define GTK_PRINT_BACKEND_LPR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_LPR, GtkPrintBackendLprClass))
|
||||
|
||||
#define _LPR_MAX_CHUNK_SIZE 8192
|
||||
|
||||
struct _GtkPrintBackendLprClass
|
||||
{
|
||||
GtkPrintBackendClass parent_class;
|
||||
};
|
||||
|
||||
struct _GtkPrintBackendLpr
|
||||
{
|
||||
GtkPrintBackend parent_instance;
|
||||
};
|
||||
|
||||
static GObjectClass *backend_parent_class;
|
||||
|
||||
static void lpr_printer_get_settings_from_options (GtkPrinter *printer,
|
||||
GtkPrinterOptionSet *options,
|
||||
GtkPrintSettings *settings);
|
||||
static GtkPrinterOptionSet *lpr_printer_get_options (GtkPrinter *printer,
|
||||
GtkPrintSettings *settings,
|
||||
GtkPageSetup *page_setup,
|
||||
GtkPrintCapabilities capabilities);
|
||||
static void lpr_printer_prepare_for_print (GtkPrinter *printer,
|
||||
GtkPrintJob *print_job,
|
||||
GtkPrintSettings *settings,
|
||||
GtkPageSetup *page_setup);
|
||||
static cairo_surface_t * lpr_printer_create_cairo_surface (GtkPrinter *printer,
|
||||
GtkPrintSettings *settings,
|
||||
double width,
|
||||
double height,
|
||||
GIOChannel *cache_io);
|
||||
static void gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend,
|
||||
GtkPrintJob *job,
|
||||
GIOChannel *data_io,
|
||||
GtkPrintJobCompleteFunc callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify dnotify);
|
||||
|
||||
G_DEFINE_DYNAMIC_TYPE (GtkPrintBackendLpr, gtk_print_backend_lpr, GTK_TYPE_PRINT_BACKEND)
|
||||
|
||||
G_MODULE_EXPORT
|
||||
void
|
||||
g_io_module_load (GIOModule *module)
|
||||
{
|
||||
g_type_module_use (G_TYPE_MODULE (module));
|
||||
|
||||
gtk_print_backend_lpr_register_type (G_TYPE_MODULE (module));
|
||||
|
||||
g_io_extension_point_implement (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME,
|
||||
GTK_TYPE_PRINT_BACKEND_LPR,
|
||||
"lpr",
|
||||
10);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT
|
||||
void
|
||||
g_io_module_unload (GIOModule *module)
|
||||
{
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT
|
||||
char **
|
||||
g_io_module_query (void)
|
||||
{
|
||||
char *eps[] = {
|
||||
(char *)GTK_PRINT_BACKEND_EXTENSION_POINT_NAME,
|
||||
NULL
|
||||
};
|
||||
|
||||
return g_strdupv (eps);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_print_backend_lpr_new:
|
||||
*
|
||||
* Creates a new #GtkPrintBackendLpr object. #GtkPrintBackendLpr
|
||||
* implements the #GtkPrintBackend interface with direct access to
|
||||
* the filesystem using Unix/Linux API calls
|
||||
*
|
||||
* Returns: the new #GtkPrintBackendLpr object
|
||||
**/
|
||||
GtkPrintBackend *
|
||||
gtk_print_backend_lpr_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_PRINT_BACKEND_LPR, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_print_backend_lpr_class_init (GtkPrintBackendLprClass *class)
|
||||
{
|
||||
GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
|
||||
|
||||
backend_parent_class = g_type_class_peek_parent (class);
|
||||
|
||||
backend_class->print_stream = gtk_print_backend_lpr_print_stream;
|
||||
backend_class->printer_create_cairo_surface = lpr_printer_create_cairo_surface;
|
||||
backend_class->printer_get_options = lpr_printer_get_options;
|
||||
backend_class->printer_get_settings_from_options = lpr_printer_get_settings_from_options;
|
||||
backend_class->printer_prepare_for_print = lpr_printer_prepare_for_print;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_print_backend_lpr_class_finalize (GtkPrintBackendLprClass *class)
|
||||
{
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_write (void *closure,
|
||||
const unsigned char *data,
|
||||
unsigned int length)
|
||||
{
|
||||
GIOChannel *io = (GIOChannel *)closure;
|
||||
gsize written;
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
|
||||
GTK_DEBUG (PRINTING, "LPR Backend: Writing %i byte chunk to temp file", length);
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
g_io_channel_write_chars (io, (const char *)data, length, &written, &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
GTK_DEBUG (PRINTING, "LPR Backend: Error writing to temp file, %s", error->message);
|
||||
|
||||
g_error_free (error);
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
}
|
||||
|
||||
GTK_DEBUG (PRINTING, "LPR Backend: Wrote %" G_GSIZE_FORMAT " bytes to temp file", written);
|
||||
|
||||
data += written;
|
||||
length -= written;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
lpr_printer_create_cairo_surface (GtkPrinter *printer,
|
||||
GtkPrintSettings *settings,
|
||||
double width,
|
||||
double height,
|
||||
GIOChannel *cache_io)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
|
||||
surface = cairo_ps_surface_create_for_stream (_cairo_write, cache_io, width, height);
|
||||
|
||||
cairo_surface_set_fallback_resolution (surface,
|
||||
2.0 * gtk_print_settings_get_printer_lpi (settings),
|
||||
2.0 * gtk_print_settings_get_printer_lpi (settings));
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GtkPrintBackend *backend;
|
||||
GtkPrintJobCompleteFunc callback;
|
||||
GtkPrintJob *job;
|
||||
gpointer user_data;
|
||||
GDestroyNotify dnotify;
|
||||
|
||||
GIOChannel *in;
|
||||
} _PrintStreamData;
|
||||
|
||||
static void
|
||||
lpr_print_cb (GtkPrintBackendLpr *print_backend,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
_PrintStreamData *ps = (_PrintStreamData *) user_data;
|
||||
|
||||
if (ps->in != NULL)
|
||||
g_io_channel_unref (ps->in);
|
||||
|
||||
if (ps->callback)
|
||||
ps->callback (ps->job, ps->user_data, error);
|
||||
|
||||
if (ps->dnotify)
|
||||
ps->dnotify (ps->user_data);
|
||||
|
||||
gtk_print_job_set_status (ps->job,
|
||||
error ? GTK_PRINT_STATUS_FINISHED_ABORTED
|
||||
: GTK_PRINT_STATUS_FINISHED);
|
||||
|
||||
if (ps->job)
|
||||
g_object_unref (ps->job);
|
||||
|
||||
g_free (ps);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lpr_write (GIOChannel *source,
|
||||
GIOCondition con,
|
||||
gpointer user_data)
|
||||
{
|
||||
char buf[_LPR_MAX_CHUNK_SIZE];
|
||||
gsize bytes_read;
|
||||
GError *error;
|
||||
GIOStatus status;
|
||||
_PrintStreamData *ps = (_PrintStreamData *) user_data;
|
||||
|
||||
error = NULL;
|
||||
|
||||
status =
|
||||
g_io_channel_read_chars (source,
|
||||
buf,
|
||||
_LPR_MAX_CHUNK_SIZE,
|
||||
&bytes_read,
|
||||
&error);
|
||||
|
||||
if (status != G_IO_STATUS_ERROR)
|
||||
{
|
||||
gsize bytes_written;
|
||||
|
||||
g_io_channel_write_chars (ps->in,
|
||||
buf,
|
||||
bytes_read,
|
||||
&bytes_written,
|
||||
&error);
|
||||
}
|
||||
|
||||
if (error != NULL || status == G_IO_STATUS_EOF)
|
||||
{
|
||||
lpr_print_cb (GTK_PRINT_BACKEND_LPR (ps->backend),
|
||||
error, user_data);
|
||||
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
GTK_DEBUG (PRINTING, "LPR Backend: %s", error->message);
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GTK_DEBUG (PRINTING, "LPR Backend: Writing %" G_GSIZE_FORMAT " byte chunk to lpr pipe", bytes_read);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define LPR_COMMAND "lpr"
|
||||
|
||||
static void
|
||||
gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend,
|
||||
GtkPrintJob *job,
|
||||
GIOChannel *data_io,
|
||||
GtkPrintJobCompleteFunc callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify dnotify)
|
||||
{
|
||||
GError *print_error = NULL;
|
||||
_PrintStreamData *ps;
|
||||
GtkPrintSettings *settings;
|
||||
int argc;
|
||||
int in_fd;
|
||||
char **argv = NULL;
|
||||
const char *cmd_line;
|
||||
|
||||
settings = gtk_print_job_get_settings (job);
|
||||
|
||||
cmd_line = gtk_print_settings_get (settings, "lpr-commandline");
|
||||
if (cmd_line == NULL)
|
||||
cmd_line = LPR_COMMAND;
|
||||
|
||||
ps = g_new0 (_PrintStreamData, 1);
|
||||
ps->callback = callback;
|
||||
ps->user_data = user_data;
|
||||
ps->dnotify = dnotify;
|
||||
ps->job = g_object_ref (job);
|
||||
ps->in = NULL;
|
||||
|
||||
/* spawn lpr with pipes and pipe ps file to lpr */
|
||||
if (!g_shell_parse_argv (cmd_line, &argc, &argv, &print_error))
|
||||
goto out;
|
||||
|
||||
if (!g_spawn_async_with_pipes (NULL,
|
||||
argv,
|
||||
NULL,
|
||||
G_SPAWN_SEARCH_PATH,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&in_fd,
|
||||
NULL,
|
||||
NULL,
|
||||
&print_error))
|
||||
goto out;
|
||||
|
||||
ps->in = g_io_channel_unix_new (in_fd);
|
||||
|
||||
g_io_channel_set_encoding (ps->in, NULL, &print_error);
|
||||
if (print_error != NULL)
|
||||
goto out;
|
||||
|
||||
g_io_channel_set_close_on_unref (ps->in, TRUE);
|
||||
|
||||
g_io_add_watch (data_io,
|
||||
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
|
||||
(GIOFunc) lpr_write,
|
||||
ps);
|
||||
|
||||
out:
|
||||
if (argv != NULL)
|
||||
g_strfreev (argv);
|
||||
|
||||
if (print_error != NULL)
|
||||
{
|
||||
lpr_print_cb (GTK_PRINT_BACKEND_LPR (print_backend), print_error, ps);
|
||||
g_error_free (print_error);
|
||||
|
||||
if (ps->in != NULL)
|
||||
g_io_channel_unref (ps->in);
|
||||
if (ps->job)
|
||||
g_object_unref (ps->job);
|
||||
g_free (ps);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_print_backend_lpr_init (GtkPrintBackendLpr *backend)
|
||||
{
|
||||
GtkPrinter *printer;
|
||||
|
||||
printer = g_object_new (GTK_TYPE_PRINTER,
|
||||
"name", _("Print to LPR"),
|
||||
"backend", backend,
|
||||
"is-virtual", FALSE,
|
||||
"accepts-pdf", TRUE,
|
||||
"accepts-ps", TRUE,
|
||||
NULL);
|
||||
gtk_printer_set_has_details (printer, TRUE);
|
||||
gtk_printer_set_icon_name (printer, "printer");
|
||||
gtk_printer_set_is_active (printer, TRUE);
|
||||
gtk_printer_set_is_default (printer, TRUE);
|
||||
|
||||
gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
|
||||
g_object_unref (printer);
|
||||
gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
|
||||
}
|
||||
|
||||
static GtkPrinterOptionSet *
|
||||
lpr_printer_get_options (GtkPrinter *printer,
|
||||
GtkPrintSettings *settings,
|
||||
GtkPageSetup *page_setup,
|
||||
GtkPrintCapabilities capabilities)
|
||||
{
|
||||
GtkPrinterOptionSet *set;
|
||||
GtkPrinterOption *option;
|
||||
const char *command;
|
||||
const char *n_up[] = {"1", "2", "4", "6", "9", "16" };
|
||||
|
||||
set = gtk_printer_option_set_new ();
|
||||
|
||||
option = gtk_printer_option_new ("gtk-n-up", _("Pages Per Sheet"), GTK_PRINTER_OPTION_TYPE_PICKONE);
|
||||
gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up), n_up, n_up);
|
||||
gtk_printer_option_set (option, "1");
|
||||
gtk_printer_option_set_add (set, option);
|
||||
g_object_unref (option);
|
||||
|
||||
option = gtk_printer_option_new ("gtk-main-page-custom-input", _("Command Line"), GTK_PRINTER_OPTION_TYPE_STRING);
|
||||
gtk_printer_option_set_activates_default (option, TRUE);
|
||||
option->group = g_strdup ("GtkPrintDialogExtension");
|
||||
if (settings != NULL &&
|
||||
(command = gtk_print_settings_get (settings, "lpr-commandline"))!= NULL)
|
||||
gtk_printer_option_set (option, command);
|
||||
else
|
||||
gtk_printer_option_set (option, LPR_COMMAND);
|
||||
gtk_printer_option_set_add (set, option);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
static void
|
||||
lpr_printer_get_settings_from_options (GtkPrinter *printer,
|
||||
GtkPrinterOptionSet *options,
|
||||
GtkPrintSettings *settings)
|
||||
{
|
||||
GtkPrinterOption *option;
|
||||
|
||||
option = gtk_printer_option_set_lookup (options, "gtk-main-page-custom-input");
|
||||
if (option)
|
||||
gtk_print_settings_set (settings, "lpr-commandline", option->value);
|
||||
|
||||
option = gtk_printer_option_set_lookup (options, "gtk-n-up");
|
||||
if (option)
|
||||
gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP, option->value);
|
||||
|
||||
option = gtk_printer_option_set_lookup (options, "gtk-n-up-layout");
|
||||
if (option)
|
||||
gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, option->value);
|
||||
}
|
||||
|
||||
static void
|
||||
lpr_printer_prepare_for_print (GtkPrinter *printer,
|
||||
GtkPrintJob *print_job,
|
||||
GtkPrintSettings *settings,
|
||||
GtkPageSetup *page_setup)
|
||||
{
|
||||
double scale;
|
||||
GtkPrintPages pages;
|
||||
GtkPageRange *ranges;
|
||||
int n_ranges;
|
||||
|
||||
pages = gtk_print_settings_get_print_pages (settings);
|
||||
gtk_print_job_set_pages (print_job, pages);
|
||||
|
||||
if (pages == GTK_PRINT_PAGES_RANGES)
|
||||
ranges = gtk_print_settings_get_page_ranges (settings, &n_ranges);
|
||||
else
|
||||
{
|
||||
ranges = NULL;
|
||||
n_ranges = 0;
|
||||
}
|
||||
|
||||
gtk_print_job_set_page_ranges (print_job, ranges, n_ranges);
|
||||
gtk_print_job_set_collate (print_job, gtk_print_settings_get_collate (settings));
|
||||
gtk_print_job_set_reverse (print_job, gtk_print_settings_get_reverse (settings));
|
||||
gtk_print_job_set_num_copies (print_job, gtk_print_settings_get_n_copies (settings));
|
||||
gtk_print_job_set_n_up (print_job, gtk_print_settings_get_number_up (settings));
|
||||
gtk_print_job_set_n_up_layout (print_job, gtk_print_settings_get_number_up_layout (settings));
|
||||
|
||||
scale = gtk_print_settings_get_scale (settings);
|
||||
if (scale != 100.0)
|
||||
gtk_print_job_set_scale (print_job, scale / 100.0);
|
||||
|
||||
gtk_print_job_set_page_set (print_job, gtk_print_settings_get_page_set (settings));
|
||||
gtk_print_job_set_rotate (print_job, TRUE);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtkprintbackendlpr.h: LPR implementation of GtkPrintBackend
|
||||
* for printing to lpr
|
||||
* Copyright (C) 2006, 2007 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_PRINT_BACKEND_LPR_H__
|
||||
#define __GTK_PRINT_BACKEND_LPR_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "gtkprintbackendprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_PRINT_BACKEND_LPR (gtk_print_backend_lpr_get_type ())
|
||||
#define GTK_PRINT_BACKEND_LPR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND_LPR, GtkPrintBackendLpr))
|
||||
#define GTK_IS_PRINT_BACKEND_LPR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND_LPR))
|
||||
|
||||
typedef struct _GtkPrintBackendLpr GtkPrintBackendLpr;
|
||||
|
||||
GtkPrintBackend *gtk_print_backend_lpr_new (void);
|
||||
GType gtk_print_backend_lpr_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_PRINT_BACKEND_LPR_H__ */
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtkprintbackendcups.h: Default implementation of GtkPrintBackend
|
||||
* for the Common Unix Print System (CUPS)
|
||||
* Copyright (C) 2006, 2007 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <glib.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
#include "gtkprintbackendutils.h"
|
||||
|
||||
/* Converts local time to UTC time. Local time has to be in one of these
|
||||
* formats: HH:MM:SS, HH:MM, HH:MM:SS {am, pm}, HH:MM {am, pm}, HH {am, pm},
|
||||
* {am, pm} HH:MM:SS, {am, pm} HH:MM, {am, pm} HH.
|
||||
* Returns a newly allocated string holding UTC time in HH:MM:SS format
|
||||
* or NULL.
|
||||
*/
|
||||
char *
|
||||
localtime_to_utctime (const char *local_time)
|
||||
{
|
||||
const char *formats_0[] = {" %I : %M : %S %p ", " %p %I : %M : %S ",
|
||||
" %H : %M : %S ",
|
||||
" %I : %M %p ", " %p %I : %M ",
|
||||
" %H : %M ",
|
||||
" %I %p ", " %p %I "};
|
||||
const char *formats_1[] = {" %H : %M : %S ", " %H : %M "};
|
||||
const char *end = NULL;
|
||||
struct tm *actual_local_time;
|
||||
struct tm *actual_utc_time;
|
||||
struct tm local_print_time;
|
||||
struct tm utc_print_time;
|
||||
struct tm diff_time;
|
||||
char *utc_time = NULL;
|
||||
int i, n;
|
||||
|
||||
if (local_time == NULL || local_time[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
n = supports_am_pm () ? G_N_ELEMENTS (formats_0) : G_N_ELEMENTS (formats_1);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
local_print_time.tm_hour = 0;
|
||||
local_print_time.tm_min = 0;
|
||||
local_print_time.tm_sec = 0;
|
||||
|
||||
if (supports_am_pm ())
|
||||
end = strptime (local_time, formats_0[i], &local_print_time);
|
||||
else
|
||||
end = strptime (local_time, formats_1[i], &local_print_time);
|
||||
|
||||
if (end != NULL && end[0] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (end != NULL && end[0] == '\0')
|
||||
{
|
||||
time_t rawtime;
|
||||
time (&rawtime);
|
||||
|
||||
actual_utc_time = g_memdup2 (gmtime (&rawtime), sizeof (struct tm));
|
||||
actual_local_time = g_memdup2 (localtime (&rawtime), sizeof (struct tm));
|
||||
|
||||
diff_time.tm_hour = actual_utc_time->tm_hour - actual_local_time->tm_hour;
|
||||
diff_time.tm_min = actual_utc_time->tm_min - actual_local_time->tm_min;
|
||||
diff_time.tm_sec = actual_utc_time->tm_sec - actual_local_time->tm_sec;
|
||||
|
||||
utc_print_time.tm_hour = ((local_print_time.tm_hour + diff_time.tm_hour) + 24) % 24;
|
||||
utc_print_time.tm_min = ((local_print_time.tm_min + diff_time.tm_min) + 60) % 60;
|
||||
utc_print_time.tm_sec = ((local_print_time.tm_sec + diff_time.tm_sec) + 60) % 60;
|
||||
|
||||
utc_time = g_strdup_printf ("%02d:%02d:%02d",
|
||||
utc_print_time.tm_hour,
|
||||
utc_print_time.tm_min,
|
||||
utc_print_time.tm_sec);
|
||||
}
|
||||
|
||||
return utc_time;
|
||||
}
|
||||
|
||||
gboolean
|
||||
supports_am_pm (void)
|
||||
{
|
||||
struct tm tmp_tm = { 0 };
|
||||
char time[8];
|
||||
int length;
|
||||
|
||||
length = strftime (time, sizeof (time), "%p", &tmp_tm);
|
||||
|
||||
return length != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a random string of "n" length
|
||||
*/
|
||||
char *
|
||||
random_string (int n)
|
||||
{
|
||||
const char charset[] = "abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
|
||||
char *str = g_new0 (char, n+1);
|
||||
getrandom (str, n, 0);
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
int rand = str[i] + 128;
|
||||
int idx = rand % ((int) sizeof charset);
|
||||
str[i] = charset[idx];
|
||||
}
|
||||
str[n] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtkprintbackendcups.h: Default implementation of GtkPrintBackend
|
||||
* for the Common Unix Print System (CUPS)
|
||||
* Copyright (C) 2006, 2007 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_PRINT_BACKEND_UTILS_H__
|
||||
#define __GTK_PRINT_BACKEND_UTILS_H__
|
||||
|
||||
char *random_string (int size);
|
||||
char *localtime_to_utctime (const char *local_time);
|
||||
gboolean supports_am_pm (void);
|
||||
|
||||
#endif /* __GTK_PRINT_BACKEND_UTILS_H__ */
|
||||
@@ -0,0 +1,137 @@
|
||||
/* GtkPrinterCpdb
|
||||
* Copyright (C) 2022, 2023 TinyTrebuchet <tinytrebuchet@protonmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <gtkprintercpdb.h>
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PRINTER_OBJ
|
||||
};
|
||||
|
||||
static void gtk_printer_cpdb_init (GtkPrinterCpdb *printer);
|
||||
static void gtk_printer_cpdb_class_init (GtkPrinterCpdbClass *class);
|
||||
|
||||
static GType gtk_printer_cpdb_type = 0;
|
||||
|
||||
static void gtk_printer_cpdb_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_printer_cpdb_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
void
|
||||
gtk_printer_cpdb_register_type (GTypeModule *module)
|
||||
{
|
||||
const GTypeInfo object_info =
|
||||
{
|
||||
sizeof (GtkPrinterCpdbClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) gtk_printer_cpdb_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (GtkPrinterCpdb),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) gtk_printer_cpdb_init,
|
||||
};
|
||||
|
||||
gtk_printer_cpdb_type = g_type_module_register_type (module,
|
||||
GTK_TYPE_PRINTER,
|
||||
"GtkPrinterCpdb",
|
||||
&object_info, 0);
|
||||
}
|
||||
|
||||
GType
|
||||
gtk_printer_cpdb_get_type (void)
|
||||
{
|
||||
return gtk_printer_cpdb_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_printer_cpdb_class_init (GtkPrinterCpdbClass *klass)
|
||||
{
|
||||
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = gtk_printer_cpdb_set_property;
|
||||
object_class->get_property = gtk_printer_cpdb_get_property;
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_PRINTER_OBJ,
|
||||
g_param_spec_pointer ("printer-obj",
|
||||
NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_printer_cpdb_init (GtkPrinterCpdb *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_printer_cpdb_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (object);
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PRINTER_OBJ:
|
||||
printer_cpdb->printer_obj = g_value_get_pointer (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_printer_cpdb_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (object);
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PRINTER_OBJ:
|
||||
g_value_set_pointer (value, printer_cpdb->printer_obj);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cpdb_printer_obj_t *
|
||||
gtk_printer_cpdb_get_printer_obj (GtkPrinterCpdb *cpdb_printer)
|
||||
{
|
||||
return cpdb_printer->printer_obj;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_printer_cpdb_set_printer_obj (GtkPrinterCpdb *cpdb_printer,
|
||||
cpdb_printer_obj_t *printer_obj)
|
||||
{
|
||||
cpdb_printer->printer_obj = printer_obj;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/* GtkPrinterCpdb
|
||||
* Copyright (C) 2022, 2023 TinyTrebuchet <tinytrebuchet@protonmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GTK_PRINTER_CPDB_H__
|
||||
#define __GTK_PRINTER_CPDB_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <cpdb/cpdb-frontend.h>
|
||||
#include <gtk/gtkprinterprivate.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_PRINTER_CPDB (gtk_printer_cpdb_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkPrinterCpdb, gtk_printer_cpdb, GTK, PRINTER_CPDB, GtkPrinter)
|
||||
|
||||
struct _GtkPrinterCpdb
|
||||
{
|
||||
GtkPrinter parent_instance;
|
||||
cpdb_printer_obj_t *printer_obj;
|
||||
};
|
||||
|
||||
void gtk_printer_cpdb_register_type (GTypeModule *module);
|
||||
|
||||
cpdb_printer_obj_t *gtk_printer_cpdb_get_printer_obj (GtkPrinterCpdb *cpdb_printer);
|
||||
|
||||
void gtk_printer_cpdb_set_printer_obj (GtkPrinterCpdb *cpdb_printer,
|
||||
cpdb_printer_obj_t *printer_obj);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_PRINTER_CPDB_H__ */
|
||||
@@ -10,8 +10,26 @@ printbackends_args = [
|
||||
'-DGTK_PRINT_BACKEND_ENABLE_UNSUPPORTED',
|
||||
] + common_cflags
|
||||
|
||||
cpdb_dep = dependency('cpdb-frontend', version : '>=1.0', required: get_option('print-cpdb'))
|
||||
cups_dep = dependency('cups', version : '>=2.0', required: get_option('print-cups'))
|
||||
if cups_dep.found()
|
||||
|
||||
# Use cpdb backend if present and enabled.
|
||||
# If not, use cups if present.
|
||||
|
||||
if get_option('print-cpdb').enabled() and cpdb_dep.found()
|
||||
print_backends += 'cpdb'
|
||||
shared_module('printbackend-cpdb',
|
||||
sources: [
|
||||
'gtkprintbackendcpdb.c',
|
||||
'gtkprintercpdb.c',
|
||||
'gtkprintbackendutils.c',
|
||||
],
|
||||
c_args: printbackends_args,
|
||||
dependencies: [libgtk_dep, cpdb_dep],
|
||||
install_dir: printbackends_install_dir,
|
||||
install: true,
|
||||
)
|
||||
elif cups_dep.found()
|
||||
print_backends += 'cups'
|
||||
shared_module('printbackend-cups',
|
||||
sources: [
|
||||
@@ -19,6 +37,7 @@ if cups_dep.found()
|
||||
'gtkprintercups.c',
|
||||
'gtkcupsutils.c',
|
||||
'gtkcupssecretsutils.c',
|
||||
'gtkprintbackendutils.c',
|
||||
],
|
||||
c_args: printbackends_args,
|
||||
dependencies: [libgtk_dep, cups_dep, colord_dep],
|
||||
@@ -26,17 +45,6 @@ if cups_dep.found()
|
||||
install_dir: printbackends_install_dir,
|
||||
install: true,
|
||||
)
|
||||
else
|
||||
# Automatic fall-back to the lpr backend
|
||||
print_backends += 'lpr'
|
||||
shared_module('printbackend-lpr',
|
||||
sources: 'gtkprintbackendlpr.c',
|
||||
c_args: printbackends_args,
|
||||
dependencies: libgtk_dep,
|
||||
name_suffix: module_suffix,
|
||||
install_dir: printbackends_install_dir,
|
||||
install: true,
|
||||
)
|
||||
endif
|
||||
|
||||
# The 'file' print backend cannot be disabled
|
||||
|
||||
+2
-2
@@ -104,6 +104,7 @@ gtk/deprecated/gtktreesortable.c
|
||||
gtk/deprecated/gtktreestore.c
|
||||
gtk/deprecated/gtktreeview.c
|
||||
gtk/deprecated/gtktreeviewcolumn.c
|
||||
gtk/deprecated/gtkvolumebutton.c
|
||||
gtk/gtkaboutdialog.c
|
||||
gtk/gtkaccelgroup.c
|
||||
gtk/gtkaccessible.c
|
||||
@@ -339,7 +340,6 @@ gtk/gtktreelistmodel.c
|
||||
gtk/gtktreelistrowsorter.c
|
||||
gtk/gtkvideo.c
|
||||
gtk/gtkviewport.c
|
||||
gtk/gtkvolumebutton.c
|
||||
gtk/gtkwidget.c
|
||||
gtk/gtkwidgetpaintable.c
|
||||
gtk/gtkwindow.c
|
||||
@@ -409,9 +409,9 @@ gtk/ui/gtkstatusbar.ui
|
||||
gtk/ui/gtkvolumebutton.ui
|
||||
modules/media/gtkffmediafile.c
|
||||
modules/media/gtkgstsink.c
|
||||
modules/printbackends/gtkprintbackendcpdb.c
|
||||
modules/printbackends/gtkprintbackendcups.c
|
||||
modules/printbackends/gtkprintbackendfile.c
|
||||
modules/printbackends/gtkprintbackendlpr.c
|
||||
modules/printbackends/gtkprintercups.c
|
||||
tools/encodesymbolic.c
|
||||
tools/gtk-builder-tool.c
|
||||
|
||||
+1042
-1013
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,6 @@ tests = [
|
||||
{ 'name': 'glcontext' },
|
||||
{ 'name': 'keysyms' },
|
||||
{ 'name': 'memorytexture' },
|
||||
{ 'name': 'pixbuf' },
|
||||
{ 'name': 'rectangle' },
|
||||
{ 'name': 'rgba' },
|
||||
{ 'name': 'seat' },
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
static void
|
||||
test_format (gconstpointer d)
|
||||
{
|
||||
const char *f = d;
|
||||
GSList *formats;
|
||||
gboolean found;
|
||||
|
||||
found = FALSE;
|
||||
|
||||
formats = gdk_pixbuf_get_formats ();
|
||||
|
||||
for (GSList *l = formats; l && !found; l = l->next)
|
||||
{
|
||||
GdkPixbufFormat *format = l->data;
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (format);
|
||||
|
||||
if (strcmp (name, f) == 0)
|
||||
found = TRUE;
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_slist_free (formats);
|
||||
|
||||
g_assert_true (found);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
(g_test_init) (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_data_func ("/pixbuf/format/png", "png", test_format);
|
||||
g_test_add_data_func ("/pixbuf/format/jpeg", "jpeg", test_format);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
mask {
|
||||
source: container {
|
||||
color {
|
||||
color: red;
|
||||
bounds: 0 0 50 50;
|
||||
}
|
||||
color {
|
||||
color: yellow;
|
||||
bounds: 50 0 50 50;
|
||||
}
|
||||
color {
|
||||
color: magenta;
|
||||
bounds: 0 50 100 50;
|
||||
}
|
||||
}
|
||||
mask: color {
|
||||
color: black;
|
||||
bounds: 20 20 50 50;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 253 B |
@@ -0,0 +1,7 @@
|
||||
container {
|
||||
texture-scale {
|
||||
texture: url("some-10x10-image-with-content.png");
|
||||
bounds: 0 0 100 100;
|
||||
filter: nearest;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 334 B |
@@ -54,6 +54,7 @@ compare_render_tests = [
|
||||
'inset-shadow-multiple',
|
||||
'invalid-transform',
|
||||
'issue-3615',
|
||||
'mask',
|
||||
'nested-rounded-clips',
|
||||
'opacity_clip',
|
||||
'opacity-overdraw',
|
||||
@@ -75,6 +76,7 @@ compare_render_tests = [
|
||||
'transform-in-transform',
|
||||
'transform-in-transform-in-transform',
|
||||
'rounded-clip-in-clip-3d', # not really 3d, but cairo fails it
|
||||
'scaled-texture',
|
||||
]
|
||||
|
||||
# these are too sensitive to differences in the renderers
|
||||
|
||||
@@ -2689,6 +2689,113 @@ test_expressions (void)
|
||||
}
|
||||
}
|
||||
|
||||
#define MY_GTK_BOX_TEMPLATE "\
|
||||
<interface>\n\
|
||||
<template class=\"MyGtkBox\" parent=\"GtkWidget\">\n\
|
||||
<child>\n\
|
||||
<object class=\"GtkLabel\" id=\"label\">\n\
|
||||
<property name=\"label\">First</property>\n\
|
||||
</object>\n\
|
||||
</child>\n\
|
||||
<child>\n\
|
||||
<object class=\"GtkLabel\" id=\"label2\">\n\
|
||||
<property name=\"label\">Second</property>\n\
|
||||
</object>\n\
|
||||
</child>\n\
|
||||
</template>\n\
|
||||
</interface>\n"
|
||||
|
||||
#define MY_TYPE_GTK_BOX (my_gtk_box_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MyGtkBox, my_gtk_box, MY, GTK_BOX, GtkWidget)
|
||||
|
||||
struct _MyGtkBox
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
GtkLabel *label;
|
||||
GtkLabel *label2;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MyGtkBox, my_gtk_box, GTK_TYPE_WIDGET);
|
||||
|
||||
static void
|
||||
my_gtk_box_init (MyGtkBox *grid)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (grid));
|
||||
}
|
||||
|
||||
static void
|
||||
my_gtk_box_dispose (GObject *obj)
|
||||
{
|
||||
MyGtkBox *my_gtk_box = MY_GTK_BOX (obj);
|
||||
GtkWidget *child;
|
||||
|
||||
while ((child = gtk_widget_get_first_child (GTK_WIDGET (my_gtk_box))))
|
||||
gtk_widget_unparent (child);
|
||||
|
||||
G_OBJECT_CLASS (my_gtk_box_parent_class)->dispose (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
my_gtk_box_class_init (MyGtkBoxClass *klass)
|
||||
{
|
||||
GBytes *template = g_bytes_new_static (MY_GTK_BOX_TEMPLATE, strlen (MY_GTK_BOX_TEMPLATE));
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
gtk_widget_class_set_template (widget_class, template);
|
||||
gtk_widget_class_bind_template_child (widget_class, MyGtkBox, label);
|
||||
gtk_widget_class_bind_template_child (widget_class, MyGtkBox, label2);
|
||||
|
||||
G_OBJECT_CLASS (klass)->dispose = my_gtk_box_dispose;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MyGtkBox *my_gtk_box;
|
||||
guint destroy_count;
|
||||
} BoxDestroyData;
|
||||
|
||||
static void
|
||||
my_label_destroy (GtkLabel *label, BoxDestroyData *data)
|
||||
{
|
||||
g_assert_true (MY_IS_GTK_BOX (data->my_gtk_box));
|
||||
/* Make sure the other label is null if it was disposed first */
|
||||
g_assert_true (!data->my_gtk_box->label2 || GTK_IS_LABEL (data->my_gtk_box->label2));
|
||||
data->destroy_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
my_label2_destroy (GtkLabel *label2, BoxDestroyData *data)
|
||||
{
|
||||
g_assert_true (MY_IS_GTK_BOX (data->my_gtk_box));
|
||||
/* Make sure the other label is null if it was disposed first */
|
||||
g_assert_true (!data->my_gtk_box->label || GTK_IS_LABEL (data->my_gtk_box->label));
|
||||
data->destroy_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
test_child_dispose_order (void)
|
||||
{
|
||||
BoxDestroyData data = { 0, };
|
||||
|
||||
/* make sure the type we are trying to register does not exist */
|
||||
g_assert_false (g_type_from_name ("MyGtkBox"));
|
||||
|
||||
/* create the template object */
|
||||
data.my_gtk_box = g_object_ref_sink (g_object_new (MY_TYPE_GTK_BOX, NULL));
|
||||
|
||||
/* Check everything is fine */
|
||||
g_assert_true (g_type_from_name ("MyGtkBox"));
|
||||
g_assert_true (MY_IS_GTK_BOX (data.my_gtk_box));
|
||||
g_assert_true (GTK_IS_LABEL (data.my_gtk_box->label));
|
||||
g_assert_true (GTK_IS_LABEL (data.my_gtk_box->label2));
|
||||
|
||||
/* Check if both labels are destroyed */
|
||||
g_signal_connect (data.my_gtk_box->label, "destroy", G_CALLBACK (my_label_destroy), &data);
|
||||
g_signal_connect (data.my_gtk_box->label2, "destroy", G_CALLBACK (my_label2_destroy), &data);
|
||||
g_object_unref (data.my_gtk_box);
|
||||
g_assert_cmpuint (data.destroy_count, ==, 2);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -2736,6 +2843,7 @@ main (int argc, char **argv)
|
||||
g_test_add_func ("/Builder/Shortcuts", test_shortcuts);
|
||||
g_test_add_func ("/Builder/Transforms", test_transforms);
|
||||
g_test_add_func ("/Builder/Expressions", test_expressions);
|
||||
g_test_add_func ("/Builder/Child Dispose Order", test_child_dispose_order);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user