Compare commits

..

60 Commits

Author SHA1 Message Date
Matthias Clasen 40b34c76e6 widget: Treat key controllers like gestures
For the purposes of cutting short event handling,
treat key controllers like gestures. It is fairly
common to have multiple key controllers on a widget,
and the event handling can inadvertently cut short
e.g. by modifier key releases that return TRUE
from handle_event.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1884
2019-05-12 19:30:56 +00:00
Matthias Clasen 1318d3748a about dialog: Fix page visibility
The handling of page visibility broke when the dialog
was ported to GtkStackPage in 52b83ac553.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1877
2019-05-12 18:20:52 +00:00
Matthias Clasen 04754d753b Reinstate the activate-focus keybinding
Commit 3b62d9c027 was a bit overzealous in
removing not just the public API for activating the focus
widget, but also the plumbing needed to make the keybinding
work.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1879
2019-05-12 18:07:33 +00:00
Benjamin Otte f8c1f7173a Merge branch 'wip/otte/for-master' into 'master'
Wip/otte/for master

See merge request GNOME/gtk!832
2019-05-12 16:27:47 +00:00
Benjamin Otte a04ea72ca1 rendernodeparser: Default color to black
Nobody wants to render transparent text.
2019-05-12 17:28:19 +02:00
Benjamin Otte 0886ade182 cssparser: Make gsk_renderer_consume_url() return a string
We don't want to return a GFile because GFile can't handle can't deal
with data: urls.
That makes the code a bit more complicated that doesn't deal with those
URLs, but it makes the other code actually work.

GtkCssImageUrl also now decodes data urls immediately instead of only at
the first load. So don't use data urls if you care about performance.
2019-05-12 17:28:19 +02:00
Benjamin Otte 0103704171 rendernodeparser: Use parser blocks
Instead of trying to do error handling manually, use the semicolon
blocks feature provided by GtkCssParser.
2019-05-12 17:28:19 +02:00
Benjamin Otte b76d5bda37 cssparser: Don't allow commit_token() on block EOF
When we're at the end of a block and gtk_css_parser_get_token() returns
NULL, gtk_css_parser_commit_token() still consumed the next token.

It does not anymore.

This does not affect the CSS parser, but it exposes issues with the
render parser, which previously just consumed too many closing } tokens
in the past.
2019-05-12 17:28:19 +02:00
Benjamin Otte 6f6b07aaae testsuite: Stop using g_test_bug()
The calls used old bugzilla URLs and nobody cared about that.
So apparently they are very unused.

There's also a potential conflict between gitlab and bugzilla URLs and
what base bug to use there.

The old usages have been converted to comments.
2019-05-12 17:28:18 +02:00
Benjamin Otte 4bccd17941 node-editor: Report all errors in tooltip
Don't just report the first one.
2019-05-12 17:27:01 +02:00
Benjamin Otte 0049b39375 node-editor: Don't remove all text tags when saving 2019-05-12 17:27:01 +02:00
Benjamin Otte 63578d832a testsuite: Don't die on the first error
Continue running the test, just mark it as a failure.
2019-05-12 17:27:01 +02:00
Benjamin Otte 3a373b9b33 rendernodeparser: Parse images differently
Instead of encoding the raw data, encode the full image to a PNG.
And instead of stuffing that encoding into a string, use a full
data: url.
And then remove the width and height properties, because they're now
implicitly included in the data.
And then change the parser to match.
And because the parser now parses regular urls on top of data: urls, we
can now load any random file.
2019-05-12 17:27:01 +02:00
Benjamin Otte 8be95ca348 css: Add data URL parsing to images 2019-05-12 17:27:01 +02:00
Benjamin Otte 5da58ba47d css: Add gtk_css_data_url_parse()
This surprisingly decodes data URLs.
2019-05-12 17:27:01 +02:00
Benjamin Otte 4505f4f17b rendernode: Set EXTEND_PAD when drawing textures 2019-05-12 15:41:53 +02:00
Christoph Reiter e0e9d8c6b5 Merge branch 'ci-master-fedora-30' into 'master'
CI: update docker image to Fedora 30

See merge request GNOME/gtk!802
2019-05-10 14:19:16 +00:00
Christoph Reiter 24fcfa91b1 CI: update docker image to fedora 30
So we don't have to build glib as a subproject.
2019-05-10 15:48:33 +02:00
Matthias Clasen 4f0ea69e9b settings: Update docs
We no longer create settings on demand.
2019-05-09 14:53:32 +00:00
Matthias Clasen f2e197a389 css provider: Stop mentioning key themes
We no longer do this.
2019-05-09 14:53:32 +00:00
Benjamin Otte 777beb0d0a glrenderer: Ensure current context for debug stuff 2019-05-08 19:47:40 +02:00
Benjamin Otte 1fa4b9f58c rendernode: Parse repeat nodes 2019-05-08 19:47:40 +02:00
Benjamin Otte 9117ee83eb node-editor: Never scale nodes up
Scaling down is fine so one can see the nodes, but scaling up just
makes the nodes wrong for no reason at all.
2019-05-08 19:47:40 +02:00
Matthias Clasen b3ff4154ec Drop the public profiler api
I meant to do this before merging the profiler
support. Somehow the commit got lost.
2019-05-08 17:00:26 +00:00
Matthias Clasen 879a0c118d Profiler: drop the public api 2019-05-08 16:57:34 +00:00
Matthias Clasen cb51699098 profiler: Update the D-Bus interface name
Sysprof is bumping its name to Sysprof3, so
lets change to that before this gets used.
2019-05-08 16:49:47 +00:00
Matthias Clasen d91f04eefd Correct theme loading docs
The docs were failing to mention the VARIANT.
2019-05-08 14:47:08 +00:00
Matthias Clasen a86160265a css provider: Remove outdated version check
When looking for versioned theme files, we were
looking for directories names gtk-4.x for x
bigger than 14, which mades sense for GTK 3,
but we are starting out at 0 again, so remove
this check.
2019-05-08 14:33:23 +00:00
Matthias Clasen 8aaa8958c4 Merge branch 'inspector-css' into 'master'
Inspector css

See merge request GNOME/gtk!830
2019-05-08 04:01:45 +00:00
Matthias Clasen 97b450dfd7 Improve the action editor more 2019-05-08 03:34:14 +00:00
Matthias Clasen 46c1e154f1 inspector: Fix showing the frame clock
We want to go to the object, not just select it
in the list (which does not even contain frame clocks).
2019-05-08 02:44:24 +00:00
Matthias Clasen fcb1408e1e Merge branch 'inspector-css' into 'master'
inspector: Port actions to a list view

See merge request GNOME/gtk!829
2019-05-08 02:27:31 +00:00
Matthias Clasen 4cc27285b1 inspector: Port actions to a list view 2019-05-08 02:20:50 +00:00
Chun-wei Fan 705bf48eed gdk/gdkprofiler.c: Don't include unistd.h unconditionally
unistd.h is not universally available, so only include it when it can be
found during the configure stage.
2019-05-07 17:58:14 -07:00
Benjamin Otte b651a355ab build: Fix
I did somethig wrong there. Whoops
2019-05-08 01:15:17 +02:00
Benjamin Otte dd299c50bf csstokenizer: Add more testcases 2019-05-08 00:58:52 +02:00
Benjamin Otte bc7972dfa7 csstokenizer: Handle backslash at end of document
Testcases included.
2019-05-08 00:58:52 +02:00
Matthias Clasen 24d6ce7e51 Merge branch 'inspector-css' into 'master'
inspector: Style the property list

See merge request GNOME/gtk!828
2019-05-07 22:21:02 +00:00
Matthias Clasen e1c1c46e34 inspector: Style the property list
Make the property list look more like a list.
2019-05-07 22:04:41 +00:00
Matthias Clasen 60a18229ee Merge branch 'gdk-win32-unimplement-vfuncs' into 'master'
GdkSurface - Don't call unimplemented NULL set_startup_id() vfunc on Win32

See merge request GNOME/gtk!825
2019-05-07 18:57:44 +00:00
Matthias Clasen 725e7c7470 emoji chooser: Name the idle
We recently added an idle that does quite a bit of work.
It should have a name.
2019-05-07 18:41:22 +00:00
Sebastian Dröge 2bd6661cd3 GdkSurface - Don't call unimplemented NULL set_startup_id() vfunc on Win32
GdkSurface::set_startup_id() is NULL on Win32 and would cause a segfault
if called.

While the documentation of the main caller of set_startup_id(),
gtk_window_set_startup_id(), mentions that it's not implemented on
Windows it can still be automatically called via Glade and simply doing
nothing on Win32 is going to be less disruptive than a segfault.
2019-05-07 21:38:46 +03:00
Matthias Clasen 31cd43a245 Merge branch 'tracing' into 'master'
Tracing

See merge request GNOME/gtk!563
2019-05-07 18:37:11 +00:00
Matthias Clasen ef446de92d Add docs
Document the various ways to start profiling.
2019-05-07 09:37:59 -07:00
Matthias Clasen 18127be3bd GtkApplication: Add a profiler dbus api
Implement the org.gnome.Sysprof2.Profiler D-Bus
api to let sysprof start and stop tracing at runtime,
and get the data directly, via a passed fd.
2019-05-07 09:37:59 -07:00
Matthias Clasen 64454a7e47 gsk: Add tracing to the vulkan renderer
Emit the equivalent of the cpu-time counter, as well
as pixel numbers i the inspector.
2019-05-07 09:37:59 -07:00
Matthias Clasen b09a0958a0 gsk: Add tracing to the gl renderer
Emit the equivalent of the cpu-time counter in the inspector.
2019-05-07 09:37:59 -07:00
Matthias Clasen c541fa9555 gsk: Add some more profiler apis
Add a way to extract the start time of timers.
This will let us reuse the profiler timers for tracing.
2019-05-07 09:37:59 -07:00
Matthias Clasen 1660bac6bd frame clock: Add tracing
Emit tracing data for frames. For now, we emit the
entire frame, and the layout and paint phases. Also
emit frames-per-second.
2019-05-07 09:37:59 -07:00
Matthias Clasen 9e40642335 Add a way to start the profiler
If SYSPROF_TRACE_FD is set in the environment,
interpret it as an fd to write profiling data
to.

If GTK_TRACE is set, write profiling data
to a file with name gtk.$PID.syscap.
2019-05-07 09:37:59 -07:00
Matthias Clasen 032bb45ce3 gdk: Add a profiler
This is writing data in the capture format of sysprof,
using the SpCaptureWriter. For now, this is using a
vendored copy of libsysprof. Eventually, we want to
use the static library that sysprof provides.
2019-05-07 09:37:59 -07:00
Marek Kašík 5a578669c2 Merge branch 'cups-deprecation-warnings' into 'master'
Fix deprecation warnings when building the CUPS print backend

See merge request GNOME/gtk!739
2019-05-07 16:32:36 +00:00
Emmanuele Bassi 3377133d19 Require CUPS >= 2.0
Drop support for versions of CUPS < 2.0, to simplify the backend code
and drop a lot of conditional blocks.
2019-05-07 18:30:47 +02:00
Emmanuele Bassi ed31ea3773 cups: Use non-deprecated API
The http* family of functions was deprecated after CUPS 1.7. We can
conditionally use it when built against a newer version of CUPS. The
additional parameters are taken directly from the fallback values
inside CUPS itself.
2019-05-07 18:30:47 +02:00
Emmanuele Bassi feddf5a694 Detect CUPS ≥ 1.7
We support CUPS ≥ 1.2, but we use API that was introduced and deprecated
at a later point.
2019-05-07 18:30:47 +02:00
Timm Bäder e847c030bd gl renderer: Fix blur nodes with radius 0 2019-05-07 17:21:16 +02:00
Timm Bäder b3c4320bc2 node editor: Do some simple syntax highlighting 2019-05-07 17:21:16 +02:00
Timm Bäder 730b52b084 testsuite: Add blur node testcase
Renderers need to handle blur radius 0 as well. Currently broken in GL
and (I guess, unless it's my driver) Vulkan.
2019-05-07 17:21:16 +02:00
Matthias Clasen 4ff578db10 Fix the compiler warning, again 2019-05-07 14:57:53 +00:00
Matthias Clasen 248c07c65e Fix a compiler warning 2019-05-07 04:01:21 +00:00
117 changed files with 3640 additions and 874 deletions
+2 -2
View File
@@ -13,7 +13,7 @@ stages:
- subprojects/pango/
fedora-x86_64:
image: registry.gitlab.gnome.org/gnome/gtk/master:v5
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
stage: build
script:
- bash -x ./.gitlab-ci/test-docker.sh
@@ -101,7 +101,7 @@ flatpak-master:icon-browser:
<<: *flatpak-master
pages:
image: registry.gitlab.gnome.org/gnome/gtk/master:v4
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
stage: deploy
script:
- meson -Ddocumentation=true _build .
+4 -4
View File
@@ -1,4 +1,4 @@
FROM fedora:29
FROM fedora:30
RUN dnf -y install \
hicolor-icon-theme \
@@ -11,6 +11,7 @@ RUN dnf -y install \
ccache \
colord-devel \
cups-devel \
dbus-daemon \
dejavu-sans-mono-fonts \
desktop-file-utils \
elfutils-libelf-devel \
@@ -59,6 +60,7 @@ RUN dnf -y install \
pango-devel \
pcre-devel \
python3 \
python3-jinja2 \
python3-pip \
python3-wheel \
redhat-rpm-config \
@@ -71,9 +73,7 @@ RUN dnf -y install \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson==0.50.0
RUN pip3 install jinja2
RUN pip3 install meson==0.50.1
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
+1 -1
View File
@@ -2,7 +2,7 @@
set -e
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v4"
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v6"
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile" .
-3
View File
@@ -24,9 +24,6 @@
/* Define to 1 if you have the <crt_externs.h> header file. */
#mesondefine HAVE_CRT_EXTERNS_H
/* Define to 1 if CUPS 1.6 API is available */
#mesondefine HAVE_CUPS_API_1_6
/* Define to 1 if you have the `dcgettext' function. */
#mesondefine HAVE_DCGETTEXT
@@ -23,6 +23,16 @@
#include "node-editor-window.h"
static const char *css =
"textview.editor {"
" color: rgb(192, 197, 206);"
" caret-color: white;"
"}"
"textview.editor text {"
" background-color: rgb(43, 48, 59);"
"}"
;
struct _NodeEditorApplication
{
GtkApplication parent;
@@ -58,6 +68,7 @@ node_editor_application_startup (GApplication *app)
{
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
const char *open_accels[2] = { "<Ctrl>O", NULL };
GtkCssProvider *provider;
G_APPLICATION_CLASS (node_editor_application_parent_class)->startup (app);
@@ -66,6 +77,13 @@ node_editor_application_startup (GApplication *app)
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
static void
+164 -6
View File
@@ -39,6 +39,7 @@ struct _NodeEditorWindow
GtkWidget *picture;
GtkWidget *text_view;
GtkTextBuffer *text_buffer;
GtkTextTagTable *tag_table;
GtkWidget *renderer_listbox;
GListStore *renderers;
@@ -67,11 +68,20 @@ get_current_text (GtkTextBuffer *buffer)
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
gtk_text_buffer_remove_all_tags (buffer, &start, &end);
return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
}
static void
text_buffer_remove_all_tags (GtkTextBuffer *buffer)
{
GtkTextIter start, end;
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
gtk_text_buffer_remove_all_tags (buffer, &start, &end);
}
static void
deserialize_error_func (const GtkCssSection *section,
const GError *error,
@@ -99,6 +109,42 @@ deserialize_error_func (const GtkCssSection *section,
g_array_append_val (self->errors, text_view_error);
}
static void
text_iter_skip_alpha_backward (GtkTextIter *iter)
{
/* Just skip to the previous non-whitespace char */
while (!gtk_text_iter_is_start (iter))
{
gunichar c = gtk_text_iter_get_char (iter);
if (g_unichar_isspace (c))
{
gtk_text_iter_forward_char (iter);
break;
}
gtk_text_iter_backward_char (iter);
}
}
static void
text_iter_skip_whitespace_backward (GtkTextIter *iter)
{
while (!gtk_text_iter_is_start (iter))
{
gunichar c = gtk_text_iter_get_char (iter);
if (g_unichar_isalpha (c))
{
gtk_text_iter_forward_char (iter);
break;
}
gtk_text_iter_backward_char (iter);
}
}
static void
text_changed (GtkTextBuffer *buffer,
NodeEditorWindow *self)
@@ -109,6 +155,7 @@ text_changed (GtkTextBuffer *buffer,
g_array_remove_range (self->errors, 0, self->errors->len);
text = get_current_text (self->text_buffer);
text_buffer_remove_all_tags (self->text_buffer);
bytes = g_bytes_new_take (text, strlen (text));
/* If this is too slow, go fix the parser performance */
@@ -141,6 +188,71 @@ text_changed (GtkTextBuffer *buffer,
{
gtk_picture_set_paintable (GTK_PICTURE (self->picture), NULL);
}
GtkTextIter iter;
gtk_text_buffer_get_start_iter (self->text_buffer, &iter);
while (!gtk_text_iter_is_end (&iter))
{
gunichar c = gtk_text_iter_get_char (&iter);
if (c == '{')
{
GtkTextIter word_end = iter;
GtkTextIter word_start;
gtk_text_iter_backward_char (&word_end);
text_iter_skip_whitespace_backward (&word_end);
word_start = word_end;
gtk_text_iter_backward_word_start (&word_start);
text_iter_skip_alpha_backward (&word_start);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "nodename",
&word_start, &word_end);
}
else if (c == ':')
{
GtkTextIter word_end = iter;
GtkTextIter word_start;
gtk_text_iter_backward_char (&word_end);
text_iter_skip_whitespace_backward (&word_end);
word_start = word_end;
gtk_text_iter_backward_word_start (&word_start);
text_iter_skip_alpha_backward (&word_start);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "propname",
&word_start, &word_end);
}
else if (c == '"')
{
GtkTextIter string_start = iter;
GtkTextIter string_end = iter;
gtk_text_iter_forward_char (&iter);
while (!gtk_text_iter_is_end (&iter))
{
c = gtk_text_iter_get_char (&iter);
if (c == '"')
{
gtk_text_iter_forward_char (&iter);
string_end = iter;
break;
}
gtk_text_iter_forward_char (&iter);
}
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "string",
&string_start, &string_end);
}
gtk_text_iter_forward_char (&iter);
}
}
static gboolean
@@ -153,6 +265,7 @@ text_view_query_tooltip_cb (GtkWidget *widget,
{
GtkTextIter iter;
guint i;
GString *text;
if (keyboard_tip)
{
@@ -170,6 +283,8 @@ text_view_query_tooltip_cb (GtkWidget *widget,
gtk_text_view_get_iter_at_position (GTK_TEXT_VIEW (self->text_view), &iter, &trailing, bx, by);
}
text = g_string_new ("");
for (i = 0; i < self->errors->len; i ++)
{
const TextViewError *e = &g_array_index (self->errors, TextViewError, i);
@@ -180,12 +295,23 @@ text_view_query_tooltip_cb (GtkWidget *widget,
if (gtk_text_iter_in_range (&iter, &start_iter, &end_iter))
{
gtk_tooltip_set_text (tooltip, e->message);
return TRUE;
if (text->len > 0)
g_string_append (text, "\n");
g_string_append (text, e->message);
}
}
return FALSE;
if (text->len > 0)
{
gtk_tooltip_set_text (tooltip, text->str);
g_string_free (text, TRUE);
return TRUE;
}
else
{
g_string_free (text, TRUE);
return FALSE;
}
}
gboolean
@@ -493,12 +619,10 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
widget_class->realize = node_editor_window_realize;
widget_class->unrealize = node_editor_window_unrealize;
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_buffer);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_view);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, picture);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, renderer_listbox);
gtk_widget_class_bind_template_callback (widget_class, text_changed);
gtk_widget_class_bind_template_callback (widget_class, text_view_query_tooltip_cb);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
gtk_widget_class_bind_template_callback (widget_class, save_cb);
@@ -520,6 +644,9 @@ node_editor_window_create_renderer_widget (gpointer item,
gtk_container_add (GTK_CONTAINER (box), label);
picture = gtk_picture_new_for_paintable (paintable);
/* don't ever scale up, we want to be as accurate as possible */
gtk_widget_set_halign (picture, GTK_ALIGN_CENTER);
gtk_widget_set_valign (picture, GTK_ALIGN_CENTER);
gtk_container_add (GTK_CONTAINER (box), picture);
row = gtk_list_box_row_new ();
@@ -559,6 +686,37 @@ node_editor_window_init (NodeEditorWindow *self)
g_array_set_clear_func (self->errors, (GDestroyNotify)text_view_error_free);
g_action_map_add_action_entries (G_ACTION_MAP (self), win_entries, G_N_ELEMENTS (win_entries), self);
self->tag_table = gtk_text_tag_table_new ();
gtk_text_tag_table_add (self->tag_table,
g_object_new (GTK_TYPE_TEXT_TAG,
"name", "error",
"underline", PANGO_UNDERLINE_ERROR,
NULL));
gtk_text_tag_table_add (self->tag_table,
g_object_new (GTK_TYPE_TEXT_TAG,
"name", "nodename",
"foreground-rgba", &(GdkRGBA) { 0.9, 0.78, 0.53, 1},
NULL));
gtk_text_tag_table_add (self->tag_table,
g_object_new (GTK_TYPE_TEXT_TAG,
"name", "propname",
"foreground-rgba", &(GdkRGBA) { 0.7, 0.55, 0.67, 1},
NULL));
gtk_text_tag_table_add (self->tag_table,
g_object_new (GTK_TYPE_TEXT_TAG,
"name", "string",
"foreground-rgba", &(GdkRGBA) { 0.63, 0.73, 0.54, 1},
NULL));
gtk_text_tag_table_add (self->tag_table,
g_object_new (GTK_TYPE_TEXT_TAG,
"name", "number",
"foreground-rgba", &(GdkRGBA) { 0.8, 0.52, 0.43, 1},
NULL));
self->text_buffer = gtk_text_buffer_new (self->tag_table);
g_signal_connect (self->text_buffer, "changed", G_CALLBACK (text_changed), self);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (self->text_view), self->text_buffer);
}
NodeEditorWindow *
+3 -13
View File
@@ -1,17 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkTextTagTable" id="tags">
<child type="tag">
<object class="GtkTextTag">
<property name="name">error</property>
<property name="underline">error</property>
</object>
</child>
</object>
<object class="GtkTextBuffer" id="text_buffer">
<property name="tag-table">tags</property>
<signal name="changed" handler="text_changed"/>
</object>
<template class="NodeEditorWindow" parent="GtkApplicationWindow">
<style>
<class name="devel"/>
@@ -61,7 +49,6 @@
<property name="expand">1</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="buffer">text_buffer</property>
<property name="wrap-mode">word</property>
<property name="monospace">1</property>
<property name="has-focus">1</property>
@@ -71,6 +58,9 @@
<property name="bottom-margin">6</property>
<property name="has-tooltip">1</property>
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
<style>
<class name="editor" />
</style>
</object>
</child>
</object>
+26
View File
@@ -574,6 +574,32 @@ nevertheless.
</refsect2>
<refsect2 id="profiling">
<title>Profiling</title>
<para>
GTK supports profiling with sysprof. It exports timing information
about frameclock phases and various characteristics of GskRenders
in a format that can be displayed by sysprof or GNOME Builder.
</para>
<para>
A simple way to capture data is to set the <envar>GTK_TRACE</envar>
environment variable. When it is set, GTK will write profiling
data to a file called
<filename>gtk.<replaceable>PID</replaceable>.syscap</filename>.
</para>
<para>
When launching the application from sysprof, it will set the
<envar>SYSPROF_TRACE_FD</envar> environment variable to point
GTK at a file descriptor to write profiling data to.
</para>
<para>
When GtkApplication registers with D-Bus, it exports the
<literal>org.gnome.Sysprof2.Profiler</literal> interface
that lets sysprof request profiling data at runtime.
</para>
</refsect2>
</refsect1>
</refentry>
+224
View File
@@ -0,0 +1,224 @@
/* sp-capture-types.h
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file 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 file 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 General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_CAPTURE_FORMAT_H
#define SP_CAPTURE_FORMAT_H
#include <glib.h>
#ifndef SP_DISABLE_GOBJECT
# include <glib-object.h>
#endif
#include "sp-clock.h"
G_BEGIN_DECLS
#define SP_CAPTURE_MAGIC (GUINT32_TO_LE(0xFDCA975E))
#define SP_CAPTURE_ALIGN (sizeof(SpCaptureAddress))
#if __WORDSIZE == 64
# define SP_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE000000000000000)
# define SP_CAPTURE_ADDRESS_FORMAT "0x%016lx"
#else
# define SP_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE0000000)
# define SP_CAPTURE_ADDRESS_FORMAT "0x%016llx"
#endif
#define SP_CAPTURE_CURRENT_TIME (sp_clock_get_current_time())
#define SP_CAPTURE_COUNTER_INT64 0
#define SP_CAPTURE_COUNTER_DOUBLE 1
typedef struct _SpCaptureReader SpCaptureReader;
typedef struct _SpCaptureWriter SpCaptureWriter;
typedef struct _SpCaptureCursor SpCaptureCursor;
typedef struct _SpCaptureCondition SpCaptureCondition;
typedef guint64 SpCaptureAddress;
typedef union
{
gint64 v64;
gdouble vdbl;
} SpCaptureCounterValue;
typedef enum
{
SP_CAPTURE_FRAME_TIMESTAMP = 1,
SP_CAPTURE_FRAME_SAMPLE = 2,
SP_CAPTURE_FRAME_MAP = 3,
SP_CAPTURE_FRAME_PROCESS = 4,
SP_CAPTURE_FRAME_FORK = 5,
SP_CAPTURE_FRAME_EXIT = 6,
SP_CAPTURE_FRAME_JITMAP = 7,
SP_CAPTURE_FRAME_CTRDEF = 8,
SP_CAPTURE_FRAME_CTRSET = 9,
SP_CAPTURE_FRAME_MARK = 10,
} SpCaptureFrameType;
#pragma pack(push, 1)
typedef struct
{
guint32 magic;
guint8 version;
guint32 little_endian : 1;
guint32 padding : 23;
gchar capture_time[64];
gint64 time;
gint64 end_time;
gchar suffix[168];
} SpCaptureFileHeader;
typedef struct
{
guint16 len;
gint16 cpu;
gint32 pid;
gint64 time;
guint8 type;
guint64 padding : 56;
guint8 data[0];
} SpCaptureFrame;
typedef struct
{
SpCaptureFrame frame;
guint64 start;
guint64 end;
guint64 offset;
guint64 inode;
gchar filename[0];
} SpCaptureMap;
typedef struct
{
SpCaptureFrame frame;
guint32 n_jitmaps;
guint8 data[0];
} SpCaptureJitmap;
typedef struct
{
SpCaptureFrame frame;
gchar cmdline[0];
} SpCaptureProcess;
typedef struct
{
SpCaptureFrame frame;
guint16 n_addrs;
guint64 padding : 48;
SpCaptureAddress addrs[0];
} SpCaptureSample;
typedef struct
{
SpCaptureFrame frame;
GPid child_pid;
} SpCaptureFork;
typedef struct
{
SpCaptureFrame frame;
} SpCaptureExit;
typedef struct
{
SpCaptureFrame frame;
} SpCaptureTimestamp;
typedef struct
{
gchar category[32];
gchar name[32];
gchar description[52];
guint32 id : 24;
guint8 type;
SpCaptureCounterValue value;
} SpCaptureCounter;
typedef struct
{
SpCaptureFrame frame;
guint16 n_counters;
guint64 padding : 48;
SpCaptureCounter counters[0];
} SpCaptureFrameCounterDefine;
typedef struct
{
/*
* 96 bytes might seem a bit odd, but the counter frame header is 32
* bytes. So this makes a nice 2-cacheline aligned size which is
* useful when the number of counters is rather small.
*/
guint32 ids[8];
SpCaptureCounterValue values[8];
} SpCaptureCounterValues;
typedef struct
{
SpCaptureFrame frame;
guint16 n_values;
guint64 padding : 48;
SpCaptureCounterValues values[0];
} SpCaptureFrameCounterSet;
typedef struct
{
SpCaptureFrame frame;
gint64 duration;
gchar group[24];
gchar name[40];
gchar message[0];
} SpCaptureMark;
#pragma pack(pop)
G_STATIC_ASSERT (sizeof (SpCaptureFileHeader) == 256);
G_STATIC_ASSERT (sizeof (SpCaptureFrame) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureMap) == 56);
G_STATIC_ASSERT (sizeof (SpCaptureJitmap) == 28);
G_STATIC_ASSERT (sizeof (SpCaptureProcess) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureSample) == 32);
G_STATIC_ASSERT (sizeof (SpCaptureFork) == 28);
G_STATIC_ASSERT (sizeof (SpCaptureExit) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureTimestamp) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureCounter) == 128);
G_STATIC_ASSERT (sizeof (SpCaptureCounterValues) == 96);
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterDefine) == 32);
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterSet) == 32);
G_STATIC_ASSERT (sizeof (SpCaptureMark) == 96);
static inline gint
sp_capture_address_compare (SpCaptureAddress a,
SpCaptureAddress b)
{
if (a < b)
return -1;
if (a > b)
return 1;
else
return 0;
}
G_END_DECLS
#endif /* SP_CAPTURE_FORMAT_H */
File diff suppressed because it is too large Load Diff
+132
View File
@@ -0,0 +1,132 @@
/* sp-capture-writer.h
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file 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 file 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 General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_CAPTURE_WRITER_H
#define SP_CAPTURE_WRITER_H
#include "capture/sp-capture-types.h"
G_BEGIN_DECLS
typedef struct _SpCaptureWriter SpCaptureWriter;
typedef struct
{
/*
* The number of frames indexed by SpCaptureFrameType
*/
gsize frame_count[16];
/*
* Padding for future expansion.
*/
gsize padding[48];
} SpCaptureStat;
SpCaptureWriter *sp_capture_writer_new (const gchar *filename,
gsize buffer_size);
SpCaptureWriter *sp_capture_writer_new_from_fd (int fd,
gsize buffer_size);
SpCaptureWriter *sp_capture_writer_ref (SpCaptureWriter *self);
void sp_capture_writer_unref (SpCaptureWriter *self);
void sp_capture_writer_stat (SpCaptureWriter *self,
SpCaptureStat *stat);
gboolean sp_capture_writer_add_map (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
guint64 start,
guint64 end,
guint64 offset,
guint64 inode,
const gchar *filename);
gboolean sp_capture_writer_add_mark (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
guint64 duration,
const gchar *group,
const gchar *name,
const gchar *message);
guint64 sp_capture_writer_add_jitmap (SpCaptureWriter *self,
const gchar *name);
gboolean sp_capture_writer_add_process (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const gchar *cmdline);
gboolean sp_capture_writer_add_sample (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const SpCaptureAddress *addrs,
guint n_addrs);
gboolean sp_capture_writer_add_fork (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
GPid child_pid);
gboolean sp_capture_writer_add_exit (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid);
gboolean sp_capture_writer_add_timestamp (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid);
gboolean sp_capture_writer_define_counters (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const SpCaptureCounter *counters,
guint n_counters);
gboolean sp_capture_writer_set_counters (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const guint *counters_ids,
const SpCaptureCounterValue *values,
guint n_counters);
gboolean sp_capture_writer_flush (SpCaptureWriter *self);
gboolean sp_capture_writer_save_as (SpCaptureWriter *self,
const gchar *filename,
GError **error);
gint sp_capture_writer_request_counter (SpCaptureWriter *self,
guint n_counters);
SpCaptureReader *sp_capture_writer_create_reader (SpCaptureWriter *self,
GError **error);
gboolean sp_capture_writer_splice (SpCaptureWriter *self,
SpCaptureWriter *dest,
GError **error);
gboolean _sp_capture_writer_splice_from_fd (SpCaptureWriter *self,
int fd,
GError **error) G_GNUC_INTERNAL;
#ifndef SP_DISABLE_GOBJECT
# define SP_TYPE_CAPTURE_WRITER (sp_capture_writer_get_type())
GType sp_capture_writer_get_type (void);
#endif
#if GLIB_CHECK_VERSION(2, 44, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpCaptureWriter, sp_capture_writer_unref)
#endif
G_END_DECLS
#endif /* SP_CAPTURE_WRITER_H */
+52
View File
@@ -0,0 +1,52 @@
/* sp-clock.c
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file 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 file 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 General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sp-clock.h"
gint sp_clock = -1;
void
sp_clock_init (void)
{
static const gint clock_ids[] = {
CLOCK_MONOTONIC_RAW,
CLOCK_MONOTONIC_COARSE,
CLOCK_MONOTONIC,
CLOCK_REALTIME_COARSE,
CLOCK_REALTIME,
};
guint i;
if (sp_clock != -1)
return;
for (i = 0; i < G_N_ELEMENTS (clock_ids); i++)
{
struct timespec ts;
int clock_id = clock_ids [i];
if (0 == clock_gettime (clock_id, &ts))
{
sp_clock = clock_id;
return;
}
}
g_assert_not_reached ();
}
+55
View File
@@ -0,0 +1,55 @@
/* sp-clock.h
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file 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 file 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 General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_CLOCK_H
#define SP_CLOCK_H
#include <glib.h>
#include <time.h>
G_BEGIN_DECLS
typedef gint SpClock;
typedef gint64 SpTimeStamp;
typedef gint32 SpTimeSpan;
extern SpClock sp_clock;
static inline SpTimeStamp
sp_clock_get_current_time (void)
{
struct timespec ts;
clock_gettime (sp_clock, &ts);
return (ts.tv_sec * G_GINT64_CONSTANT (1000000000)) + ts.tv_nsec;
}
static inline SpTimeSpan
sp_clock_get_relative_time (SpTimeStamp epoch)
{
return sp_clock_get_current_time () - epoch;
}
void sp_clock_init (void);
G_END_DECLS
#endif /* SP_CLOCK_H */
+6
View File
@@ -26,6 +26,7 @@
#include "gdkversionmacros.h"
#include "gdkprofilerprivate.h"
#include "gdkinternals.h"
#include "gdkintl.h"
@@ -211,6 +212,11 @@ gdk_pre_parse (void)
_gdk_debug_flags = g_parse_debug_string (debug_string,
(GDebugKey *) gdk_debug_keys,
G_N_ELEMENTS (gdk_debug_keys));
if (g_getenv ("SYSPROF_TRACE_FD"))
gdk_profiler_start (atoi (g_getenv ("SYSPROF_TRACE_FD")));
else if (g_getenv ("GTK_TRACE"))
gdk_profiler_start (-1);
}
#endif /* G_ENABLE_DEBUG */
+105 -3
View File
@@ -29,6 +29,7 @@
#include "gdkinternals.h"
#include "gdkframeclockprivate.h"
#include "gdk.h"
#include "gdkprofilerprivate.h"
#ifdef G_OS_WIN32
#include <windows.h>
@@ -113,6 +114,96 @@ get_sleep_serial (void)
return sleep_serial;
}
static guint fps_counter = 0;
static void
add_timings_to_profiler (GdkFrameTimings *timings)
{
gdk_profiler_add_mark (timings->frame_time * 1000,
(timings->frame_end_time - timings->frame_time) * 1000,
"frame", "");
if (timings->layout_start_time != 0)
gdk_profiler_add_mark (timings->layout_start_time * 1000,
(timings->paint_start_time - timings->layout_start_time) * 1000,
"layout", "");
if (timings->paint_start_time != 0)
gdk_profiler_add_mark (timings->paint_start_time * 1000,
(timings->frame_end_time - timings->paint_start_time) * 1000,
"paint", "");
}
static gint64
guess_refresh_interval (GdkFrameClock *frame_clock)
{
gint64 interval;
gint64 i;
interval = G_MAXINT64;
for (i = gdk_frame_clock_get_history_start (frame_clock);
i < gdk_frame_clock_get_frame_counter (frame_clock);
i++)
{
GdkFrameTimings *t, *before;
gint64 ts, before_ts;
t = gdk_frame_clock_get_timings (frame_clock, i);
before = gdk_frame_clock_get_timings (frame_clock, i - 1);
if (t == NULL || before == NULL)
continue;
ts = gdk_frame_timings_get_frame_time (t);
before_ts = gdk_frame_timings_get_frame_time (before);
if (ts == 0 || before_ts == 0)
continue;
interval = MIN (interval, ts - before_ts);
}
if (interval == G_MAXINT64)
return 0;
return interval;
}
static double
frame_clock_get_fps (GdkFrameClock *frame_clock)
{
GdkFrameTimings *start, *end;
gint64 start_counter, end_counter;
gint64 start_timestamp, end_timestamp;
gint64 interval;
start_counter = gdk_frame_clock_get_history_start (frame_clock);
end_counter = gdk_frame_clock_get_frame_counter (frame_clock);
start = gdk_frame_clock_get_timings (frame_clock, start_counter);
for (end = gdk_frame_clock_get_timings (frame_clock, end_counter);
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
end = gdk_frame_clock_get_timings (frame_clock, end_counter))
end_counter--;
if (end_counter - start_counter < 4)
return 0.0;
start_timestamp = gdk_frame_timings_get_presentation_time (start);
end_timestamp = gdk_frame_timings_get_presentation_time (end);
if (start_timestamp == 0 || end_timestamp == 0)
{
start_timestamp = gdk_frame_timings_get_frame_time (start);
end_timestamp = gdk_frame_timings_get_frame_time (end);
}
interval = gdk_frame_timings_get_refresh_interval (end);
if (interval == 0)
{
interval = guess_refresh_interval (frame_clock);
if (interval == 0)
return 0.0;
}
return ((double) end_counter - start_counter) * G_USEC_PER_SEC / (end_timestamp - start_timestamp);
}
static void
gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
{
@@ -123,6 +214,11 @@ gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
priv->frame_time = g_get_monotonic_time (); /* more sane than zero */
priv->freeze_count = 0;
#ifdef G_ENABLE_DEBUG
if (fps_counter == 0)
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
#endif
}
static void
@@ -405,7 +501,7 @@ gdk_frame_clock_paint_idle (void *data)
{
int iter;
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES))
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
{
if (priv->phase != GDK_FRAME_CLOCK_PHASE_LAYOUT &&
(priv->requested & GDK_FRAME_CLOCK_PHASE_LAYOUT))
@@ -435,7 +531,7 @@ gdk_frame_clock_paint_idle (void *data)
if (priv->freeze_count == 0)
{
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES))
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
{
if (priv->phase != GDK_FRAME_CLOCK_PHASE_PAINT &&
(priv->requested & GDK_FRAME_CLOCK_PHASE_PAINT))
@@ -462,7 +558,7 @@ gdk_frame_clock_paint_idle (void *data)
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES))
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
timings->frame_end_time = g_get_monotonic_time ();
#endif /* G_ENABLE_DEBUG */
}
@@ -475,6 +571,12 @@ gdk_frame_clock_paint_idle (void *data)
}
#ifdef G_ENABLE_DEBUG
if (gdk_profiler_is_running ())
{
add_timings_to_profiler (timings);
gdk_profiler_set_counter (fps_counter, timings->frame_end_time * 1000, frame_clock_get_fps (clock));
}
if (GDK_DEBUG_CHECK (FRAMES))
{
if (timings && timings->complete)
+230
View File
@@ -0,0 +1,230 @@
/* GDK - The GIMP Drawing Kit
*
* gdkprofiler.c: A simple profiler
*
* Copyright © 2018 Matthias Clasen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "gdkversionmacros.h"
#include "gdkprofilerprivate.h"
#include "gdkframeclockprivate.h"
#ifndef G_OS_WIN32
#include "capture/sp-capture-writer.h"
static SpCaptureWriter *writer = NULL;
static gboolean running = FALSE;
static void
profiler_stop (void)
{
if (writer)
sp_capture_writer_unref (writer);
}
void
gdk_profiler_start (int fd)
{
if (writer)
return;
sp_clock_init ();
if (fd == -1)
{
gchar *filename;
filename = g_strdup_printf ("gtk.%d.syscap", getpid ());
g_print ("Writing profiling data to %s\n", filename);
writer = sp_capture_writer_new (filename, 16*1024);
g_free (filename);
}
else if (fd > 2)
writer = sp_capture_writer_new_from_fd (fd, 16*1024);
if (writer)
running = TRUE;
atexit (profiler_stop);
}
void
gdk_profiler_stop (void)
{
running = FALSE;
}
gboolean
gdk_profiler_is_running (void)
{
return running;
}
void
gdk_profiler_add_mark (gint64 start,
guint64 duration,
const char *name,
const char *message)
{
if (!running)
return;
sp_capture_writer_add_mark (writer,
start,
-1, getpid (),
duration,
"gtk", name, message);
}
static guint
define_counter (const char *name,
const char *description,
int type)
{
SpCaptureCounter counter;
if (!writer)
return 0;
counter.id = (guint) sp_capture_writer_request_counter (writer, 1);
counter.type = type;
counter.value.vdbl = 0;
g_strlcpy (counter.category, "gtk", sizeof counter.category);
g_strlcpy (counter.name, name, sizeof counter.name);
g_strlcpy (counter.description, description, sizeof counter.name);
sp_capture_writer_define_counters (writer,
SP_CAPTURE_CURRENT_TIME,
-1,
getpid (),
&counter,
1);
return counter.id;
}
guint
gdk_profiler_define_counter (const char *name,
const char *description)
{
return define_counter (name, description, SP_CAPTURE_COUNTER_DOUBLE);
}
guint
gdk_profiler_define_int_counter (const char *name,
const char *description)
{
return define_counter (name, description, SP_CAPTURE_COUNTER_INT64);
}
void
gdk_profiler_set_counter (guint id,
gint64 time,
double val)
{
SpCaptureCounterValue value;
if (!running)
return;
value.vdbl = val;
sp_capture_writer_set_counters (writer,
time,
-1, getpid (),
&id, &value, 1);
}
void
gdk_profiler_set_int_counter (guint id,
gint64 time,
gint64 val)
{
SpCaptureCounterValue value;
if (!running)
return;
value.v64 = val;
sp_capture_writer_set_counters (writer,
time,
-1, getpid (),
&id, &value, 1);
}
#else
void
gdk_profiler_start (int fd)
{
}
void
gdk_profiler_stop (void)
{
}
gboolean
gdk_profiler_is_running (void)
{
return FALSE;
}
void
gdk_profiler_add_mark (gint64 start,
guint64 duration,
const char *name,
const char *message)
{
}
guint
gdk_profiler_define_counter (const char *name,
const char *description)
{
return 0;
}
void
gdk_profiler_set_counter (guint id,
gint64 time,
double value)
{
}
guint
gdk_profiler_define_int_counter (const char *name,
const char *description)
{
return 0;
}
void
gdk_profiler_set_int_counter (guint id,
gint64 time,
gint64 value)
{
}
#endif /* G_OS_WIN32 */
+46
View File
@@ -0,0 +1,46 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2018 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 __GDK_PROFILER_PRIVATE_H__
#define __GDK_PROFILER_PRIVATE_H__
#include "gdk/gdkframeclock.h"
#include "gdk/gdkdisplay.h"
G_BEGIN_DECLS
void gdk_profiler_start (int fd);
void gdk_profiler_stop (void);
gboolean gdk_profiler_is_running (void);
void gdk_profiler_add_mark (gint64 start,
guint64 duration,
const char *name,
const char *message);
guint gdk_profiler_define_counter (const char *name,
const char *description);
void gdk_profiler_set_counter (guint id,
gint64 time,
double value);
guint gdk_profiler_define_int_counter (const char *name,
const char *description);
void gdk_profiler_set_int_counter (guint id,
gint64 time,
gint64 value);
G_END_DECLS
#endif /* __GDK_PROFILER_PRIVATE_H__ */
+4 -1
View File
@@ -4202,7 +4202,10 @@ void
gdk_surface_set_startup_id (GdkSurface *surface,
const gchar *startup_id)
{
GDK_SURFACE_IMPL_GET_CLASS (surface->impl)->set_startup_id (surface, startup_id);
GdkSurfaceImplClass *klass = GDK_SURFACE_IMPL_GET_CLASS (surface->impl);
if (klass->set_startup_id)
klass->set_startup_id (surface, startup_id);
}
/**
+8
View File
@@ -45,8 +45,16 @@ gdk_public_sources = files([
'gdkvulkancontext.c',
'gdksurface.c',
'gdksurfaceimpl.c',
'gdkprofiler.c'
])
if not win32_enabled
gdk_public_sources += files([
'capture/sp-capture-writer.c',
'capture/sp-clock.c'
])
endif
gdk_public_headers = files([
'gdk-autocleanup.h',
'gdk.h',
+16 -2
View File
@@ -21,6 +21,7 @@
#include "gdk/gdkgltextureprivate.h"
#include "gdk/gdkglcontextprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include <epoxy/gl.h>
#include <cairo-ft.h>
@@ -1268,10 +1269,17 @@ render_blur_node (GskGLRenderer *self,
const float min_y = builder->dy + node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const float blur_radius = gsk_blur_node_get_radius (node);
int texture_id;
gboolean is_offscreen;
RenderOp op;
if (blur_radius <= 0)
{
gsk_gl_renderer_add_render_ops (self, gsk_blur_node_get_child (node), builder);
return;
}
/* TODO(perf): We're forcing the child offscreen even if it's a texture
* so the resulting offscreen texture is bigger by the gaussian blur factor
* (see gsk_blur_node_new), but we didn't have to do that if the blur
@@ -3001,7 +3009,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
gsize buffer_size;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 gpu_time, cpu_time;
gint64 gpu_time, cpu_time, start_time;
#endif
#ifdef G_ENABLE_DEBUG
@@ -3109,6 +3117,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
#ifdef G_ENABLE_DEBUG
gsk_profiler_counter_inc (profiler, self->profile_counters.frames);
start_time = gsk_profiler_timer_get_start (profiler, self->profile_timers.cpu_time);
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
@@ -3116,6 +3125,10 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
gsk_profiler_timer_set (profiler, self->profile_timers.gpu_time, gpu_time);
gsk_profiler_push_samples (profiler);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (start_time, cpu_time, "render", "");
#endif
}
@@ -3132,6 +3145,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
g_return_val_if_fail (self->gl_context != NULL, NULL);
gdk_gl_context_make_current (self->gl_context);
gdk_gl_context_push_debug_group_printf (self->gl_context,
"Render %s<%p> to texture", root->node_class->type_name, root);
@@ -3139,7 +3153,6 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
height = ceilf (viewport->size.height);
self->scale_factor = gdk_surface_get_scale_factor (gsk_renderer_get_surface (renderer));
gdk_gl_context_make_current (self->gl_context);
/* Prepare our framebuffer */
gsk_gl_driver_begin_frame (self->gl_driver);
@@ -3191,6 +3204,7 @@ gsk_gl_renderer_render (GskRenderer *renderer,
if (self->gl_context == NULL)
return;
gdk_gl_context_make_current (self->gl_context);
gdk_gl_context_push_debug_group_printf (self->gl_context,
"Render root node %p", root);
+13
View File
@@ -365,6 +365,19 @@ gsk_profiler_timer_get (GskProfiler *profiler,
return timer->value;
}
gint64
gsk_profiler_timer_get_start (GskProfiler *profiler,
GQuark timer_id)
{
NamedTimer *timer;
timer = gsk_profiler_get_timer (profiler, timer_id);
if (timer == NULL)
return 0;
return timer->start_time;
}
void
gsk_profiler_reset (GskProfiler *profiler)
{
+2
View File
@@ -40,6 +40,8 @@ gint64 gsk_profiler_counter_get (GskProfiler *profiler,
GQuark counter_id);
gint64 gsk_profiler_timer_get (GskProfiler *profiler,
GQuark timer_id);
gint64 gsk_profiler_timer_get_start (GskProfiler *profiler,
GQuark timer_id);
void gsk_profiler_reset (GskProfiler *profiler);
+5 -1
View File
@@ -636,6 +636,7 @@ gsk_texture_node_draw (GskRenderNode *node,
{
GskTextureNode *self = (GskTextureNode *) node;
cairo_surface_t *surface;
cairo_pattern_t *pattern;
surface = gdk_texture_download_surface (self->texture);
@@ -646,11 +647,14 @@ gsk_texture_node_draw (GskRenderNode *node,
node->bounds.size.width / gdk_texture_get_width (self->texture),
node->bounds.size.height / gdk_texture_get_height (self->texture));
cairo_set_source_surface (cr, surface, 0, 0);
pattern = cairo_pattern_create_for_surface (surface);
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
cairo_set_source (cr, pattern);
cairo_paint (cr);
cairo_restore (cr);
cairo_pattern_destroy (pattern);
cairo_surface_destroy (surface);
}
+157 -126
View File
@@ -1,13 +1,16 @@
#include "gskrendernodeparserprivate.h"
#include <gdk/gdkrgbaprivate.h>
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcssparserprivate.h"
#include "gskroundedrectprivate.h"
#include "gskrendernodeprivate.h"
#include "gsktransformprivate.h"
#include "gdk/gdkrgbaprivate.h"
#include "gdk/gdktextureprivate.h"
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcssparserprivate.h"
#include "gtk/css/gtkcssdataurlprivate.h"
typedef struct _Declaration Declaration;
struct _Declaration
@@ -18,17 +21,12 @@ struct _Declaration
};
static gboolean
parse_semicolon (GtkCssParser *parser)
check_eof (GtkCssParser *parser)
{
const GtkCssToken *token;
token = gtk_css_parser_get_token (parser);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_warn_syntax (parser, "No ';' at end of block");
return TRUE;
}
else if (!gtk_css_token_is (token, GTK_CSS_TOKEN_SEMICOLON))
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_error_syntax (parser, "Expected ';' at end of statement");
return FALSE;
@@ -62,7 +60,7 @@ parse_rect (GtkCssParser *parser,
graphene_rect_t r;
if (!parse_rect_without_semicolon (parser, &r) ||
!parse_semicolon (parser))
!check_eof (parser))
return FALSE;
graphene_rect_init_from_rect (out_rect, &r);
@@ -70,35 +68,70 @@ parse_rect (GtkCssParser *parser,
}
static gboolean
parse_data (GtkCssParser *parser,
gpointer out_data)
parse_texture (GtkCssParser *parser,
gpointer out_data)
{
const GtkCssToken *token;
struct {
guchar *data;
gsize data_len;
} *texture_data = out_data;
GdkTexture *texture;
GError *error = NULL;
GtkCssLocation start_location;
char *url, *scheme;
token = gtk_css_parser_get_token (parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
start_location = *gtk_css_parser_get_start_location (parser);
url = gtk_css_parser_consume_url (parser);
if (url == NULL)
return FALSE;
if (!g_str_has_prefix (token->string.string, "data:;base64,"))
scheme = g_uri_parse_scheme (url);
if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
{
gtk_css_parser_error_value (parser, "Only base64 encoded data is allowed");
GInputStream *stream;
GdkPixbuf *pixbuf;
GBytes *bytes;
texture = NULL;
bytes = gtk_css_data_url_parse (url, NULL, &error);
if (bytes)
{
stream = g_memory_input_stream_new_from_bytes (bytes);
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
g_object_unref (stream);
if (pixbuf != NULL)
{
texture = gdk_texture_new_for_pixbuf (pixbuf);
g_object_unref (pixbuf);
}
}
}
else
{
GFile *file;
file = gtk_css_parser_resolve_url (parser, url);
texture = gdk_texture_new_from_file (file, &error);
g_object_unref (file);
}
g_free (scheme);
g_free (url);
if (texture == NULL)
{
gtk_css_parser_emit_error (parser,
&start_location,
gtk_css_parser_get_end_location (parser),
error);
g_clear_error (&error);
return FALSE;
}
texture_data->data = g_base64_decode (token->string.string + strlen ("data:;base64,"),
&texture_data->data_len);
gtk_css_parser_consume_token (parser);
if (!parse_semicolon (parser))
if (!check_eof (parser))
{
g_free (texture_data->data);
g_object_unref (texture);
return FALSE;
}
*(GdkTexture **) out_data = texture;
return TRUE;
}
@@ -116,7 +149,7 @@ parse_rounded_rect (GtkCssParser *parser,
if (!gtk_css_parser_try_delim (parser, '/'))
{
if (!parse_semicolon (parser))
if (!check_eof (parser))
return FALSE;
gsk_rounded_rect_init_from_rect (out_rect, &r, 0);
return TRUE;
@@ -171,7 +204,7 @@ parse_rounded_rect (GtkCssParser *parser,
corners[i].height = corners[i].width;
}
if (!parse_semicolon (parser))
if (!check_eof (parser))
return FALSE;
gsk_rounded_rect_init (out_rect, &r, &corners[0], &corners[1], &corners[2], &corners[3]);
@@ -186,7 +219,7 @@ parse_color (GtkCssParser *parser,
GdkRGBA color;
if (!gdk_rgba_parser_parse (parser, &color) ||
!parse_semicolon (parser))
!check_eof (parser))
return FALSE;
*(GdkRGBA *) out_color = color;
@@ -201,7 +234,7 @@ parse_double (GtkCssParser *parser,
double d;
if (!gtk_css_parser_consume_number (parser, &d) ||
!parse_semicolon (parser))
!check_eof (parser))
return FALSE;
*(double *) out_double = d;
@@ -217,7 +250,7 @@ parse_point (GtkCssParser *parser,
if (!gtk_css_parser_consume_number (parser, &x) ||
!gtk_css_parser_consume_number (parser, &y) ||
!parse_semicolon (parser))
!check_eof (parser))
return FALSE;
graphene_point_init (out_point, x, y);
@@ -232,7 +265,7 @@ parse_transform (GtkCssParser *parser,
GskTransform *transform;
if (!gsk_transform_parser_parse (parser, &transform) ||
!parse_semicolon (parser))
!check_eof (parser))
{
gsk_transform_unref (transform);
return FALSE;
@@ -258,7 +291,7 @@ parse_string (GtkCssParser *parser,
s = g_strdup (token->string.string);
gtk_css_parser_consume_token (parser);
if (!parse_semicolon (parser))
if (!check_eof (parser))
{
g_free (s);
return FALSE;
@@ -313,7 +346,7 @@ parse_stops (GtkCssParser *parser,
g_array_free (*(GArray **) out_stops, TRUE);
*(GArray **) out_stops = stops;
return parse_semicolon (parser);
return check_eof (parser);
error:
g_array_free (stops, TRUE);
@@ -333,7 +366,7 @@ parse_colors4 (GtkCssParser *parser,
return FALSE;
}
return parse_semicolon (parser);
return check_eof (parser);
}
static gboolean
@@ -371,7 +404,7 @@ parse_shadows (GtkCssParser *parser,
break;
}
return parse_semicolon (parser);
return check_eof (parser);
}
static const struct
@@ -407,7 +440,7 @@ parse_blend_mode (GtkCssParser *parser,
{
if (gtk_css_parser_try_ident (parser, blend_modes[i].name))
{
if (!parse_semicolon (parser))
if (!check_eof (parser))
return FALSE;
*(GskBlendMode *) out_mode = blend_modes[i].mode;
return TRUE;
@@ -444,7 +477,7 @@ parse_font (GtkCssParser *parser,
/* Skip font name token */
gtk_css_parser_consume_token (parser);
return parse_semicolon (parser);
return check_eof (parser);
}
static gboolean
@@ -497,7 +530,7 @@ parse_glyphs (GtkCssParser *parser,
*((PangoGlyphString **)out_glyphs) = glyph_string;
return parse_semicolon (parser);
return check_eof (parser);
}
static gboolean
@@ -517,15 +550,15 @@ parse_container_node (GtkCssParser *parser)
token = gtk_css_parser_get_token (parser))
{
node = NULL;
/* We don't wand a semicolon here, but the parse_node function will figure
* that out itself and return an error if we encounter one.
*/
gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_OPEN_CURLY);
if (parse_node (parser, &node))
{
g_ptr_array_add (nodes, node);
}
else
{
gtk_css_parser_skip_until (parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (parser);
}
g_ptr_array_add (nodes, node);
gtk_css_parser_end_block (parser);
}
node = gsk_container_node_new ((GskRenderNode **) nodes->pdata, nodes->len);
@@ -535,25 +568,6 @@ parse_container_node (GtkCssParser *parser)
return node;
}
static void
parse_declarations_sync (GtkCssParser *parser)
{
const GtkCssToken *token;
for (token = gtk_css_parser_get_token (parser);
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
token = gtk_css_parser_get_token (parser))
{
if (gtk_css_token_is (token, GTK_CSS_TOKEN_SEMICOLON) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_CURLY))
{
gtk_css_parser_skip (parser);
break;
}
gtk_css_parser_skip (parser);
}
}
static guint
parse_declarations (GtkCssParser *parser,
const Declaration *declarations,
@@ -569,6 +583,8 @@ parse_declarations (GtkCssParser *parser,
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
token = gtk_css_parser_get_token (parser))
{
gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_OPEN_CURLY);
for (i = 0; i < n_declarations; i++)
{
if (gtk_css_token_is_ident (token, declarations[i].name))
@@ -578,7 +594,6 @@ parse_declarations (GtkCssParser *parser,
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
{
gtk_css_parser_error_syntax (parser, "Expected ':' after variable declaration");
parse_declarations_sync (parser);
}
else
{
@@ -587,8 +602,6 @@ parse_declarations (GtkCssParser *parser,
gtk_css_parser_warn_syntax (parser, "Variable \"%s\" defined multiple times", declarations[i].name);
if (declarations[i].parse_func (parser, declarations[i].result))
parsed |= (1 << i);
else
parse_declarations_sync (parser);
}
break;
}
@@ -599,8 +612,9 @@ parse_declarations (GtkCssParser *parser,
gtk_css_parser_error_syntax (parser, "No variable named \"%s\"", token->string.string);
else
gtk_css_parser_error_syntax (parser, "Expected a variable name");
parse_declarations_sync (parser);
}
gtk_css_parser_end_block (parser);
}
return parsed;
@@ -691,35 +705,21 @@ static GskRenderNode *
parse_texture_node (GtkCssParser *parser)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0);
struct {
guchar *data;
gsize data_len;
} texture_data = { NULL, 0 };
double width = 0.0;
double height = 0.0;
GdkTexture *texture = NULL;
const Declaration declarations[] = {
{ "bounds", parse_rect, &bounds },
{ "width", parse_double, &width },
{ "height", parse_double, &height },
{ "texture", parse_data, &texture_data }
{ "texture", parse_texture, &texture }
};
GdkTexture *texture;
GdkPixbuf *pixbuf;
GskRenderNode *node;
parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
pixbuf = gdk_pixbuf_new_from_data (texture_data.data,
GDK_COLORSPACE_RGB,
TRUE,
8,
(int)width,
(int)height,
4 * (int)width,
(GdkPixbufDestroyNotify)g_free, NULL);
if (texture == NULL)
{
gtk_css_parser_error_syntax (parser, "Missing \"texture\" property definition");
return NULL;
}
texture = gdk_texture_new_for_pixbuf (pixbuf);
g_object_unref (pixbuf);
node = gsk_texture_node_new (texture, &bounds);
g_object_unref (texture);
@@ -903,13 +903,46 @@ parse_blend_node (GtkCssParser *parser)
return result;
}
static GskRenderNode *
parse_repeat_node (GtkCssParser *parser)
{
GskRenderNode *child = NULL;
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0);
graphene_rect_t child_bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0);
const Declaration declarations[] = {
{ "child", parse_node, &child },
{ "bounds", parse_rect, &bounds },
{ "child-bounds", parse_rect, &child_bounds },
};
GskRenderNode *result;
guint parse_result;
parse_result = parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
if (child == NULL)
{
gtk_css_parser_error_syntax (parser, "Missing \"child\" property definition");
return NULL;
}
if (!(parse_result & (1 << 1)))
gsk_render_node_get_bounds (child, &bounds);
if (!(parse_result & (1 << 2)))
gsk_render_node_get_bounds (child, &child_bounds);
result = gsk_repeat_node_new (&bounds, child, &child_bounds);
gsk_render_node_unref (child);
return result;
}
static GskRenderNode *
parse_text_node (GtkCssParser *parser)
{
PangoFont *font = NULL;
double x = 0;
double y = 0;
GdkRGBA color = { 0, 0, 0, 0 };
GdkRGBA color = { 0, 0, 0, 1 };
PangoGlyphString *glyphs = NULL;
const Declaration declarations[] = {
{ "font", parse_font, &font },
@@ -1091,53 +1124,46 @@ parse_node (GtkCssParser *parser,
{ "blur", parse_blur_node },
{ "debug", parse_debug_node },
{ "blend", parse_blend_node },
#if 0
{ "repeat", parse_repeat_node },
#if 0
{ "cairo", parse_cairo_node },
#endif
};
GskRenderNode **node_p = out_node;
const GtkCssToken *token;
guint i;
token = gtk_css_parser_get_token (parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
gtk_css_parser_error_syntax (parser, "Expected a node name");
return FALSE;
}
for (i = 0; i < G_N_ELEMENTS (node_parsers); i++)
{
if (gtk_css_token_is_ident (token, node_parsers[i].name))
if (gtk_css_parser_try_ident (parser, node_parsers[i].name))
{
GskRenderNode *node;
gtk_css_parser_consume_token (parser);
token = gtk_css_parser_get_token (parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_CURLY))
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_error_syntax (parser, "Expected '{' after node name");
return FALSE;
}
gtk_css_parser_start_block (parser);
gtk_css_parser_end_block_prelude (parser);
node = node_parsers[i].func (parser);
if (node)
{
token = gtk_css_parser_get_token (parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
gtk_css_parser_error_syntax (parser, "Expected '}' at end of node definition");
g_clear_pointer (node_p, gsk_render_node_unref);
*node_p = node;
}
gtk_css_parser_end_block (parser);
return node != NULL;
}
}
gtk_css_parser_error_value (parser, "\"%s\" is not a valid node name", token->string.string);
if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT))
gtk_css_parser_error_value (parser, "\"%s\" is not a valid node name",
gtk_css_parser_get_token (parser)->string.string);
else
gtk_css_parser_error_syntax (parser, "Expected a node name");
return FALSE;
}
@@ -1464,6 +1490,16 @@ append_node_param (Printer *p,
render_node_print (p, node);
}
static cairo_status_t
surface_write (void *closure,
const unsigned char *data,
unsigned int length)
{
g_byte_array_append (closure, data, length);
return CAIRO_STATUS_SUCCESS;
}
static void
render_node_print (Printer *p,
GskRenderNode *node)
@@ -1704,30 +1740,25 @@ render_node_print (Printer *p,
case GSK_TEXTURE_NODE:
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
int stride;
int len;
guchar *data;
cairo_surface_t *surface;
GByteArray *array;
char *b64;
start_node (p, "texture");
append_rect_param (p, "bounds", &node->bounds);
/* TODO: width and height here are unnecessary and can later be computed from the data length? */
append_float_param (p, "width", gdk_texture_get_width (texture));
append_float_param (p, "height", gdk_texture_get_height (texture));
stride = 4 * gdk_texture_get_width (texture);
len = sizeof (guchar) * stride * gdk_texture_get_height (texture);
data = g_malloc (len);
gdk_texture_download (texture, data, stride);
b64 = g_base64_encode (data, len);
surface = gdk_texture_download_surface (texture);
array = g_byte_array_new ();
cairo_surface_write_to_png_stream (surface, surface_write, array);
b64 = g_base64_encode (array->data, array->len);
_indent (p);
g_string_append_printf (p->str, "texture: \"data:;base64,%s\";\n", b64);
g_string_append_printf (p->str, "texture: url(\"data:image/png;base64,%s\");\n", b64);
end_node (p);
g_free (b64);
g_free (data);
g_byte_array_free (array, TRUE);
cairo_surface_destroy (surface);
}
break;
+24 -1
View File
@@ -13,6 +13,7 @@
#include "gskvulkanglyphcacheprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include <graphene.h>
@@ -38,6 +39,9 @@ typedef struct {
} ProfileTimers;
#endif
static guint texture_pixels_counter;
static guint fallback_pixels_counter;
struct _GskVulkanRenderer
{
GskRenderer parent_instance;
@@ -170,7 +174,7 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
GdkTexture *texture;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 cpu_time;
gint64 cpu_time, start_time;
#endif
#ifdef G_ENABLE_DEBUG
@@ -201,10 +205,22 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
gsk_vulkan_render_free (render);
#ifdef G_ENABLE_DEBUG
start_time = gsk_profiler_timer_get_start (profiler, self->profile_timers.cpu_time);
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
gsk_profiler_push_samples (profiler);
if (gdk_profiler_is_running ())
{
gdk_profiler_add_mark (start_time, cpu_time, "render", "");
gdk_profiler_set_int_counter (texture_pixels_counter,
start_time + cpu_time,
gsk_profiler_counter_get (profiler, self->profile_counters.texture_pixels));
gdk_profiler_set_int_counter (fallback_pixels_counter,
start_time + cpu_time,
gsk_profiler_counter_get (profiler, self->profile_counters.fallback_pixels));
}
#endif
return texture;
@@ -284,6 +300,13 @@ gsk_vulkan_renderer_init (GskVulkanRenderer *self)
self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE);
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), SYNC))
self->profile_timers.gpu_time = gsk_profiler_add_timer (profiler, "gpu-time", "GPU time", FALSE, TRUE);
if (texture_pixels_counter == 0)
{
texture_pixels_counter = gdk_profiler_define_int_counter ("texture-pixels", "Texture Pixels");
fallback_pixels_counter = gdk_profiler_define_int_counter ("fallback-pixels", "Fallback Pixels");
}
#endif
}
+1 -3
View File
@@ -244,7 +244,6 @@ gtk_notebook_page_accessible_new (GtkNotebookAccessible *notebook,
AtkObject *atk_object;
GtkNotebookPageAccessible *page;
GtkNotebook *nb;
GtkWidget *notebook_page;
g_return_val_if_fail (GTK_IS_NOTEBOOK_ACCESSIBLE (notebook), NULL);
g_return_val_if_fail (GTK_WIDGET (child), NULL);
@@ -261,9 +260,8 @@ gtk_notebook_page_accessible_new (GtkNotebookAccessible *notebook,
atk_object_set_parent (gtk_widget_get_accessible (child), atk_object);
nb = GTK_NOTEBOOK (gtk_accessible_get_widget (page->priv->notebook));
notebook_page = gtk_notebook_get_page (nb, child);
g_signal_connect (notebook_page,
g_signal_connect (gtk_notebook_get_page (nb, child),
"notify::tab-label",
G_CALLBACK (notify_tab_label), page);
+175
View File
@@ -0,0 +1,175 @@
/* GStreamer data:// uri source element
* Copyright (C) 2009 Igalia S.L
* Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*<private>
* SECTION:data-url
* @title: data: URLs
*
* These function allow encoding and decoding of data: URLs, see
* [RFC 2397](http://tools.ietf.org/html/rfc2397) for more information.
*/
#include "config.h"
#include "gtkcssdataurlprivate.h"
#include "../gtkintl.h"
#include <string.h>
/*<private>
* gtk_css_data_url_parse:
* @url: the URL to parse
* @out_mimetype: (out nullable optional): Return location to set the contained
* mime type to. If no mime type was specified, this value is set to %NULL.
* @error: error location or %NULL for none
*
* Decodes a data URL according to RFC2397 and returns the decoded data.
*
* Returns: a new #GBytes with the decoded data or %NULL on error
**/
GBytes *
gtk_css_data_url_parse (const char *url,
char **out_mimetype,
GError **error)
{
char *mimetype = NULL;
const char *parameters_start;
const char *data_start;
GBytes *bytes;
gboolean base64 = FALSE;
char *charset = NULL;
gpointer bdata;
gsize bsize;
/* url must be an URI as defined in RFC 2397
* data:[<mediatype>][;base64],<data>
*/
if (g_ascii_strncasecmp ("data:", url, 5) != 0)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_FILENAME,
_("Not a data: URL"));
return NULL;
}
url += 5;
parameters_start = strchr (url, ';');
data_start = strchr (url, ',');
if (data_start == NULL)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_FILENAME,
_("Malformed data: URL"));
return NULL;
}
if (parameters_start > data_start)
parameters_start = NULL;
if (data_start != url && parameters_start != url)
{
mimetype = g_strndup (url,
(parameters_start ? parameters_start
: data_start) - url);
}
else
{
mimetype = NULL;
}
if (parameters_start != NULL)
{
char *parameters_str;
char **parameters;
guint i;
parameters_str = g_strndup (parameters_start + 1, data_start - parameters_start - 1);
parameters = g_strsplit (parameters_str, ";", -1);
for (i = 0; parameters[i] != NULL; i++)
{
if (g_ascii_strcasecmp ("base64", parameters[i]) == 0)
{
base64 = TRUE;
}
else if (g_ascii_strncasecmp ("charset=", parameters[i], 8) == 0)
{
g_free (charset);
charset = g_strdup (parameters[i] + 8);
}
}
g_free (parameters_str);
g_strfreev (parameters);
}
/* Skip comma */
data_start += 1;
if (base64)
{
bdata = g_base64_decode (data_start, &bsize);
}
else
{
/* URI encoded, i.e. "percent" encoding */
/* XXX: This doesn't allow nul bytes */
bdata = g_uri_unescape_string (data_start, NULL);
if (bdata == NULL)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_FILENAME,
_("Could not unescape string"));
g_free (mimetype);
return NULL;
}
bsize = strlen (bdata);
}
/* Convert to UTF8 */
if ((mimetype == NULL || g_ascii_strcasecmp ("text/plain", mimetype) == 0) &&
charset && g_ascii_strcasecmp ("US-ASCII", charset) != 0
&& g_ascii_strcasecmp ("UTF-8", charset) != 0)
{
gsize read;
gsize written;
gpointer data;
data = g_convert_with_fallback (bdata, bsize,
"UTF-8", charset,
(char *) "*",
&read, &written, NULL);
g_free (bdata);
bdata = data;
bsize = written;
}
bytes = g_bytes_new_take (bdata, bsize);
g_free (charset);
if (out_mimetype)
*out_mimetype = mimetype;
else
g_free (mimetype);
return bytes;
}
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright © 2019 Benjamin Otte
*
* 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/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_DATA_URL_PRIVATE_H__
#define __GTK_CSS_DATA_URL_PRIVATE_H__
#include <gio/gio.h>
G_BEGIN_DECLS
GBytes * gtk_css_data_url_parse (const char *url,
char **out_mimetype,
GError **error);
G_END_DECLS
#endif /* __GTK_CSS_DATA_URL_PRIVATE_H__ */
+14 -14
View File
@@ -335,7 +335,9 @@ gtk_css_parser_consume_token (GtkCssParser *self)
/* unpreserved tokens MUST be consumed via start_block() */
g_assert (gtk_css_token_is_preserved (&self->token, NULL));
gtk_css_token_clear (&self->token);
/* Don't consume any tokens at the end of a block */
if (!gtk_css_token_is (gtk_css_parser_peek_token (self), GTK_CSS_TOKEN_EOF))
gtk_css_token_clear (&self->token);
}
void
@@ -435,7 +437,15 @@ gtk_css_parser_end_block (GtkCssParser *self)
else
{
g_array_set_size (self->blocks, self->blocks->len - 1);
gtk_css_parser_skip (self);
if (gtk_css_token_is_preserved (&self->token, NULL))
{
gtk_css_token_clear (&self->token);
}
else
{
gtk_css_parser_start_block (self);
gtk_css_parser_end_block (self);
}
}
}
@@ -963,11 +973,10 @@ gtk_css_parser_parse_url_arg (GtkCssParser *parser,
*
* Returns: (nullable) (transfer full): the resulting URL or %NULL on error
**/
GFile *
char *
gtk_css_parser_consume_url (GtkCssParser *self)
{
const GtkCssToken *token;
GFile *result;
char *url;
token = gtk_css_parser_get_token (self);
@@ -988,16 +997,7 @@ gtk_css_parser_consume_url (GtkCssParser *self)
return NULL;
}
result = gtk_css_parser_resolve_url (self, url);
if (result == NULL)
{
gtk_css_parser_error_import (self, "Could not resolve \"%s\" to a valid URL", url);
g_free (url);
return NULL;
}
g_free (url);
return result;
return url;
}
gboolean
+1 -1
View File
@@ -134,7 +134,7 @@ gboolean gtk_css_parser_try_token (GtkCssParser
char * gtk_css_parser_consume_ident (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
char * gtk_css_parser_consume_string (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
GFile * gtk_css_parser_consume_url (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
char * gtk_css_parser_consume_url (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
gboolean gtk_css_parser_consume_number (GtkCssParser *self,
double *number);
gboolean gtk_css_parser_consume_integer (GtkCssParser *self,
+25 -17
View File
@@ -633,13 +633,6 @@ is_name (char c)
|| c == '-';
}
static gboolean
is_valid_escape (char c1, char c2)
{
return c1 == '\\'
&& !is_newline (c2);
}
static gboolean
is_non_printable (char c)
{
@@ -650,6 +643,25 @@ is_non_printable (char c)
|| c == 0x7F;
}
static gboolean
is_valid_escape (const char *data,
const char *end)
{
switch (end - data)
{
default:
if (is_newline (data[1]))
return FALSE;
G_GNUC_FALLTHROUGH;
case 1:
return data[0] == '\\';
case 0:
return FALSE;
}
}
static inline gsize
gtk_css_tokenizer_remaining (GtkCssTokenizer *tokenizer)
{
@@ -659,15 +671,7 @@ gtk_css_tokenizer_remaining (GtkCssTokenizer *tokenizer)
static gboolean
gtk_css_tokenizer_has_valid_escape (GtkCssTokenizer *tokenizer)
{
switch (gtk_css_tokenizer_remaining (tokenizer))
{
case 0:
return FALSE;
case 1:
return *tokenizer->data == '\\';
default:
return is_valid_escape (tokenizer->data[0], tokenizer->data[1]);
}
return is_valid_escape (tokenizer->data, tokenizer->end);
}
static gboolean
@@ -814,7 +818,11 @@ gtk_css_tokenizer_read_escape (GtkCssTokenizer *tokenizer)
if (i == 0)
{
value = g_utf8_get_char_validated (tokenizer->data, gtk_css_tokenizer_remaining (tokenizer));
gsize remaining = gtk_css_tokenizer_remaining (tokenizer);
if (remaining == 0)
return 0xFFFD;
value = g_utf8_get_char_validated (tokenizer->data, remaining);
if (value == (gunichar) -1 || value == (gunichar) -2)
value = 0;
+1
View File
@@ -5,6 +5,7 @@ gtk_css_public_sources = files([
])
gtk_css_private_sources = files([
'gtkcssdataurl.c',
'gtkcssparser.c',
'gtkcsstokenizer.c',
])
+1
View File
@@ -70,6 +70,7 @@ for f in get_files('inspector', '.ui'):
xml += '''
<file>inspector/logo.png</file>
<file>inspector/inspector.css</file>
<file>emoji/emoji.data</file>
</gresource>
</gresources>'''
+1 -2
View File
@@ -684,7 +684,7 @@ update_credits_button_visibility (GtkAboutDialog *about)
gboolean show;
GtkStackPage *page;
page = gtk_stack_get_page (GTK_STACK (priv->stack), priv->system_page);
page = gtk_stack_get_page (GTK_STACK (priv->stack), priv->credits_page);
show = (priv->authors != NULL ||
priv->documenters != NULL ||
@@ -2155,7 +2155,6 @@ add_credits_section (GtkAboutDialog *about,
gtk_widget_set_halign (label, GTK_ALIGN_END);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
gtk_grid_attach (grid, label, 0, *row, 1, 1);
gtk_widget_show (label);
for (p = people; *p; p++)
{
+149
View File
@@ -21,6 +21,11 @@
#include "config.h"
#include "gtkapplication.h"
#include "gdkprofilerprivate.h"
#ifdef G_OS_UNIX
#include <gio/gunixfdlist.h>
#endif
#include <stdlib.h>
@@ -603,6 +608,148 @@ gtk_application_finalize (GObject *object)
G_OBJECT_CLASS (gtk_application_parent_class)->finalize (object);
}
#ifdef G_OS_UNIX
static const gchar org_gnome_Sysprof3_Profiler_xml[] =
"<node>"
"<interface name='org.gnome.Sysprof3.Profiler'>"
"<method name='Start'>"
"<arg type='h' name='fd' direction='in'/>"
"</method>"
"<method name='Stop'>"
"</method>"
"</interface>"
"</node>";
static GDBusInterfaceInfo *org_gnome_Sysprof3_Profiler;
static void
sysprof_profiler_method_call (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
if (strcmp (method_name, "Start") == 0)
{
GDBusMessage *message;
GUnixFDList *fd_list;
int fd = -1;
int idx;
if (gdk_profiler_is_running ())
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Profiler already running");
return;
}
g_variant_get (parameters, "(h)", &idx);
message = g_dbus_method_invocation_get_message (invocation);
fd_list = g_dbus_message_get_unix_fd_list (message);
if (fd_list)
fd = g_unix_fd_list_get (fd_list, idx, NULL);
gdk_profiler_start (fd);
}
else if (strcmp (method_name, "Stop") == 0)
{
if (!gdk_profiler_is_running ())
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Profiler not running");
return;
}
gdk_profiler_stop ();
}
else
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_UNKNOWN_METHOD,
"Unknown method");
return;
}
g_dbus_method_invocation_return_value (invocation, NULL);
}
static gboolean
gtk_application_dbus_register (GApplication *application,
GDBusConnection *connection,
const char *obect_path,
GError **error)
{
GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) application;
GDBusInterfaceVTable vtable = {
sysprof_profiler_method_call,
NULL,
NULL
};
if (org_gnome_Sysprof3_Profiler == NULL)
{
GDBusNodeInfo *info;
info = g_dbus_node_info_new_for_xml (org_gnome_Sysprof3_Profiler_xml, error);
if (info == NULL)
return FALSE;
org_gnome_Sysprof3_Profiler = g_dbus_node_info_lookup_interface (info, "org.gnome.Sysprof3.Profiler");
g_dbus_interface_info_ref (org_gnome_Sysprof3_Profiler);
g_dbus_node_info_unref (info);
}
dbus->profiler_id = g_dbus_connection_register_object (connection,
"/org/gtk/Profiler",
org_gnome_Sysprof3_Profiler,
&vtable,
NULL,
NULL,
error);
return TRUE;
}
static void
gtk_application_dbus_unregister (GApplication *application,
GDBusConnection *connection,
const char *obect_path)
{
GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) application;
g_dbus_connection_unregister_object (connection, dbus->profiler_id);
}
#else
static gboolean
gtk_application_dbus_register (GApplication *application,
GDBusConnection *connection,
const char *obect_path,
GError **error)
{
return TRUE;
}
static void
gtk_application_dbus_unregister (GApplication *application,
GDBusConnection *connection,
const char *obect_path)
{
}
#endif
static void
gtk_application_class_init (GtkApplicationClass *class)
{
@@ -619,6 +766,8 @@ gtk_application_class_init (GtkApplicationClass *class)
application_class->after_emit = gtk_application_after_emit;
application_class->startup = gtk_application_startup;
application_class->shutdown = gtk_application_shutdown;
application_class->dbus_register = gtk_application_dbus_register;
application_class->dbus_unregister = gtk_application_dbus_unregister;
class->window_added = gtk_application_window_added;
class->window_removed = gtk_application_window_removed;
+1
View File
@@ -127,6 +127,7 @@ typedef struct
gchar *menubar_path;
guint menubar_id;
guint profiler_id;
/* Session management... */
GDBusProxy *sm_proxy;
+10 -4
View File
@@ -245,10 +245,16 @@ gtk_css_image_recolor_parse_arg (GtkCssParser *parser,
switch (arg)
{
case 0:
self->file = gtk_css_parser_consume_url (parser);
if (self->file == NULL)
return 0;
return 1;
{
char *url = gtk_css_parser_consume_url (parser);
if (url == NULL)
return 0;
self->file = gtk_css_parser_resolve_url (parser, url);
g_free (url);
if (self->file == NULL)
return 0;
return 1;
}
case 1:
self->palette = gtk_css_palette_value_parse (parser);
+45 -3
View File
@@ -27,6 +27,8 @@
#include "gtkcssimagepaintableprivate.h"
#include "gtkstyleproviderprivate.h"
#include "gtk/css/gtkcssdataurlprivate.h"
G_DEFINE_TYPE (GtkCssImageUrl, _gtk_css_image_url, GTK_TYPE_CSS_IMAGE)
static GtkCssImage *
@@ -163,12 +165,52 @@ static gboolean
gtk_css_image_url_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
GtkCssImageUrl *self = GTK_CSS_IMAGE_URL (image);
char *url, *scheme;
url->file = gtk_css_parser_consume_url (parser);
if (url->file == NULL)
url = gtk_css_parser_consume_url (parser);
if (url == NULL)
return FALSE;
scheme = g_uri_parse_scheme (url);
if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
{
GInputStream *stream;
GdkPixbuf *pixbuf;
GBytes *bytes;
GError *error = NULL;
bytes = gtk_css_data_url_parse (url, NULL, &error);
if (bytes)
{
stream = g_memory_input_stream_new_from_bytes (bytes);
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
g_object_unref (stream);
if (pixbuf == NULL)
{
gtk_css_parser_emit_error (parser,
gtk_css_parser_get_start_location (parser),
gtk_css_parser_get_end_location (parser),
error);
g_clear_error (&error);
}
else
{
GdkTexture *texture = gdk_texture_new_for_pixbuf (pixbuf);
self->loaded_image = gtk_css_image_paintable_new (GDK_PAINTABLE (texture), GDK_PAINTABLE (texture));
g_object_unref (texture);
g_object_unref (pixbuf);
}
}
}
else
{
self->file = gtk_css_parser_resolve_url (parser, url);
}
g_free (url);
g_free (scheme);
return TRUE;
}
+14 -12
View File
@@ -61,18 +61,16 @@
* In addition, certain files will be read when GTK+ is initialized. First, the
* file `$XDG_CONFIG_HOME/gtk-4.0/gtk.css` is loaded if it exists. Then, GTK+
* loads the first existing file among
* `XDG_DATA_HOME/themes/THEME/gtk-VERSION/gtk.css`,
* `$HOME/.themes/THEME/gtk-VERSION/gtk.css`,
* `$XDG_DATA_DIRS/themes/THEME/gtk-VERSION/gtk.css` and
* `DATADIR/share/themes/THEME/gtk-VERSION/gtk.css`, where `THEME` is the name of
* the current theme (see the #GtkSettings:gtk-theme-name setting), `DATADIR`
* `XDG_DATA_HOME/themes/THEME/gtk-VERSION/gtk-VARIANT.css`,
* `$HOME/.themes/THEME/gtk-VERSION/gtk-VARIANT.css`,
* `$XDG_DATA_DIRS/themes/THEME/gtk-VERSION/gtk-VARIANT.css` and
* `DATADIR/share/themes/THEME/gtk-VERSION/gtk-VARIANT.css`, where `THEME` is the name of
* the current theme (see the #GtkSettings:gtk-theme-name setting),
* VARIANT is the variant to load (see the #GtkSettings:gtk-application-prefer-dark-theme setting), `DATADIR`
* is the prefix configured when GTK+ was compiled (unless overridden by the
* `GTK_DATA_PREFIX` environment variable), and `VERSION` is the GTK+ version number.
* If no file is found for the current version, GTK+ tries older versions all the
* way back to 4.0.
*
* In the same way, GTK+ tries to load a gtk-keys.css file for the current
* key theme, as defined by #GtkSettings:gtk-key-theme-name.
*/
@@ -697,7 +695,14 @@ parse_import (GtkCssScanner *scanner)
}
else
{
file = gtk_css_parser_consume_url (scanner->parser);
char *url = gtk_css_parser_consume_url (scanner->parser);
if (url)
{
file = gtk_css_parser_resolve_url (scanner->parser, url);
g_free (url);
}
else
file = NULL;
}
if (file == NULL)
@@ -1283,9 +1288,6 @@ _gtk_css_find_theme_dir (const gchar *dir,
for (i = MINOR; i >= 0; i = i - 2)
{
if (i < 14)
i = 0;
subsubdir = g_strdup_printf ("gtk-4.%d", i);
path = g_build_filename (base, subsubdir, file, NULL);
g_free (subsubdir);
+1
View File
@@ -686,6 +686,7 @@ gtk_emoji_chooser_init (GtkEmojiChooser *chooser)
populate_recent_section (chooser);
chooser->populate_idle = g_idle_add (populate_emoji_chooser, chooser);
g_source_set_name_by_id (chooser->populate_idle, "[gtk] populate_emoji_chooser");
}
static void
+1 -12
View File
@@ -87,18 +87,7 @@
* Applications can override system-wide settings by setting the property
* of the GtkSettings object with g_object_set(). This should be restricted
* to special cases though; GtkSettings are not meant as an application
* configuration facility. When doing so, you need to be aware that settings
* that are specific to individual widgets may not be available before the
* widget type has been realized at least once. The following example
* demonstrates a way to do this:
* |[<!-- language="C" -->
* gtk_init ();
*
* // make sure the type is realized
* g_type_class_unref (g_type_class_ref (GTK_TYPE_BUTTON));
*
* g_object_set (gtk_settings_get_default (), "gtk-enable-animations", FALSE, NULL);
* ]|
* configuration facility.
*
* There is one GtkSettings instance per display. It can be obtained with
* gtk_settings_get_for_display(), but in many cases, it is more convenient
-1
View File
@@ -78,7 +78,6 @@ gtk_test_init (int *argcp,
g_test_init (argcp, argvp, NULL);
gtk_disable_setlocale();
setlocale (LC_ALL, "en_US.UTF-8");
g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=%s");
/* XSendEvent() doesn't work yet on XI2 events.
* So at the moment gdk_test_simulate_* can only
+4 -1
View File
@@ -47,6 +47,7 @@
#include "gtkgestureprivate.h"
#include "gtkgesturesingle.h"
#include "gtkgestureswipe.h"
#include "gtkeventcontrollerkey.h"
#include "gtkintl.h"
#include "gtklayoutmanagerprivate.h"
#include "gtkmain.h"
@@ -5225,7 +5226,9 @@ gtk_widget_run_controllers (GtkWidget *widget,
* to collaborate with anything else. Break early if any such event
* controller handled the event.
*/
if (handled && !GTK_IS_GESTURE (controller))
if (handled &&
!GTK_IS_GESTURE (controller) &&
!GTK_IS_EVENT_CONTROLLER_KEY (controller))
break;
}
+11
View File
@@ -431,6 +431,7 @@ static void gtk_window_move_focus (GtkWidget *widget,
GtkDirectionType dir);
static void gtk_window_real_activate_default (GtkWindow *window);
static void gtk_window_real_activate_focus (GtkWindow *window);
static void gtk_window_keys_changed (GtkWindow *window);
static gboolean gtk_window_enable_debugging (GtkWindow *window,
gboolean toggle);
@@ -804,6 +805,7 @@ gtk_window_class_init (GtkWindowClass *klass)
container_class->forall = gtk_window_forall;
klass->activate_default = gtk_window_real_activate_default;
klass->activate_focus = gtk_window_real_activate_focus;
klass->keys_changed = gtk_window_keys_changed;
klass->enable_debugging = gtk_window_enable_debugging;
klass->close_request = gtk_window_close_request;
@@ -6232,6 +6234,15 @@ get_active_region_type (GtkWindow *window, gint x, gint y)
return GTK_WINDOW_REGION_CONTENT;
}
static void
gtk_window_real_activate_focus (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
gtk_widget_activate (priv->focus_widget);
}
static gboolean
gtk_window_has_mnemonic_modifier_pressed (GtkWindow *window)
{
+30 -15
View File
@@ -45,7 +45,8 @@ enum
PROP_0,
PROP_GROUP,
PROP_PREFIX,
PROP_NAME
PROP_NAME,
PROP_SIZEGROUP
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorActionEditor, gtk_inspector_action_editor, GTK_TYPE_BOX)
@@ -55,9 +56,8 @@ gtk_inspector_action_editor_init (GtkInspectorActionEditor *editor)
{
editor->priv = gtk_inspector_action_editor_get_instance_private (editor);
g_object_set (editor,
"orientation", GTK_ORIENTATION_VERTICAL,
"orientation", GTK_ORIENTATION_HORIZONTAL,
"spacing", 10,
"margin", 10,
NULL);
}
@@ -238,6 +238,9 @@ action_enabled_changed_cb (GActionGroup *group,
gboolean enabled,
GtkInspectorActionEditor *r)
{
if (!g_str_equal (action_name, r->priv->name))
return;
r->priv->enabled = enabled;
if (r->priv->parameter_entry)
{
@@ -252,6 +255,9 @@ action_state_changed_cb (GActionGroup *group,
GVariant *state,
GtkInspectorActionEditor *r)
{
if (!g_str_equal (action_name, r->priv->name))
return;
if (r->priv->state_entry)
variant_editor_set_value (r->priv->state_entry, state);
}
@@ -261,34 +267,30 @@ constructed (GObject *object)
{
GtkInspectorActionEditor *r = GTK_INSPECTOR_ACTION_EDITOR (object);
GVariant *state;
gchar *fullname;
GtkWidget *row;
GtkWidget *activate;
GtkWidget *label;
r->priv->enabled = g_action_group_get_action_enabled (r->priv->group, r->priv->name);
state = g_action_group_get_action_state (r->priv->group, r->priv->name);
fullname = g_strdup_printf ("%s.%s", r->priv->prefix, r->priv->name);
gtk_container_add (GTK_CONTAINER (r), gtk_label_new (fullname));
g_free (fullname);
r->priv->sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
activate = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_container_add (GTK_CONTAINER (row), activate);
gtk_size_group_add_widget (r->priv->sg, activate);
r->priv->activate_button = gtk_button_new_with_label (_("Activate"));
g_signal_connect (r->priv->activate_button, "clicked", G_CALLBACK (activate_action), r);
gtk_size_group_add_widget (r->priv->sg, r->priv->activate_button);
gtk_widget_set_sensitive (r->priv->activate_button, r->priv->enabled);
gtk_container_add (GTK_CONTAINER (row), r->priv->activate_button);
gtk_container_add (GTK_CONTAINER (activate), r->priv->activate_button);
r->priv->parameter_type = g_action_group_get_action_parameter_type (r->priv->group, r->priv->name);
if (r->priv->parameter_type)
{
r->priv->parameter_entry = variant_editor_new (r->priv->parameter_type, parameter_changed, r);
gtk_widget_set_sensitive (r->priv->parameter_entry, r->priv->enabled);
gtk_container_add (GTK_CONTAINER (row), r->priv->parameter_entry);
gtk_container_add (GTK_CONTAINER (activate), r->priv->parameter_entry);
}
gtk_container_add (GTK_CONTAINER (r), row);
@@ -297,7 +299,7 @@ constructed (GObject *object)
{
r->priv->state_type = g_variant_type_copy (g_variant_get_type (state));
row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
label = gtk_label_new (_("State"));
label = gtk_label_new (_("Set State"));
gtk_size_group_add_widget (r->priv->sg, label);
gtk_container_add (GTK_CONTAINER (row), label);
r->priv->state_entry = variant_editor_new (r->priv->state_type, state_changed, r);
@@ -350,6 +352,10 @@ get_property (GObject *object,
g_value_set_string (value, r->priv->name);
break;
case PROP_SIZEGROUP:
g_value_set_object (value, r->priv->sg);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -380,6 +386,10 @@ set_property (GObject *object,
r->priv->name = g_value_dup_string (value);
break;
case PROP_SIZEGROUP:
r->priv->sg = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
@@ -407,16 +417,21 @@ gtk_inspector_action_editor_class_init (GtkInspectorActionEditorClass *klass)
g_object_class_install_property (object_class, PROP_NAME,
g_param_spec_string ("name", "Name", "The action name",
NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_SIZEGROUP,
g_param_spec_object ("sizegroup", "Size Group", "The Size Group for activate",
GTK_TYPE_SIZE_GROUP, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
}
GtkWidget *
gtk_inspector_action_editor_new (GActionGroup *group,
const gchar *prefix,
const gchar *name)
const gchar *name,
GtkSizeGroup *activate)
{
return g_object_new (GTK_TYPE_INSPECTOR_ACTION_EDITOR,
"group", group,
"prefix", prefix,
"name", name,
"sizegroup", activate,
NULL);
}
+3 -1
View File
@@ -20,6 +20,7 @@
#include <gtk/gtkbox.h>
#include <gtk/gtksizegroup.h>
#define GTK_TYPE_INSPECTOR_ACTION_EDITOR (gtk_inspector_action_editor_get_type())
@@ -49,7 +50,8 @@ G_BEGIN_DECLS
GType gtk_inspector_action_editor_get_type (void);
GtkWidget *gtk_inspector_action_editor_new (GActionGroup *group,
const gchar *prefix,
const gchar *name);
const gchar *name,
GtkSizeGroup *activate);
G_END_DECLS
+114 -85
View File
@@ -29,6 +29,9 @@
#include "gtkpopover.h"
#include "gtklabel.h"
#include "gtkstack.h"
#include "gtklistbox.h"
#include "gtkstylecontext.h"
#include "gtksizegroup.h"
enum
{
@@ -42,9 +45,14 @@ enum
struct _GtkInspectorActionsPrivate
{
GtkListStore *model;
GtkWidget *list;
GtkSizeGroup *prefix;
GtkSizeGroup *name;
GtkSizeGroup *enabled;
GtkSizeGroup *parameter;
GtkSizeGroup *state;
GtkSizeGroup *activate;
GHashTable *groups;
GHashTable *iters;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorActions, gtk_inspector_actions, GTK_TYPE_BOX)
@@ -53,10 +61,6 @@ static void
gtk_inspector_actions_init (GtkInspectorActions *sl)
{
sl->priv = gtk_inspector_actions_get_instance_private (sl);
sl->priv->iters = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify) gtk_tree_iter_free);
sl->priv->groups = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
@@ -70,11 +74,15 @@ add_action (GtkInspectorActions *sl,
const gchar *prefix,
const gchar *name)
{
GtkTreeIter iter;
gboolean enabled;
const gchar *parameter;
GVariant *state;
gchar *state_string;
GtkWidget *row;
GtkWidget *label;
GtkWidget *box;
char *key = g_strconcat (prefix, ".", name, NULL);
GtkWidget *editor;
enabled = g_action_group_get_action_enabled (group, name);
parameter = (const gchar *)g_action_group_get_action_parameter_type (group, name);
@@ -83,21 +91,82 @@ add_action (GtkInspectorActions *sl,
state_string = g_variant_print (state, FALSE);
else
state_string = g_strdup ("");
gtk_list_store_append (sl->priv->model, &iter);
gtk_list_store_set (sl->priv->model, &iter,
COLUMN_PREFIX, prefix,
COLUMN_NAME, name,
COLUMN_ENABLED, enabled,
COLUMN_PARAMETER, parameter,
COLUMN_STATE, state_string,
COLUMN_GROUP, group,
-1);
g_hash_table_insert (sl->priv->iters,
g_strconcat (prefix, ".", name, NULL),
gtk_tree_iter_copy (&iter));
row = gtk_list_box_row_new ();
g_object_set_data_full (G_OBJECT (row), "key", key, g_free);
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add (GTK_CONTAINER (row), box);
label = gtk_label_new (prefix);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->prefix, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (name);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->name, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (enabled ? "+" : "-");
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->enabled, label);
gtk_container_add (GTK_CONTAINER (box), label);
g_object_set_data (G_OBJECT (row), "enabled", label);
label = gtk_label_new (parameter);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->parameter, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (state_string);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_size_group_add_widget (sl->priv->state, label);
gtk_container_add (GTK_CONTAINER (box), label);
g_object_set_data (G_OBJECT (row), "state", label);
editor = gtk_inspector_action_editor_new (group, prefix, name, sl->priv->activate);
gtk_style_context_add_class (gtk_widget_get_style_context (editor), "cell");
gtk_container_add (GTK_CONTAINER (box), editor);
gtk_container_add (GTK_CONTAINER (sl->priv->list), row);
g_free (state_string);
}
static GtkWidget *
find_row (GtkInspectorActions *sl,
const char *prefix,
const char *action_name)
{
GtkWidget *row = NULL;
GtkWidget *widget;
char *key = g_strconcat (prefix, ".", action_name, NULL);
for (widget = gtk_widget_get_first_child (sl->priv->list);
widget;
widget = gtk_widget_get_next_sibling (widget))
{
const char *rkey = g_object_get_data (G_OBJECT (widget), "key");
if (g_str_equal (key, rkey))
{
row = widget;
break;
}
}
g_free (key);
return row;
}
static void
action_added_cb (GActionGroup *group,
const gchar *action_name,
@@ -114,14 +183,12 @@ action_removed_cb (GActionGroup *group,
GtkInspectorActions *sl)
{
const gchar *prefix;
gchar *key;
GtkTreeIter *iter;
GtkWidget *row;
prefix = g_hash_table_lookup (sl->priv->groups, group);
key = g_strconcat (prefix, ".", action_name, NULL);
iter = g_hash_table_lookup (sl->priv->iters, key);
gtk_list_store_remove (sl->priv->model, iter);
g_hash_table_remove (sl->priv->iters, key);
g_free (key);
row = find_row (sl, prefix, action_name);
if (row)
gtk_container_remove (GTK_CONTAINER (sl->priv->list), row);
}
static void
@@ -131,15 +198,14 @@ action_enabled_changed_cb (GActionGroup *group,
GtkInspectorActions *sl)
{
const gchar *prefix;
gchar *key;
GtkTreeIter *iter;
GtkWidget *row;
GtkWidget *label;
prefix = g_hash_table_lookup (sl->priv->groups, group);
key = g_strconcat (prefix, ".", action_name, NULL);
iter = g_hash_table_lookup (sl->priv->iters, key);
gtk_list_store_set (sl->priv->model, iter,
COLUMN_ENABLED, enabled,
-1);
g_free (key);
row = find_row (sl, prefix, action_name);
label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "enabled"));
gtk_label_set_label (GTK_LABEL (label), enabled ? "+" : "-" );
}
static void
@@ -149,21 +215,20 @@ action_state_changed_cb (GActionGroup *group,
GtkInspectorActions *sl)
{
const gchar *prefix;
gchar *key;
GtkTreeIter *iter;
gchar *state_string;
GtkWidget *row;
GtkWidget *label;
prefix = g_hash_table_lookup (sl->priv->groups, group);
key = g_strconcat (prefix, ".", action_name, NULL);
iter = g_hash_table_lookup (sl->priv->iters, key);
row = find_row (sl, prefix, action_name);
if (state)
state_string = g_variant_print (state, FALSE);
else
state_string = g_strdup ("");
gtk_list_store_set (sl->priv->model, iter,
COLUMN_STATE, state_string,
-1);
label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "state"));
gtk_label_set_label (GTK_LABEL (label), state_string);
g_free (state_string);
g_free (key);
}
static void
@@ -214,8 +279,6 @@ gtk_inspector_actions_set_object (GtkInspectorActions *sl,
g_object_set (page, "visible", FALSE, NULL);
g_hash_table_foreach (sl->priv->groups, disconnect_group, sl);
g_hash_table_remove_all (sl->priv->groups);
g_hash_table_remove_all (sl->priv->iters);
gtk_list_store_clear (sl->priv->model);
if (GTK_IS_APPLICATION (object))
add_group (sl, page, G_ACTION_GROUP (object), "app");
@@ -238,53 +301,19 @@ gtk_inspector_actions_set_object (GtkInspectorActions *sl,
}
}
static void
row_activated (GtkTreeView *tv,
GtkTreePath *path,
GtkTreeViewColumn *col,
GtkInspectorActions *sl)
{
GtkTreeIter iter;
GdkRectangle rect;
GtkWidget *popover;
gchar *prefix;
gchar *name;
GActionGroup *group;
GtkWidget *editor;
gtk_tree_model_get_iter (GTK_TREE_MODEL (sl->priv->model), &iter, path);
gtk_tree_model_get (GTK_TREE_MODEL (sl->priv->model),
&iter,
COLUMN_PREFIX, &prefix,
COLUMN_NAME, &name,
COLUMN_GROUP, &group,
-1);
gtk_tree_model_get_iter (GTK_TREE_MODEL (sl->priv->model), &iter, path);
gtk_tree_view_get_cell_area (tv, path, col, &rect);
gtk_tree_view_convert_bin_window_to_widget_coords (tv, rect.x, rect.y, &rect.x, &rect.y);
popover = gtk_popover_new (GTK_WIDGET (tv));
gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
editor = gtk_inspector_action_editor_new (group, prefix, name);
gtk_container_add (GTK_CONTAINER (popover), editor);
gtk_popover_popup (GTK_POPOVER (popover));
g_signal_connect (popover, "hide", G_CALLBACK (gtk_widget_destroy), NULL);
g_free (name);
g_free (prefix);
}
static void
gtk_inspector_actions_class_init (GtkInspectorActionsClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/actions.ui");
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, model);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, list);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, prefix);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, name);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, enabled);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, parameter);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, state);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, activate);
}
// vim: set et sw=2 ts=2:
+85 -70
View File
@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="gtk40">
<object class="GtkListStore" id="model">
<columns>
@@ -11,84 +12,98 @@
</object>
<template class="GtkInspectorActions" parent="GtkBox">
<property name="orientation">vertical</property>
<style>
<class name="view"/>
</style>
<child>
<object class="GtkBox">
<style>
<class name="header"/>
</style>
<child>
<object class="GtkLabel" id="prefix_heading">
<property name="label" translatable="yes">Prefix</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="name_heading">
<property name="label" translatable="yes">Name</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="enabled_heading">
<property name="label" translatable="yes">Enabled</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="parameter_heading">
<property name="label" translatable="yes">Parameter Type</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="state_heading">
<property name="label" translatable="yes">State</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="changes_heading">
<property name="label" translatable="yes"></property>
<property name="xalign">0</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="expand">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkTreeView">
<property name="model">model</property>
<property name="enable-search">0</property>
<property name="activate-on-single-click">1</property>
<signal name="row-activated" handler="row_activated"/>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Prefix</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Name</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Enabled</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Parameter Type</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">State</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">4</attribute>
</attributes>
</child>
</object>
</child>
<object class="GtkListBox" id="list">
<style>
<class name="list"/>
</style>
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</template>
<object class="GtkSizeGroup" id="prefix">
<property name="mode">horizontal</property>
<widgets>
<widget name="prefix_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="name">
<property name="mode">horizontal</property>
<widgets>
<widget name="name_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="enabled">
<property name="mode">horizontal</property>
<widgets>
<widget name="enabled_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="parameter">
<property name="mode">horizontal</property>
<widgets>
<widget name="parameter_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="state">
<property name="mode">horizontal</property>
<widgets>
<widget name="state_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="activate">
<property name="mode">horizontal</property>
</object>
</interface>
+35
View File
@@ -0,0 +1,35 @@
/* some style for the inspector */
.header {
background: lightgray;
border: 1px solid gray;
}
.header>* {
padding: 2px;
font-weight: bold;
}
.header sort_indicator {
min-width: 16px;
}
.header>*:not(:last-child) {
border-right: 1px solid gray;
}
.list .cell {
font-size: smaller;
padding: 0 2px;
min-height: 24px;
}
.list .cell entry,
.list .cell spinbutton,
.list .cell button,
.list .cell combobox
{
min-height: 24px;
min-width: 0;
padding: 0 4px;
}
+1 -1
View File
@@ -180,7 +180,7 @@ show_object (GtkInspectorMiscInfo *sl,
const gchar *tab)
{
g_object_set_data_full (G_OBJECT (sl->priv->object_tree), "next-tab", g_strdup (tab), g_free);
gtk_inspector_object_tree_select_object (sl->priv->object_tree, object);
gtk_inspector_object_tree_activate_object (sl->priv->object_tree, object);
}
static void
+7 -6
View File
@@ -43,6 +43,7 @@
#include "gtksizegroup.h"
#include "gtkroot.h"
#include "gtkgesturemultipress.h"
#include "gtkstylecontext.h"
enum
{
@@ -105,17 +106,13 @@ apply_sort (GtkInspectorPropList *pl,
if (column == COLUMN_NAME)
{
gtk_widget_hide (pl->priv->origin_sort_indicator);
gtk_widget_show (pl->priv->name_sort_indicator);
gtk_image_clear (GTK_IMAGE (pl->priv->origin_sort_indicator));
gtk_image_set_from_icon_name (GTK_IMAGE (pl->priv->name_sort_indicator),
icon_name);
}
else
{
gtk_widget_show (pl->priv->origin_sort_indicator);
gtk_widget_hide (pl->priv->name_sort_indicator);
gtk_image_clear (GTK_IMAGE (pl->priv->name_sort_indicator));
gtk_image_set_from_icon_name (GTK_IMAGE (pl->priv->origin_sort_indicator),
icon_name);
}
@@ -540,24 +537,28 @@ gtk_inspector_prop_list_create_row (GtkInspectorPropList *pl,
gtk_container_add (GTK_CONTAINER (row), box);
label = gtk_label_new (prop->name);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_widget_set_sensitive (label, writable);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (pl->priv->names, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (type ? type : "");
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_widget_set_sensitive (label, writable);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (pl->priv->types, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (g_type_name (prop->owner_type));
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_widget_set_sensitive (label, writable);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (pl->priv->origins, label);
gtk_container_add (GTK_CONTAINER (box), label);
widget = gtk_inspector_prop_editor_new (pl->priv->object, prop->name, pl->priv->values);
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "cell");
gtk_container_add (GTK_CONTAINER (box), widget);
g_signal_connect (widget, "show-object", G_CALLBACK (show_object), pl);
+16 -3
View File
@@ -15,6 +15,7 @@
</style>
<child>
<object class="GtkBox" id="name_heading">
<property name="hexpand">0</property>
<child>
<object class="GtkGestureMultiPress">
<signal name="pressed" handler="sort_changed" swapped="no"/>
@@ -30,6 +31,9 @@
</child>
<child>
<object class="GtkImage" id="name_sort_indicator">
<style>
<class name="sort_indicator"/>
</style>
</object>
</child>
</object>
@@ -42,6 +46,7 @@
</child>
<child>
<object class="GtkBox" id="origin_heading">
<property name="hexpand">0</property>
<child>
<object class="GtkGestureMultiPress">
<signal name="pressed" handler="sort_changed" swapped="no"/>
@@ -57,6 +62,9 @@
</child>
<child>
<object class="GtkImage" id="origin_sort_indicator">
<style>
<class name="sort_indicator"/>
</style>
</object>
</child>
</object>
@@ -65,9 +73,7 @@
<object class="GtkLabel" id="value_heading">
<property name="label">Value</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="hexpand">0</property>
</object>
</child>
</object>
@@ -78,6 +84,9 @@
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListBox" id="list2">
<style>
<class name="list"/>
</style>
<property name="selection-mode">none</property>
</object>
</child>
@@ -87,21 +96,25 @@
</child>
</template>
<object class="GtkSizeGroup" id="names">
<property name="mode">horizontal</property>
<widgets>
<widget name="name_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="types">
<property name="mode">horizontal</property>
<widgets>
<widget name="type_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="origins">
<property name="mode">horizontal</property>
<widgets>
<widget name="origin_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="values">
<property name="mode">horizontal</property>
<widgets>
<widget name="value_heading"/>
</widgets>
+11
View File
@@ -54,6 +54,9 @@
#include "gtkwindowgroup.h"
#include "gtkrevealer.h"
#include "gtklayoutmanager.h"
#include "gtkcssprovider.h"
#include "gtkstylecontext.h"
G_DEFINE_TYPE (GtkInspectorWindow, gtk_inspector_window, GTK_TYPE_WINDOW)
@@ -290,11 +293,19 @@ static void
gtk_inspector_window_realize (GtkWidget *widget)
{
GskRenderer *renderer;
GtkCssProvider *provider;
GTK_WIDGET_CLASS (gtk_inspector_window_parent_class)->realize (widget);
renderer = gtk_root_get_renderer (GTK_ROOT (widget));
gsk_renderer_set_debug_flags (renderer, 0);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gtk/libgtk/inspector/inspector.css");
gtk_style_context_add_provider_for_display (gtk_widget_get_display (widget),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
}
static void
+3
View File
@@ -111,6 +111,7 @@
<child>
<object class="GtkStackPage">
<property name="name">credits</property>
<property name="visible">0</property>
<property name="title" translatable="yes">Credits</property>
<property name="child">
<object class="GtkBox" id="credits_page">
@@ -147,6 +148,7 @@
<child>
<object class="GtkStackPage">
<property name="name">license</property>
<property name="visible">0</property>
<property name="title" translatable="yes">License</property>
<property name="child">
<object class="GtkBox" id="license_page">
@@ -189,6 +191,7 @@
<child>
<object class="GtkStackPage">
<property name="name">system</property>
<property name="visible">0</property>
<property name="title" translatable="yes">System</property>
<property name="child">
<object class="GtkBox" id="system_page">
+21 -36
View File
@@ -81,28 +81,6 @@ static GtkCupsRequestStateFunc get_states[] = {
_get_read_data
};
#ifndef HAVE_CUPS_API_1_6
#define ippSetOperation(ipp_request, ipp_op_id) ipp_request->request.op.operation_id = ipp_op_id
#define ippSetRequestId(ipp_request, ipp_rq_id) ipp_request->request.op.request_id = ipp_rq_id
#define ippSetState(ipp_request, ipp_state) ipp_request->state = ipp_state
#define ippGetString(attr, index, foo) attr->values[index].string.text
#define ippGetCount(attr) attr->num_values
int
ippSetVersion (ipp_t *ipp,
int major,
int minor)
{
if (!ipp || major < 0 || minor < 0)
return 0;
ipp->request.any.version[0] = major;
ipp->request.any.version[1] = minor;
return 1;
}
#endif
static void
gtk_cups_result_set_error (GtkCupsResult *result,
GtkCupsErrorType error_type,
@@ -168,10 +146,10 @@ gtk_cups_request_new_with_username (http_t *connection,
}
else
{
request->http = NULL;
request->http = httpConnectEncrypt (request->server,
ippPort (),
cupsEncryption ());
request->http = httpConnect2 (request->server, ippPort (),
NULL, AF_UNSPEC,
cupsEncryption (),
1, 30000, NULL);
if (request->http)
httpBlocking (request->http, 0);
@@ -686,10 +664,10 @@ _connect (GtkCupsRequest *request)
if (request->http == NULL)
{
request->http = httpConnectEncrypt (request->server,
ippPort (),
cupsEncryption ());
request->http = httpConnect2 (request->server, ippPort (),
NULL, AF_UNSPEC,
cupsEncryption (),
1, 30000, NULL);
if (request->http == NULL)
request->attempts++;
@@ -741,7 +719,11 @@ _post_send (GtkCupsRequest *request)
if (httpPost (request->http, request->resource))
{
if (httpReconnect (request->http))
int res;
res = httpReconnect2 (request->http, 30000, NULL);
if (res)
{
request->state = GTK_CUPS_POST_DONE;
request->poll_state = GTK_CUPS_HTTP_IDLE;
@@ -1039,7 +1021,7 @@ _post_check (GtkCupsRequest *request)
}
if (auth_result ||
httpReconnect (request->http))
httpReconnect2 (request->http, 30000, NULL))
{
/* if the password has been used, reset password_state
* so that we ask for a new one next time around
@@ -1098,7 +1080,7 @@ _post_check (GtkCupsRequest *request)
request->state = GTK_CUPS_POST_CONNECT;
/* Reconnect... */
httpReconnect (request->http);
httpReconnect2 (request->http, 30000, NULL);
/* Upgrade with encryption... */
httpEncryption (request->http, HTTP_ENCRYPT_REQUIRED);
@@ -1226,7 +1208,10 @@ _get_send (GtkCupsRequest *request)
if (httpGet (request->http, request->resource))
{
if (httpReconnect (request->http))
int reconnect;
reconnect = httpReconnect2 (request->http, 30000, NULL);
if (reconnect)
{
request->state = GTK_CUPS_GET_DONE;
request->poll_state = GTK_CUPS_HTTP_IDLE;
@@ -1335,7 +1320,7 @@ _get_check (GtkCupsRequest *request)
}
if (auth_result ||
httpReconnect (request->http))
httpReconnect2 (request->http, 30000, NULL))
{
/* if the password has been used, reset password_state
* so that we ask for a new one next time around
@@ -1367,7 +1352,7 @@ _get_check (GtkCupsRequest *request)
request->state = GTK_CUPS_GET_CONNECT;
/* Reconnect... */
httpReconnect (request->http);
httpReconnect2 (request->http, 30000, NULL);
/* Upgrade with encryption... */
httpEncryption (request->http, HTTP_ENCRYPT_REQUIRED);
+37 -173
View File
@@ -24,13 +24,12 @@
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
/* Cups 1.6 deprecates ppdFindAttr(), ppdFindCustomOption(),
* ppdFirstCustomParam(), and ppdNextCustomParam() among others. This
* turns off the warning so that it will compile.
*/
#ifdef HAVE_CUPS_API_1_6
# define _PPD_DEPRECATED
#endif
#define _PPD_DEPRECATED
#include <cups/cups.h>
#include <cups/language.h>
@@ -71,7 +70,6 @@ typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass;
#define _CUPS_MAX_ATTEMPTS 10
#define _CUPS_MAX_CHUNK_SIZE 8192
#ifdef HAVE_CUPS_API_1_6
#define AVAHI_IF_UNSPEC -1
#define AVAHI_PROTO_INET 0
#define AVAHI_PROTO_INET6 1
@@ -81,7 +79,6 @@ typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass;
#define AVAHI_SERVER_IFACE "org.freedesktop.Avahi.Server"
#define AVAHI_SERVICE_BROWSER_IFACE "org.freedesktop.Avahi.ServiceBrowser"
#define AVAHI_SERVICE_RESOLVER_IFACE "org.freedesktop.Avahi.ServiceResolver"
#endif
/* define this to see warnings about ignored ppd options */
#undef PRINT_IGNORED_OPTIONS
@@ -143,14 +140,14 @@ struct _GtkPrintBackendCups
#ifdef HAVE_COLORD
CdClient *colord_client;
#endif
#ifdef HAVE_CUPS_API_1_6
GDBusConnection *dbus_connection;
gchar *avahi_default_printer;
guint avahi_service_browser_subscription_id;
guint avahi_service_browser_subscription_ids[2];
gchar *avahi_service_browser_paths[2];
GCancellable *avahi_cancellable;
#endif
char *avahi_default_printer;
guint avahi_service_browser_subscription_id;
guint avahi_service_browser_subscription_ids[2];
char *avahi_service_browser_paths[2];
GCancellable *avahi_cancellable;
gboolean secrets_service_available;
guint secrets_service_watch_id;
GCancellable *secrets_service_cancellable;
@@ -228,9 +225,7 @@ static gboolean is_address_local (const gchar
static gboolean request_auth_info (gpointer data);
static void lookup_auth_info (gpointer data);
#ifdef HAVE_CUPS_API_1_6
static void avahi_request_printer_list (GtkPrintBackendCups *cups_backend);
#endif
static void secrets_service_appeared_cb (GDBusConnection *connection,
const gchar *name,
@@ -272,51 +267,6 @@ g_io_module_query (void)
return g_strdupv (eps);
}
/* CUPS 1.6 Getter/Setter Functions CUPS 1.6 makes private most of the
* IPP structures and enforces access via new getter functions, which
* are unfortunately not available in earlier versions. We define
* below those getter functions as macros for use when building
* against earlier CUPS versions.
*/
#ifndef HAVE_CUPS_API_1_6
#define ippGetOperation(ipp_request) ipp_request->request.op.operation_id
#define ippGet:Integer(attr, index) attr->values[index].integer
#define ippGetBoolean(attr, index) attr->values[index].boolean
#define ippGetString(attr, index, foo) attr->values[index].string.text
#define ippGetValueTag(attr) attr->value_tag
#define ippGetName(attr) attr->name
#define ippGetCount(attr) attr->num_values
#define ippGetGroupTag(attr) attr->group_tag
#define ippGetCollection(attr, index) attr->values[index].collection
static int
ippGetRange (ipp_attribute_t *attr,
int element,
int *upper)
{
*upper = attr->values[element].range.upper;
return (attr->values[element].range.lower);
}
static ipp_attribute_t *
ippFirstAttribute (ipp_t *ipp)
{
if (!ipp)
return (NULL);
return (ipp->current = ipp->attrs);
}
static ipp_attribute_t *
ippNextAttribute (ipp_t *ipp)
{
if (!ipp || !ipp->current)
return (NULL);
return (ipp->current = ipp->current->next);
}
#endif
/*
* GtkPrintBackendCups
*/
@@ -737,10 +687,13 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
cups_printer = GTK_PRINTER_CUPS (gtk_print_job_get_printer (job));
settings = gtk_print_job_get_settings (job);
#ifdef HAVE_CUPS_API_1_6
if (cups_printer->avahi_browsed)
{
http = httpConnect (cups_printer->hostname, cups_printer->port);
http = httpConnect2 (cups_printer->hostname, cups_printer->port,
NULL, AF_UNSPEC,
HTTP_ENCRYPTION_IF_REQUESTED,
1, 30000,
NULL);
if (http)
{
request = gtk_cups_request_new_with_username (http,
@@ -779,7 +732,6 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
}
}
else
#endif
{
request = gtk_cups_request_new_with_username (NULL,
GTK_CUPS_POST,
@@ -889,9 +841,7 @@ void overwrite_and_free (gpointer data)
static void
gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
{
#ifdef HAVE_CUPS_API_1_6
gint i;
#endif
int i;
backend_cups->list_printers_poll = FALSE;
backend_cups->got_default_printer = FALSE;
@@ -912,7 +862,6 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
backend_cups->colord_client = cd_client_new ();
#endif
#ifdef HAVE_CUPS_API_1_6
backend_cups->dbus_connection = NULL;
backend_cups->avahi_default_printer = NULL;
backend_cups->avahi_service_browser_subscription_id = 0;
@@ -921,7 +870,6 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
backend_cups->avahi_service_browser_paths[i] = NULL;
backend_cups->avahi_service_browser_subscription_ids[i] = 0;
}
#endif
cups_get_local_default_printer (backend_cups);
@@ -957,11 +905,9 @@ gtk_print_backend_cups_finalize (GObject *object)
g_object_unref (backend_cups->colord_client);
#endif
#ifdef HAVE_CUPS_API_1_6
g_clear_object (&backend_cups->avahi_cancellable);
g_clear_pointer (&backend_cups->avahi_default_printer, g_free);
g_clear_object (&backend_cups->dbus_connection);
#endif
g_clear_object (&backend_cups->secrets_service_cancellable);
if (backend_cups->secrets_service_watch_id != 0)
@@ -976,9 +922,7 @@ static void
gtk_print_backend_cups_dispose (GObject *object)
{
GtkPrintBackendCups *backend_cups;
#ifdef HAVE_CUPS_API_1_6
gint i;
#endif
int i;
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
@@ -994,7 +938,6 @@ gtk_print_backend_cups_dispose (GObject *object)
g_source_remove (backend_cups->default_printer_poll);
backend_cups->default_printer_poll = 0;
#ifdef HAVE_CUPS_API_1_6
g_cancellable_cancel (backend_cups->avahi_cancellable);
for (i = 0; i < 2; i++)
@@ -1030,7 +973,6 @@ gtk_print_backend_cups_dispose (GObject *object)
backend_cups->avahi_service_browser_subscription_id);
backend_cups->avahi_service_browser_subscription_id = 0;
}
#endif
backend_parent_class->dispose (object);
}
@@ -1784,18 +1726,8 @@ cups_request_job_info_cb (GtkPrintBackendCups *print_backend,
state = 0;
#ifdef HAVE_CUPS_API_1_6
attr = ippFindAttribute (response, "job-state", IPP_TAG_ENUM);
state = ippGetInteger (attr, 0);
#else
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
if (!attr->name)
continue;
_CUPS_MAP_ATTR_INT (attr, state, "job-state");
}
#endif
done = FALSE;
switch (state)
@@ -2031,9 +1963,7 @@ typedef struct
gboolean default_printer;
gboolean got_printer_type;
gboolean remote_printer;
#ifdef HAVE_CUPS_API_1_6
gboolean avahi_printer;
#endif
gchar **auth_info_required;
gint default_number_up;
guchar ipp_version_major;
@@ -2464,13 +2394,11 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
char *cups_server; /* CUPS server */
#ifdef HAVE_COLORD
#ifdef HAVE_CUPS_API_1_6
if (info->avahi_printer)
cups_printer = gtk_printer_cups_new (info->printer_name,
backend,
NULL);
else
#endif
cups_printer = gtk_printer_cups_new (info->printer_name,
backend,
cups_backend->colord_client);
@@ -2546,9 +2474,7 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0)
gtk_printer_set_is_default (printer, TRUE);
#ifdef HAVE_CUPS_API_1_6
cups_printer->avahi_browsed = info->avahi_printer;
#endif
gtk_print_backend_add_printer (backend, printer);
return printer;
@@ -2727,7 +2653,6 @@ set_default_printer (GtkPrintBackendCups *cups_backend,
}
}
#ifdef HAVE_CUPS_API_1_6
static void
cups_request_printer_info_cb (GtkPrintBackendCups *cups_backend,
GtkCupsResult *result,
@@ -2850,7 +2775,7 @@ cups_request_printer_info (const gchar *printer_uri,
GtkCupsRequest *request;
http_t *http;
http = httpConnect (host, port);
http = httpConnect2 (host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
if (http)
{
request = gtk_cups_request_new_with_username (http,
@@ -2918,9 +2843,7 @@ find_printer_by_uuid (GtkPrintBackendCups *backend,
printer_uuid += 5;
printer_uuid = g_strndup (printer_uuid, 36);
#if GLIB_CHECK_VERSION(2, 52, 0)
if (g_uuid_string_is_valid (printer_uuid))
#endif
{
if (g_strcmp0 (printer_uuid, UUID) == 0)
{
@@ -3493,7 +3416,6 @@ avahi_request_printer_list (GtkPrintBackendCups *cups_backend)
cups_backend->avahi_cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SYSTEM, cups_backend->avahi_cancellable, avahi_create_browsers, cups_backend);
}
#endif
static void
cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
@@ -3542,7 +3464,6 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
removed_printer_checklist = gtk_print_backend_get_printer_list (backend);
response = gtk_cups_result_get_response (result);
#ifdef HAVE_CUPS_API_1_6
for (attr = ippFirstAttribute (response); attr != NULL;
attr = ippNextAttribute (response))
{
@@ -3558,42 +3479,21 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
if (attr == NULL)
break;
while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
{
cups_printer_handle_attribute (cups_backend, attr, info);
attr = ippNextAttribute (response);
}
#else
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
GtkPrinter *printer;
gboolean status_changed = FALSE;
GList *node;
PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
info->default_number_up = 1;
/* Skip leading attributes until we hit a printer...
*/
while (attr != NULL && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
attr = attr->next;
if (attr == NULL)
break;
while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
{
cups_printer_handle_attribute (cups_backend, attr, info);
attr = attr->next;
}
#endif
{
cups_printer_handle_attribute (cups_backend, attr, info);
attr = ippNextAttribute (response);
}
if (info->printer_name == NULL ||
(info->printer_uri == NULL && info->member_uris == NULL))
{
if (attr == NULL)
break;
else
continue;
}
{
if (attr == NULL)
break;
else
continue;
}
if (info->got_printer_type)
{
@@ -3691,9 +3591,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
{
for (iter = removed_printer_checklist; iter; iter = iter->next)
{
#ifdef HAVE_CUPS_API_1_6
if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
#endif
{
mark_printer_inactive (GTK_PRINTER (iter->data), backend);
list_has_changed = TRUE;
@@ -3715,12 +3613,8 @@ done:
g_free (remote_default_printer);
}
#ifdef HAVE_CUPS_API_1_6
if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL)
{
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
#endif
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
static void
@@ -3809,9 +3703,7 @@ cups_get_printer_list (GtkPrintBackend *backend)
g_source_set_name_by_id (cups_backend->list_printers_poll, "[gtk] cups_request_printer_list");
}
#ifdef HAVE_CUPS_API_1_6
avahi_request_printer_list (cups_backend);
#endif
}
}
@@ -3847,26 +3739,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
GTK_PRINTER_CUPS (printer)->reading_ppd = FALSE;
print_backend->reading_ppds--;
#ifndef HAVE_CUPS_API_1_6
if (gtk_cups_result_is_error (result))
{
gboolean success = FALSE;
/* If we get a 404 then it is just a raw printer without a ppd
and not an error. */
if ((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) &&
(gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND))
{
gtk_printer_set_has_details (printer, TRUE);
success = TRUE;
}
g_signal_emit_by_name (printer, "details-acquired", success);
return;
}
#endif
if (!gtk_cups_result_is_error (result))
{
/* let ppdOpenFd take over the ownership of the open file */
@@ -3876,7 +3748,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
ppdMarkDefaults (data->printer->ppd_file);
}
#ifdef HAVE_CUPS_API_1_6
fstat (g_io_channel_unix_get_fd (data->ppd_io), &data_info);
/*
* Standalone Avahi printers and raw printers don't have PPD files or have
@@ -3896,7 +3767,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
return;
}
#endif
gtk_printer_set_has_details (printer, TRUE);
g_signal_emit_by_name (printer, "details-acquired", TRUE);
@@ -3922,11 +3792,7 @@ cups_request_ppd (GtkPrinter *printer)
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
if (cups_printer->remote
#ifdef HAVE_CUPS_API_1_6
&& !cups_printer->avahi_browsed
#endif
)
if (cups_printer->remote && !cups_printer->avahi_browsed)
{
GtkCupsConnectionState state;
@@ -3960,9 +3826,10 @@ cups_request_ppd (GtkPrinter *printer)
}
}
http = httpConnectEncrypt (cups_printer->hostname,
cups_printer->port,
cupsEncryption ());
http = httpConnect2 (cups_printer->hostname, cups_printer->port,
NULL, AF_UNSPEC,
cupsEncryption (),
1, 30000, NULL);
data = g_new0 (GetPPDData, 1);
@@ -4266,13 +4133,14 @@ cups_request_default_printer_cb (GtkPrintBackendCups *print_backend,
response = gtk_cups_result_get_response (result);
if ((attr = ippFindAttribute (response, "printer-name", IPP_TAG_NAME)) != NULL)
print_backend->default_printer = g_strdup (ippGetString (attr, 0, NULL));
print_backend->default_printer = g_strdup (ippGetString (attr, 0, NULL));
print_backend->got_default_printer = TRUE;
if (print_backend->default_printer != NULL)
{
printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (print_backend), print_backend->default_printer);
printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (print_backend),
print_backend->default_printer);
if (printer != NULL)
{
gtk_printer_set_is_default (printer, TRUE);
@@ -4325,11 +4193,7 @@ cups_printer_request_details (GtkPrinter *printer)
if (!cups_printer->reading_ppd &&
gtk_printer_cups_get_ppd (cups_printer) == NULL)
{
if (cups_printer->remote
#ifdef HAVE_CUPS_API_1_6
&& !cups_printer->avahi_browsed
#endif
)
if (cups_printer->remote && !cups_printer->avahi_browsed)
{
if (cups_printer->get_remote_ppd_poll == 0)
{
+4 -4
View File
@@ -115,12 +115,10 @@ gtk_printer_cups_init (GtkPrinterCups *printer)
printer->remote_cups_connection_test = NULL;
printer->auth_info_required = NULL;
printer->default_number_up = 1;
#ifdef HAVE_CUPS_API_1_6
printer->avahi_browsed = FALSE;
printer->avahi_name = NULL;
printer->avahi_type = NULL;
printer->avahi_domain = NULL;
#endif
printer->ipp_version_major = 1;
printer->ipp_version_minor = 1;
printer->supports_copies = FALSE;
@@ -176,17 +174,19 @@ gtk_printer_cups_finalize (GObject *object)
g_object_unref (printer->colord_profile);
#endif
#ifdef HAVE_CUPS_API_1_6
g_free (printer->avahi_name);
g_free (printer->avahi_type);
g_free (printer->avahi_domain);
#endif
g_strfreev (printer->covers);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (printer->ppd_file)
ppdClose (printer->ppd_file);
G_GNUC_END_IGNORE_DEPRECATIONS
g_free (printer->media_default);
g_list_free_full (printer->media_supported, g_free);
g_list_free_full (printer->media_size_supported, g_free);
+6 -5
View File
@@ -81,6 +81,7 @@ struct _GtkPrinterCups
guint get_remote_ppd_poll;
gint get_remote_ppd_attempts;
GtkCupsConnectionTest *remote_cups_connection_test;
#ifdef HAVE_COLORD
CdClient *colord_client;
CdDevice *colord_device;
@@ -89,12 +90,12 @@ struct _GtkPrinterCups
gchar *colord_title;
gchar *colord_qualifier;
#endif
#ifdef HAVE_CUPS_API_1_6
gboolean avahi_browsed;
gchar *avahi_name;
gchar *avahi_type;
gchar *avahi_domain;
#endif
char *avahi_name;
char *avahi_type;
char *avahi_domain;
guchar ipp_version_major;
guchar ipp_version_minor;
gboolean supports_copies;
+2 -6
View File
@@ -26,11 +26,7 @@ if enable_cups
cups_major_version = cc.compute_int('CUPS_VERSION_MAJOR', prefix : '#include <cups/cups.h>')
cups_minor_version = cc.compute_int('CUPS_VERSION_MINOR', prefix : '#include <cups/cups.h>')
message('Found CUPS version: @0@.@1@'.format(cups_major_version, cups_minor_version))
if cups_major_version > 1 or cups_minor_version >= 2
if cups_major_version > 1 or cups_minor_version >= 6
cdata.set('HAVE_CUPS_API_1_6', 1)
endif
if cups_major_version >= 2
if cc.compiles('#include <cups/http.h> \n http_t http; char *s = http.authstring;')
cdata.set('HAVE_HTTP_AUTHSTRING', 1,
description :'Define if cups http_t authstring field is accessible')
@@ -42,7 +38,7 @@ if enable_cups
print_backends += ['cups']
else
error('Need CUPS version >= 1.2')
error('Need CUPS version >= 2.0')
endif
else
error('Cannot find CUPS headers in default prefix.')
+1 -3
View File
@@ -27,7 +27,7 @@ test_popover_parent (void)
GtkWidget *p;
AtkObject *a;
g_test_bug ("733923");
/*http://bugzilla.gnome.org/show_bug.cgi?id=733923 */
w = gtk_entry_new ();
@@ -50,8 +50,6 @@ main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugzilla.gnome.org/");
g_test_add_func ("/popover/accessible-parent", test_popover_parent);
return g_test_run ();
+1 -3
View File
@@ -1064,7 +1064,7 @@ test_bold_label (void)
AtkObject *atk_obj;
gchar *text;
g_test_bug ("126797");
/*http://bugzilla.gnome.org/show_bug.cgi?id=126797 */
label = gtk_label_new ("<b>Bold?</b>");
g_object_ref_sink (label);
@@ -1089,8 +1089,6 @@ main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugzilla.gnome.org/");
g_test_add_func ("/text/bold/GtkLabel", test_bold_label);
add_text_tests (gtk_label_new (""));
-2
View File
@@ -119,8 +119,6 @@ main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugzilla.gnome.org/");
add_value_tests (gtk_spin_button_new_with_range (0, 100, 1));
add_value_tests (gtk_level_bar_new_for_interval (0, 100));
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright © 2019 Benjamin Otte
*
* 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/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "../../gtk/css/gtkcssdataurlprivate.h"
#include <locale.h>
typedef struct _Test Test;
struct _Test
{
const char *name;
const char *url;
const char *mimetype;
const char *contents;
gsize contents_len;
};
#define CONTENTS(data) (data), sizeof(data) - 1
Test tests[] = {
{ "simple",
"data:,HelloWorld",
NULL, CONTENTS("HelloWorld") },
{ "nodata",
"data:,",
NULL, CONTENTS("") },
{ "case_sensitive",
"dATa:,HelloWorld",
NULL, CONTENTS("HelloWorld") },
{ "semicolon_after_comma",
"data:,;base64",
NULL, CONTENTS(";base64") },
{ "mimetype",
"data:image/png,nopng",
"image/png", CONTENTS("nopng") },
{ "charset",
"data:text/plain;charset=ISO-8859-1,Timm B\344der",
"text/plain", CONTENTS("Timm Bäder") },
{ "charset_base64",
"data:text/plain;charset=ISO-8859-5;base64,wOPh29DdILjW0ePb0OLe0g==",
"text/plain", CONTENTS("Руслан Ижбулатов") },
};
static void
test_parse (gconstpointer data)
{
const Test *test = data;
GError *error = NULL;
char *mimetype = NULL;
GBytes *bytes;
bytes = gtk_css_data_url_parse (test->url, &mimetype, &error);
g_assert (bytes != NULL);
g_assert_no_error (error);
if (test->mimetype == NULL)
g_assert (mimetype == NULL);
else
g_assert_cmpstr (mimetype, ==, test->mimetype);
g_assert_cmpmem (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes),
test->contents, test->contents_len);
g_bytes_unref (bytes);
}
int
main (int argc, char *argv[])
{
guint i;
g_test_init (&argc, &argv, NULL);
setlocale (LC_ALL, "C");
for (i = 0; i < G_N_ELEMENTS (tests); i++)
{
char *name = g_strdup_printf ("/css/data/load/%s", tests[i].name);
g_test_add_data_func (name, &tests[i], test_parse);
g_free (name);
}
return g_test_run ();
}
+16
View File
@@ -20,6 +20,22 @@ test('api', test_api,
],
suite: 'css')
test_data = executable('data', ['data.c', '../../gtk/css/gtkcssdataurl.c'],
include_directories: [confinc, ],
dependencies: gtk_deps,
install: get_option('install-tests'),
install_dir: testexecdir)
test('data', test_data,
args: ['--tap', '-k' ],
env: [ 'GIO_USE_VOLUME_MONITOR=unix',
'GSETTINGS_BACKEND=memory',
'GTK_CSD=1',
'G_ENABLE_DIAGNOSTIC=0',
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
suite: 'css')
if get_option('install-tests')
conf = configuration_data()
conf.set('libexecdir', gtk_libexecdir)
@@ -0,0 +1,2 @@
a {
animation-name: \
@@ -0,0 +1,2 @@
backslash-eof-is-identifier.css:2:3-20: error: GTK_CSS_PARSER_WARNING_SYNTAX
backslash-eof-is-identifier.css:1:3-2:20: error: GTK_CSS_PARSER_WARNING_SYNTAX
@@ -0,0 +1,3 @@
a {
animation-name: ;
}
+1
View File
@@ -0,0 +1 @@
\
+1
View File
@@ -0,0 +1 @@
backslash.css:1:2: error: GTK_CSS_PARSER_ERROR_SYNTAX
@@ -0,0 +1,2 @@
a {
animation-name: -\
@@ -0,0 +1,2 @@
dash-backslash-eof-is-identifier.css:2:3-21: error: GTK_CSS_PARSER_WARNING_SYNTAX
dash-backslash-eof-is-identifier.css:1:3-2:21: error: GTK_CSS_PARSER_WARNING_SYNTAX
@@ -0,0 +1,3 @@
a {
animation-name: -;
}
@@ -0,0 +1,2 @@
a {
animation-name: -\
@@ -0,0 +1,3 @@
dash-backslash-newline-is-delim.css:2:19-20: error: GTK_CSS_PARSER_ERROR_SYNTAX
dash-backslash-newline-is-delim.css:2:3-3:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
dash-backslash-newline-is-delim.css:1:3-3:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
@@ -0,0 +1,2 @@
a {
}
@@ -0,0 +1,2 @@
a {
animation-name: --
@@ -0,0 +1,2 @@
dash-dash-eof-is-identifier.css:2:3-21: error: GTK_CSS_PARSER_WARNING_SYNTAX
dash-dash-eof-is-identifier.css:1:3-2:21: error: GTK_CSS_PARSER_WARNING_SYNTAX
@@ -0,0 +1,3 @@
a {
animation-name: --;
}
@@ -0,0 +1,2 @@
a {
animation-name: -
@@ -0,0 +1,3 @@
dash-eof-is-delim.css:2:19-20: error: GTK_CSS_PARSER_ERROR_SYNTAX
dash-eof-is-delim.css:2:3-20: error: GTK_CSS_PARSER_WARNING_SYNTAX
dash-eof-is-delim.css:1:3-2:20: error: GTK_CSS_PARSER_WARNING_SYNTAX
@@ -0,0 +1,2 @@
a {
}
+18
View File
@@ -160,6 +160,12 @@ test_data = [
'background-shorthand-single.ref.css',
'background-size.css',
'background-size.ref.css',
'backslash.css',
'backslash.errors',
'backslash.ref.css',
'backslash-eof-is-identifier.css',
'backslash-eof-is-identifier.errors',
'backslash-eof-is-identifier.ref.css',
'border-color.css',
'border-color-currentcolor.css',
'border-color-currentcolor.ref.css',
@@ -220,6 +226,18 @@ test_data = [
'css-21-malformed-statements.errors',
'css-21-malformed-statements.ref.css',
'currentcolor-everywhere.css',
'dash-backslash-eof-is-identifier.ref.css',
'dash-backslash-eof-is-identifier.css',
'dash-backslash-eof-is-identifier.errors',
'dash-backslash-newline-is-delim.ref.css',
'dash-backslash-newline-is-delim.errors',
'dash-backslash-newline-is-delim.css',
'dash-dash-eof-is-identifier.ref.css',
'dash-dash-eof-is-identifier.css',
'dash-dash-eof-is-identifier.errors',
'dash-eof-is-delim.ref.css',
'dash-eof-is-delim.css',
'dash-eof-is-delim.errors',
'declarations.css',
'declarations.errors',
'declarations-invalid-01.css',
-2
View File
@@ -181,8 +181,6 @@ main (int argc, char *argv[])
g_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugzilla.gnome.org");
enum_class = g_type_class_ref (GDK_TYPE_MEMORY_FORMAT);
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
-2
View File
@@ -72,8 +72,6 @@ main (int argc, char *argv[])
gtk_init ();
g_test_bug_base ("http://bugzilla.gnome.org/");
g_test_add_func ("/rectangle/equal", test_rectangle_equal);
g_test_add_func ("/rectangle/intersect", test_rectangle_intersect);
g_test_add_func ("/rectangle/union", test_rectangle_union);
+7 -9
View File
@@ -121,7 +121,7 @@ test_color_parse_nonsense (void)
GdkRGBA color;
gboolean res;
g_test_bug ("667485");
/*http://bugzilla.gnome.org/show_bug.cgi?id=667485 */
res = gdk_rgba_parse (&color, "rgb(,,)");
g_assert (!res);
@@ -151,14 +151,12 @@ test_color_parse_nonsense (void)
int
main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugzilla.gnome.org");
g_test_add_func ("/rgba/parse", test_color_parse);
g_test_add_func ("/rgba/parse/nonsense", test_color_parse_nonsense);
g_test_add_func ("/rgba/to-string", test_color_to_string);
g_test_add_func ("/rgba/copy", test_color_copy);
g_test_add_func ("/rgba/parse", test_color_parse);
g_test_add_func ("/rgba/parse/nonsense", test_color_parse_nonsense);
g_test_add_func ("/rgba/to-string", test_color_to_string);
g_test_add_func ("/rgba/copy", test_color_copy);
return g_test_run ();
return g_test_run ();
}
-2
View File
@@ -111,8 +111,6 @@ main (int argc, char *argv[])
gtk_init ();
g_test_bug_base ("http://bugzilla.gnome.org/");
g_test_add_func ("/seat/list", test_list_seats);
g_test_add_func ("/seat/default", test_default_seat);
+2 -1
View File
@@ -61,7 +61,8 @@ deserialize_error_func (const GtkCssSection *section,
{
char *section_str = gtk_css_section_to_string (section);
g_error ("Error at %s: %s", section_str, error->message);
g_test_message ("Error at %s: %s", section_str, error->message);
g_test_fail ();
free (section_str);
}
+7
View File
@@ -0,0 +1,7 @@
blur {
blur: 0;
child :color {
color: red;
bounds: 0 0 100 100;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

+11
View File
@@ -0,0 +1,11 @@
/* Add a color node to blow up the bounds so that
we can test the texture bounds work. */
color {
bounds: 0 0 50 50;
color: white;
}
texture {
bounds: 10 10 30 30;
texture: url('data:,<svg><rect width="10" height="10" style="fill:red"/></svg>');
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

+4 -2
View File
@@ -26,8 +26,11 @@ serialize_deserialize = executable(
)
compare_render_tests = [
'blend-normal',
'blend-difference',
'clip-coordinates-3d',
'clipped_rounded_clip',
'color-blur0',
'cross-fade-in-opacity',
'opacity_clip',
'outset_shadow_offset_both',
@@ -36,8 +39,7 @@ compare_render_tests = [
'outset_shadow_rounded_top',
'outset_shadow_simple',
'shadow-in-opacity',
'blend-normal',
'blend-difference',
'texture-url',
]
renderers = [
File diff suppressed because one or more lines are too long
-1
View File
@@ -454,7 +454,6 @@ main (int argc, char *argv[])
g_test_init (&argc, &argv, NULL);
setlocale (LC_ALL, "C");
g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=%s");
create_masks ();
-1
View File
@@ -745,7 +745,6 @@ int
main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv);
g_test_bug_base ("http://bugzilla.gnome.org/");
gtk_test_register_all_types();
g_test_add_func ("/tests/iconview-new", test_iconview_new);
-1
View File
@@ -311,7 +311,6 @@ main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
setlocale (LC_ALL, "C");
g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=%s");
number_quark = g_quark_from_static_string ("Hell and fire was spawned to be released.");
changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?");
+7 -7
View File
@@ -5727,7 +5727,7 @@ specific_bug_301558 (void)
int i;
gboolean add;
g_test_bug ("301558");
/*http://bugzilla.gnome.org/show_bug.cgi?id=301558 */
tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
gtk_tree_store_append (tree, &iter, NULL);
@@ -5803,7 +5803,7 @@ specific_bug_311955 (void)
int n;
GtkTreePath *path;
g_test_bug ("311955");
/*http://bugzilla.gnome.org/show_bug.cgi?id=311955 */
store = gtk_tree_store_new (1, G_TYPE_INT);
@@ -5972,7 +5972,7 @@ specific_bug_346800 (void)
store = gtk_tree_store_newv (2, columns);
model = GTK_TREE_MODEL (store);
g_test_bug ("346800");
/*http://bugzilla.gnome.org/show_bug.cgi?id=346800 */
filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
gtk_tree_model_filter_set_visible_column (filter, 1);
@@ -6031,7 +6031,7 @@ specific_bug_464173 (void)
GtkWidget *view G_GNUC_UNUSED;
gboolean visible = TRUE;
g_test_bug ("464173");
/*http://bugzilla.gnome.org/show_bug.cgi?id=464173 */
model = gtk_tree_store_new (1, G_TYPE_STRING);
gtk_tree_store_append (model, &iter1, NULL);
@@ -6075,7 +6075,7 @@ specific_bug_540201 (void)
GtkWidget *tree_view G_GNUC_UNUSED;
g_test_bug ("540201");
/*http://bugzilla.gnome.org/show_bug.cgi?id=540201 */
store = gtk_tree_store_new (1, G_TYPE_INT);
@@ -6128,7 +6128,7 @@ specific_bug_549287 (void)
GtkTreeIter iter;
GtkTreeIter *swap, *parent, *child;
g_test_bug ("529287");
/*http://bugzilla.gnome.org/show_bug.cgi?id=529287 */
store = gtk_tree_store_new (1, G_TYPE_STRING);
filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
@@ -6227,7 +6227,7 @@ specific_bug_621076 (void)
GtkTreeIter item_iter;
SignalMonitor *monitor;
g_test_bug ("621076");
/*http://bugzilla.gnome.org/show_bug.cgi?id=621076 */
store = gtk_tree_store_new (1, G_TYPE_STRING);
filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
-1
View File
@@ -356,7 +356,6 @@ main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
setlocale (LC_ALL, "C");
g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=%s");
number_quark = g_quark_from_static_string ("Hell and fire was spawned to be released.");
changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?");
-1
View File
@@ -22,7 +22,6 @@ main (int argc, char *argv[])
g_test_init (&argc, &argv, NULL);
gtk_disable_setlocale();
setlocale (LC_ALL, "C");
g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=%s");
g_test_add_func ("/main/init", test_init);

Some files were not shown because too many files have changed in this diff Show More