Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 40b34c76e6 | |||
| 1318d3748a | |||
| 04754d753b | |||
| f8c1f7173a | |||
| a04ea72ca1 | |||
| 0886ade182 | |||
| 0103704171 | |||
| b76d5bda37 | |||
| 6f6b07aaae | |||
| 4bccd17941 | |||
| 0049b39375 | |||
| 63578d832a | |||
| 3a373b9b33 | |||
| 8be95ca348 | |||
| 5da58ba47d | |||
| 4505f4f17b | |||
| e0e9d8c6b5 | |||
| 24fcfa91b1 | |||
| 4f0ea69e9b | |||
| f2e197a389 | |||
| 777beb0d0a | |||
| 1fa4b9f58c | |||
| 9117ee83eb | |||
| b3ff4154ec | |||
| 879a0c118d | |||
| cb51699098 | |||
| d91f04eefd | |||
| a86160265a | |||
| 8aaa8958c4 | |||
| 97b450dfd7 | |||
| 46c1e154f1 | |||
| fcb1408e1e | |||
| 4cc27285b1 | |||
| 705bf48eed | |||
| b651a355ab | |||
| dd299c50bf | |||
| bc7972dfa7 | |||
| 24d6ce7e51 | |||
| e1c1c46e34 | |||
| 60a18229ee | |||
| 725e7c7470 | |||
| 2bd6661cd3 | |||
| 31cd43a245 | |||
| ef446de92d | |||
| 18127be3bd | |||
| 64454a7e47 | |||
| b09a0958a0 | |||
| c541fa9555 | |||
| 1660bac6bd | |||
| 9e40642335 | |||
| 032bb45ce3 | |||
| 5a578669c2 | |||
| 3377133d19 | |||
| ed31ea3773 | |||
| feddf5a694 | |||
| e847c030bd | |||
| b3c4320bc2 | |||
| 730b52b084 | |||
| 4ff578db10 | |||
| 248c07c65e |
+2
-2
@@ -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 .
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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" .
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ gtk_css_public_sources = files([
|
||||
])
|
||||
|
||||
gtk_css_private_sources = files([
|
||||
'gtkcssdataurl.c',
|
||||
'gtkcssparser.c',
|
||||
'gtkcsstokenizer.c',
|
||||
])
|
||||
|
||||
@@ -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>'''
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -127,6 +127,7 @@ typedef struct
|
||||
|
||||
gchar *menubar_path;
|
||||
guint menubar_id;
|
||||
guint profiler_id;
|
||||
|
||||
/* Session management... */
|
||||
GDBusProxy *sm_proxy;
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.')
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 (""));
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -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: �;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
\
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 |
@@ -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 |
@@ -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
@@ -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 ();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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?");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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?");
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user