Compare commits
25 Commits
wip/cherge
...
ci-rebuild
Author | SHA1 | Date | |
---|---|---|---|
|
79b30bdf0a | ||
|
b832b3fd35 | ||
|
c0391ce193 | ||
|
05d36b2ba4 | ||
|
a904292bfb | ||
|
65cf59408b | ||
|
b269a4712a | ||
|
ebd74e112d | ||
|
3c39c5259e | ||
|
f5a6d93939 | ||
|
30dddf2412 | ||
|
b43950d0f7 | ||
|
6e5a183c98 | ||
|
d224110b48 | ||
|
8f356c2e8c | ||
|
139ed2c900 | ||
|
32e21d5402 | ||
|
fb3d8b8523 | ||
|
380523b41b | ||
|
2fda256bb0 | ||
|
c71a66b6f6 | ||
|
cb92778478 | ||
|
ab67936a64 | ||
|
0ae2c1a8a7 | ||
|
575bd64698 |
@@ -26,7 +26,7 @@ variables:
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true -Dintrospection=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v49"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v50"
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
@@ -422,7 +422,7 @@ asan-build:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- CC=clang meson setup
|
||||
--buildtype=debugoptimized
|
||||
-Db_sanitize=address
|
||||
-Db_sanitize=address,undefined
|
||||
-Db_lundef=false
|
||||
-Dbuild-demos=false
|
||||
-Dbuild-tests=false
|
||||
|
Binary file not shown.
@@ -2,8 +2,6 @@ FROM fedora:39
|
||||
|
||||
RUN dnf -y install \
|
||||
adwaita-icon-theme \
|
||||
atk-devel \
|
||||
at-spi2-atk-devel \
|
||||
avahi-gobject-devel \
|
||||
cairo-devel \
|
||||
cairo-gobject-devel \
|
||||
@@ -18,7 +16,6 @@ RUN dnf -y install \
|
||||
dejavu-sans-mono-fonts \
|
||||
desktop-file-utils \
|
||||
diffutils \
|
||||
docbook-style-xsl \
|
||||
elfutils-libelf-devel \
|
||||
expat-devel \
|
||||
fribidi-devel \
|
||||
|
@@ -11,7 +11,7 @@ multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:detect_leaks=0:allocator_may_return_null=1
|
||||
export G_SLICE=always-malloc
|
||||
export UBSAN_OPTIONS=silence_unsigned_overflow=1
|
||||
|
||||
case "${setup}" in
|
||||
x11*)
|
||||
|
@@ -184,6 +184,12 @@ create_cogs (void)
|
||||
return picture;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_cogs (GtkFishbowl *fb)
|
||||
{
|
||||
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (gtk_widget_get_native (GTK_WIDGET (fb))));
|
||||
}
|
||||
|
||||
static void
|
||||
mapped (GtkWidget *w)
|
||||
{
|
||||
@@ -218,36 +224,41 @@ create_graph (void)
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
GtkWidget * (*create_func) (void);
|
||||
GtkWidget * (* create_func) (void);
|
||||
gboolean (* check) (GtkFishbowl *fb);
|
||||
} widget_types[] = {
|
||||
{ "Icon", create_icon },
|
||||
{ "Button", create_button },
|
||||
{ "Blurbutton", create_blurred_button },
|
||||
{ "Fontbutton", create_font_button },
|
||||
{ "Levelbar", create_level_bar },
|
||||
{ "Label", create_label },
|
||||
{ "Spinner", create_spinner },
|
||||
{ "Spinbutton", create_spinbutton },
|
||||
{ "Video", create_video },
|
||||
{ "Gears", create_gears },
|
||||
{ "Switch", create_switch },
|
||||
{ "Menubutton", create_menu_button },
|
||||
{ "Shader", create_cogs },
|
||||
{ "Tiger", create_tiger },
|
||||
{ "Graph", create_graph },
|
||||
{ "Icon", create_icon, NULL },
|
||||
{ "Button", create_button, NULL },
|
||||
{ "Blurbutton", create_blurred_button, NULL },
|
||||
{ "Fontbutton", create_font_button, NULL },
|
||||
{ "Levelbar", create_level_bar, NULL },
|
||||
{ "Label", create_label, NULL },
|
||||
{ "Spinner", create_spinner, NULL },
|
||||
{ "Spinbutton", create_spinbutton, NULL },
|
||||
{ "Video", create_video, NULL },
|
||||
{ "Gears", create_gears, NULL },
|
||||
{ "Switch", create_switch, NULL },
|
||||
{ "Menubutton", create_menu_button, NULL },
|
||||
{ "Shader", create_cogs, check_cogs },
|
||||
{ "Tiger", create_tiger, NULL },
|
||||
{ "Graph", create_graph, NULL },
|
||||
};
|
||||
|
||||
static int selected_widget_type = -1;
|
||||
static const int N_WIDGET_TYPES = G_N_ELEMENTS (widget_types);
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
set_widget_type (GtkFishbowl *fishbowl,
|
||||
int widget_type_index)
|
||||
{
|
||||
GtkWidget *window;
|
||||
|
||||
if (widget_type_index == selected_widget_type)
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
if (widget_types[widget_type_index].check != NULL &&
|
||||
!widget_types[widget_type_index].check (fishbowl))
|
||||
return FALSE;
|
||||
|
||||
selected_widget_type = widget_type_index;
|
||||
|
||||
@@ -257,6 +268,8 @@ set_widget_type (GtkFishbowl *fishbowl,
|
||||
window = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (fishbowl)));
|
||||
gtk_window_set_title (GTK_WINDOW (window),
|
||||
widget_types[selected_widget_type].name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
@@ -264,14 +277,17 @@ fishbowl_next_button_clicked_cb (GtkButton *source,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFishbowl *fishbowl = user_data;
|
||||
int new_index;
|
||||
int new_index = selected_widget_type;
|
||||
|
||||
if (selected_widget_type + 1 >= N_WIDGET_TYPES)
|
||||
new_index = 0;
|
||||
else
|
||||
new_index = selected_widget_type + 1;
|
||||
do
|
||||
{
|
||||
if (new_index + 1 >= N_WIDGET_TYPES)
|
||||
new_index = 0;
|
||||
else
|
||||
new_index = new_index + 1;
|
||||
|
||||
set_widget_type (fishbowl, new_index);
|
||||
}
|
||||
while (!set_widget_type (fishbowl, new_index));
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
@@ -279,14 +295,18 @@ fishbowl_prev_button_clicked_cb (GtkButton *source,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFishbowl *fishbowl = user_data;
|
||||
int new_index;
|
||||
int new_index = selected_widget_type;
|
||||
|
||||
if (selected_widget_type - 1 < 0)
|
||||
new_index = N_WIDGET_TYPES - 1;
|
||||
else
|
||||
new_index = selected_widget_type - 1;
|
||||
do
|
||||
{
|
||||
if (new_index - 1 < 0)
|
||||
new_index = N_WIDGET_TYPES - 1;
|
||||
else
|
||||
new_index = new_index - 1;
|
||||
|
||||
set_widget_type (fishbowl, new_index);
|
||||
}
|
||||
|
||||
while (!set_widget_type (fishbowl, new_index));
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
|
@@ -827,13 +827,25 @@ demo_search_changed_cb (GtkSearchEntry *entry,
|
||||
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demo_can_run (GtkWidget *window,
|
||||
const char *name)
|
||||
{
|
||||
if (name != NULL && strcmp (name, "gltransition") == 0)
|
||||
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (GTK_NATIVE (window)));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_demo_model (void)
|
||||
create_demo_model (GtkWidget *window)
|
||||
{
|
||||
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
|
||||
DemoData *demo = gtk_demos;
|
||||
GtkDemo *d;
|
||||
|
||||
gtk_widget_realize (window);
|
||||
|
||||
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
d->name = "main";
|
||||
d->title = "GTK Demo";
|
||||
@@ -845,16 +857,20 @@ create_demo_model (void)
|
||||
|
||||
while (demo->title)
|
||||
{
|
||||
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
DemoData *children = demo->children;
|
||||
DemoData *children = demo->children;
|
||||
|
||||
d->name = demo->name;
|
||||
d->title = demo->title;
|
||||
d->keywords = demo->keywords;
|
||||
d->filename = demo->filename;
|
||||
d->func = demo->func;
|
||||
if (demo_can_run (window, demo->name))
|
||||
{
|
||||
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
|
||||
g_list_store_append (store, d);
|
||||
d->name = demo->name;
|
||||
d->title = demo->title;
|
||||
d->keywords = demo->keywords;
|
||||
d->filename = demo->filename;
|
||||
d->func = demo->func;
|
||||
|
||||
g_list_store_append (store, d);
|
||||
}
|
||||
|
||||
if (children)
|
||||
{
|
||||
@@ -862,15 +878,19 @@ create_demo_model (void)
|
||||
|
||||
while (children->title)
|
||||
{
|
||||
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
if (demo_can_run (window, children->name))
|
||||
{
|
||||
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
|
||||
child->name = children->name;
|
||||
child->title = children->title;
|
||||
child->keywords = children->keywords;
|
||||
child->filename = children->filename;
|
||||
child->func = children->func;
|
||||
child->name = children->name;
|
||||
child->title = children->title;
|
||||
child->keywords = children->keywords;
|
||||
child->filename = children->filename;
|
||||
child->func = children->func;
|
||||
|
||||
g_list_store_append (G_LIST_STORE (d->children_model), child);
|
||||
}
|
||||
|
||||
g_list_store_append (G_LIST_STORE (d->children_model), child);
|
||||
children++;
|
||||
}
|
||||
}
|
||||
@@ -936,7 +956,7 @@ activate (GApplication *app)
|
||||
search_bar = GTK_WIDGET (gtk_builder_get_object (builder, "searchbar"));
|
||||
g_signal_connect (search_bar, "notify::search-mode-enabled", G_CALLBACK (clear_search), NULL);
|
||||
|
||||
listmodel = create_demo_model ();
|
||||
listmodel = create_demo_model (window);
|
||||
treemodel = gtk_tree_list_model_new (G_LIST_MODEL (listmodel),
|
||||
FALSE,
|
||||
TRUE,
|
||||
|
@@ -290,7 +290,7 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
EGLDisplay egl_display = gdk_display_get_egl_display (display);
|
||||
GdkGLContext *share = gdk_display_get_gl_context (display);
|
||||
GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share);
|
||||
GdkGLContextPrivate *share_priv = share ? gdk_gl_context_get_instance_private (share) : NULL;
|
||||
EGLConfig egl_config;
|
||||
EGLContext ctx;
|
||||
EGLint context_attribs[N_EGL_ATTRS], i = 0, flags = 0;
|
||||
|
@@ -20,6 +20,7 @@ struct _GskGLFrame
|
||||
|
||||
GLuint globals_buffer_id;
|
||||
guint next_texture_slot;
|
||||
GLsync sync;
|
||||
|
||||
GHashTable *vaos;
|
||||
};
|
||||
@@ -34,7 +35,23 @@ G_DEFINE_TYPE (GskGLFrame, gsk_gl_frame, GSK_TYPE_GPU_FRAME)
|
||||
static gboolean
|
||||
gsk_gl_frame_is_busy (GskGpuFrame *frame)
|
||||
{
|
||||
return FALSE;
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
|
||||
if (!self->sync)
|
||||
return FALSE;
|
||||
|
||||
return glClientWaitSync (self->sync, 0, 0) == GL_TIMEOUT_EXPIRED;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_wait (GskGpuFrame *frame)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
|
||||
if (!self->sync)
|
||||
return;
|
||||
|
||||
glClientWaitSync (self->sync, 0, G_MAXINT64);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -50,6 +67,12 @@ gsk_gl_frame_cleanup (GskGpuFrame *frame)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
|
||||
if (self->sync)
|
||||
{
|
||||
glClientWaitSync (self->sync, 0, -1);
|
||||
glDeleteSync (self->sync);
|
||||
}
|
||||
|
||||
self->next_texture_slot = 0;
|
||||
|
||||
GSK_GPU_FRAME_CLASS (gsk_gl_frame_parent_class)->cleanup (frame);
|
||||
@@ -160,6 +183,8 @@ gsk_gl_frame_submit (GskGpuFrame *frame,
|
||||
{
|
||||
op = gsk_gpu_op_gl_command (op, frame, &state);
|
||||
}
|
||||
|
||||
self->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -180,6 +205,7 @@ gsk_gl_frame_class_init (GskGLFrameClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gpu_frame_class->is_busy = gsk_gl_frame_is_busy;
|
||||
gpu_frame_class->wait = gsk_gl_frame_wait;
|
||||
gpu_frame_class->setup = gsk_gl_frame_setup;
|
||||
gpu_frame_class->cleanup = gsk_gl_frame_cleanup;
|
||||
gpu_frame_class->upload_texture = gsk_gl_frame_upload_texture;
|
||||
|
@@ -505,6 +505,12 @@ gsk_gpu_frame_is_busy (GskGpuFrame *self)
|
||||
return GSK_GPU_FRAME_GET_CLASS (self)->is_busy (self);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_frame_wait (GskGpuFrame *self)
|
||||
{
|
||||
GSK_GPU_FRAME_GET_CLASS (self)->wait (self);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_texture (gpointer user_data,
|
||||
GdkTexture *texture)
|
||||
|
@@ -24,6 +24,7 @@ struct _GskGpuFrameClass
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* is_busy) (GskGpuFrame *self);
|
||||
void (* wait) (GskGpuFrame *self);
|
||||
void (* setup) (GskGpuFrame *self);
|
||||
void (* cleanup) (GskGpuFrame *self);
|
||||
GskGpuImage * (* upload_texture) (GskGpuFrame *self,
|
||||
@@ -69,6 +70,7 @@ GskGpuBuffer * gsk_gpu_frame_write_storage_buffer (GskGpuF
|
||||
gsize *out_offset);
|
||||
|
||||
gboolean gsk_gpu_frame_is_busy (GskGpuFrame *self);
|
||||
void gsk_gpu_frame_wait (GskGpuFrame *self);
|
||||
|
||||
void gsk_gpu_frame_render (GskGpuFrame *self,
|
||||
gint64 timestamp,
|
||||
|
@@ -3000,8 +3000,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
guint i, num_glyphs;
|
||||
float scale, inv_scale;
|
||||
GdkRGBA color;
|
||||
gboolean glyph_align;
|
||||
gboolean hinting;
|
||||
float align_scale_x, align_scale_y;
|
||||
float inv_align_scale_x, inv_align_scale_y;
|
||||
unsigned int flags_mask;
|
||||
GskGpuImage *last_image;
|
||||
guint32 descriptor;
|
||||
const float inv_pango_scale = 1.f / PANGO_SCALE;
|
||||
|
||||
if (self->opacity < 1.0 &&
|
||||
gsk_text_node_has_color_glyphs (node))
|
||||
@@ -3024,45 +3028,38 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
||||
inv_scale = 1.f / scale;
|
||||
|
||||
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
|
||||
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
|
||||
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
|
||||
{
|
||||
align_scale_x = scale * 4;
|
||||
align_scale_y = scale;
|
||||
flags_mask = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
align_scale_x = align_scale_y = scale * 4;
|
||||
flags_mask = 15;
|
||||
}
|
||||
|
||||
inv_align_scale_x = 1 / align_scale_x;
|
||||
inv_align_scale_y = 1 / align_scale_y;
|
||||
|
||||
last_image = NULL;
|
||||
descriptor = 0;
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
graphene_rect_t glyph_bounds, glyph_tex_rect;
|
||||
graphene_point_t glyph_offset, glyph_origin;
|
||||
guint32 descriptor;
|
||||
GskGpuGlyphLookupFlags flags;
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
|
||||
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
|
||||
|
||||
if (hinting && glyph_align)
|
||||
{
|
||||
/* Force glyph_origin.y to be device pixel aligned.
|
||||
* The hinter expects that.
|
||||
*/
|
||||
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||
flags = ((int) glyph_origin.x & 3);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||
}
|
||||
else if (glyph_align)
|
||||
{
|
||||
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||
glyph_origin.y = floor (glyph_origin.y * scale * 4 + .5);
|
||||
flags = ((int) glyph_origin.x & 3) |
|
||||
(((int) glyph_origin.y & 3) << 2);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph_origin.x = floor (glyph_origin.x * scale + .5) * inv_scale;
|
||||
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||
flags = 0;
|
||||
}
|
||||
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
|
||||
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
|
||||
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
|
||||
glyph_origin.x *= inv_align_scale_x;
|
||||
glyph_origin.y *= inv_align_scale_y;
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
@@ -3084,7 +3081,11 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||
|
||||
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
if (image != last_image)
|
||||
{
|
||||
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
last_image = image;
|
||||
}
|
||||
|
||||
if (glyphs[i].attr.is_color)
|
||||
gsk_gpu_texture_op (self->frame,
|
||||
@@ -3104,7 +3105,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
&glyph_tex_rect,
|
||||
&color);
|
||||
|
||||
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
||||
offset.x += glyphs[i].geometry.width * inv_pango_scale;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3121,8 +3122,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
guint32 tex_id;
|
||||
GskGpuImage *last_image;
|
||||
graphene_point_t offset;
|
||||
gboolean glyph_align;
|
||||
gboolean hinting;
|
||||
float align_scale_x, align_scale_y;
|
||||
float inv_align_scale_x, inv_align_scale_y;
|
||||
unsigned int flags_mask;
|
||||
const float inv_pango_scale = 1.f / PANGO_SCALE;
|
||||
|
||||
if (gsk_text_node_has_color_glyphs (node))
|
||||
return FALSE;
|
||||
@@ -3142,8 +3145,20 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
|
||||
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
|
||||
|
||||
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
|
||||
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
|
||||
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
|
||||
{
|
||||
align_scale_x = scale * 4;
|
||||
align_scale_y = scale;
|
||||
flags_mask = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
align_scale_x = align_scale_y = scale * 4;
|
||||
flags_mask = 15;
|
||||
}
|
||||
|
||||
inv_align_scale_x = 1 / align_scale_x;
|
||||
inv_align_scale_y = 1 / align_scale_y;
|
||||
|
||||
last_image = NULL;
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
@@ -3153,34 +3168,14 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
graphene_point_t glyph_offset, glyph_origin;
|
||||
GskGpuGlyphLookupFlags flags;
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
|
||||
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
|
||||
|
||||
if (hinting && glyph_align)
|
||||
{
|
||||
/* Force glyph_origin.y to be device pixel aligned.
|
||||
* The hinter expects that.
|
||||
*/
|
||||
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
||||
flags = ((int) glyph_origin.x & 3);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
|
||||
}
|
||||
else if (glyph_align)
|
||||
{
|
||||
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
||||
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
|
||||
flags = ((int) glyph_origin.x & 3) |
|
||||
(((int) glyph_origin.y & 3) << 2);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph_origin.x = roundf (glyph_origin.x * scale) * inv_scale;
|
||||
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
|
||||
flags = 0;
|
||||
}
|
||||
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
|
||||
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
|
||||
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
|
||||
glyph_origin.x *= inv_align_scale_x;
|
||||
glyph_origin.y *= inv_align_scale_y;
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
@@ -3220,7 +3215,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
),
|
||||
&glyph_origin);
|
||||
|
||||
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
||||
offset.x += glyphs[i].geometry.width * inv_pango_scale;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@@ -30,7 +30,6 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
|
||||
{ "blit", GSK_GPU_OPTIMIZE_BLIT, "Use shaders instead of vkCmdBlit()/glBlitFramebuffer()" },
|
||||
{ "gradients", GSK_GPU_OPTIMIZE_GRADIENTS, "Don't supersample gradients" },
|
||||
{ "mipmap", GSK_GPU_OPTIMIZE_MIPMAP, "Avoid creating mipmaps" },
|
||||
{ "glyph-align", GSK_GPU_OPTIMIZE_GLYPH_ALIGN, "Never align glyphs to the subpixel grid" },
|
||||
|
||||
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
|
||||
};
|
||||
@@ -167,24 +166,36 @@ static GskGpuFrame *
|
||||
gsk_gpu_renderer_get_frame (GskGpuRenderer *self)
|
||||
{
|
||||
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
|
||||
GskGpuFrame *earliest_frame = NULL;
|
||||
gint64 earliest_time = G_MAXINT64;
|
||||
guint i;
|
||||
|
||||
while (TRUE)
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
if (priv->frames[i] == NULL)
|
||||
{
|
||||
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
|
||||
return priv->frames[i];
|
||||
}
|
||||
gint64 timestamp;
|
||||
|
||||
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
return priv->frames[i];
|
||||
if (priv->frames[i] == NULL)
|
||||
{
|
||||
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
|
||||
return priv->frames[i];
|
||||
}
|
||||
|
||||
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, GSK_GPU_MAX_FRAMES);
|
||||
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
return priv->frames[i];
|
||||
|
||||
timestamp = gsk_gpu_frame_get_timestamp (priv->frames[i]);
|
||||
if (timestamp < earliest_time)
|
||||
{
|
||||
earliest_time = timestamp;
|
||||
earliest_frame = priv->frames[i];
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (earliest_frame);
|
||||
|
||||
gsk_gpu_frame_wait (earliest_frame);
|
||||
|
||||
return earliest_frame;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -218,31 +229,17 @@ gsk_gpu_renderer_unrealize (GskRenderer *renderer)
|
||||
{
|
||||
GskGpuRenderer *self = GSK_GPU_RENDERER (renderer);
|
||||
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
|
||||
gsize i, j;
|
||||
gsize i;
|
||||
|
||||
gsk_gpu_renderer_make_current (self);
|
||||
|
||||
while (TRUE)
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
for (i = 0, j = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
if (priv->frames[i] == NULL)
|
||||
break;
|
||||
if (gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
{
|
||||
if (i > j)
|
||||
{
|
||||
priv->frames[j] = priv->frames[i];
|
||||
priv->frames[i] = NULL;
|
||||
}
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
g_clear_object (&priv->frames[i]);
|
||||
}
|
||||
if (j == 0)
|
||||
if (priv->frames[i] == NULL)
|
||||
break;
|
||||
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, j);
|
||||
if (gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
gsk_gpu_frame_wait (priv->frames[i]);
|
||||
g_clear_object (&priv->frames[i]);
|
||||
}
|
||||
|
||||
g_clear_object (&priv->context);
|
||||
|
@@ -35,9 +35,6 @@ struct _GskGpuRendererClass
|
||||
|
||||
void (* make_current) (GskGpuRenderer *self);
|
||||
GskGpuImage * (* get_backbuffer) (GskGpuRenderer *self);
|
||||
void (* wait) (GskGpuRenderer *self,
|
||||
GskGpuFrame **frame,
|
||||
gsize n_frames);
|
||||
|
||||
double (* get_scale) (GskGpuRenderer *self);
|
||||
GdkDmabufFormats * (* get_dmabuf_formats) (GskGpuRenderer *self);
|
||||
|
@@ -118,8 +118,7 @@ typedef enum {
|
||||
GSK_GPU_OPTIMIZE_BLIT = 1 << 3,
|
||||
GSK_GPU_OPTIMIZE_GRADIENTS = 1 << 4,
|
||||
GSK_GPU_OPTIMIZE_MIPMAP = 1 << 5,
|
||||
GSK_GPU_OPTIMIZE_GLYPH_ALIGN = 1 << 6,
|
||||
/* These require hardware support */
|
||||
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 7,
|
||||
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 6,
|
||||
} GskGpuOptimizations;
|
||||
|
||||
|
@@ -119,13 +119,6 @@ gsk_ngl_renderer_get_backbuffer (GskGpuRenderer *renderer)
|
||||
return self->backbuffer;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_ngl_renderer_wait (GskGpuRenderer *self,
|
||||
GskGpuFrame **frame,
|
||||
gsize n_frames)
|
||||
{
|
||||
}
|
||||
|
||||
static double
|
||||
gsk_ngl_renderer_get_scale (GskGpuRenderer *self)
|
||||
{
|
||||
@@ -164,7 +157,6 @@ gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
|
||||
gpu_renderer_class->create_context = gsk_ngl_renderer_create_context;
|
||||
gpu_renderer_class->make_current = gsk_ngl_renderer_make_current;
|
||||
gpu_renderer_class->get_backbuffer = gsk_ngl_renderer_get_backbuffer;
|
||||
gpu_renderer_class->wait = gsk_ngl_renderer_wait;
|
||||
gpu_renderer_class->get_scale = gsk_ngl_renderer_get_scale;
|
||||
gpu_renderer_class->get_dmabuf_formats = gsk_ngl_renderer_get_dmabuf_formats;
|
||||
|
||||
|
@@ -74,6 +74,21 @@ gsk_vulkan_frame_is_busy (GskGpuFrame *frame)
|
||||
return vkGetFenceStatus (device, self->vk_fence) == VK_NOT_READY;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_frame_wait (GskGpuFrame *frame)
|
||||
{
|
||||
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
|
||||
VkDevice vk_device;
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)));
|
||||
|
||||
GSK_VK_CHECK (vkWaitForFences, vk_device,
|
||||
1,
|
||||
&self->vk_fence,
|
||||
VK_FALSE,
|
||||
INT64_MAX);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_frame_setup (GskGpuFrame *frame)
|
||||
{
|
||||
@@ -387,6 +402,7 @@ gsk_vulkan_frame_class_init (GskVulkanFrameClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gpu_frame_class->is_busy = gsk_vulkan_frame_is_busy;
|
||||
gpu_frame_class->wait = gsk_vulkan_frame_wait;
|
||||
gpu_frame_class->setup = gsk_vulkan_frame_setup;
|
||||
gpu_frame_class->cleanup = gsk_vulkan_frame_cleanup;
|
||||
gpu_frame_class->upload_texture = gsk_vulkan_frame_upload_texture;
|
||||
|
@@ -129,31 +129,6 @@ gsk_vulkan_renderer_get_backbuffer (GskGpuRenderer *renderer)
|
||||
return self->targets[gdk_vulkan_context_get_draw_index (context)];
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_renderer_wait (GskGpuRenderer *renderer,
|
||||
GskGpuFrame **frames,
|
||||
gsize n_frames)
|
||||
{
|
||||
VkFence *fences;
|
||||
VkDevice vk_device;
|
||||
gsize i;
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_renderer_get_device (renderer)));
|
||||
|
||||
fences = g_alloca (sizeof (VkFence) * n_frames);
|
||||
|
||||
for (i = 0; i < n_frames; i++)
|
||||
{
|
||||
fences[i] = gsk_vulkan_frame_get_vk_fence (GSK_VULKAN_FRAME (frames[i]));
|
||||
}
|
||||
|
||||
GSK_VK_CHECK (vkWaitForFences, vk_device,
|
||||
n_frames,
|
||||
fences,
|
||||
VK_FALSE,
|
||||
INT64_MAX);
|
||||
}
|
||||
|
||||
static GdkDmabufFormats *
|
||||
gsk_vulkan_renderer_get_dmabuf_formats (GskGpuRenderer *renderer)
|
||||
{
|
||||
@@ -189,7 +164,6 @@ gsk_vulkan_renderer_class_init (GskVulkanRendererClass *klass)
|
||||
gpu_renderer_class->create_context = gsk_vulkan_renderer_create_context;
|
||||
gpu_renderer_class->make_current = gsk_vulkan_renderer_make_current;
|
||||
gpu_renderer_class->get_backbuffer = gsk_vulkan_renderer_get_backbuffer;
|
||||
gpu_renderer_class->wait = gsk_vulkan_renderer_wait;
|
||||
gpu_renderer_class->get_dmabuf_formats = gsk_vulkan_renderer_get_dmabuf_formats;
|
||||
|
||||
renderer_class->unrealize = gsk_vulkan_renderer_unrealize;
|
||||
|
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
static inline void G_GNUC_PURE
|
||||
gsk_point_interpolate (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2,
|
||||
float t,
|
||||
graphene_point_t *p)
|
||||
{
|
||||
p->x = p1->x * (1 - t) + p2->x * t;
|
||||
p->Y = p1->y * (1 - t) + p2->y * t;
|
||||
}
|
||||
|
||||
static inline float G_GNUC_PURE
|
||||
gsk_point_distance (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2)
|
||||
{
|
||||
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
|
||||
}
|
@@ -8754,11 +8754,11 @@ gtk_text_view_retrieve_surrounding_handler (GtkIMContext *context,
|
||||
gboolean flip;
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (text_view->priv->buffer, &start,
|
||||
gtk_text_buffer_get_insert (text_view->priv->buffer));
|
||||
gtk_text_buffer_get_iter_at_mark (text_view->priv->buffer, &end,
|
||||
gtk_text_buffer_get_selection_bound (text_view->priv->buffer));
|
||||
gtk_text_buffer_get_iter_at_mark (text_view->priv->buffer, &end,
|
||||
gtk_text_buffer_get_insert (text_view->priv->buffer));
|
||||
|
||||
flip = gtk_text_iter_compare (&start, &end) < 0;
|
||||
flip = gtk_text_iter_compare (&start, &end) > 0;
|
||||
|
||||
gtk_text_iter_order (&start, &end);
|
||||
|
||||
@@ -8784,13 +8784,13 @@ gtk_text_view_retrieve_surrounding_handler (GtkIMContext *context,
|
||||
|
||||
if (flip)
|
||||
{
|
||||
anchor_pos = strlen (pre);
|
||||
cursor_pos = anchor_pos + strlen (sel);
|
||||
cursor_pos = strlen (pre);
|
||||
anchor_pos = cursor_pos + strlen (sel);
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor_pos = strlen (pre);
|
||||
anchor_pos = cursor_pos + strlen (sel);
|
||||
anchor_pos = strlen (pre);
|
||||
cursor_pos = anchor_pos + strlen (sel);
|
||||
}
|
||||
|
||||
text = g_strconcat (pre, sel, post, NULL);
|
||||
|
@@ -307,7 +307,6 @@ elif cc.get_id() == 'gcc' or cc.get_id() == 'clang'
|
||||
|
||||
extra_warnings = [
|
||||
'address',
|
||||
'array-bounds',
|
||||
'empty-body',
|
||||
'enum-int-mismatch',
|
||||
'implicit',
|
||||
|
@@ -3639,6 +3639,19 @@ avahi_request_printer_list (GtkPrintBackendCups *cups_backend)
|
||||
g_bus_get (G_BUS_TYPE_SYSTEM, cups_backend->avahi_cancellable, avahi_create_browsers, cups_backend);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print backend can be disposed together with all its printers
|
||||
* as a reaction to user stopping enumeration of printers.
|
||||
*/
|
||||
static void
|
||||
backend_finalized_cb (gpointer data,
|
||||
GObject *where_the_object_was)
|
||||
{
|
||||
gboolean *backend_finalized = data;
|
||||
|
||||
*backend_finalized = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
|
||||
GtkCupsResult *result,
|
||||
@@ -3651,6 +3664,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
|
||||
GList *removed_printer_checklist;
|
||||
char *remote_default_printer = NULL;
|
||||
GList *iter;
|
||||
gboolean backend_finalized = FALSE;
|
||||
|
||||
list_has_changed = FALSE;
|
||||
|
||||
@@ -3683,6 +3697,8 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
|
||||
*/
|
||||
removed_printer_checklist = gtk_print_backend_get_printer_list (backend);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (backend), backend_finalized_cb, &backend_finalized);
|
||||
|
||||
response = gtk_cups_result_get_response (result);
|
||||
for (attr = ippFirstAttribute (response); attr != NULL;
|
||||
attr = ippNextAttribute (response))
|
||||
@@ -3800,6 +3816,9 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
|
||||
{
|
||||
g_signal_emit_by_name (backend, "printer-added", printer);
|
||||
|
||||
if (backend_finalized)
|
||||
break;
|
||||
|
||||
gtk_printer_set_is_new (printer, FALSE);
|
||||
}
|
||||
|
||||
@@ -3837,36 +3856,44 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
|
||||
break;
|
||||
}
|
||||
|
||||
/* look at the removed printers checklist and mark any printer
|
||||
as inactive if it is in the list, emitting a printer_removed signal */
|
||||
if (removed_printer_checklist != NULL)
|
||||
if (!backend_finalized)
|
||||
{
|
||||
for (iter = removed_printer_checklist; iter; iter = iter->next)
|
||||
g_object_weak_unref (G_OBJECT (backend), backend_finalized_cb, &backend_finalized);
|
||||
|
||||
/* look at the removed printers checklist and mark any printer
|
||||
as inactive if it is in the list, emitting a printer_removed signal */
|
||||
if (removed_printer_checklist != NULL)
|
||||
{
|
||||
if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
|
||||
for (iter = removed_printer_checklist; iter; iter = iter->next)
|
||||
{
|
||||
mark_printer_inactive (GTK_PRINTER (iter->data), backend);
|
||||
list_has_changed = TRUE;
|
||||
if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
|
||||
{
|
||||
mark_printer_inactive (GTK_PRINTER (iter->data), backend);
|
||||
list_has_changed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (removed_printer_checklist);
|
||||
}
|
||||
|
||||
g_list_free (removed_printer_checklist);
|
||||
|
||||
done:
|
||||
if (list_has_changed)
|
||||
g_signal_emit_by_name (backend, "printer-list-changed");
|
||||
|
||||
gtk_print_backend_set_list_done (backend);
|
||||
|
||||
if (!cups_backend->got_default_printer && remote_default_printer != NULL)
|
||||
if (!backend_finalized)
|
||||
{
|
||||
set_default_printer (cups_backend, remote_default_printer);
|
||||
g_free (remote_default_printer);
|
||||
}
|
||||
if (list_has_changed)
|
||||
g_signal_emit_by_name (backend, "printer-list-changed");
|
||||
|
||||
if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL)
|
||||
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
|
||||
gtk_print_backend_set_list_done (backend);
|
||||
|
||||
if (!cups_backend->got_default_printer && remote_default_printer != NULL)
|
||||
{
|
||||
set_default_printer (cups_backend, remote_default_printer);
|
||||
g_free (remote_default_printer);
|
||||
}
|
||||
|
||||
if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL)
|
||||
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -73,9 +73,10 @@ test_textview_surrounding (void)
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter iter;
|
||||
GtkTextIter start, end;
|
||||
GtkTextIter bound, insert;
|
||||
gboolean ret;
|
||||
char *text;
|
||||
int cursor_pos, selection_bound;
|
||||
int anchor_pos, cursor_pos;
|
||||
|
||||
widget = gtk_text_view_new ();
|
||||
controller = gtk_text_view_get_key_controller (GTK_TEXT_VIEW (widget));
|
||||
@@ -89,12 +90,12 @@ test_textview_surrounding (void)
|
||||
ret = gtk_im_context_get_surrounding_with_selection (context,
|
||||
&text,
|
||||
&cursor_pos,
|
||||
&selection_bound);
|
||||
&anchor_pos);
|
||||
|
||||
g_assert_true (ret);
|
||||
g_assert_cmpstr (text, ==, "abcd\nefgh\nijkl");
|
||||
g_assert_cmpint (cursor_pos, ==, 7);
|
||||
g_assert_cmpint (selection_bound, ==, 7);
|
||||
g_assert_cmpint (anchor_pos, ==, 7);
|
||||
|
||||
g_free (text);
|
||||
|
||||
@@ -122,19 +123,19 @@ test_textview_surrounding (void)
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
||||
gtk_text_buffer_set_text (buffer, "ab cd\nef gh\nijkl", -1);
|
||||
gtk_text_buffer_get_iter_at_line_offset (buffer, &start, 1, 4);
|
||||
gtk_text_buffer_get_iter_at_line_offset (buffer, &end, 2, 2);
|
||||
gtk_text_buffer_select_range (buffer, &start, &end);
|
||||
gtk_text_buffer_get_iter_at_line_offset (buffer, &bound, 1, 4);
|
||||
gtk_text_buffer_get_iter_at_line_offset (buffer, &insert, 2, 2);
|
||||
gtk_text_buffer_select_range (buffer, &insert, &bound);
|
||||
|
||||
ret = gtk_im_context_get_surrounding_with_selection (context,
|
||||
&text,
|
||||
&cursor_pos,
|
||||
&selection_bound);
|
||||
&anchor_pos);
|
||||
|
||||
g_assert_true (ret);
|
||||
g_assert_cmpstr (text, ==, "cd\nef gh\nijkl");
|
||||
g_assert_cmpint (anchor_pos, ==, 7);
|
||||
g_assert_cmpint (cursor_pos, ==, 11);
|
||||
g_assert_cmpint (selection_bound, ==, 7);
|
||||
|
||||
g_free (text);
|
||||
|
||||
|
@@ -4,6 +4,9 @@ GTK_BUILDER_TOOL=${GTK_BUILDER_TOOL:-gtk4-builder-tool}
|
||||
TEST_DATA_DIR=${G_TEST_SRCDIR:-.}/validate-data
|
||||
TEST_RESULT_DIR=${TEST_RESULT_DIR:-/tmp}/validate
|
||||
|
||||
# https://gitlab.freedesktop.org/mesa/mesa/-/issues/10293
|
||||
export LIBGL_ALWAYS_SOFTWARE=true
|
||||
|
||||
mkdir -p "$TEST_RESULT_DIR"
|
||||
|
||||
shopt -s nullglob
|
||||
|
Reference in New Issue
Block a user