Compare commits

..

114 Commits

Author SHA1 Message Date
Matthias Clasen 979e3cd685 Change the setup of theme resources
Make Adwaita-dark a standalone separate
theme with the expected directory layout.
2019-05-08 19:00:00 +00:00
Matthias Clasen 4cfde0bdc8 settings: Adapt to css provider api change
Pass a fallback theme name instead of a variant.
2019-05-08 18:59:30 +00:00
Matthias Clasen 872dd9856b css provider: Change gtk_css_provider_load_named
Instead of taking an optional variant, take
an optional fallback theme name. So, instead
of load_named (p, "Adwaita", "dark"), you now
call load_named (p, "Adwaita-dark", "Adwaita").
2019-05-08 18:57:43 +00:00
Matthias Clasen df0648bd74 css provider: Drop an unused field 2019-05-08 18:23:04 +00:00
Matthias Clasen dbd20a6ba6 css provider: Drop an unused private api
This was only used for settings, and we are
not loading theme settings anymore.
2019-05-08 18:01:54 +00:00
Matthias Clasen bc64f7d815 settings: Stop loading theme settings
This was invented for Windows themes, back in
the day, and we don't ship a Windows theme
anymore. We want to get to a place where
settings are always in GSettings.
2019-05-08 17:59:09 +00:00
Matthias Clasen b3ff4154ec Drop the public profiler api
I meant to do this before merging the profiler
support. Somehow the commit got lost.
2019-05-08 17:00:26 +00:00
Matthias Clasen 879a0c118d Profiler: drop the public api 2019-05-08 16:57:34 +00:00
Matthias Clasen cb51699098 profiler: Update the D-Bus interface name
Sysprof is bumping its name to Sysprof3, so
lets change to that before this gets used.
2019-05-08 16:49:47 +00:00
Matthias Clasen d91f04eefd Correct theme loading docs
The docs were failing to mention the VARIANT.
2019-05-08 14:47:08 +00:00
Matthias Clasen a86160265a css provider: Remove outdated version check
When looking for versioned theme files, we were
looking for directories names gtk-4.x for x
bigger than 14, which mades sense for GTK 3,
but we are starting out at 0 again, so remove
this check.
2019-05-08 14:33:23 +00:00
Matthias Clasen 8aaa8958c4 Merge branch 'inspector-css' into 'master'
Inspector css

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

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

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

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

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

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

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

See merge request GNOME/gtk!739
2019-05-07 16:32:36 +00:00
Emmanuele Bassi 3377133d19 Require CUPS >= 2.0
Drop support for versions of CUPS < 2.0, to simplify the backend code
and drop a lot of conditional blocks.
2019-05-07 18:30:47 +02:00
Emmanuele Bassi ed31ea3773 cups: Use non-deprecated API
The http* family of functions was deprecated after CUPS 1.7. We can
conditionally use it when built against a newer version of CUPS. The
additional parameters are taken directly from the fallback values
inside CUPS itself.
2019-05-07 18:30:47 +02:00
Emmanuele Bassi feddf5a694 Detect CUPS ≥ 1.7
We support CUPS ≥ 1.2, but we use API that was introduced and deprecated
at a later point.
2019-05-07 18:30:47 +02:00
Timm Bäder e847c030bd gl renderer: Fix blur nodes with radius 0 2019-05-07 17:21:16 +02:00
Timm Bäder b3c4320bc2 node editor: Do some simple syntax highlighting 2019-05-07 17:21:16 +02:00
Timm Bäder 730b52b084 testsuite: Add blur node testcase
Renderers need to handle blur radius 0 as well. Currently broken in GL
and (I guess, unless it's my driver) Vulkan.
2019-05-07 17:21:16 +02:00
Matthias Clasen 4ff578db10 Fix the compiler warning, again 2019-05-07 14:57:53 +00:00
Matthias Clasen 248c07c65e Fix a compiler warning 2019-05-07 04:01:21 +00:00
Matthias Clasen b01cf6be65 3.96 2019-05-07 03:27:04 +00:00
Matthias Clasen a0c6d88858 Mark a failing reftest as xfail
I don't know why we expect different window types
to render identically in the first place.
2019-05-07 03:27:04 +00:00
Matthias Clasen 68560a941a Update a11y tests 2019-05-07 02:21:30 +00:00
Matthias Clasen 77b7817266 a11y: Stop using child-notify
This was showing up in the accessibility tests failing.
2019-05-07 02:21:30 +00:00
Matthias Clasen c6a42e92bb widget: Revert the event translation change
This is a temporary revert to make menus work
in the 3.96 release, until we land the popup
surface work and port menus to it.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1755
2019-05-06 22:20:51 +00:00
Benjamin Otte 73ff7baa1b Merge branch 'wip/headers' into 'master'
Wip/headers

See merge request GNOME/gtk!824
2019-05-06 18:24:49 +00:00
Benjamin Otte e29cf84ac4 broadway: Install headers
How are we going to check a display for its broadway-ness otherwise?
2019-05-06 20:15:49 +02:00
Benjamin Otte 7ae675b469 build: Install the backend headers in the backend directories
That's where they are in the sources and we include them from other
headers. So make sure the directories match.
2019-05-06 20:14:53 +02:00
Piotr Drąg b87b281df1 Update POTFILES.skip 2019-05-06 18:55:40 +02:00
Timm Bäder 4869013a8d gl renderer: Fix coloring shader
We *just* pre-multiplied u_color but then didn't use its rgb values.
This fixes backdrop scale marks in Adwaita to not be white.
2019-05-06 17:58:55 +02:00
Timm Bäder 3e2107846d gl renderer: Fix blend shader 2019-05-06 17:34:48 +02:00
Timm Bäder c8865459fc testsuite: Add blend-difference test case
Comparing blend nodes with mode: difference
2019-05-06 17:34:48 +02:00
Timm Bäder 8559593a18 testsuite: Add a blend node test case
This is currently broken in the GL renderer.
2019-05-06 17:34:48 +02:00
Timm Bäder 759a97403c Some node editor improvements 2019-05-06 17:34:48 +02:00
Matthias Clasen a8aa7afa13 Merge branch 'header-bar-leak4' into 'master'
GtkHeaderBar: Don't leak decoration layout

See merge request GNOME/gtk!822
2019-05-06 14:17:17 +00:00
Emmanuele Bassi ecc8f9cf72 Merge branch 'issue-1863' into 'master'
Allow setting the GtkLayoutManager type per-class

Closes #1863

See merge request GNOME/gtk!821
2019-05-06 12:01:47 +00:00
Emmanuele Bassi fe473dbef8 Make get_layout_manager_type() public
The inspector, and other tools introspecting the widget structure like
gtk-builder-tool and Glade, may very well want to access the default
layout manager used by a class, especially if there are layout
properties involved, without having a whitelist of widget/layout manager
associations.
2019-05-06 12:15:21 +01:00
Emmanuele Bassi 59c6862a03 Use gtk_widget_class_set_layout_manager_type()
Instead of manually creating the layout manager inside the instance
initialization function, we can let GtkWidget do that for us.
2019-05-06 12:06:27 +01:00
Guido Günther e98973e2c0 GtkHeaderBar: Don't leak decoration layout
Currently we leak priv->decoration_layout if the layout is set
multiple times.
2019-05-06 12:59:20 +02:00
Emmanuele Bassi c6b2184aa0 Allow specifying the layout manager for a widget type
Some widgets have a well-defined layout manager created alongside their
own instance; if they do, we can handle the layout manager creation at
the GtkWidget instantiation.
2019-05-06 11:57:32 +01:00
Benjamin Otte 562e492056 csstokenizer: Consume the \ when encountering an error
Otherwise we infinitely end up with the error again.

Testcases added.
2019-05-06 05:56:06 +02:00
Matthias Clasen 15b8ee4564 Merge branch 'simplify-tests' into 'master'
Simplify tests

See merge request GNOME/gtk!820
2019-05-05 20:19:13 +00:00
Matthias Clasen d61e77dab4 Add some tests
These test various aspects of ui file conversion.
2019-05-05 17:13:38 +00:00
Matthias Clasen d8e92d4859 builder-tool: Handle layout properties more properly
Change things so we first rewrite the whole tree,
and then simplify the rewritten tree. And look
for paramspecs for layout properties.
2019-05-05 17:13:38 +00:00
Matthias Clasen 4eb00a3e41 builder-tool: Stop warnings for stack rewrites
When rewriting a GtkStack from 3 to 4, we were emitting
warnings for missing child properties. Stop doing that.
2019-05-05 17:13:38 +00:00
Matthias Clasen 82eee65334 testsuite: Add tests for ui file rewriting
Add a test script that runs
gtk4-builder-tool simplify --3to4.
No actual tests yet.
2019-05-05 17:13:13 +00:00
Matthias Clasen 4f6cc46278 Fix the simplify test
The script was returning the wrong number of tests.
2019-05-05 15:21:58 +00:00
Matthias Clasen 84d3848c01 Merge branch 'focus-fixes' into 'master'
Focus fixes

See merge request GNOME/gtk!819
2019-05-05 14:20:04 +00:00
Piotr Drąg b4093e59ee Update POTFILES.skip 2019-05-05 16:11:04 +02:00
Matthias Clasen c4013eeb26 Merge branch 'builder-tool-fixes' into 'master'
Builder tool fixes

See merge request GNOME/gtk!817
2019-05-05 06:57:21 +00:00
Matthias Clasen 96cce3ae23 Merge branch 'emoji-chooser-fixes' into 'master'
Emoji chooser fixes

See merge request GNOME/gtk!816
2019-05-05 06:41:31 +00:00
Matthias Clasen 09b6dbb7ef builder-tool: Handle default values changing
The default value of GtkWidget::visible changed
from FALSE to TRUE from GTK 3 to 4. Make --3to4
deal with this by ensuring the visible property
is explicitly set, before simplifying.
2019-05-04 23:41:30 -07:00
Benjamin Otte cfea8de6b5 Merge branch 'wip/otte/nodeeditor2' into 'master'
Use a text based format for render node files

See merge request GNOME/gtk!815
2019-05-05 05:40:54 +00:00
Timm Bäder d5d48af7f7 gl renderer: Reset opacity when offscreen-rendering crossfade nodes
A pattern emerges...
2019-05-05 07:18:39 +02:00
Benjamin Otte 43a5ff8e01 testsuite: Add serialize test for debug node 2019-05-05 07:18:39 +02:00
Benjamin Otte 00b947124f node-editor: Add renderings with alternative renderers
That's pretty rough around the edges, but it mostly works.
Apart from sizing, screw listbox sizing.
2019-05-05 07:18:39 +02:00
Benjamin Otte 3f24ad741a gsk: Export gsk_vulkan_renderer_new() 2019-05-05 07:18:39 +02:00
Benjamin Otte cc5f2f8995 gsk: Export gsk_broadway_renderer_new()
... when broadway is enabled.
2019-05-05 07:18:39 +02:00
Benjamin Otte 6594ccf716 gsk: Export gsk_gl_renderer_new() 2019-05-05 07:18:39 +02:00
Benjamin Otte 559ae8b326 gsk: Export Cairo renderer 2019-05-05 07:18:39 +02:00
Benjamin Otte da5b99f807 testsuite: Add rounded-rect parsing test 2019-05-05 07:18:39 +02:00
Benjamin Otte 008b7bc94f Add gtk4-node-editor
It's meant to be a little editor for render nodes so we can do testing
with it.
2019-05-05 07:18:39 +02:00
Benjamin Otte b4f5baf4fa rendernode: Parse and print blend nodes properly 2019-05-05 07:18:39 +02:00
Timm Bäder 8c04129b94 testsuite: Add nodeparser test case
A serialized frame from the widget factory!
2019-05-05 07:18:39 +02:00
Timm Bäder 5010461066 ci: Don't disable the gsk suite 2019-05-05 07:18:39 +02:00
Timm Bäder dde69802cd Add error func to node deserialization 2019-05-05 07:18:39 +02:00
Benjamin Otte 5530331b35 testsuite: Black out parts of reftest 2019-05-05 07:18:39 +02:00
Timm Bäder a55ebf2350 testsuite: Remove old cairo/vulkan tests
They are still in the old binary format and haven't worked for a while.
2019-05-05 07:18:39 +02:00
Timm Bäder fb63364f30 rendernode: Remove old GVariant (de)serialization code
We're doing the CSS thing now.
2019-05-05 07:18:39 +02:00
Timm Bäder 58666c6210 testsuite: Add another gl renderer test 2019-05-05 07:18:39 +02:00
Benjamin Otte 3a9fa035ee testsuite: Remove gl_tests infrastructure
They're now completely migrated to the new compare infrastructure, that
also tests Vulkan and Cairo.
2019-05-05 07:18:39 +02:00
Timm Bäder 1000d971f9 testsuite: Add cross-fade-in-opacity test
Making sure that an opacity node doesn't end up reviving a node that's
hidden because the cross-fade has progress 0 or 1.
2019-05-05 07:18:39 +02:00
Timm Bäder 349e6af2c8 testsuite: Remove broken GL comparison tests
These only work on special hardware, which not even I have anymore.
We'll need to redo them in a way that works on different systems.
2019-05-05 07:18:39 +02:00
Timm Bäder 44b3b8937a testsuite: Print serialized nodes when parsing fails 2019-05-05 07:18:39 +02:00
Timm Bäder 9598e16753 testsuite: add shadow node parser test 2019-05-05 07:18:39 +02:00
Timm Bäder 61a963d78d testsuite: add another nodeparser crash test 2019-05-05 07:18:39 +02:00
Timm Bäder e31856fe1b testsuite: Add serialize-deserialize tests
Check that we can successfully deserialize a node, then serialize it
again and deserialize that result once more.
2019-05-05 07:18:39 +02:00
Benjamin Otte 1d6134f87d testsuite: Add a broken test
This also adds some build magic so all tests that contain "-3d" in them
won't be added to the Cairo renderer.

Of course, this new test is such a test.
2019-05-05 07:18:39 +02:00
Benjamin Otte 08e9725797 Move working tests to new directory
These are tests that are working on both GL and Cairo now.

Some tests got black boxes over the areas that aren't easy to compare.
2019-05-05 07:18:39 +02:00
Timm Bäder 4d98e96124 testsuite: Port gl tests to text-based format 2019-05-05 07:18:39 +02:00
Benjamin Otte 50e10cd771 testsuite: Delete some node tests
These are the tests that aren't going to be made to work, so let's just
delete them.
2019-05-05 07:18:39 +02:00
Benjamin Otte b6838cb9f4 testsuite: Add tests for the new node parsing code
This adds a test tool gsk/node-parser that takes node files and parses
them.

A few of these node files have been added, for crashes I encountered while
developing the new parsing code.
2019-05-05 07:18:39 +02:00
Timm Bäder 01a7c7a8b2 Parse render nodes from text files
Instead of the previous approach using GVariant, this new approach uses
human-readable text files as the serialization format for render nodes.

The format is a custom one, but it is inspired by QML and conforms to
the CSS syntax. Because of that, we can use the CSS machinery from GTK
to parse it, and in particular share code to parse properties that GTK's
CSS machinery also supports, such as colors.

This commit breaks all existing usages of node files - such as the
testsuite and various test tools - they will be fixed in further
commits.
2019-05-05 07:18:39 +02:00
Benjamin Otte 3c6aa84e44 cssparser: Add gtk_css_parser_has_number() 2019-05-05 07:18:39 +02:00
Asier Sarasua Garmendia bf2ae5aa81 Update Basque translation 2019-05-04 19:34:25 +00:00
Matthias Clasen 44b0a893fc entry: Drop our own Emoji chooser
We were using one Emoji chooser when triggered
via the context menu, and another one when
triggered via the icon.

Change things to always use the same Emoji
chooser instance.
2019-05-04 18:54:37 +00:00
Matthias Clasen 32fd55a66d window: Stop duplicating focus change events
We had code in gtkwindow.c that generated duplicate,
and defective, focus-change events, in the following
way:
- gtkmain.c generates a chain of focus-change events
  for moving focus from one window to another
- gtkwindow.c catches a focus-in event in the middle
  of this chain and sets itself as 'active'
- and then it proceeds to generate focus-change
  events towards its own focus widget without a
  related target
This is not necessary since we gtkmain.c already
generates a complete sequence of focus-change events.
So stop doing it.
2019-05-04 18:22:33 +00:00
Matthias Clasen 9af01bea5e window: Make _gtk_window_set_is_active static
It is not used outside gtkwindow.c.
2019-05-04 18:22:28 +00:00
Matthias Clasen 40fe3d94ac builder-tool: Handle GtkWidget::visible properly
This property has a 'smart' default that depends
on the class of the object we're creating. Take
that into account when deciding whether to omit
properties that are set to their default value.
2019-05-04 18:18:42 +00:00
Matthias Clasen 6fe203d0e2 emoji chooser: Make Escape work again
Escape is expected to close the Emoji chooser.
2019-05-04 18:18:20 +00:00
Matthias Clasen 7b6f652630 emoji chooser: Fix handling of no recent Emoji
If the recent section is empty, we want to hide
it, make its button insensitive, and select the
next section, initially. This was not working
properly, since nothing was ever setting the
section box to invisible.
2019-05-04 18:18:09 +00:00
267 changed files with 14762 additions and 6224 deletions
-1
View File
@@ -32,7 +32,6 @@ xvfb-run -a -s "-screen 0 1024x768x24" \
--timeout-multiplier 2 \
--print-errorlogs \
--suite=gtk \
--no-suite=gtk:gsk \
--no-suite=gtk:a11y
# Save the exit code
-3
View File
@@ -24,9 +24,6 @@
/* Define to 1 if you have the <crt_externs.h> header file. */
#mesondefine HAVE_CRT_EXTERNS_H
/* Define to 1 if CUPS 1.6 API is available */
#mesondefine HAVE_CUPS_API_1_6
/* Define to 1 if you have the `dcgettext' function. */
#mesondefine HAVE_DCGETTEXT
+1
View File
@@ -1,3 +1,4 @@
subdir('gtk-demo')
subdir('icon-browser')
subdir('node-editor')
subdir('widget-factory')
+323
View File
@@ -0,0 +1,323 @@
/*
* 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 "config.h"
#include "gtkrendererpaintableprivate.h"
#include <gtk/gtk.h>
struct _GtkRendererPaintable
{
GObject parent_instance;
GskRenderer *renderer;
GdkPaintable *paintable;
};
struct _GtkRendererPaintableClass
{
GObjectClass parent_class;
};
enum {
PROP_0,
PROP_PAINTABLE,
PROP_RENDERER,
N_PROPS
};
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
gtk_renderer_paintable_paintable_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkRendererPaintable *self = GTK_RENDERER_PAINTABLE (paintable);
GtkSnapshot *node_snapshot;
GskRenderNode *node;
GdkTexture *texture;
if (self->paintable == NULL)
return;
if (self->renderer == NULL ||
!gsk_renderer_is_realized (self->renderer))
{
gdk_paintable_snapshot (self->paintable, snapshot, width, height);
return;
}
node_snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (self->paintable, node_snapshot, width, height);
node = gtk_snapshot_free_to_node (node_snapshot);
if (node == NULL)
return;
texture = gsk_renderer_render_texture (self->renderer,
node,
&GRAPHENE_RECT_INIT (0, 0, width, height));
gdk_paintable_snapshot (GDK_PAINTABLE (texture), snapshot, width, height);
g_object_unref (texture);
}
static int
gtk_renderer_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable)
{
GtkRendererPaintable *self = GTK_RENDERER_PAINTABLE (paintable);
if (self->paintable == NULL)
return 0;
return gdk_paintable_get_intrinsic_width (self->paintable);
}
static int
gtk_renderer_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable)
{
GtkRendererPaintable *self = GTK_RENDERER_PAINTABLE (paintable);
if (self->paintable == NULL)
return 0;
return gdk_paintable_get_intrinsic_height (self->paintable);
}
static double
gtk_renderer_paintable_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
{
GtkRendererPaintable *self = GTK_RENDERER_PAINTABLE (paintable);
if (self->paintable == NULL)
return 0.0;
return gdk_paintable_get_intrinsic_aspect_ratio (self->paintable);
}
static void
gtk_renderer_paintable_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = gtk_renderer_paintable_paintable_snapshot;
iface->get_intrinsic_width = gtk_renderer_paintable_paintable_get_intrinsic_width;
iface->get_intrinsic_height = gtk_renderer_paintable_paintable_get_intrinsic_height;
iface->get_intrinsic_aspect_ratio = gtk_renderer_paintable_paintable_get_intrinsic_aspect_ratio;
}
G_DEFINE_TYPE_EXTENDED (GtkRendererPaintable, gtk_renderer_paintable, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_renderer_paintable_paintable_init))
static void
gtk_renderer_paintable_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkRendererPaintable *self = GTK_RENDERER_PAINTABLE (object);
switch (prop_id)
{
case PROP_PAINTABLE:
gtk_renderer_paintable_set_paintable (self, g_value_get_object (value));
break;
case PROP_RENDERER:
gtk_renderer_paintable_set_renderer (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_renderer_paintable_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkRendererPaintable *self = GTK_RENDERER_PAINTABLE (object);
switch (prop_id)
{
case PROP_PAINTABLE:
g_value_set_object (value, self->paintable);
break;
case PROP_RENDERER:
g_value_set_object (value, self->renderer);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_renderer_paintable_unset_paintable (GtkRendererPaintable *self)
{
guint flags;
if (self->paintable == NULL)
return;
flags = gdk_paintable_get_flags (self->paintable);
if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
g_signal_handlers_disconnect_by_func (self->paintable,
gdk_paintable_invalidate_contents,
self);
if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0)
g_signal_handlers_disconnect_by_func (self->paintable,
gdk_paintable_invalidate_size,
self);
g_clear_object (&self->paintable);
}
static void
gtk_renderer_paintable_dispose (GObject *object)
{
GtkRendererPaintable *self = GTK_RENDERER_PAINTABLE (object);
g_clear_object (&self->renderer);
gtk_renderer_paintable_unset_paintable (self);
G_OBJECT_CLASS (gtk_renderer_paintable_parent_class)->dispose (object);
}
static void
gtk_renderer_paintable_class_init (GtkRendererPaintableClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gtk_renderer_paintable_get_property;
gobject_class->set_property = gtk_renderer_paintable_set_property;
gobject_class->dispose = gtk_renderer_paintable_dispose;
properties[PROP_PAINTABLE] =
g_param_spec_object ("paintable",
"Paintable",
"The paintable to be shown",
GDK_TYPE_PAINTABLE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
properties[PROP_RENDERER] =
g_param_spec_object ("renderer",
"Renderer",
"Renderer used to render the paintable",
GSK_TYPE_RENDERER,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gtk_renderer_paintable_init (GtkRendererPaintable *self)
{
}
GdkPaintable *
gtk_renderer_paintable_new (GskRenderer *renderer,
GdkPaintable *paintable)
{
g_return_val_if_fail (renderer == NULL || GSK_IS_RENDERER (renderer), NULL);
g_return_val_if_fail (paintable == NULL || GDK_IS_PAINTABLE (paintable), NULL);
return g_object_new (GTK_TYPE_RENDERER_PAINTABLE,
"renderer", renderer,
"paintable", paintable,
NULL);
}
void
gtk_renderer_paintable_set_renderer (GtkRendererPaintable *self,
GskRenderer *renderer)
{
g_return_if_fail (GTK_IS_RENDERER_PAINTABLE (self));
g_return_if_fail (renderer == NULL || GSK_IS_RENDERER (renderer));
if (!g_set_object (&self->renderer, renderer))
return;
if (self->paintable)
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RENDERER]);
}
GskRenderer *
gtk_renderer_paintable_get_renderer (GtkRendererPaintable *self)
{
g_return_val_if_fail (GTK_IS_RENDERER_PAINTABLE (self), NULL);
return self->renderer;
}
void
gtk_renderer_paintable_set_paintable (GtkRendererPaintable *self,
GdkPaintable *paintable)
{
g_return_if_fail (GTK_IS_RENDERER_PAINTABLE (self));
g_return_if_fail (paintable == NULL || GDK_IS_PAINTABLE (paintable));
if (self->paintable == paintable)
return;
gtk_renderer_paintable_unset_paintable (self);
if (paintable)
{
const guint flags = gdk_paintable_get_flags (paintable);
self->paintable = g_object_ref (paintable);
if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
g_signal_connect_swapped (paintable,
"invalidate-contents",
G_CALLBACK (gdk_paintable_invalidate_contents),
self);
if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0)
g_signal_connect_swapped (paintable,
"invalidate-size",
G_CALLBACK (gdk_paintable_invalidate_size),
self);
}
gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PAINTABLE]);
}
GdkPaintable *
gtk_renderer_paintable_get_paintable (GtkRendererPaintable *self)
{
g_return_val_if_fail (GTK_IS_RENDERER_PAINTABLE (self), NULL);
return self->paintable;
}
@@ -0,0 +1,43 @@
/*
* 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_RENDERER_PAINTABLE_H__
#define __GTK_RENDERER_PAINTABLE_H__
#include <gsk/gsk.h>
G_BEGIN_DECLS
#define GTK_TYPE_RENDERER_PAINTABLE (gtk_renderer_paintable_get_type ())
G_DECLARE_FINAL_TYPE (GtkRendererPaintable, gtk_renderer_paintable, GTK, RENDERER_PAINTABLE, GObject)
GdkPaintable * gtk_renderer_paintable_new (GskRenderer *renderer,
GdkPaintable *paintable);
void gtk_renderer_paintable_set_renderer (GtkRendererPaintable *self,
GskRenderer *renderer);
GskRenderer * gtk_renderer_paintable_get_renderer (GtkRendererPaintable *self) G_GNUC_PURE;
void gtk_renderer_paintable_set_paintable (GtkRendererPaintable *self,
GdkPaintable *paintable);
GdkPaintable * gtk_renderer_paintable_get_paintable (GtkRendererPaintable *self) G_GNUC_PURE;
G_END_DECLS
#endif /* __GTK_RENDERER_PAINTABLE_H__ */
+28
View File
@@ -0,0 +1,28 @@
/*
* 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 "config.h"
#include <node-editor-application.h>
int
main (int argc, char *argv[])
{
return g_application_run (G_APPLICATION (node_editor_application_new ()), argc, argv);
}
+18
View File
@@ -0,0 +1,18 @@
node_editor_sources = [
'gtkrendererpaintable.c',
'main.c',
'node-editor-application.c',
'node-editor-window.c',
]
node_editor_resources = gnome.compile_resources('node_editor_resources',
'node-editor.gresource.xml',
source_dir: '.')
executable('gtk4-node-editor',
node_editor_sources, node_editor_resources,
dependencies: libgtk_dep,
include_directories: confinc,
gui_app: true,
link_args: extra_demo_ldflags,
install: false)
+132
View File
@@ -0,0 +1,132 @@
/*
* 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 "config.h"
#include "node-editor-application.h"
#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;
};
struct _NodeEditorApplicationClass
{
GtkApplicationClass parent_class;
};
G_DEFINE_TYPE(NodeEditorApplication, node_editor_application, GTK_TYPE_APPLICATION);
static void
node_editor_application_init (NodeEditorApplication *app)
{
}
static void
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
g_application_quit (G_APPLICATION (data));
}
static GActionEntry app_entries[] =
{
{ "quit", quit_activated, NULL, NULL, NULL }
};
static void
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);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
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
node_editor_application_activate (GApplication *app)
{
NodeEditorWindow *win;
win = node_editor_window_new (NODE_EDITOR_APPLICATION (app));
gtk_window_present (GTK_WINDOW (win));
}
static void
node_editor_application_open (GApplication *app,
GFile **files,
gint n_files,
const gchar *hint)
{
NodeEditorWindow *win;
gint i;
for (i = 0; i < n_files; i++)
{
win = node_editor_window_new (NODE_EDITOR_APPLICATION (app));
node_editor_window_load (win, files[i]);
gtk_window_present (GTK_WINDOW (win));
}
}
static void
node_editor_application_class_init (NodeEditorApplicationClass *class)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
application_class->startup = node_editor_application_startup;
application_class->activate = node_editor_application_activate;
application_class->open = node_editor_application_open;
}
NodeEditorApplication *
node_editor_application_new (void)
{
return g_object_new (NODE_EDITOR_APPLICATION_TYPE,
"application-id", "org.gtk.gtk4.NodeEditor",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}
@@ -0,0 +1,38 @@
/*
* 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 __NODE_EDITOR_APPLICATION_H__
#define __NODE_EDITOR_APPLICATION_H__
#include <gtk/gtk.h>
#define NODE_EDITOR_APPLICATION_TYPE (node_editor_application_get_type ())
#define NODE_EDITOR_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NODE_EDITOR_APPLICATION_TYPE, NodeEditorApplication))
typedef struct _NodeEditorApplication NodeEditorApplication;
typedef struct _NodeEditorApplicationClass NodeEditorApplicationClass;
GType node_editor_application_get_type (void);
NodeEditorApplication *node_editor_application_new (void);
#endif /* __NODE_EDITOR_APPLICATION_H__ */
+701
View File
@@ -0,0 +1,701 @@
/*
* 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 "config.h"
#include "node-editor-window.h"
#include "gtkrendererpaintableprivate.h"
#include "gsk/gskrendernodeparserprivate.h"
typedef struct
{
gsize start_chars;
gsize end_chars;
char *message;
} TextViewError;
struct _NodeEditorWindow
{
GtkApplicationWindow parent;
GtkWidget *picture;
GtkWidget *text_view;
GtkTextBuffer *text_buffer;
GtkTextTagTable *tag_table;
GtkWidget *renderer_listbox;
GListStore *renderers;
GdkPaintable *paintable;
GArray *errors;
};
struct _NodeEditorWindowClass
{
GtkApplicationWindowClass parent_class;
};
G_DEFINE_TYPE(NodeEditorWindow, node_editor_window, GTK_TYPE_APPLICATION_WINDOW);
static void
text_view_error_free (TextViewError *e)
{
g_free (e->message);
}
static gchar *
get_current_text (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);
return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
}
static void
deserialize_error_func (const GtkCssSection *section,
const GError *error,
gpointer user_data)
{
const GtkCssLocation *start_location = gtk_css_section_get_start_location (section);
const GtkCssLocation *end_location = gtk_css_section_get_end_location (section);
NodeEditorWindow *self = user_data;
GtkTextIter start_iter, end_iter;
TextViewError text_view_error;
gtk_text_buffer_get_iter_at_line_offset (self->text_buffer, &start_iter,
start_location->lines,
start_location->line_chars);
gtk_text_buffer_get_iter_at_line_offset (self->text_buffer, &end_iter,
end_location->lines,
end_location->line_chars);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "error",
&start_iter, &end_iter);
text_view_error.start_chars = start_location->chars;
text_view_error.end_chars = end_location->chars;
text_view_error.message = g_strdup (error->message);
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)
{
GskRenderNode *node;
char *text;
GBytes *bytes;
g_array_remove_range (self->errors, 0, self->errors->len);
text = get_current_text (self->text_buffer);
bytes = g_bytes_new_take (text, strlen (text));
/* If this is too slow, go fix the parser performance */
node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
g_bytes_unref (bytes);
if (node)
{
/* XXX: Is this code necessary or can we have API to turn nodes into paintables? */
GtkSnapshot *snapshot;
GdkPaintable *paintable;
graphene_rect_t bounds;
guint i;
snapshot = gtk_snapshot_new ();
gsk_render_node_get_bounds (node, &bounds);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i++)
{
gpointer item = g_list_model_get_item (G_LIST_MODEL (self->renderers), i);
gtk_renderer_paintable_set_paintable (item, paintable);
g_object_unref (item);
}
g_clear_object (&paintable);
}
else
{
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
text_view_query_tooltip_cb (GtkWidget *widget,
int x,
int y,
gboolean keyboard_tip,
GtkTooltip *tooltip,
NodeEditorWindow *self)
{
GtkTextIter iter;
guint i;
if (keyboard_tip)
{
gint offset;
g_object_get (self->text_buffer, "cursor-position", &offset, NULL);
gtk_text_buffer_get_iter_at_offset (self->text_buffer, &iter, offset);
}
else
{
gint bx, by, trailing;
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (self->text_view), GTK_TEXT_WINDOW_TEXT,
x, y, &bx, &by);
gtk_text_view_get_iter_at_position (GTK_TEXT_VIEW (self->text_view), &iter, &trailing, bx, by);
}
for (i = 0; i < self->errors->len; i ++)
{
const TextViewError *e = &g_array_index (self->errors, TextViewError, i);
GtkTextIter start_iter, end_iter;
gtk_text_buffer_get_iter_at_offset (self->text_buffer, &start_iter, e->start_chars);
gtk_text_buffer_get_iter_at_offset (self->text_buffer, &end_iter, e->end_chars);
if (gtk_text_iter_in_range (&iter, &start_iter, &end_iter))
{
gtk_tooltip_set_text (tooltip, e->message);
return TRUE;
}
}
return FALSE;
}
gboolean
node_editor_window_load (NodeEditorWindow *self,
GFile *file)
{
GtkTextIter end;
GBytes *bytes;
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
if (bytes == NULL)
return FALSE;
if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL))
{
g_bytes_unref (bytes);
return FALSE;
}
gtk_text_buffer_get_end_iter (self->text_buffer, &end);
gtk_text_buffer_insert (self->text_buffer,
&end,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes));
g_bytes_unref (bytes);
return TRUE;
}
static void
open_response_cb (GtkWidget *dialog,
gint response,
NodeEditorWindow *self)
{
gtk_widget_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
node_editor_window_load (self, file);
g_object_unref (file);
}
gtk_widget_destroy (dialog);
}
static void
show_open_filechooser (NodeEditorWindow *self)
{
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Open node file",
GTK_WINDOW (self),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Load", GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_widget_show (dialog);
}
static void
open_cb (GtkWidget *button,
NodeEditorWindow *self)
{
show_open_filechooser (self);
}
static void
save_response_cb (GtkWidget *dialog,
gint response,
NodeEditorWindow *self)
{
gtk_widget_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
char *text, *filename;
GError *error = NULL;
text = get_current_text (self->text_buffer);
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!g_file_set_contents (filename, text, -1, &error))
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Saving failed");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
g_error_free (error);
}
g_free (filename);
}
gtk_widget_destroy (dialog);
}
static void
save_cb (GtkWidget *button,
NodeEditorWindow *self)
{
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Save node",
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Save", GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_widget_show (dialog);
}
static GdkTexture *
create_texture (NodeEditorWindow *self)
{
GdkPaintable *paintable;
GtkSnapshot *snapshot;
GskRenderer *renderer;
GskRenderNode *node;
GdkTexture *texture;
paintable = gtk_picture_get_paintable (GTK_PICTURE (self->picture));
if (paintable == NULL ||
gdk_paintable_get_intrinsic_width (paintable) <= 0 ||
gdk_paintable_get_intrinsic_height (paintable) <= 0)
return NULL;
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, gdk_paintable_get_intrinsic_width (paintable), gdk_paintable_get_intrinsic_height (paintable));
node = gtk_snapshot_free_to_node (snapshot);
if (node == NULL)
return NULL;
/* ahem */
renderer = GTK_ROOT_GET_IFACE (gtk_widget_get_root (GTK_WIDGET (self)))->get_renderer (gtk_widget_get_root (GTK_WIDGET (self)));
texture = gsk_renderer_render_texture (renderer, node, NULL);
gsk_render_node_unref (node);
return texture;
}
static void
export_image_response_cb (GtkWidget *dialog,
gint response,
GdkTexture *texture)
{
gtk_widget_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!gdk_texture_save_to_png (texture, filename))
{
GtkWidget *message_dialog;
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (dialog))),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Exporting to image failed");
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (message_dialog);
}
g_free (filename);
}
gtk_widget_destroy (dialog);
g_object_unref (texture);
}
static void
export_image_cb (GtkWidget *button,
NodeEditorWindow *self)
{
GdkTexture *texture;
GtkWidget *dialog;
texture = create_texture (self);
if (texture == NULL)
return;
dialog = gtk_file_chooser_dialog_new ("",
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Save", GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
g_signal_connect (dialog, "response", G_CALLBACK (export_image_response_cb), texture);
gtk_widget_show (dialog);
}
static void
node_editor_window_finalize (GObject *object)
{
NodeEditorWindow *self = (NodeEditorWindow *)object;
g_array_free (self->errors, TRUE);
g_clear_object (&self->renderers);
G_OBJECT_CLASS (node_editor_window_parent_class)->finalize (object);
}
static void
node_editor_window_add_renderer (NodeEditorWindow *self,
GskRenderer *renderer,
const char *description)
{
GdkSurface *surface;
GdkPaintable *paintable;
surface = gtk_widget_get_surface (GTK_WIDGET (self));
g_assert (surface != NULL);
if (renderer != NULL && !gsk_renderer_realize (renderer, surface, NULL))
{
g_object_unref (renderer);
return;
}
paintable = gtk_renderer_paintable_new (renderer, gtk_picture_get_paintable (GTK_PICTURE (self->picture)));
g_object_set_data_full (G_OBJECT (paintable), "description", g_strdup (description), g_free);
g_clear_object (&renderer);
g_list_store_append (self->renderers, paintable);
g_object_unref (paintable);
}
static void
node_editor_window_realize (GtkWidget *widget)
{
NodeEditorWindow *self = NODE_EDITOR_WINDOW (widget);
GTK_WIDGET_CLASS (node_editor_window_parent_class)->realize (widget);
#if 0
node_editor_window_add_renderer (self,
NULL,
"Default");
#endif
node_editor_window_add_renderer (self,
gsk_gl_renderer_new (),
"OpenGL");
#ifdef GDK_RENDERING_VULKAN
node_editor_window_add_renderer (self,
gsk_vulkan_renderer_new (),
"Vulkan");
#endif
#ifdef GDK_WINDOWING_BROADWAY
node_editor_window_add_renderer (self,
gsk_broadway_renderer_new (),
"Broadway");
#endif
node_editor_window_add_renderer (self,
gsk_cairo_renderer_new (),
"Cairo");
}
static void
node_editor_window_unrealize (GtkWidget *widget)
{
NodeEditorWindow *self = NODE_EDITOR_WINDOW (widget);
g_list_store_remove_all (self->renderers);
GTK_WIDGET_CLASS (node_editor_window_parent_class)->unrealize (widget);
}
static void
node_editor_window_class_init (NodeEditorWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->finalize = node_editor_window_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/node-editor/node-editor-window.ui");
widget_class->realize = node_editor_window_realize;
widget_class->unrealize = node_editor_window_unrealize;
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_view_query_tooltip_cb);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
gtk_widget_class_bind_template_callback (widget_class, save_cb);
gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
}
static GtkWidget *
node_editor_window_create_renderer_widget (gpointer item,
gpointer user_data)
{
GdkPaintable *paintable = item;
GtkWidget *box, *label, *picture;
GtkWidget *row;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_size_request (box, 120, 90);
label = gtk_label_new (g_object_get_data (G_OBJECT (paintable), "description"));
gtk_container_add (GTK_CONTAINER (box), label);
picture = gtk_picture_new_for_paintable (paintable);
gtk_container_add (GTK_CONTAINER (box), picture);
row = gtk_list_box_row_new ();
gtk_container_add (GTK_CONTAINER (row), box);
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
return row;
}
static void
window_open (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
NodeEditorWindow *self = user_data;
show_open_filechooser (self);
}
static GActionEntry win_entries[] = {
{ "open", window_open, NULL, NULL, NULL },
};
static void
node_editor_window_init (NodeEditorWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->renderers = g_list_store_new (GDK_TYPE_PAINTABLE);
gtk_list_box_bind_model (GTK_LIST_BOX (self->renderer_listbox),
G_LIST_MODEL (self->renderers),
node_editor_window_create_renderer_widget,
self,
NULL);
self->errors = g_array_new (FALSE, TRUE, sizeof (TextViewError));
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 *
node_editor_window_new (NodeEditorApplication *application)
{
return g_object_new (NODE_EDITOR_WINDOW_TYPE,
"application", application,
NULL);
}
+42
View File
@@ -0,0 +1,42 @@
/*
* 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 __NODE_EDITOR_WINDOW_H__
#define __NODE_EDITOR_WINDOW_H__
#include <gtk/gtk.h>
#include "node-editor-application.h"
#define NODE_EDITOR_WINDOW_TYPE (node_editor_window_get_type ())
#define NODE_EDITOR_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NODE_EDITOR_WINDOW_TYPE, NodeEditorWindow))
typedef struct _NodeEditorWindow NodeEditorWindow;
typedef struct _NodeEditorWindowClass NodeEditorWindowClass;
GType node_editor_window_get_type (void);
NodeEditorWindow * node_editor_window_new (NodeEditorApplication *application);
gboolean node_editor_window_load (NodeEditorWindow *self,
GFile *file);
#endif /* __NODE_EDITOR_WINDOW_H__ */
+103
View File
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="NodeEditorWindow" parent="GtkApplicationWindow">
<style>
<class name="devel"/>
</style>
<property name="title" translatable="yes">GTK Node Editor</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="title" translatable="yes">GTK Node Editor</property>
<property name="show-title-buttons">1</property>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-open-symbolic</property>
<property name="tooltip-text">Open node file</property>
<signal name="clicked" handler="open_cb"/>
</object>
</child>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-save-symbolic</property>
<property name="tooltip-text">Save to node file</property>
<signal name="clicked" handler="save_cb"/>
</object>
</child>
<child type="start">
<object class="GtkButton">
<property name="icon-name">insert-image-symbolic</property>
<property name="tooltip-text">Export to image</property>
<signal name="clicked" handler="export_image_cb"/>
</object>
</child>
<child type="title">
<object class="GtkLabel">
<property name="label" translatable="yes">GTK Node Editor</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPaned">
<property name="shrink-child2">false</property>
<property name="position">400</property>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="expand">1</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="wrap-mode">word</property>
<property name="monospace">1</property>
<property name="has-focus">1</property>
<property name="top-margin">6</property>
<property name="left-margin">6</property>
<property name="right-margin">6</property>
<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>
</child>
<child>
<object class="GtkBox">
<child>
<object class="GtkScrolledWindow">
<property name="expand">1</property>
<property name="min-content-height">100</property>
<property name="min-content-width">100</property>
<child>
<object class="GtkViewport">
<child>
<object class="GtkPicture" id="picture">
<property name="can-shrink">0</property>
<property name="halign">center</property>
<property name="valign">center</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListBox" id="renderer_listbox">
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gtk/gtk4/node-editor">
<file preprocess="xml-stripblanks">node-editor-window.ui</file>
</gresource>
</gresources>
+6 -1
View File
@@ -1,12 +1,17 @@
<SECTION>
<FILE>GskRenderer</FILE>
gsk_renderer_new_for_surface
gsk_renderer_get_surface
gsk_renderer_realize
gsk_renderer_unrealize
gsk_renderer_is_realized
gsk_renderer_render
gsk_renderer_render_texture
<SUBSECTION>
gsk_renderer_new_for_surface
gsk_gl_renderer_new
gsk_cairo_renderer_new
gsk_vulkan_renderer_new
gsk_broadway_renderer_new
<SUBSECTION Standard>
GSK_IS_RENDERER
GSK_RENDERER
+26
View File
@@ -574,6 +574,32 @@ nevertheless.
</refsect2>
<refsect2 id="profiling">
<title>Profiling</title>
<para>
GTK supports profiling with sysprof. It exports timing information
about frameclock phases and various characteristics of GskRenders
in a format that can be displayed by sysprof or GNOME Builder.
</para>
<para>
A simple way to capture data is to set the <envar>GTK_TRACE</envar>
environment variable. When it is set, GTK will write profiling
data to a file called
<filename>gtk.<replaceable>PID</replaceable>.syscap</filename>.
</para>
<para>
When launching the application from sysprof, it will set the
<envar>SYSPROF_TRACE_FD</envar> environment variable to point
GTK at a file descriptor to write profiling data to.
</para>
<para>
When GtkApplication registers with D-Bus, it exports the
<literal>org.gnome.Sysprof2.Profiler</literal> interface
that lets sysprof request profiling data at runtime.
</para>
</refsect2>
</refsect1>
</refentry>
+1 -3
View File
@@ -24,9 +24,7 @@ gdk_broadway_public_headers = [
'gdkbroadwaymonitor.h',
]
# Broadway backend headers aren't installed it seems
#install_headers(gdk_broadway_public_headers, subdir: 'gtk-4.0/gdk/broadway/')
#install_headers('gdkbroadway.h', subdir: 'gtk-4.0/gdk/')
install_headers(gdk_broadway_public_headers, 'gdkbroadway.h', subdir: 'gtk-4.0/gdk/broadway/')
gdk_broadway_deps = [shmlib]
+224
View File
@@ -0,0 +1,224 @@
/* sp-capture-types.h
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_CAPTURE_FORMAT_H
#define SP_CAPTURE_FORMAT_H
#include <glib.h>
#ifndef SP_DISABLE_GOBJECT
# include <glib-object.h>
#endif
#include "sp-clock.h"
G_BEGIN_DECLS
#define SP_CAPTURE_MAGIC (GUINT32_TO_LE(0xFDCA975E))
#define SP_CAPTURE_ALIGN (sizeof(SpCaptureAddress))
#if __WORDSIZE == 64
# define SP_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE000000000000000)
# define SP_CAPTURE_ADDRESS_FORMAT "0x%016lx"
#else
# define SP_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE0000000)
# define SP_CAPTURE_ADDRESS_FORMAT "0x%016llx"
#endif
#define SP_CAPTURE_CURRENT_TIME (sp_clock_get_current_time())
#define SP_CAPTURE_COUNTER_INT64 0
#define SP_CAPTURE_COUNTER_DOUBLE 1
typedef struct _SpCaptureReader SpCaptureReader;
typedef struct _SpCaptureWriter SpCaptureWriter;
typedef struct _SpCaptureCursor SpCaptureCursor;
typedef struct _SpCaptureCondition SpCaptureCondition;
typedef guint64 SpCaptureAddress;
typedef union
{
gint64 v64;
gdouble vdbl;
} SpCaptureCounterValue;
typedef enum
{
SP_CAPTURE_FRAME_TIMESTAMP = 1,
SP_CAPTURE_FRAME_SAMPLE = 2,
SP_CAPTURE_FRAME_MAP = 3,
SP_CAPTURE_FRAME_PROCESS = 4,
SP_CAPTURE_FRAME_FORK = 5,
SP_CAPTURE_FRAME_EXIT = 6,
SP_CAPTURE_FRAME_JITMAP = 7,
SP_CAPTURE_FRAME_CTRDEF = 8,
SP_CAPTURE_FRAME_CTRSET = 9,
SP_CAPTURE_FRAME_MARK = 10,
} SpCaptureFrameType;
#pragma pack(push, 1)
typedef struct
{
guint32 magic;
guint8 version;
guint32 little_endian : 1;
guint32 padding : 23;
gchar capture_time[64];
gint64 time;
gint64 end_time;
gchar suffix[168];
} SpCaptureFileHeader;
typedef struct
{
guint16 len;
gint16 cpu;
gint32 pid;
gint64 time;
guint8 type;
guint64 padding : 56;
guint8 data[0];
} SpCaptureFrame;
typedef struct
{
SpCaptureFrame frame;
guint64 start;
guint64 end;
guint64 offset;
guint64 inode;
gchar filename[0];
} SpCaptureMap;
typedef struct
{
SpCaptureFrame frame;
guint32 n_jitmaps;
guint8 data[0];
} SpCaptureJitmap;
typedef struct
{
SpCaptureFrame frame;
gchar cmdline[0];
} SpCaptureProcess;
typedef struct
{
SpCaptureFrame frame;
guint16 n_addrs;
guint64 padding : 48;
SpCaptureAddress addrs[0];
} SpCaptureSample;
typedef struct
{
SpCaptureFrame frame;
GPid child_pid;
} SpCaptureFork;
typedef struct
{
SpCaptureFrame frame;
} SpCaptureExit;
typedef struct
{
SpCaptureFrame frame;
} SpCaptureTimestamp;
typedef struct
{
gchar category[32];
gchar name[32];
gchar description[52];
guint32 id : 24;
guint8 type;
SpCaptureCounterValue value;
} SpCaptureCounter;
typedef struct
{
SpCaptureFrame frame;
guint16 n_counters;
guint64 padding : 48;
SpCaptureCounter counters[0];
} SpCaptureFrameCounterDefine;
typedef struct
{
/*
* 96 bytes might seem a bit odd, but the counter frame header is 32
* bytes. So this makes a nice 2-cacheline aligned size which is
* useful when the number of counters is rather small.
*/
guint32 ids[8];
SpCaptureCounterValue values[8];
} SpCaptureCounterValues;
typedef struct
{
SpCaptureFrame frame;
guint16 n_values;
guint64 padding : 48;
SpCaptureCounterValues values[0];
} SpCaptureFrameCounterSet;
typedef struct
{
SpCaptureFrame frame;
gint64 duration;
gchar group[24];
gchar name[40];
gchar message[0];
} SpCaptureMark;
#pragma pack(pop)
G_STATIC_ASSERT (sizeof (SpCaptureFileHeader) == 256);
G_STATIC_ASSERT (sizeof (SpCaptureFrame) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureMap) == 56);
G_STATIC_ASSERT (sizeof (SpCaptureJitmap) == 28);
G_STATIC_ASSERT (sizeof (SpCaptureProcess) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureSample) == 32);
G_STATIC_ASSERT (sizeof (SpCaptureFork) == 28);
G_STATIC_ASSERT (sizeof (SpCaptureExit) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureTimestamp) == 24);
G_STATIC_ASSERT (sizeof (SpCaptureCounter) == 128);
G_STATIC_ASSERT (sizeof (SpCaptureCounterValues) == 96);
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterDefine) == 32);
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterSet) == 32);
G_STATIC_ASSERT (sizeof (SpCaptureMark) == 96);
static inline gint
sp_capture_address_compare (SpCaptureAddress a,
SpCaptureAddress b)
{
if (a < b)
return -1;
if (a > b)
return 1;
else
return 0;
}
G_END_DECLS
#endif /* SP_CAPTURE_FORMAT_H */
File diff suppressed because it is too large Load Diff
+132
View File
@@ -0,0 +1,132 @@
/* sp-capture-writer.h
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_CAPTURE_WRITER_H
#define SP_CAPTURE_WRITER_H
#include "capture/sp-capture-types.h"
G_BEGIN_DECLS
typedef struct _SpCaptureWriter SpCaptureWriter;
typedef struct
{
/*
* The number of frames indexed by SpCaptureFrameType
*/
gsize frame_count[16];
/*
* Padding for future expansion.
*/
gsize padding[48];
} SpCaptureStat;
SpCaptureWriter *sp_capture_writer_new (const gchar *filename,
gsize buffer_size);
SpCaptureWriter *sp_capture_writer_new_from_fd (int fd,
gsize buffer_size);
SpCaptureWriter *sp_capture_writer_ref (SpCaptureWriter *self);
void sp_capture_writer_unref (SpCaptureWriter *self);
void sp_capture_writer_stat (SpCaptureWriter *self,
SpCaptureStat *stat);
gboolean sp_capture_writer_add_map (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
guint64 start,
guint64 end,
guint64 offset,
guint64 inode,
const gchar *filename);
gboolean sp_capture_writer_add_mark (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
guint64 duration,
const gchar *group,
const gchar *name,
const gchar *message);
guint64 sp_capture_writer_add_jitmap (SpCaptureWriter *self,
const gchar *name);
gboolean sp_capture_writer_add_process (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const gchar *cmdline);
gboolean sp_capture_writer_add_sample (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const SpCaptureAddress *addrs,
guint n_addrs);
gboolean sp_capture_writer_add_fork (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
GPid child_pid);
gboolean sp_capture_writer_add_exit (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid);
gboolean sp_capture_writer_add_timestamp (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid);
gboolean sp_capture_writer_define_counters (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const SpCaptureCounter *counters,
guint n_counters);
gboolean sp_capture_writer_set_counters (SpCaptureWriter *self,
gint64 time,
gint cpu,
GPid pid,
const guint *counters_ids,
const SpCaptureCounterValue *values,
guint n_counters);
gboolean sp_capture_writer_flush (SpCaptureWriter *self);
gboolean sp_capture_writer_save_as (SpCaptureWriter *self,
const gchar *filename,
GError **error);
gint sp_capture_writer_request_counter (SpCaptureWriter *self,
guint n_counters);
SpCaptureReader *sp_capture_writer_create_reader (SpCaptureWriter *self,
GError **error);
gboolean sp_capture_writer_splice (SpCaptureWriter *self,
SpCaptureWriter *dest,
GError **error);
gboolean _sp_capture_writer_splice_from_fd (SpCaptureWriter *self,
int fd,
GError **error) G_GNUC_INTERNAL;
#ifndef SP_DISABLE_GOBJECT
# define SP_TYPE_CAPTURE_WRITER (sp_capture_writer_get_type())
GType sp_capture_writer_get_type (void);
#endif
#if GLIB_CHECK_VERSION(2, 44, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpCaptureWriter, sp_capture_writer_unref)
#endif
G_END_DECLS
#endif /* SP_CAPTURE_WRITER_H */
+52
View File
@@ -0,0 +1,52 @@
/* sp-clock.c
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sp-clock.h"
gint sp_clock = -1;
void
sp_clock_init (void)
{
static const gint clock_ids[] = {
CLOCK_MONOTONIC_RAW,
CLOCK_MONOTONIC_COARSE,
CLOCK_MONOTONIC,
CLOCK_REALTIME_COARSE,
CLOCK_REALTIME,
};
guint i;
if (sp_clock != -1)
return;
for (i = 0; i < G_N_ELEMENTS (clock_ids); i++)
{
struct timespec ts;
int clock_id = clock_ids [i];
if (0 == clock_gettime (clock_id, &ts))
{
sp_clock = clock_id;
return;
}
}
g_assert_not_reached ();
}
+55
View File
@@ -0,0 +1,55 @@
/* sp-clock.h
*
* Copyright © 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_CLOCK_H
#define SP_CLOCK_H
#include <glib.h>
#include <time.h>
G_BEGIN_DECLS
typedef gint SpClock;
typedef gint64 SpTimeStamp;
typedef gint32 SpTimeSpan;
extern SpClock sp_clock;
static inline SpTimeStamp
sp_clock_get_current_time (void)
{
struct timespec ts;
clock_gettime (sp_clock, &ts);
return (ts.tv_sec * G_GINT64_CONSTANT (1000000000)) + ts.tv_nsec;
}
static inline SpTimeSpan
sp_clock_get_relative_time (SpTimeStamp epoch)
{
return sp_clock_get_current_time () - epoch;
}
void sp_clock_init (void);
G_END_DECLS
#endif /* SP_CLOCK_H */
+6
View File
@@ -26,6 +26,7 @@
#include "gdkversionmacros.h"
#include "gdkprofilerprivate.h"
#include "gdkinternals.h"
#include "gdkintl.h"
@@ -211,6 +212,11 @@ gdk_pre_parse (void)
_gdk_debug_flags = g_parse_debug_string (debug_string,
(GDebugKey *) gdk_debug_keys,
G_N_ELEMENTS (gdk_debug_keys));
if (g_getenv ("SYSPROF_TRACE_FD"))
gdk_profiler_start (atoi (g_getenv ("SYSPROF_TRACE_FD")));
else if (g_getenv ("GTK_TRACE"))
gdk_profiler_start (-1);
}
#endif /* G_ENABLE_DEBUG */
+105 -3
View File
@@ -29,6 +29,7 @@
#include "gdkinternals.h"
#include "gdkframeclockprivate.h"
#include "gdk.h"
#include "gdkprofilerprivate.h"
#ifdef G_OS_WIN32
#include <windows.h>
@@ -113,6 +114,96 @@ get_sleep_serial (void)
return sleep_serial;
}
static guint fps_counter = 0;
static void
add_timings_to_profiler (GdkFrameTimings *timings)
{
gdk_profiler_add_mark (timings->frame_time * 1000,
(timings->frame_end_time - timings->frame_time) * 1000,
"frame", "");
if (timings->layout_start_time != 0)
gdk_profiler_add_mark (timings->layout_start_time * 1000,
(timings->paint_start_time - timings->layout_start_time) * 1000,
"layout", "");
if (timings->paint_start_time != 0)
gdk_profiler_add_mark (timings->paint_start_time * 1000,
(timings->frame_end_time - timings->paint_start_time) * 1000,
"paint", "");
}
static gint64
guess_refresh_interval (GdkFrameClock *frame_clock)
{
gint64 interval;
gint64 i;
interval = G_MAXINT64;
for (i = gdk_frame_clock_get_history_start (frame_clock);
i < gdk_frame_clock_get_frame_counter (frame_clock);
i++)
{
GdkFrameTimings *t, *before;
gint64 ts, before_ts;
t = gdk_frame_clock_get_timings (frame_clock, i);
before = gdk_frame_clock_get_timings (frame_clock, i - 1);
if (t == NULL || before == NULL)
continue;
ts = gdk_frame_timings_get_frame_time (t);
before_ts = gdk_frame_timings_get_frame_time (before);
if (ts == 0 || before_ts == 0)
continue;
interval = MIN (interval, ts - before_ts);
}
if (interval == G_MAXINT64)
return 0;
return interval;
}
static double
frame_clock_get_fps (GdkFrameClock *frame_clock)
{
GdkFrameTimings *start, *end;
gint64 start_counter, end_counter;
gint64 start_timestamp, end_timestamp;
gint64 interval;
start_counter = gdk_frame_clock_get_history_start (frame_clock);
end_counter = gdk_frame_clock_get_frame_counter (frame_clock);
start = gdk_frame_clock_get_timings (frame_clock, start_counter);
for (end = gdk_frame_clock_get_timings (frame_clock, end_counter);
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
end = gdk_frame_clock_get_timings (frame_clock, end_counter))
end_counter--;
if (end_counter - start_counter < 4)
return 0.0;
start_timestamp = gdk_frame_timings_get_presentation_time (start);
end_timestamp = gdk_frame_timings_get_presentation_time (end);
if (start_timestamp == 0 || end_timestamp == 0)
{
start_timestamp = gdk_frame_timings_get_frame_time (start);
end_timestamp = gdk_frame_timings_get_frame_time (end);
}
interval = gdk_frame_timings_get_refresh_interval (end);
if (interval == 0)
{
interval = guess_refresh_interval (frame_clock);
if (interval == 0)
return 0.0;
}
return ((double) end_counter - start_counter) * G_USEC_PER_SEC / (end_timestamp - start_timestamp);
}
static void
gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
{
@@ -123,6 +214,11 @@ gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
priv->frame_time = g_get_monotonic_time (); /* more sane than zero */
priv->freeze_count = 0;
#ifdef G_ENABLE_DEBUG
if (fps_counter == 0)
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
#endif
}
static void
@@ -405,7 +501,7 @@ gdk_frame_clock_paint_idle (void *data)
{
int iter;
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES))
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
{
if (priv->phase != GDK_FRAME_CLOCK_PHASE_LAYOUT &&
(priv->requested & GDK_FRAME_CLOCK_PHASE_LAYOUT))
@@ -435,7 +531,7 @@ gdk_frame_clock_paint_idle (void *data)
if (priv->freeze_count == 0)
{
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES))
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
{
if (priv->phase != GDK_FRAME_CLOCK_PHASE_PAINT &&
(priv->requested & GDK_FRAME_CLOCK_PHASE_PAINT))
@@ -462,7 +558,7 @@ gdk_frame_clock_paint_idle (void *data)
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES))
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
timings->frame_end_time = g_get_monotonic_time ();
#endif /* G_ENABLE_DEBUG */
}
@@ -475,6 +571,12 @@ gdk_frame_clock_paint_idle (void *data)
}
#ifdef G_ENABLE_DEBUG
if (gdk_profiler_is_running ())
{
add_timings_to_profiler (timings);
gdk_profiler_set_counter (fps_counter, timings->frame_end_time * 1000, frame_clock_get_fps (clock));
}
if (GDK_DEBUG_CHECK (FRAMES))
{
if (timings && timings->complete)
+230
View File
@@ -0,0 +1,230 @@
/* GDK - The GIMP Drawing Kit
*
* gdkprofiler.c: A simple profiler
*
* Copyright © 2018 Matthias Clasen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "gdkversionmacros.h"
#include "gdkprofilerprivate.h"
#include "gdkframeclockprivate.h"
#ifndef G_OS_WIN32
#include "capture/sp-capture-writer.h"
static SpCaptureWriter *writer = NULL;
static gboolean running = FALSE;
static void
profiler_stop (void)
{
if (writer)
sp_capture_writer_unref (writer);
}
void
gdk_profiler_start (int fd)
{
if (writer)
return;
sp_clock_init ();
if (fd == -1)
{
gchar *filename;
filename = g_strdup_printf ("gtk.%d.syscap", getpid ());
g_print ("Writing profiling data to %s\n", filename);
writer = sp_capture_writer_new (filename, 16*1024);
g_free (filename);
}
else if (fd > 2)
writer = sp_capture_writer_new_from_fd (fd, 16*1024);
if (writer)
running = TRUE;
atexit (profiler_stop);
}
void
gdk_profiler_stop (void)
{
running = FALSE;
}
gboolean
gdk_profiler_is_running (void)
{
return running;
}
void
gdk_profiler_add_mark (gint64 start,
guint64 duration,
const char *name,
const char *message)
{
if (!running)
return;
sp_capture_writer_add_mark (writer,
start,
-1, getpid (),
duration,
"gtk", name, message);
}
static guint
define_counter (const char *name,
const char *description,
int type)
{
SpCaptureCounter counter;
if (!writer)
return 0;
counter.id = (guint) sp_capture_writer_request_counter (writer, 1);
counter.type = type;
counter.value.vdbl = 0;
g_strlcpy (counter.category, "gtk", sizeof counter.category);
g_strlcpy (counter.name, name, sizeof counter.name);
g_strlcpy (counter.description, description, sizeof counter.name);
sp_capture_writer_define_counters (writer,
SP_CAPTURE_CURRENT_TIME,
-1,
getpid (),
&counter,
1);
return counter.id;
}
guint
gdk_profiler_define_counter (const char *name,
const char *description)
{
return define_counter (name, description, SP_CAPTURE_COUNTER_DOUBLE);
}
guint
gdk_profiler_define_int_counter (const char *name,
const char *description)
{
return define_counter (name, description, SP_CAPTURE_COUNTER_INT64);
}
void
gdk_profiler_set_counter (guint id,
gint64 time,
double val)
{
SpCaptureCounterValue value;
if (!running)
return;
value.vdbl = val;
sp_capture_writer_set_counters (writer,
time,
-1, getpid (),
&id, &value, 1);
}
void
gdk_profiler_set_int_counter (guint id,
gint64 time,
gint64 val)
{
SpCaptureCounterValue value;
if (!running)
return;
value.v64 = val;
sp_capture_writer_set_counters (writer,
time,
-1, getpid (),
&id, &value, 1);
}
#else
void
gdk_profiler_start (int fd)
{
}
void
gdk_profiler_stop (void)
{
}
gboolean
gdk_profiler_is_running (void)
{
return FALSE;
}
void
gdk_profiler_add_mark (gint64 start,
guint64 duration,
const char *name,
const char *message)
{
}
guint
gdk_profiler_define_counter (const char *name,
const char *description)
{
return 0;
}
void
gdk_profiler_set_counter (guint id,
gint64 time,
double value)
{
}
guint
gdk_profiler_define_int_counter (const char *name,
const char *description)
{
return 0;
}
void
gdk_profiler_set_int_counter (guint id,
gint64 time,
gint64 value)
{
}
#endif /* G_OS_WIN32 */
+46
View File
@@ -0,0 +1,46 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2018 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_PROFILER_PRIVATE_H__
#define __GDK_PROFILER_PRIVATE_H__
#include "gdk/gdkframeclock.h"
#include "gdk/gdkdisplay.h"
G_BEGIN_DECLS
void gdk_profiler_start (int fd);
void gdk_profiler_stop (void);
gboolean gdk_profiler_is_running (void);
void gdk_profiler_add_mark (gint64 start,
guint64 duration,
const char *name,
const char *message);
guint gdk_profiler_define_counter (const char *name,
const char *description);
void gdk_profiler_set_counter (guint id,
gint64 time,
double value);
guint gdk_profiler_define_int_counter (const char *name,
const char *description);
void gdk_profiler_set_int_counter (guint id,
gint64 time,
gint64 value);
G_END_DECLS
#endif /* __GDK_PROFILER_PRIVATE_H__ */
+4 -1
View File
@@ -4202,7 +4202,10 @@ void
gdk_surface_set_startup_id (GdkSurface *surface,
const gchar *startup_id)
{
GDK_SURFACE_IMPL_GET_CLASS (surface->impl)->set_startup_id (surface, startup_id);
GdkSurfaceImplClass *klass = GDK_SURFACE_IMPL_GET_CLASS (surface->impl);
if (klass->set_startup_id)
klass->set_startup_id (surface, startup_id);
}
/**
+8
View File
@@ -45,8 +45,16 @@ gdk_public_sources = files([
'gdkvulkancontext.c',
'gdksurface.c',
'gdksurfaceimpl.c',
'gdkprofiler.c'
])
if not win32_enabled
gdk_public_sources += files([
'capture/sp-capture-writer.c',
'capture/sp-clock.c'
])
endif
gdk_public_headers = files([
'gdk-autocleanup.h',
'gdk.h',
+1 -2
View File
@@ -33,8 +33,7 @@ gdk_quartz_public_headers = files([
'gdkquartzsurface.h',
])
install_headers(gdk_quartz_public_headers, subdir: 'gtk-4.0/gdk/quartz/')
install_headers('gdkquartz.h', subdir: 'gtk-4.0/gdk/')
install_headers(gdk_quartz_public_headers, 'gdkquartz.h', subdir: 'gtk-4.0/gdk/quartz/')
gdk_quartz_deps = [ # FIXME
]
+1 -2
View File
@@ -26,8 +26,7 @@ gdk_wayland_public_headers = files([
'gdkwaylandsurface.h'
])
install_headers(gdk_wayland_public_headers, subdir: 'gtk-4.0/gdk/wayland/')
install_headers('gdkwayland.h', subdir: 'gtk-4.0/gdk/')
install_headers(gdk_wayland_public_headers, 'gdkwayland.h', subdir: 'gtk-4.0/gdk/wayland/')
gdk_wayland_deps = [
shmlib,
+1 -2
View File
@@ -42,8 +42,7 @@ gdk_win32_public_headers = files([
'gdkwin32surface.h',
])
install_headers(gdk_win32_public_headers, subdir: 'gtk-4.0/gdk/win32/')
install_headers('gdkwin32.h', subdir: 'gtk-4.0/gdk/')
install_headers(gdk_win32_public_headers, 'gdkwin32.h', subdir: 'gtk-4.0/gdk/win32/')
gdk_win32_deps = [ # FIXME
pangowin32_dep
+1 -2
View File
@@ -54,8 +54,7 @@ gdk_x11_public_headers = files([
'gdkx11surface.h',
])
install_headers(gdk_x11_public_headers, subdir: 'gtk-4.0/gdk/x11/')
install_headers('gdkx.h', subdir: 'gtk-4.0/gdk/')
install_headers(gdk_x11_public_headers, 'gdkx.h', subdir: 'gtk-4.0/gdk/x11/')
gdk_x11_deps = [
xrender_dep,
+22 -1
View File
@@ -1,6 +1,7 @@
#include "config.h"
#include "gskbroadwayrendererprivate.h"
#include "gskbroadwayrenderer.h"
#include "broadway/gdkprivate-broadway.h"
#include "gskdebugprivate.h"
@@ -827,3 +828,23 @@ static void
gsk_broadway_renderer_init (GskBroadwayRenderer *self)
{
}
/**
* gsk_broadway_renderer_new:
*
* Creates a new Broadway renderer.
*
* The Broadway renderer is the default renderer for the broadway backend.
* It will only work with broadway surfaces, otherwise it will fail the
* call to gdk_renderer_realize().
*
* This function is only available when GTK was compiled with Broadway
* support.
*
* Returns: a new Broadway renderer.
**/
GskRenderer *
gsk_broadway_renderer_new (void)
{
return g_object_new (GSK_TYPE_BROADWAY_RENDERER, NULL);
}
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright © 2019 Alexander Larsson
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_BROADWAY_RENDERER_H__
#define __GSK_BROADWAY_RENDERER_H__
#include <gdk/gdk.h>
#include <gsk/gskrenderer.h>
#ifdef GDK_WINDOWING_BROADWAY
#include <gdk/broadway/gdkbroadway.h>
G_BEGIN_DECLS
#define GSK_TYPE_BROADWAY_RENDERER (gsk_broadway_renderer_get_type ())
#define GSK_BROADWAY_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_BROADWAY_RENDERER, GskBroadwayRenderer))
#define GSK_IS_BROADWAY_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_BROADWAY_RENDERER))
#define GSK_BROADWAY_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_BROADWAY_RENDERER, GskBroadwayRendererClass))
#define GSK_IS_BROADWAY_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_BROADWAY_RENDERER))
#define GSK_BROADWAY_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_BROADWAY_RENDERER, GskBroadwayRendererClass))
typedef struct _GskBroadwayRenderer GskBroadwayRenderer;
typedef struct _GskBroadwayRendererClass GskBroadwayRendererClass;
GDK_AVAILABLE_IN_ALL
GType gsk_broadway_renderer_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderer * gsk_broadway_renderer_new (void);
G_END_DECLS
#endif /* GDK_WINDOWING_BROADWAY */
#endif /* __GSK_BROADWAY_RENDERER_H__ */
-24
View File
@@ -1,24 +0,0 @@
#ifndef __GSK_BROADWAY_RENDERER_PRIVATE_H__
#define __GSK_BROADWAY_RENDERER_PRIVATE_H__
#include "broadway/gdkbroadway.h"
#include <gsk/gskrenderer.h>
G_BEGIN_DECLS
#define GSK_TYPE_BROADWAY_RENDERER (gsk_broadway_renderer_get_type ())
#define GSK_BROADWAY_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_BROADWAY_RENDERER, GskBroadwayRenderer))
#define GSK_IS_BROADWAY_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_BROADWAY_RENDERER))
#define GSK_BROADWAY_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_BROADWAY_RENDERER, GskBroadwayRendererClass))
#define GSK_IS_BROADWAY_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_BROADWAY_RENDERER))
#define GSK_BROADWAY_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_BROADWAY_RENDERER, GskBroadwayRendererClass))
typedef struct _GskBroadwayRenderer GskBroadwayRenderer;
typedef struct _GskBroadwayRendererClass GskBroadwayRendererClass;
GType gsk_broadway_renderer_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GSK_BROADWAY_RENDERER_PRIVATE_H__ */
+31 -4
View File
@@ -1,6 +1,6 @@
#include "config.h"
#include "gskglrendererprivate.h"
#include "gskglrenderer.h"
#include "gskdebugprivate.h"
#include "gskenums.h"
@@ -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
@@ -1883,13 +1891,13 @@ render_cross_fade_node (GskGLRenderer *self,
&node->bounds,
start_node,
&start_texture_id, &is_offscreen1,
FORCE_OFFSCREEN | RESET_CLIP);
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY);
add_offscreen_ops (self, builder,
&node->bounds,
end_node,
&end_texture_id, &is_offscreen2,
FORCE_OFFSCREEN | RESET_CLIP);
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY);
ops_set_program (builder, &self->cross_fade_program);
op.op = OP_CHANGE_CROSS_FADE;
@@ -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
}
@@ -3281,3 +3294,17 @@ gsk_gl_renderer_init (GskGLRenderer *self)
}
#endif
}
/**
* gsk_gl_renderer_new:
*
* Creates a new #GskRenderer using OpenGL. This is the default renderer
* used by GTK.
*
* Returns: a new GL renderer
**/
GskRenderer *
gsk_gl_renderer_new (void)
{
return g_object_new (GSK_TYPE_GL_RENDERER, NULL);
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright © 2016 Endless
* 2018 Timm Bäder <mail@baedert.org>
*
* 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: Timm Bäder <mail@baedert.org>
*/
#ifndef __GSK_GL_RENDERER_H__
#define __GSK_GL_RENDERER_H__
#include <gsk/gskrenderer.h>
G_BEGIN_DECLS
#define GSK_TYPE_GL_RENDERER (gsk_gl_renderer_get_type ())
#define GSK_GL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_GL_RENDERER, GskGLRenderer))
#define GSK_IS_GL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_GL_RENDERER))
#define GSK_GL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_GL_RENDERER, GskGLRendererClass))
#define GSK_IS_GL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_GL_RENDERER))
#define GSK_GL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_GL_RENDERER, GskGLRendererClass))
typedef struct _GskGLRenderer GskGLRenderer;
typedef struct _GskGLRendererClass GskGLRendererClass;
GDK_AVAILABLE_IN_ALL
GType gsk_gl_renderer_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderer * gsk_gl_renderer_new (void);
G_END_DECLS
#endif /* __GSK_GL_RENDERER_H__ */
-23
View File
@@ -1,23 +0,0 @@
#ifndef __GSK_GL_RENDERER_PRIVATE_H__
#define __GSK_GL_RENDERER_PRIVATE_H__
#include <gsk/gskrenderer.h>
G_BEGIN_DECLS
#define GSK_TYPE_GL_RENDERER (gsk_gl_renderer_get_type ())
#define GSK_GL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_GL_RENDERER, GskGLRenderer))
#define GSK_IS_GL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_GL_RENDERER))
#define GSK_GL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_GL_RENDERER, GskGLRendererClass))
#define GSK_IS_GL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_GL_RENDERER))
#define GSK_GL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_GL_RENDERER, GskGLRendererClass))
typedef struct _GskGLRenderer GskGLRenderer;
typedef struct _GskGLRendererClass GskGLRendererClass;
GType gsk_gl_renderer_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GSK_GL_RENDERER_PRIVATE_H__ */
+1 -1
View File
@@ -7,7 +7,7 @@
#include "gskgldriverprivate.h"
#include "gskroundedrectprivate.h"
#include "gskglrendererprivate.h"
#include "gskglrenderer.h"
#include "gskrendernodeprivate.h"
#define GL_N_VERTICES 6
+5
View File
@@ -26,6 +26,11 @@
#include <gsk/gskroundedrect.h>
#include <gsk/gsktransform.h>
#include <gsk/gskcairorenderer.h>
#include <gsk/gl/gskglrenderer.h>
#include <gsk/broadway/gskbroadwayrenderer.h>
#include <gsk/vulkan/gskvulkanrenderer.h>
#include <gsk/gsktypes.h>
#include <gsk/gskenumtypes.h>
+41 -1
View File
@@ -1,6 +1,26 @@
/*
* Copyright © 2016 Endless
* 2018 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 "config.h"
#include "gskcairorendererprivate.h"
#include "gskcairorenderer.h"
#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
@@ -159,3 +179,23 @@ gsk_cairo_renderer_init (GskCairoRenderer *self)
self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE);
#endif
}
/**
* gsk_cairo_renderer_new:
*
* Creates a new Cairo renderer.
*
* The Cairo renderer is the fallback renderer drawing in ways similar
* to how GTK 3 drew its content. Its primary use is as comparison tool.
*
* The Cairo renderer is incomplete. It cannot render 3D transformed
* content and will instead render an error marker. Its usage should be
* avoided.
*
* Returns: a new Cairo renderer.
**/
GskRenderer *
gsk_cairo_renderer_new (void)
{
return g_object_new (GSK_TYPE_CAIRO_RENDERER, NULL);
}
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright © 2016 Endless
* 2018 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 __GSK_CAIRO_RENDERER_H__
#define __GSK_CAIRO_RENDERER_H__
#include <cairo.h>
#include <gsk/gskrenderer.h>
G_BEGIN_DECLS
#define GSK_TYPE_CAIRO_RENDERER (gsk_cairo_renderer_get_type ())
#define GSK_CAIRO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_CAIRO_RENDERER, GskCairoRenderer))
#define GSK_IS_CAIRO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_CAIRO_RENDERER))
#define GSK_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_CAIRO_RENDERER, GskCairoRendererClass))
#define GSK_IS_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_CAIRO_RENDERER))
#define GSK_CAIRO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_CAIRO_RENDERER, GskCairoRendererClass))
typedef struct _GskCairoRenderer GskCairoRenderer;
typedef struct _GskCairoRendererClass GskCairoRendererClass;
GDK_AVAILABLE_IN_ALL
GType gsk_cairo_renderer_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderer * gsk_cairo_renderer_new (void);
G_END_DECLS
#endif /* __GSK_CAIRO_RENDERER_H__ */
-24
View File
@@ -1,24 +0,0 @@
#ifndef __GSK_CAIRO_RENDERER_PRIVATE_H__
#define __GSK_CAIRO_RENDERER_PRIVATE_H__
#include <cairo.h>
#include <gsk/gskrenderer.h>
G_BEGIN_DECLS
#define GSK_TYPE_CAIRO_RENDERER (gsk_cairo_renderer_get_type ())
#define GSK_CAIRO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_CAIRO_RENDERER, GskCairoRenderer))
#define GSK_IS_CAIRO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_CAIRO_RENDERER))
#define GSK_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_CAIRO_RENDERER, GskCairoRendererClass))
#define GSK_IS_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_CAIRO_RENDERER))
#define GSK_CAIRO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_CAIRO_RENDERER, GskCairoRendererClass))
typedef struct _GskCairoRenderer GskCairoRenderer;
typedef struct _GskCairoRendererClass GskCairoRendererClass;
GType gsk_cairo_renderer_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GSK_CAIRO_RENDERER_PRIVATE_H__ */
+13
View File
@@ -365,6 +365,19 @@ gsk_profiler_timer_get (GskProfiler *profiler,
return timer->value;
}
gint64
gsk_profiler_timer_get_start (GskProfiler *profiler,
GQuark timer_id)
{
NamedTimer *timer;
timer = gsk_profiler_get_timer (profiler, timer_id);
if (timer == NULL)
return 0;
return timer->start_time;
}
void
gsk_profiler_reset (GskProfiler *profiler)
{
+2
View File
@@ -40,6 +40,8 @@ gint64 gsk_profiler_counter_get (GskProfiler *profiler,
GQuark counter_id);
gint64 gsk_profiler_timer_get (GskProfiler *profiler,
GQuark timer_id);
gint64 gsk_profiler_timer_get_start (GskProfiler *profiler,
GQuark timer_id);
void gsk_profiler_reset (GskProfiler *profiler);
+4 -4
View File
@@ -36,9 +36,9 @@
#include "gskrendererprivate.h"
#include "gskcairorendererprivate.h"
#include "gskcairorenderer.h"
#include "gskdebugprivate.h"
#include "gl/gskglrendererprivate.h"
#include "gl/gskglrenderer.h"
#include "gskprofilerprivate.h"
#include "gskrendernodeprivate.h"
@@ -55,10 +55,10 @@
#include <gdk/wayland/gdkwayland.h>
#endif
#ifdef GDK_WINDOWING_BROADWAY
#include "broadway/gskbroadwayrendererprivate.h"
#include "broadway/gskbroadwayrenderer.h"
#endif
#ifdef GDK_RENDERING_VULKAN
#include "vulkan/gskvulkanrendererprivate.h"
#include "vulkan/gskvulkanrenderer.h"
#endif
typedef struct
+8 -41
View File
@@ -42,6 +42,7 @@
#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeparserprivate.h"
#include <graphene-gobject.h>
@@ -328,19 +329,11 @@ gsk_render_node_diff (GskRenderNode *node1,
GBytes *
gsk_render_node_serialize (GskRenderNode *node)
{
GVariant *node_variant, *variant;
GBytes *result;
char *str;
node_variant = gsk_render_node_serialize_node (node);
variant = g_variant_new ("(suuv)",
GSK_RENDER_NODE_SERIALIZATION_ID,
(guint32) GSK_RENDER_NODE_SERIALIZATION_VERSION,
(guint32) gsk_render_node_get_node_type (node),
node_variant);
result = g_variant_get_data_as_bytes (variant);
g_variant_unref (variant);
str = gsk_render_node_serialize_to_string (node);
result = g_bytes_new_take (str, strlen (str));
return result;
}
@@ -394,39 +387,13 @@ gsk_render_node_write_to_file (GskRenderNode *node,
* error.
**/
GskRenderNode *
gsk_render_node_deserialize (GBytes *bytes,
GError **error)
gsk_render_node_deserialize (GBytes *bytes,
GskParseErrorFunc error_func,
gpointer user_data)
{
char *id_string;
guint32 version, node_type;
GVariant *variant, *node_variant;
GskRenderNode *node = NULL;
variant = g_variant_new_from_bytes (G_VARIANT_TYPE ("(suuv)"), bytes, FALSE);
g_variant_get (variant, "(suuv)", &id_string, &version, &node_type, &node_variant);
if (!g_str_equal (id_string, GSK_RENDER_NODE_SERIALIZATION_ID))
{
g_set_error (error, GSK_SERIALIZATION_ERROR, GSK_SERIALIZATION_UNSUPPORTED_FORMAT,
"Data not in GskRenderNode serialization format.");
goto out;
}
if (version != GSK_RENDER_NODE_SERIALIZATION_VERSION)
{
g_set_error (error, GSK_SERIALIZATION_ERROR, GSK_SERIALIZATION_UNSUPPORTED_VERSION,
"Format version %u not supported.", version);
goto out;
}
node = gsk_render_node_deserialize_node (node_type, node_variant, error);
out:
g_free (id_string);
g_variant_unref (node_variant);
g_variant_unref (variant);
node = gsk_render_node_deserialize_from_bytes (bytes, error_func, user_data);
return node;
}
+8 -2
View File
@@ -25,6 +25,7 @@
#include <gsk/gskroundedrect.h>
#include <gsk/gsktypes.h>
#include <gtk/css/gtkcss.h>
G_BEGIN_DECLS
@@ -52,6 +53,10 @@ struct _GskShadow
float radius;
};
typedef void (* GskParseErrorFunc) (const GtkCssSection *section,
const GError *error,
gpointer user_data);
GDK_AVAILABLE_IN_ALL
GType gsk_render_node_get_type (void) G_GNUC_CONST;
@@ -81,8 +86,9 @@ gboolean gsk_render_node_write_to_file (GskRenderNode *
const char *filename,
GError **error);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_render_node_deserialize (GBytes *bytes,
GError **error);
GskRenderNode * gsk_render_node_deserialize (GBytes *bytes,
GskParseErrorFunc error_func,
gpointer user_data);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_debug_node_new (GskRenderNode *child,
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+12
View File
@@ -0,0 +1,12 @@
#ifndef __GSK_RENDER_NODE_PARSER_PRIVATE_H__
#define __GSK_RENDER_NODE_PARSER_PRIVATE_H__
#include "gskrendernode.h"
GskRenderNode * gsk_render_node_deserialize_from_bytes (GBytes *bytes,
GskParseErrorFunc error_func,
gpointer user_data);
char * gsk_render_node_serialize_to_string (GskRenderNode *root);
#endif
-8
View File
@@ -33,9 +33,6 @@ struct _GskRenderNodeClass
void (* diff) (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
GVariant * (* serialize) (GskRenderNode *node);
GskRenderNode * (* deserialize) (GVariant *variant,
GError **error);
};
GskRenderNode * gsk_render_node_new (const GskRenderNodeClass *node_class,
@@ -50,11 +47,6 @@ void gsk_render_node_diff_impossible (GskRenderNode *nod
GskRenderNode *node2,
cairo_region_t *region);
GVariant * gsk_render_node_serialize_node (GskRenderNode *node);
GskRenderNode * gsk_render_node_deserialize_node (GskRenderNodeType type,
GVariant *variant,
GError **error);
GskRenderNode * gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds,
cairo_surface_t *surface);
+24 -5
View File
@@ -22,22 +22,23 @@ gsk_private_gl_shaders = [
gsk_public_sources = files([
'gskdiff.c',
'gskcairorenderer.c',
'gskrenderer.c',
'gskrendernode.c',
'gskrendernodeimpl.c',
'gskroundedrect.c',
'gsktransform.c',
'gl/gskglrenderer.c',
])
gsk_private_sources = files([
'gskcairoblur.c',
'gskcairorenderer.c',
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
'gskrendernodeparser.c',
'gl/gskshaderbuilder.c',
'gl/gskglprofiler.c',
'gl/gskglrenderer.c',
'gl/gskglglyphcache.c',
'gl/gskglimage.c',
'gl/gskgldriver.c',
@@ -47,17 +48,35 @@ gsk_private_sources = files([
])
gsk_public_headers = files([
'gskcairorenderer.h',
'gskenums.h',
'gskrenderer.h',
'gskrendernode.h',
'gskroundedrect.h',
'gsktransform.h',
'gsktypes.h',
'gsk-autocleanup.h'
'gsk-autocleanup.h',
])
install_headers(gsk_public_headers, 'gsk.h', subdir: 'gtk-4.0/gsk')
gsk_public_gl_headers = files([
'gl/gskglrenderer.h'
])
install_headers(gsk_public_gl_headers, subdir: 'gtk-4.0/gsk/gl')
gsk_public_headers += gsk_public_gl_headers
gsk_public_broadway_headers = files([
'broadway/gskbroadwayrenderer.h'
])
install_headers(gsk_public_broadway_headers, subdir: 'gtk-4.0/gsk/broadway')
gsk_public_headers += gsk_public_broadway_headers
gsk_public_vulkan_headers = files([
'vulkan/gskvulkanrenderer.h'
])
install_headers(gsk_public_vulkan_headers, subdir: 'gtk-4.0/gsk/vulkan')
gsk_public_headers += gsk_public_vulkan_headers
gsk_private_vulkan_shaders = []
# This is an odd split because we use configure_file() below to workaround
# a limitation in meson preventing using custom_target() with gnome.compile_resources()
@@ -97,7 +116,7 @@ if have_vulkan
endif # have_vulkan
if get_variable('broadway_enabled')
gsk_private_sources += files([
gsk_public_sources += files([
'broadway/gskbroadwayrenderer.c',
])
endif
+16 -16
View File
@@ -264,22 +264,22 @@ void main() {
vec4 result;
switch(u_mode) {
case 0: result = normal(bottom_color, top_color); break;
case 1: result = multiply(bottom_color, top_color); break;
case 2: result = screen(bottom_color, top_color); break;
case 3: result = overlay(bottom_color, top_color); break;
case 4: result = darken(bottom_color, top_color); break;
case 5: result = lighten(bottom_color, top_color); break;
case 6: result = color_dodge(bottom_color, top_color); break;
case 7: result = color_burn(bottom_color, top_color); break;
case 8: result = hard_light(bottom_color, top_color); break;
case 9: result = soft_light(bottom_color, top_color); break;
case 10: result = difference(bottom_color, top_color); break;
case 11: result = exclusion(bottom_color, top_color); break;
case 12: result = color(bottom_color, top_color); break;
case 13: result = hue(bottom_color, top_color); break;
case 14: result = saturation(bottom_color, top_color); break;
case 15: result = luminosity(bottom_color, top_color); break;
case 0: result = normal(top_color, bottom_color); break;
case 1: result = multiply(top_color, bottom_color); break;
case 2: result = screen(top_color, bottom_color); break;
case 3: result = overlay(top_color, bottom_color); break;
case 4: result = darken(top_color, bottom_color); break;
case 5: result = lighten(top_color, bottom_color); break;
case 6: result = color_dodge(top_color, bottom_color); break;
case 7: result = color_burn(top_color, bottom_color); break;
case 8: result = hard_light(top_color, bottom_color); break;
case 9: result = soft_light(top_color, bottom_color); break;
case 10: result = difference(top_color, bottom_color); break;
case 11: result = exclusion(top_color, bottom_color); break;
case 12: result = color(top_color, bottom_color); break;
case 13: result = hue(top_color, bottom_color); break;
case 14: result = saturation(top_color, bottom_color); break;
case 15: result = luminosity(top_color, bottom_color); break;
default: discard;
}
+2 -1
View File
@@ -8,7 +8,8 @@ void main() {
color.rgb *= color.a;
// u_source is drawn using cairo, so already pre-multiplied.
color = vec4(u_color.rgb * diffuse.a * u_alpha, diffuse.a * color.a * u_alpha);
color = vec4(color.rgb * diffuse.a * u_alpha,
color.a * diffuse.a * u_alpha);
setOutputColor(color);
}
+43 -1
View File
@@ -13,6 +13,7 @@
#include "gskvulkanglyphcacheprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include <graphene.h>
@@ -38,6 +39,9 @@ typedef struct {
} ProfileTimers;
#endif
static guint texture_pixels_counter;
static guint fallback_pixels_counter;
struct _GskVulkanRenderer
{
GskRenderer parent_instance;
@@ -170,7 +174,7 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
GdkTexture *texture;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 cpu_time;
gint64 cpu_time, start_time;
#endif
#ifdef G_ENABLE_DEBUG
@@ -201,10 +205,22 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
gsk_vulkan_render_free (render);
#ifdef G_ENABLE_DEBUG
start_time = gsk_profiler_timer_get_start (profiler, self->profile_timers.cpu_time);
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
gsk_profiler_push_samples (profiler);
if (gdk_profiler_is_running ())
{
gdk_profiler_add_mark (start_time, cpu_time, "render", "");
gdk_profiler_set_int_counter (texture_pixels_counter,
start_time + cpu_time,
gsk_profiler_counter_get (profiler, self->profile_counters.texture_pixels));
gdk_profiler_set_int_counter (fallback_pixels_counter,
start_time + cpu_time,
gsk_profiler_counter_get (profiler, self->profile_counters.fallback_pixels));
}
#endif
return texture;
@@ -284,6 +300,13 @@ gsk_vulkan_renderer_init (GskVulkanRenderer *self)
self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE);
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), SYNC))
self->profile_timers.gpu_time = gsk_profiler_add_timer (profiler, "gpu-time", "GPU time", FALSE, TRUE);
if (texture_pixels_counter == 0)
{
texture_pixels_counter = gdk_profiler_define_int_counter ("texture-pixels", "Texture Pixels");
fallback_pixels_counter = gdk_profiler_define_int_counter ("fallback-pixels", "Fallback Pixels");
}
#endif
}
@@ -364,3 +387,22 @@ gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
{
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, scale);
}
/**
* gsk_vulkan_renderer_new:
*
* Creates a new Vulkan renderer.
*
* The Vulkan renderer is a renderer that uses the Vulkan library for
* rendering.
*
* This function is only available when GTK was compiled with Vulkan
* support.
*
* Returns: a new Vulkan renderer
**/
GskRenderer *
gsk_vulkan_renderer_new (void)
{
return g_object_new (GSK_TYPE_VULKAN_RENDERER, NULL);
}
+51
View File
@@ -0,0 +1,51 @@
/*
* Copyright © 2016 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/>.
*/
#ifndef __GSK_VULKAN_RENDERER_H__
#define __GSK_VULKAN_RENDERER_H__
#include <gdk/gdk.h>
#include <gsk/gskrenderer.h>
#ifdef GDK_RENDERING_VULKAN
#include <vulkan/vulkan.h>
G_BEGIN_DECLS
#define GSK_TYPE_VULKAN_RENDERER (gsk_vulkan_renderer_get_type ())
#define GSK_VULKAN_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_VULKAN_RENDERER, GskVulkanRenderer))
#define GSK_IS_VULKAN_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_VULKAN_RENDERER))
#define GSK_VULKAN_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_VULKAN_RENDERER, GskVulkanRendererClass))
#define GSK_IS_VULKAN_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_VULKAN_RENDERER))
#define GSK_VULKAN_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_VULKAN_RENDERER, GskVulkanRendererClass))
typedef struct _GskVulkanRenderer GskVulkanRenderer;
typedef struct _GskVulkanRendererClass GskVulkanRendererClass;
GDK_AVAILABLE_IN_ALL
GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderer * gsk_vulkan_renderer_new (void);
G_END_DECLS
#endif /* GDK_WINDOWING_VULKAN */
#endif /* __GSK_VULKAN_RENDERER_H__ */
+1 -16
View File
@@ -1,26 +1,11 @@
#ifndef __GSK_VULKAN_RENDERER_PRIVATE_H__
#define __GSK_VULKAN_RENDERER_PRIVATE_H__
#include <vulkan/vulkan.h>
#include <gsk/gskrenderer.h>
#include "gskvulkanrenderer.h"
#include "gskvulkanimageprivate.h"
G_BEGIN_DECLS
#define GSK_TYPE_VULKAN_RENDERER (gsk_vulkan_renderer_get_type ())
#define GSK_VULKAN_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_VULKAN_RENDERER, GskVulkanRenderer))
#define GSK_IS_VULKAN_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_VULKAN_RENDERER))
#define GSK_VULKAN_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_VULKAN_RENDERER, GskVulkanRendererClass))
#define GSK_IS_VULKAN_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_VULKAN_RENDERER))
#define GSK_VULKAN_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_VULKAN_RENDERER, GskVulkanRendererClass))
typedef struct _GskVulkanRenderer GskVulkanRenderer;
typedef struct _GskVulkanRendererClass GskVulkanRendererClass;
GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST;
GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
GdkTexture *texture,
GskVulkanUploader *uploader);
+4 -2
View File
@@ -243,6 +243,7 @@ gtk_notebook_page_accessible_new (GtkNotebookAccessible *notebook,
GObject *object;
AtkObject *atk_object;
GtkNotebookPageAccessible *page;
GtkNotebook *nb;
g_return_val_if_fail (GTK_IS_NOTEBOOK_ACCESSIBLE (notebook), NULL);
g_return_val_if_fail (GTK_WIDGET (child), NULL);
@@ -258,9 +259,10 @@ gtk_notebook_page_accessible_new (GtkNotebookAccessible *notebook,
atk_object->layer = ATK_LAYER_WIDGET;
atk_object_set_parent (gtk_widget_get_accessible (child), atk_object);
nb = GTK_NOTEBOOK (gtk_accessible_get_widget (page->priv->notebook));
g_signal_connect (gtk_accessible_get_widget (page->priv->notebook),
"child-notify::tab-label",
g_signal_connect (gtk_notebook_get_page (nb, child),
"notify::tab-label",
G_CALLBACK (notify_tab_label), page);
return atk_object;
+9
View File
@@ -1000,6 +1000,15 @@ gtk_css_parser_consume_url (GtkCssParser *self)
return result;
}
gboolean
gtk_css_parser_has_number (GtkCssParser *self)
{
return gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SIGNED_NUMBER)
|| gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SIGNLESS_NUMBER)
|| gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SIGNED_INTEGER)
|| gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SIGNLESS_INTEGER);
}
gboolean
gtk_css_parser_consume_number (GtkCssParser *self,
double *number)
+1
View File
@@ -118,6 +118,7 @@ gboolean gtk_css_parser_has_token (GtkCssParser
GtkCssTokenType token_type);
gboolean gtk_css_parser_has_ident (GtkCssParser *self,
const char *ident);
gboolean gtk_css_parser_has_number (GtkCssParser *self);
gboolean gtk_css_parser_has_integer (GtkCssParser *self);
gboolean gtk_css_parser_has_function (GtkCssParser *self,
const char *name);
+26 -17
View File
@@ -633,13 +633,6 @@ is_name (char c)
|| c == '-';
}
static gboolean
is_valid_escape (char c1, char c2)
{
return c1 == '\\'
&& !is_newline (c2);
}
static gboolean
is_non_printable (char c)
{
@@ -650,6 +643,25 @@ is_non_printable (char c)
|| c == 0x7F;
}
static gboolean
is_valid_escape (const char *data,
const char *end)
{
switch (end - data)
{
default:
if (is_newline (data[1]))
return FALSE;
G_GNUC_FALLTHROUGH;
case 1:
return data[0] == '\\';
case 0:
return FALSE;
}
}
static inline gsize
gtk_css_tokenizer_remaining (GtkCssTokenizer *tokenizer)
{
@@ -659,15 +671,7 @@ gtk_css_tokenizer_remaining (GtkCssTokenizer *tokenizer)
static gboolean
gtk_css_tokenizer_has_valid_escape (GtkCssTokenizer *tokenizer)
{
switch (gtk_css_tokenizer_remaining (tokenizer))
{
case 0:
return FALSE;
case 1:
return *tokenizer->data == '\\';
default:
return is_valid_escape (tokenizer->data[0], tokenizer->data[1]);
}
return is_valid_escape (tokenizer->data, tokenizer->end);
}
static gboolean
@@ -814,7 +818,11 @@ gtk_css_tokenizer_read_escape (GtkCssTokenizer *tokenizer)
if (i == 0)
{
value = g_utf8_get_char_validated (tokenizer->data, gtk_css_tokenizer_remaining (tokenizer));
gsize remaining = gtk_css_tokenizer_remaining (tokenizer);
if (remaining == 0)
return 0xFFFD;
value = g_utf8_get_char_validated (tokenizer->data, remaining);
if (value == (gunichar) -1 || value == (gunichar) -2)
value = 0;
@@ -1376,6 +1384,7 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
else
{
gtk_css_token_init (token, GTK_CSS_TOKEN_DELIM, '\\');
gtk_css_tokenizer_consume_ascii (tokenizer);
gtk_css_tokenizer_parse_error (error, "Newline may not follow '\' escape character");
return FALSE;
}
+2 -1
View File
@@ -18,7 +18,7 @@ def get_files(subdir,extension):
xml += '''
<file>theme/Adwaita/gtk.css</file>
<file>theme/Adwaita/gtk-dark.css</file>
<file alias='theme/Adwaita-dark/gtk.css'>theme/Adwaita/gtk-dark.css</file>
<file>theme/Adwaita/gtk-contained.css</file>
<file>theme/Adwaita/gtk-contained-dark.css</file>
'''
@@ -70,6 +70,7 @@ for f in get_files('inspector', '.ui'):
xml += '''
<file>inspector/logo.png</file>
<file>inspector/inspector.css</file>
<file>emoji/emoji.data</file>
</gresource>
</gresources>'''
+149
View File
@@ -21,6 +21,11 @@
#include "config.h"
#include "gtkapplication.h"
#include "gdkprofilerprivate.h"
#ifdef G_OS_UNIX
#include <gio/gunixfdlist.h>
#endif
#include <stdlib.h>
@@ -603,6 +608,148 @@ gtk_application_finalize (GObject *object)
G_OBJECT_CLASS (gtk_application_parent_class)->finalize (object);
}
#ifdef G_OS_UNIX
static const gchar org_gnome_Sysprof3_Profiler_xml[] =
"<node>"
"<interface name='org.gnome.Sysprof3.Profiler'>"
"<method name='Start'>"
"<arg type='h' name='fd' direction='in'/>"
"</method>"
"<method name='Stop'>"
"</method>"
"</interface>"
"</node>";
static GDBusInterfaceInfo *org_gnome_Sysprof3_Profiler;
static void
sysprof_profiler_method_call (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
if (strcmp (method_name, "Start") == 0)
{
GDBusMessage *message;
GUnixFDList *fd_list;
int fd = -1;
int idx;
if (gdk_profiler_is_running ())
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Profiler already running");
return;
}
g_variant_get (parameters, "(h)", &idx);
message = g_dbus_method_invocation_get_message (invocation);
fd_list = g_dbus_message_get_unix_fd_list (message);
if (fd_list)
fd = g_unix_fd_list_get (fd_list, idx, NULL);
gdk_profiler_start (fd);
}
else if (strcmp (method_name, "Stop") == 0)
{
if (!gdk_profiler_is_running ())
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Profiler not running");
return;
}
gdk_profiler_stop ();
}
else
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_UNKNOWN_METHOD,
"Unknown method");
return;
}
g_dbus_method_invocation_return_value (invocation, NULL);
}
static gboolean
gtk_application_dbus_register (GApplication *application,
GDBusConnection *connection,
const char *obect_path,
GError **error)
{
GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) application;
GDBusInterfaceVTable vtable = {
sysprof_profiler_method_call,
NULL,
NULL
};
if (org_gnome_Sysprof3_Profiler == NULL)
{
GDBusNodeInfo *info;
info = g_dbus_node_info_new_for_xml (org_gnome_Sysprof3_Profiler_xml, error);
if (info == NULL)
return FALSE;
org_gnome_Sysprof3_Profiler = g_dbus_node_info_lookup_interface (info, "org.gnome.Sysprof3.Profiler");
g_dbus_interface_info_ref (org_gnome_Sysprof3_Profiler);
g_dbus_node_info_unref (info);
}
dbus->profiler_id = g_dbus_connection_register_object (connection,
"/org/gtk/Profiler",
org_gnome_Sysprof3_Profiler,
&vtable,
NULL,
NULL,
error);
return TRUE;
}
static void
gtk_application_dbus_unregister (GApplication *application,
GDBusConnection *connection,
const char *obect_path)
{
GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) application;
g_dbus_connection_unregister_object (connection, dbus->profiler_id);
}
#else
static gboolean
gtk_application_dbus_register (GApplication *application,
GDBusConnection *connection,
const char *obect_path,
GError **error)
{
return TRUE;
}
static void
gtk_application_dbus_unregister (GApplication *application,
GDBusConnection *connection,
const char *obect_path)
{
}
#endif
static void
gtk_application_class_init (GtkApplicationClass *class)
{
@@ -619,6 +766,8 @@ gtk_application_class_init (GtkApplicationClass *class)
application_class->after_emit = gtk_application_after_emit;
application_class->startup = gtk_application_startup;
application_class->shutdown = gtk_application_shutdown;
application_class->dbus_register = gtk_application_dbus_register;
application_class->dbus_unregister = gtk_application_dbus_unregister;
class->window_added = gtk_application_window_added;
class->window_removed = gtk_application_window_removed;
+1
View File
@@ -127,6 +127,7 @@ typedef struct
gchar *menubar_path;
guint menubar_id;
guint profiler_id;
/* Session management... */
GDBusProxy *sm_proxy;
+1 -3
View File
@@ -161,6 +161,7 @@ gtk_box_class_init (GtkBoxClass *class)
g_object_class_install_properties (object_class, LAST_PROP, props);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_FILLER);
gtk_widget_class_set_css_name (widget_class, I_("box"));
}
@@ -344,12 +345,9 @@ static void
gtk_box_init (GtkBox *box)
{
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
GtkLayoutManager *box_layout = gtk_box_layout_new (GTK_ORIENTATION_HORIZONTAL);
gtk_widget_set_has_surface (GTK_WIDGET (box), FALSE);
gtk_widget_set_layout_manager (GTK_WIDGET (box), box_layout);
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (box));
}
+62 -86
View File
@@ -61,11 +61,12 @@
* 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
@@ -116,7 +117,6 @@ struct _GtkCssProviderPrivate
GArray *rulesets;
GtkCssSelectorTree *tree;
GResource *resource;
gchar *path;
};
enum {
@@ -601,8 +601,6 @@ gtk_css_provider_finalize (GObject *object)
priv->resource = NULL;
}
g_free (priv->path);
G_OBJECT_CLASS (gtk_css_provider_parent_class)->finalize (object);
}
@@ -652,12 +650,6 @@ gtk_css_provider_reset (GtkCssProvider *css_provider)
priv->resource = NULL;
}
if (priv->path)
{
g_free (priv->path);
priv->path = NULL;
}
g_hash_table_remove_all (priv->symbolic_colors);
g_hash_table_remove_all (priv->keyframes);
@@ -1234,17 +1226,6 @@ _gtk_get_theme_dir (void)
return g_build_filename (var, "share", "themes", NULL);
}
/* Return the path that this providers gtk.css was loaded from,
* if it is part of a theme, otherwise NULL.
*/
const gchar *
_gtk_css_provider_get_theme_dir (GtkCssProvider *provider)
{
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (provider);
return priv->path;
}
#if (GTK_MINOR_VERSION % 2)
#define MINOR (GTK_MINOR_VERSION + 1)
#else
@@ -1253,17 +1234,16 @@ _gtk_css_provider_get_theme_dir (GtkCssProvider *provider)
/*
* Look for
* $dir/$subdir/gtk-4.16/gtk-$variant.css
* $dir/$subdir/gtk-4.14/gtk-$variant.css
* $dir/$subdir/gtk-4.16/gtk.css
* $dir/$subdir/gtk-4.14/gtk.css
* ...
* $dir/$subdir/gtk-4.0/gtk-$variant.css
* $dir/$subdir/gtk-4.0/gtk.css
* and return the first found file.
*/
static gchar *
_gtk_css_find_theme_dir (const gchar *dir,
const gchar *subdir,
const gchar *name,
const gchar *variant)
const gchar *name)
{
gchar *file;
gchar *base;
@@ -1271,10 +1251,7 @@ _gtk_css_find_theme_dir (const gchar *dir,
gint i;
gchar *path;
if (variant)
file = g_strconcat ("gtk-", variant, ".css", NULL);
else
file = g_strdup ("gtk.css");
file = g_strdup ("gtk.css");
if (subdir)
base = g_build_filename (dir, subdir, name, NULL);
@@ -1283,9 +1260,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);
@@ -1306,8 +1280,7 @@ _gtk_css_find_theme_dir (const gchar *dir,
#undef MINOR
static gchar *
_gtk_css_find_theme (const gchar *name,
const gchar *variant)
_gtk_css_find_theme (const gchar *name)
{
gchar *path;
const char *const *dirs;
@@ -1315,12 +1288,12 @@ _gtk_css_find_theme (const gchar *name,
char *dir;
/* First look in the user's data directory */
path = _gtk_css_find_theme_dir (g_get_user_data_dir (), "themes", name, variant);
path = _gtk_css_find_theme_dir (g_get_user_data_dir (), "themes", name);
if (path)
return path;
/* Next look in the user's home directory */
path = _gtk_css_find_theme_dir (g_get_home_dir (), ".themes", name, variant);
path = _gtk_css_find_theme_dir (g_get_home_dir (), ".themes", name);
if (path)
return path;
@@ -1328,62 +1301,42 @@ _gtk_css_find_theme (const gchar *name,
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i]; i++)
{
path = _gtk_css_find_theme_dir (dirs[i], "themes", name, variant);
path = _gtk_css_find_theme_dir (dirs[i], "themes", name);
if (path)
return path;
}
/* Finally, try in the default theme directory */
dir = _gtk_get_theme_dir ();
path = _gtk_css_find_theme_dir (dir, NULL, name, variant);
path = _gtk_css_find_theme_dir (dir, NULL, name);
g_free (dir);
return path;
}
/**
* gtk_css_provider_load_named:
* @provider: a #GtkCssProvider
* @name: A theme name
* @variant: (allow-none): variant to load, for example, "dark", or
* %NULL for the default
*
* Loads a theme from the usual theme paths. The actual process of
* finding the theme might change between releases, but it is
* guaranteed that this function uses the same mechanism to load the
* theme that GTK uses for loading its own theme.
**/
void
gtk_css_provider_load_named (GtkCssProvider *provider,
const gchar *name,
const gchar *variant)
static gboolean
gtk_css_provider_load_theme (GtkCssProvider *provider,
const gchar *name)
{
gchar *path;
gchar *resource_path;
g_return_if_fail (GTK_IS_CSS_PROVIDER (provider));
g_return_if_fail (name != NULL);
gtk_css_provider_reset (provider);
/* try loading the resource for the theme. This is mostly meant for built-in
* themes.
*/
if (variant)
resource_path = g_strdup_printf ("/org/gtk/libgtk/theme/%s/gtk-%s.css", name, variant);
else
resource_path = g_strdup_printf ("/org/gtk/libgtk/theme/%s/gtk.css", name);
resource_path = g_strconcat ("/org/gtk/libgtk/theme/", name, "/gtk.css", NULL);
if (g_resources_get_info (resource_path, 0, NULL, NULL, NULL))
{
gtk_css_provider_load_from_resource (provider, resource_path);
g_free (resource_path);
return;
return TRUE;
}
g_free (resource_path);
/* Next try looking for files in the various theme directories. */
path = _gtk_css_find_theme (name, variant);
path = _gtk_css_find_theme (name);
if (path)
{
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (provider);
@@ -1402,26 +1355,49 @@ gtk_css_provider_load_named (GtkCssProvider *provider,
/* Only set this after load, as load_from_path will clear it */
priv->resource = resource;
priv->path = dir;
g_free (dir);
g_free (path);
}
else
{
/* Things failed! Fall back! Fall back! */
if (variant)
{
/* If there was a variant, try without */
gtk_css_provider_load_named (provider, name, NULL);
}
else
{
/* Worst case, fall back to the default */
g_return_if_fail (!g_str_equal (name, DEFAULT_THEME_NAME)); /* infloop protection */
gtk_css_provider_load_named (provider, DEFAULT_THEME_NAME, NULL);
}
return TRUE;
}
return FALSE;
}
/**
* gtk_css_provider_load_named:
* @provider: a #GtkCssProvider
* @name: A theme name
* @fallback: (allow-none): Fallback theme to load if @name is
* not available, or %NULL for the default
*
* Loads a theme from the usual theme paths. The actual process of
* finding the theme might change between releases, but it is
* guaranteed that this function uses the same mechanism to load the
* theme that GTK uses for loading its own theme.
*
* The @fallback can be used to try loading THEME-dark,
* falling back to THEME.
**/
void
gtk_css_provider_load_named (GtkCssProvider *provider,
const gchar *name,
const gchar *fallback)
{
g_return_if_fail (GTK_IS_CSS_PROVIDER (provider));
g_return_if_fail (name != NULL);
gtk_css_provider_reset (provider);
if (gtk_css_provider_load_theme (provider, name))
return;
if (fallback &&
gtk_css_provider_load_theme (provider, fallback))
return;
gtk_css_provider_load_theme (provider, DEFAULT_THEME_NAME);
}
static int
+1 -1
View File
@@ -80,7 +80,7 @@ void gtk_css_provider_load_from_resource (GtkCssProvider *css_provid
GDK_AVAILABLE_IN_ALL
void gtk_css_provider_load_named (GtkCssProvider *provider,
const char *name,
const char *variant);
const char *fallback);
G_END_DECLS
-2
View File
@@ -24,8 +24,6 @@ G_BEGIN_DECLS
gchar *_gtk_get_theme_dir (void);
const gchar *_gtk_css_provider_get_theme_dir (GtkCssProvider *provider);
void gtk_css_provider_set_keep_css_sections (void);
G_END_DECLS
+17 -9
View File
@@ -153,11 +153,9 @@ populate_recent_section (GtkEmojiChooser *chooser)
empty = FALSE;
}
if (!empty)
{
gtk_widget_show (chooser->recent.box);
gtk_widget_set_sensitive (chooser->recent.button, TRUE);
}
gtk_widget_set_visible (chooser->recent.box, !empty);
gtk_widget_set_sensitive (chooser->recent.button, !empty);
g_variant_unref (variant);
}
@@ -458,15 +456,12 @@ populate_emoji_chooser (gpointer data)
return G_SOURCE_CONTINUE;
}
/* We scroll to the top on show, so check the right button for the 1st time */
gtk_widget_set_state_flags (chooser->recent.button, GTK_STATE_FLAG_CHECKED, FALSE);
g_variant_iter_free (chooser->iter);
chooser->iter = NULL;
chooser->box = NULL;
chooser->populate_idle = 0;
return G_SOURCE_REMOVE;
return G_SOURCE_REMOVE;
}
static void
@@ -496,6 +491,9 @@ adj_value_changed (GtkAdjustment *adj,
EmojiSection const *section = sections[i];
GtkAllocation alloc;
if (!gtk_widget_get_visible (section->box))
continue;
if (section->heading)
gtk_widget_get_allocation (section->heading, &alloc);
else
@@ -611,6 +609,13 @@ search_changed (GtkEntry *entry,
update_headings (chooser);
}
static void
stop_search (GtkEntry *entry,
gpointer data)
{
gtk_popover_popdown (GTK_POPOVER (data));
}
static void
setup_section (GtkEmojiChooser *chooser,
EmojiSection *section,
@@ -681,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
@@ -693,6 +699,7 @@ gtk_emoji_chooser_show (GtkWidget *widget)
adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (chooser->scrolled_window));
gtk_adjustment_set_value (adj, 0);
adj_value_changed (adj, chooser);
gtk_editable_set_text (GTK_EDITABLE (chooser->search_entry), "");
}
@@ -761,6 +768,7 @@ gtk_emoji_chooser_class_init (GtkEmojiChooserClass *klass)
gtk_widget_class_bind_template_callback (widget_class, emoji_activated);
gtk_widget_class_bind_template_callback (widget_class, search_changed);
gtk_widget_class_bind_template_callback (widget_class, stop_search);
gtk_widget_class_bind_template_callback (widget_class, pressed_cb);
gtk_widget_class_bind_template_callback (widget_class, long_pressed_cb);
}
+6 -29
View File
@@ -3447,42 +3447,19 @@ gtk_entry_enter_text (GtkEntry *entry,
gtk_text_enter_text (GTK_TEXT (priv->text), text);
}
static void
gtk_entry_insert_emoji (GtkEntry *entry)
{
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
GtkWidget *chooser;
GdkRectangle rect;
if (gtk_widget_get_ancestor (GTK_WIDGET (entry), GTK_TYPE_EMOJI_CHOOSER) != NULL)
return;
chooser = GTK_WIDGET (g_object_get_data (G_OBJECT (entry), "gtk-emoji-chooser"));
if (!chooser)
{
chooser = gtk_emoji_chooser_new ();
g_object_set_data (G_OBJECT (entry), "gtk-emoji-chooser", chooser);
gtk_popover_set_relative_to (GTK_POPOVER (chooser), GTK_WIDGET (entry));
if (priv->show_emoji_icon)
{
gtk_entry_get_icon_area (entry, GTK_ENTRY_ICON_SECONDARY, &rect);
gtk_popover_set_pointing_to (GTK_POPOVER (chooser), &rect);
}
g_signal_connect_swapped (chooser, "emoji-picked", G_CALLBACK (gtk_entry_enter_text), entry);
}
gtk_popover_popup (GTK_POPOVER (chooser));
}
static void
pick_emoji (GtkEntry *entry,
int icon,
GdkEvent *event,
gpointer data)
{
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
if (gtk_widget_get_ancestor (GTK_WIDGET (entry), GTK_TYPE_EMOJI_CHOOSER) != NULL)
return;
if (icon == GTK_ENTRY_ICON_SECONDARY)
gtk_entry_insert_emoji (entry);
g_signal_emit_by_name (priv->text, "insert-emoji");
}
static void
+2 -2
View File
@@ -422,6 +422,8 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
_gtk_file_chooser_install_properties (gobject_class);
gtk_widget_class_set_css_name (widget_class, I_("filechooserbutton"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
static void
@@ -497,8 +499,6 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
target_list,
GDK_ACTION_COPY);
gdk_content_formats_unref (target_list);
gtk_widget_set_layout_manager (GTK_WIDGET (button), gtk_bin_layout_new ());
}
+2 -2
View File
@@ -8326,6 +8326,8 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_callback (widget_class, widget_key_press_cb);
gtk_widget_class_set_css_name (widget_class, I_("filechooser"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
static void
@@ -8467,8 +8469,6 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
*/
post_process_ui (impl);
gtk_widget_set_layout_manager (GTK_WIDGET (impl), gtk_bin_layout_new ());
profile_end ("end", NULL);
}
+4 -2
View File
@@ -96,11 +96,14 @@ static void
gtk_fixed_class_init (GtkFixedClass *klass)
{
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
container_class->add = gtk_fixed_add;
container_class->remove = gtk_fixed_remove;
container_class->forall = gtk_fixed_forall;
container_class->child_type = gtk_fixed_child_type;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_FIXED_LAYOUT);
}
static GType
@@ -117,8 +120,7 @@ gtk_fixed_init (GtkFixed *self)
gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN);
priv->layout = gtk_fixed_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (self), priv->layout);
priv->layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
}
/**
-1
View File
@@ -107,7 +107,6 @@ gtk_gizmo_new (const char *css_name,
{
GtkGizmo *gizmo = GTK_GIZMO (g_object_new (GTK_TYPE_GIZMO,
"css-name", css_name,
"name", css_name,
NULL));
gizmo->measure_func = measure_func;
+3 -2
View File
@@ -380,6 +380,8 @@ gtk_grid_class_init (GtkGridClass *class)
g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
gtk_widget_class_set_css_name (widget_class, I_("grid"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_GRID_LAYOUT);
}
static void
@@ -389,8 +391,7 @@ gtk_grid_init (GtkGrid *grid)
gtk_widget_set_has_surface (GTK_WIDGET (grid), FALSE);
priv->layout_manager = gtk_grid_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (grid), priv->layout_manager);
priv->layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (grid));
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (grid));
+1
View File
@@ -2045,6 +2045,7 @@ gtk_header_bar_set_decoration_layout (GtkHeaderBar *bar,
priv = gtk_header_bar_get_instance_private (bar);
g_free (priv->decoration_layout);
priv->decoration_layout = g_strdup (layout);
priv->decoration_layout_set = (layout != NULL);
+3 -2
View File
@@ -302,6 +302,8 @@ gtk_overlay_class_init (GtkOverlayClass *klass)
GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
gtk_widget_class_set_css_name (widget_class, I_("overlay"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_OVERLAY_LAYOUT);
}
static void
@@ -311,8 +313,7 @@ gtk_overlay_init (GtkOverlay *overlay)
gtk_widget_set_has_surface (GTK_WIDGET (overlay), FALSE);
priv->layout = gtk_overlay_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (overlay), priv->layout);
priv->layout = gtk_widget_get_layout_manager (GTK_WIDGET (overlay));
}
static GtkBuildableIface *parent_buildable_iface;
+13 -15
View File
@@ -2208,29 +2208,27 @@ static void
settings_update_theme (GtkSettings *settings)
{
GtkSettingsPrivate *priv = settings->priv;
gchar *theme_name;
gchar *theme_variant;
const gchar *theme_dir;
gchar *path;
char *theme_name;
char *theme_variant;
char *theme_fallback;
get_theme_name (settings, &theme_name, &theme_variant);
if (theme_variant)
{
theme_fallback = theme_name;
theme_name = g_strconcat (theme_fallback, "-", theme_variant, NULL);
}
else
theme_fallback = NULL;
gtk_css_provider_load_named (priv->theme_provider,
theme_name,
theme_variant);
/* reload per-theme settings */
theme_dir = _gtk_css_provider_get_theme_dir (priv->theme_provider);
if (theme_dir)
{
path = g_build_filename (theme_dir, "settings.ini", NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS))
gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_THEME);
g_free (path);
}
theme_fallback);
g_free (theme_name);
g_free (theme_variant);
g_free (theme_fallback);
}
const cairo_font_options_t *
+64 -20
View File
@@ -497,6 +497,7 @@ struct _GtkWidgetClassPrivate
GType accessible_type;
AtkRole accessible_role;
const char *css_name;
GType layout_manager_type;
};
enum {
@@ -2740,6 +2741,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
{
GtkWidget *widget = GTK_WIDGET (instance);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GType layout_manager_type;
widget->priv = priv;
@@ -2808,6 +2810,10 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_ROOT))
priv->root = (GtkRoot *) widget;
layout_manager_type = gtk_widget_class_get_layout_manager_type (g_class);
if (layout_manager_type != G_TYPE_INVALID)
gtk_widget_set_layout_manager (widget, g_object_new (layout_manager_type, NULL));
}
/**
@@ -5249,11 +5255,7 @@ _gtk_widget_captured_event (GtkWidget *widget,
return TRUE;
event_copy = gdk_event_copy (event);
if (!translate_event_coordinates (event_copy, widget))
{
g_object_unref (event_copy);
return FALSE;
}
translate_event_coordinates (event_copy, widget);
return_val = gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_CAPTURE);
@@ -5355,11 +5357,7 @@ gtk_widget_event_internal (GtkWidget *widget,
event_copy = gdk_event_copy (event);
if (!translate_event_coordinates (event_copy, widget))
{
g_object_unref (event_copy);
return FALSE;
}
translate_event_coordinates (event_copy, widget);
if (widget == gtk_get_event_target (event_copy))
return_val |= gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_TARGET);
@@ -6739,17 +6737,17 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (!priv->realized)
g_warning ("%s %p is mapped but not realized",
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (widget), widget);
if (!priv->visible)
g_warning ("%s %p is mapped but not visible",
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (widget), widget);
if (!GTK_IS_ROOT (widget))
{
if (!priv->child_visible)
g_warning ("%s %p is mapped but not child_visible",
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (widget), widget);
}
}
else
@@ -6799,8 +6797,8 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (priv->realized)
g_warning ("%s %p is not realized but child %s %p is realized",
parent ? gtk_widget_get_name (parent) : "no parent", parent,
gtk_widget_get_name (widget), widget);
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
G_OBJECT_TYPE_NAME (widget), widget);
}
if (parent &&
@@ -6812,8 +6810,8 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (!priv->mapped)
g_warning ("%s %p is mapped but visible child %s %p is not mapped",
gtk_widget_get_name (parent), parent,
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (parent), parent,
G_OBJECT_TYPE_NAME (widget), widget);
}
else if (!GTK_IS_ROOT (widget))
{
@@ -6821,10 +6819,10 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (priv->mapped)
g_warning ("%s %p is mapped but visible=%d child_visible=%d parent %s %p mapped=%d",
gtk_widget_get_name (widget), widget,
G_OBJECT_TYPE_NAME (widget), widget,
priv->visible,
priv->child_visible,
parent ? gtk_widget_get_name (parent) : "no parent", parent,
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
parent ? parent->priv->mapped : FALSE);
}
}
@@ -12986,7 +12984,7 @@ gtk_widget_snapshot (GtkWidget *widget,
if (_gtk_widget_get_alloc_needed (widget))
{
g_warning ("Trying to snapshot %s %p without a current allocation", gtk_widget_get_name (widget), widget);
g_warning ("Trying to snapshot %s %p without a current allocation", G_OBJECT_TYPE_NAME (widget), widget);
return;
}
@@ -13575,6 +13573,52 @@ gtk_widget_get_height (GtkWidget *widget)
return priv->height;
}
/**
* gtk_widget_class_set_layout_manager_type:
* @widget_class: class to set the layout manager type for
* @type: The object type that implements the #GtkLayoutManager for @widget_class
*
* Sets the type to be used for creating layout managers for widgets of
* @widget_class. The given @type must be a subtype of #GtkLayoutManager.
*
* This function should only be called from class init functions of widgets.
**/
void
gtk_widget_class_set_layout_manager_type (GtkWidgetClass *widget_class,
GType type)
{
GtkWidgetClassPrivate *priv;
g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
g_return_if_fail (g_type_is_a (type, GTK_TYPE_LAYOUT_MANAGER));
priv = widget_class->priv;
priv->layout_manager_type = type;
}
/**
* gtk_widget_class_get_layout_manager_type:
* @widget_class: a #GtkWidgetClass
*
* Retrieves the type of the #GtkLayoutManager used by the #GtkWidget class.
*
* See also: gtk_widget_class_set_layout_manager_type()
*
* Returns: a #GtkLayoutManager subclass, or %G_TYPE_INVALID
*/
GType
gtk_widget_class_get_layout_manager_type (GtkWidgetClass *widget_class)
{
GtkWidgetClassPrivate *priv;
g_return_val_if_fail (GTK_IS_WIDGET_CLASS (widget_class), G_TYPE_INVALID);
priv = widget_class->priv;
return priv->layout_manager_type;
}
/**
* gtk_widget_set_layout_manager:
* @widget: a #GtkWidget
+6
View File
@@ -414,6 +414,12 @@ void gtk_widget_set_layout_manager (GtkWidget *widge
GDK_AVAILABLE_IN_ALL
GtkLayoutManager * gtk_widget_get_layout_manager (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_set_layout_manager_type (GtkWidgetClass *widget_class,
GType type);
GDK_AVAILABLE_IN_ALL
GType gtk_widget_class_get_layout_manager_type (GtkWidgetClass *widget_class);
GDK_AVAILABLE_IN_ALL
void gtk_widget_add_accelerator (GtkWidget *widget,
const gchar *accel_signal,
+9 -69
View File
@@ -503,6 +503,8 @@ static void gtk_window_do_popup (GtkWindow *window,
static void gtk_window_style_updated (GtkWidget *widget);
static void gtk_window_state_flags_changed (GtkWidget *widget,
GtkStateFlags previous_state);
static void _gtk_window_set_is_active (GtkWindow *window,
gboolean is_active);
static GListStore *toplevel_list = NULL;
static guint window_signals[LAST_SIGNAL] = { 0 };
@@ -6230,47 +6232,6 @@ get_active_region_type (GtkWindow *window, gint x, gint y)
return GTK_WINDOW_REGION_CONTENT;
}
static void
do_focus_change (GtkWidget *widget,
gboolean in)
{
GdkSeat *seat;
GdkDevice *device;
GdkEvent *event;
GtkRoot *root;
GtkStateFlags flags;
seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
device = gdk_seat_get_keyboard (seat);
event = gdk_event_new (GDK_FOCUS_CHANGE);
gdk_event_set_display (event, gtk_widget_get_display (widget));
gdk_event_set_device (event, device);
event->any.type = GDK_FOCUS_CHANGE;
event->any.surface = _gtk_widget_get_surface (widget);
if (event->any.surface)
g_object_ref (event->any.surface);
event->focus_change.in = in;
event->focus_change.mode = GDK_CROSSING_STATE_CHANGED;
event->focus_change.detail = GDK_NOTIFY_ANCESTOR;
flags = GTK_STATE_FLAG_FOCUSED;
root = gtk_widget_get_root (widget);
if (!GTK_IS_WINDOW (root) || gtk_window_get_focus_visible (GTK_WINDOW (root)))
flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
if (in)
gtk_widget_set_state_flags (widget, flags, FALSE);
else
gtk_widget_unset_state_flags (widget, flags);
gtk_widget_set_has_focus (widget, in);
gtk_widget_event (widget, event);
g_object_unref (event);
}
static gboolean
gtk_window_has_mnemonic_modifier_pressed (GtkWindow *window)
{
@@ -8946,7 +8907,7 @@ gtk_window_activate_key (GtkWindow *window,
return gtk_window_activate_menubar (window, event);
}
/**
/*
* _gtk_window_set_is_active:
* @window: a #GtkWindow
* @is_active: %TRUE if the window is in the currently active toplevel
@@ -8955,40 +8916,19 @@ gtk_window_activate_key (GtkWindow *window,
* of the currently active toplevel window (taking into account inter-process
* embedding.)
**/
void
static void
_gtk_window_set_is_active (GtkWindow *window,
gboolean is_active)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
g_return_if_fail (GTK_IS_WINDOW (window));
if (priv->is_active == is_active)
return;
is_active = is_active != FALSE;
priv->is_active = is_active;
if (is_active != priv->is_active)
{
GtkWidget *widget = GTK_WIDGET (window);
priv->is_active = is_active;
if (is_active)
{
if (priv->focus_widget &&
priv->focus_widget != widget &&
!gtk_widget_has_focus (priv->focus_widget))
do_focus_change (priv->focus_widget, TRUE);
}
else
{
if (priv->focus_widget &&
priv->focus_widget != widget &&
gtk_widget_has_focus (priv->focus_widget))
do_focus_change (priv->focus_widget, FALSE);
}
g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_IS_ACTIVE]);
_gtk_window_accessible_set_is_active (window, is_active);
}
g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_IS_ACTIVE]);
_gtk_window_accessible_set_is_active (window, is_active);
}
/**
-3
View File
@@ -47,9 +47,6 @@ gboolean _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *
void _gtk_window_unset_focus_and_default (GtkWindow *window,
GtkWidget *widget);
void _gtk_window_set_is_active (GtkWindow *window,
gboolean is_active);
void _gtk_window_set_allocation (GtkWindow *window,
int width,
int height,
+30 -15
View File
@@ -45,7 +45,8 @@ enum
PROP_0,
PROP_GROUP,
PROP_PREFIX,
PROP_NAME
PROP_NAME,
PROP_SIZEGROUP
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorActionEditor, gtk_inspector_action_editor, GTK_TYPE_BOX)
@@ -55,9 +56,8 @@ gtk_inspector_action_editor_init (GtkInspectorActionEditor *editor)
{
editor->priv = gtk_inspector_action_editor_get_instance_private (editor);
g_object_set (editor,
"orientation", GTK_ORIENTATION_VERTICAL,
"orientation", GTK_ORIENTATION_HORIZONTAL,
"spacing", 10,
"margin", 10,
NULL);
}
@@ -238,6 +238,9 @@ action_enabled_changed_cb (GActionGroup *group,
gboolean enabled,
GtkInspectorActionEditor *r)
{
if (!g_str_equal (action_name, r->priv->name))
return;
r->priv->enabled = enabled;
if (r->priv->parameter_entry)
{
@@ -252,6 +255,9 @@ action_state_changed_cb (GActionGroup *group,
GVariant *state,
GtkInspectorActionEditor *r)
{
if (!g_str_equal (action_name, r->priv->name))
return;
if (r->priv->state_entry)
variant_editor_set_value (r->priv->state_entry, state);
}
@@ -261,34 +267,30 @@ constructed (GObject *object)
{
GtkInspectorActionEditor *r = GTK_INSPECTOR_ACTION_EDITOR (object);
GVariant *state;
gchar *fullname;
GtkWidget *row;
GtkWidget *activate;
GtkWidget *label;
r->priv->enabled = g_action_group_get_action_enabled (r->priv->group, r->priv->name);
state = g_action_group_get_action_state (r->priv->group, r->priv->name);
fullname = g_strdup_printf ("%s.%s", r->priv->prefix, r->priv->name);
gtk_container_add (GTK_CONTAINER (r), gtk_label_new (fullname));
g_free (fullname);
r->priv->sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
activate = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_container_add (GTK_CONTAINER (row), activate);
gtk_size_group_add_widget (r->priv->sg, activate);
r->priv->activate_button = gtk_button_new_with_label (_("Activate"));
g_signal_connect (r->priv->activate_button, "clicked", G_CALLBACK (activate_action), r);
gtk_size_group_add_widget (r->priv->sg, r->priv->activate_button);
gtk_widget_set_sensitive (r->priv->activate_button, r->priv->enabled);
gtk_container_add (GTK_CONTAINER (row), r->priv->activate_button);
gtk_container_add (GTK_CONTAINER (activate), r->priv->activate_button);
r->priv->parameter_type = g_action_group_get_action_parameter_type (r->priv->group, r->priv->name);
if (r->priv->parameter_type)
{
r->priv->parameter_entry = variant_editor_new (r->priv->parameter_type, parameter_changed, r);
gtk_widget_set_sensitive (r->priv->parameter_entry, r->priv->enabled);
gtk_container_add (GTK_CONTAINER (row), r->priv->parameter_entry);
gtk_container_add (GTK_CONTAINER (activate), r->priv->parameter_entry);
}
gtk_container_add (GTK_CONTAINER (r), row);
@@ -297,7 +299,7 @@ constructed (GObject *object)
{
r->priv->state_type = g_variant_type_copy (g_variant_get_type (state));
row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
label = gtk_label_new (_("State"));
label = gtk_label_new (_("Set State"));
gtk_size_group_add_widget (r->priv->sg, label);
gtk_container_add (GTK_CONTAINER (row), label);
r->priv->state_entry = variant_editor_new (r->priv->state_type, state_changed, r);
@@ -350,6 +352,10 @@ get_property (GObject *object,
g_value_set_string (value, r->priv->name);
break;
case PROP_SIZEGROUP:
g_value_set_object (value, r->priv->sg);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -380,6 +386,10 @@ set_property (GObject *object,
r->priv->name = g_value_dup_string (value);
break;
case PROP_SIZEGROUP:
r->priv->sg = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
@@ -407,16 +417,21 @@ gtk_inspector_action_editor_class_init (GtkInspectorActionEditorClass *klass)
g_object_class_install_property (object_class, PROP_NAME,
g_param_spec_string ("name", "Name", "The action name",
NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_SIZEGROUP,
g_param_spec_object ("sizegroup", "Size Group", "The Size Group for activate",
GTK_TYPE_SIZE_GROUP, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
}
GtkWidget *
gtk_inspector_action_editor_new (GActionGroup *group,
const gchar *prefix,
const gchar *name)
const gchar *name,
GtkSizeGroup *activate)
{
return g_object_new (GTK_TYPE_INSPECTOR_ACTION_EDITOR,
"group", group,
"prefix", prefix,
"name", name,
"sizegroup", activate,
NULL);
}
+3 -1
View File
@@ -20,6 +20,7 @@
#include <gtk/gtkbox.h>
#include <gtk/gtksizegroup.h>
#define GTK_TYPE_INSPECTOR_ACTION_EDITOR (gtk_inspector_action_editor_get_type())
@@ -49,7 +50,8 @@ G_BEGIN_DECLS
GType gtk_inspector_action_editor_get_type (void);
GtkWidget *gtk_inspector_action_editor_new (GActionGroup *group,
const gchar *prefix,
const gchar *name);
const gchar *name,
GtkSizeGroup *activate);
G_END_DECLS
+114 -85
View File
@@ -29,6 +29,9 @@
#include "gtkpopover.h"
#include "gtklabel.h"
#include "gtkstack.h"
#include "gtklistbox.h"
#include "gtkstylecontext.h"
#include "gtksizegroup.h"
enum
{
@@ -42,9 +45,14 @@ enum
struct _GtkInspectorActionsPrivate
{
GtkListStore *model;
GtkWidget *list;
GtkSizeGroup *prefix;
GtkSizeGroup *name;
GtkSizeGroup *enabled;
GtkSizeGroup *parameter;
GtkSizeGroup *state;
GtkSizeGroup *activate;
GHashTable *groups;
GHashTable *iters;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorActions, gtk_inspector_actions, GTK_TYPE_BOX)
@@ -53,10 +61,6 @@ static void
gtk_inspector_actions_init (GtkInspectorActions *sl)
{
sl->priv = gtk_inspector_actions_get_instance_private (sl);
sl->priv->iters = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify) gtk_tree_iter_free);
sl->priv->groups = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
@@ -70,11 +74,15 @@ add_action (GtkInspectorActions *sl,
const gchar *prefix,
const gchar *name)
{
GtkTreeIter iter;
gboolean enabled;
const gchar *parameter;
GVariant *state;
gchar *state_string;
GtkWidget *row;
GtkWidget *label;
GtkWidget *box;
char *key = g_strconcat (prefix, ".", name, NULL);
GtkWidget *editor;
enabled = g_action_group_get_action_enabled (group, name);
parameter = (const gchar *)g_action_group_get_action_parameter_type (group, name);
@@ -83,21 +91,82 @@ add_action (GtkInspectorActions *sl,
state_string = g_variant_print (state, FALSE);
else
state_string = g_strdup ("");
gtk_list_store_append (sl->priv->model, &iter);
gtk_list_store_set (sl->priv->model, &iter,
COLUMN_PREFIX, prefix,
COLUMN_NAME, name,
COLUMN_ENABLED, enabled,
COLUMN_PARAMETER, parameter,
COLUMN_STATE, state_string,
COLUMN_GROUP, group,
-1);
g_hash_table_insert (sl->priv->iters,
g_strconcat (prefix, ".", name, NULL),
gtk_tree_iter_copy (&iter));
row = gtk_list_box_row_new ();
g_object_set_data_full (G_OBJECT (row), "key", key, g_free);
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add (GTK_CONTAINER (row), box);
label = gtk_label_new (prefix);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->prefix, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (name);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->name, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (enabled ? "+" : "-");
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->enabled, label);
gtk_container_add (GTK_CONTAINER (box), label);
g_object_set_data (G_OBJECT (row), "enabled", label);
label = gtk_label_new (parameter);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (sl->priv->parameter, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (state_string);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_size_group_add_widget (sl->priv->state, label);
gtk_container_add (GTK_CONTAINER (box), label);
g_object_set_data (G_OBJECT (row), "state", label);
editor = gtk_inspector_action_editor_new (group, prefix, name, sl->priv->activate);
gtk_style_context_add_class (gtk_widget_get_style_context (editor), "cell");
gtk_container_add (GTK_CONTAINER (box), editor);
gtk_container_add (GTK_CONTAINER (sl->priv->list), row);
g_free (state_string);
}
static GtkWidget *
find_row (GtkInspectorActions *sl,
const char *prefix,
const char *action_name)
{
GtkWidget *row = NULL;
GtkWidget *widget;
char *key = g_strconcat (prefix, ".", action_name, NULL);
for (widget = gtk_widget_get_first_child (sl->priv->list);
widget;
widget = gtk_widget_get_next_sibling (widget))
{
const char *rkey = g_object_get_data (G_OBJECT (widget), "key");
if (g_str_equal (key, rkey))
{
row = widget;
break;
}
}
g_free (key);
return row;
}
static void
action_added_cb (GActionGroup *group,
const gchar *action_name,
@@ -114,14 +183,12 @@ action_removed_cb (GActionGroup *group,
GtkInspectorActions *sl)
{
const gchar *prefix;
gchar *key;
GtkTreeIter *iter;
GtkWidget *row;
prefix = g_hash_table_lookup (sl->priv->groups, group);
key = g_strconcat (prefix, ".", action_name, NULL);
iter = g_hash_table_lookup (sl->priv->iters, key);
gtk_list_store_remove (sl->priv->model, iter);
g_hash_table_remove (sl->priv->iters, key);
g_free (key);
row = find_row (sl, prefix, action_name);
if (row)
gtk_container_remove (GTK_CONTAINER (sl->priv->list), row);
}
static void
@@ -131,15 +198,14 @@ action_enabled_changed_cb (GActionGroup *group,
GtkInspectorActions *sl)
{
const gchar *prefix;
gchar *key;
GtkTreeIter *iter;
GtkWidget *row;
GtkWidget *label;
prefix = g_hash_table_lookup (sl->priv->groups, group);
key = g_strconcat (prefix, ".", action_name, NULL);
iter = g_hash_table_lookup (sl->priv->iters, key);
gtk_list_store_set (sl->priv->model, iter,
COLUMN_ENABLED, enabled,
-1);
g_free (key);
row = find_row (sl, prefix, action_name);
label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "enabled"));
gtk_label_set_label (GTK_LABEL (label), enabled ? "+" : "-" );
}
static void
@@ -149,21 +215,20 @@ action_state_changed_cb (GActionGroup *group,
GtkInspectorActions *sl)
{
const gchar *prefix;
gchar *key;
GtkTreeIter *iter;
gchar *state_string;
GtkWidget *row;
GtkWidget *label;
prefix = g_hash_table_lookup (sl->priv->groups, group);
key = g_strconcat (prefix, ".", action_name, NULL);
iter = g_hash_table_lookup (sl->priv->iters, key);
row = find_row (sl, prefix, action_name);
if (state)
state_string = g_variant_print (state, FALSE);
else
state_string = g_strdup ("");
gtk_list_store_set (sl->priv->model, iter,
COLUMN_STATE, state_string,
-1);
label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "state"));
gtk_label_set_label (GTK_LABEL (label), state_string);
g_free (state_string);
g_free (key);
}
static void
@@ -214,8 +279,6 @@ gtk_inspector_actions_set_object (GtkInspectorActions *sl,
g_object_set (page, "visible", FALSE, NULL);
g_hash_table_foreach (sl->priv->groups, disconnect_group, sl);
g_hash_table_remove_all (sl->priv->groups);
g_hash_table_remove_all (sl->priv->iters);
gtk_list_store_clear (sl->priv->model);
if (GTK_IS_APPLICATION (object))
add_group (sl, page, G_ACTION_GROUP (object), "app");
@@ -238,53 +301,19 @@ gtk_inspector_actions_set_object (GtkInspectorActions *sl,
}
}
static void
row_activated (GtkTreeView *tv,
GtkTreePath *path,
GtkTreeViewColumn *col,
GtkInspectorActions *sl)
{
GtkTreeIter iter;
GdkRectangle rect;
GtkWidget *popover;
gchar *prefix;
gchar *name;
GActionGroup *group;
GtkWidget *editor;
gtk_tree_model_get_iter (GTK_TREE_MODEL (sl->priv->model), &iter, path);
gtk_tree_model_get (GTK_TREE_MODEL (sl->priv->model),
&iter,
COLUMN_PREFIX, &prefix,
COLUMN_NAME, &name,
COLUMN_GROUP, &group,
-1);
gtk_tree_model_get_iter (GTK_TREE_MODEL (sl->priv->model), &iter, path);
gtk_tree_view_get_cell_area (tv, path, col, &rect);
gtk_tree_view_convert_bin_window_to_widget_coords (tv, rect.x, rect.y, &rect.x, &rect.y);
popover = gtk_popover_new (GTK_WIDGET (tv));
gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
editor = gtk_inspector_action_editor_new (group, prefix, name);
gtk_container_add (GTK_CONTAINER (popover), editor);
gtk_popover_popup (GTK_POPOVER (popover));
g_signal_connect (popover, "hide", G_CALLBACK (gtk_widget_destroy), NULL);
g_free (name);
g_free (prefix);
}
static void
gtk_inspector_actions_class_init (GtkInspectorActionsClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/actions.ui");
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, model);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, list);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, prefix);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, name);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, enabled);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, parameter);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, state);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, activate);
}
// vim: set et sw=2 ts=2:
+85 -70
View File
@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="gtk40">
<object class="GtkListStore" id="model">
<columns>
@@ -11,84 +12,98 @@
</object>
<template class="GtkInspectorActions" parent="GtkBox">
<property name="orientation">vertical</property>
<style>
<class name="view"/>
</style>
<child>
<object class="GtkBox">
<style>
<class name="header"/>
</style>
<child>
<object class="GtkLabel" id="prefix_heading">
<property name="label" translatable="yes">Prefix</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="name_heading">
<property name="label" translatable="yes">Name</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="enabled_heading">
<property name="label" translatable="yes">Enabled</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="parameter_heading">
<property name="label" translatable="yes">Parameter Type</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="state_heading">
<property name="label" translatable="yes">State</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="changes_heading">
<property name="label" translatable="yes"></property>
<property name="xalign">0</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="expand">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkTreeView">
<property name="model">model</property>
<property name="enable-search">0</property>
<property name="activate-on-single-click">1</property>
<signal name="row-activated" handler="row_activated"/>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Prefix</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Name</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Enabled</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Parameter Type</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">State</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">4</attribute>
</attributes>
</child>
</object>
</child>
<object class="GtkListBox" id="list">
<style>
<class name="list"/>
</style>
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</template>
<object class="GtkSizeGroup" id="prefix">
<property name="mode">horizontal</property>
<widgets>
<widget name="prefix_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="name">
<property name="mode">horizontal</property>
<widgets>
<widget name="name_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="enabled">
<property name="mode">horizontal</property>
<widgets>
<widget name="enabled_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="parameter">
<property name="mode">horizontal</property>
<widgets>
<widget name="parameter_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="state">
<property name="mode">horizontal</property>
<widgets>
<widget name="state_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="activate">
<property name="mode">horizontal</property>
</object>
</interface>
+35
View File
@@ -0,0 +1,35 @@
/* some style for the inspector */
.header {
background: lightgray;
border: 1px solid gray;
}
.header>* {
padding: 2px;
font-weight: bold;
}
.header sort_indicator {
min-width: 16px;
}
.header>*:not(:last-child) {
border-right: 1px solid gray;
}
.list .cell {
font-size: smaller;
padding: 0 2px;
min-height: 24px;
}
.list .cell entry,
.list .cell spinbutton,
.list .cell button,
.list .cell combobox
{
min-height: 24px;
min-width: 0;
padding: 0 4px;
}
+1 -1
View File
@@ -180,7 +180,7 @@ show_object (GtkInspectorMiscInfo *sl,
const gchar *tab)
{
g_object_set_data_full (G_OBJECT (sl->priv->object_tree), "next-tab", g_strdup (tab), g_free);
gtk_inspector_object_tree_select_object (sl->priv->object_tree, object);
gtk_inspector_object_tree_activate_object (sl->priv->object_tree, object);
}
static void
+7 -6
View File
@@ -43,6 +43,7 @@
#include "gtksizegroup.h"
#include "gtkroot.h"
#include "gtkgesturemultipress.h"
#include "gtkstylecontext.h"
enum
{
@@ -105,17 +106,13 @@ apply_sort (GtkInspectorPropList *pl,
if (column == COLUMN_NAME)
{
gtk_widget_hide (pl->priv->origin_sort_indicator);
gtk_widget_show (pl->priv->name_sort_indicator);
gtk_image_clear (GTK_IMAGE (pl->priv->origin_sort_indicator));
gtk_image_set_from_icon_name (GTK_IMAGE (pl->priv->name_sort_indicator),
icon_name);
}
else
{
gtk_widget_show (pl->priv->origin_sort_indicator);
gtk_widget_hide (pl->priv->name_sort_indicator);
gtk_image_clear (GTK_IMAGE (pl->priv->name_sort_indicator));
gtk_image_set_from_icon_name (GTK_IMAGE (pl->priv->origin_sort_indicator),
icon_name);
}
@@ -540,24 +537,28 @@ gtk_inspector_prop_list_create_row (GtkInspectorPropList *pl,
gtk_container_add (GTK_CONTAINER (row), box);
label = gtk_label_new (prop->name);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_widget_set_sensitive (label, writable);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (pl->priv->names, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (type ? type : "");
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_widget_set_sensitive (label, writable);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (pl->priv->types, label);
gtk_container_add (GTK_CONTAINER (box), label);
label = gtk_label_new (g_type_name (prop->owner_type));
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
gtk_widget_set_sensitive (label, writable);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_size_group_add_widget (pl->priv->origins, label);
gtk_container_add (GTK_CONTAINER (box), label);
widget = gtk_inspector_prop_editor_new (pl->priv->object, prop->name, pl->priv->values);
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "cell");
gtk_container_add (GTK_CONTAINER (box), widget);
g_signal_connect (widget, "show-object", G_CALLBACK (show_object), pl);
+16 -3
View File
@@ -15,6 +15,7 @@
</style>
<child>
<object class="GtkBox" id="name_heading">
<property name="hexpand">0</property>
<child>
<object class="GtkGestureMultiPress">
<signal name="pressed" handler="sort_changed" swapped="no"/>
@@ -30,6 +31,9 @@
</child>
<child>
<object class="GtkImage" id="name_sort_indicator">
<style>
<class name="sort_indicator"/>
</style>
</object>
</child>
</object>
@@ -42,6 +46,7 @@
</child>
<child>
<object class="GtkBox" id="origin_heading">
<property name="hexpand">0</property>
<child>
<object class="GtkGestureMultiPress">
<signal name="pressed" handler="sort_changed" swapped="no"/>
@@ -57,6 +62,9 @@
</child>
<child>
<object class="GtkImage" id="origin_sort_indicator">
<style>
<class name="sort_indicator"/>
</style>
</object>
</child>
</object>
@@ -65,9 +73,7 @@
<object class="GtkLabel" id="value_heading">
<property name="label">Value</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="hexpand">0</property>
</object>
</child>
</object>
@@ -78,6 +84,9 @@
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListBox" id="list2">
<style>
<class name="list"/>
</style>
<property name="selection-mode">none</property>
</object>
</child>
@@ -87,21 +96,25 @@
</child>
</template>
<object class="GtkSizeGroup" id="names">
<property name="mode">horizontal</property>
<widgets>
<widget name="name_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="types">
<property name="mode">horizontal</property>
<widgets>
<widget name="type_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="origins">
<property name="mode">horizontal</property>
<widgets>
<widget name="origin_heading"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="values">
<property name="mode">horizontal</property>
<widgets>
<widget name="value_heading"/>
</widgets>
+11
View File
@@ -54,6 +54,9 @@
#include "gtkwindowgroup.h"
#include "gtkrevealer.h"
#include "gtklayoutmanager.h"
#include "gtkcssprovider.h"
#include "gtkstylecontext.h"
G_DEFINE_TYPE (GtkInspectorWindow, gtk_inspector_window, GTK_TYPE_WINDOW)
@@ -290,11 +293,19 @@ static void
gtk_inspector_window_realize (GtkWidget *widget)
{
GskRenderer *renderer;
GtkCssProvider *provider;
GTK_WIDGET_CLASS (gtk_inspector_window_parent_class)->realize (widget);
renderer = gtk_root_get_renderer (GTK_ROOT (widget));
gsk_renderer_set_debug_flags (renderer, 0);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gtk/libgtk/inspector/inspector.css");
gtk_style_context_add_provider_for_display (gtk_widget_get_display (widget),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
}
static void
+2
View File
@@ -1083,6 +1083,8 @@ if build_gir
gtk_introspection_sources = [
gtk_public_headers,
gtk_public_sources,
gtk_deprecated_headers,
gtk_deprecated_sources,
a11y_headers,
a11y_sources,
gtktypebuiltins_h,
+259 -75
View File
@@ -141,8 +141,24 @@ typedef enum {
PROP_KIND_OBJECT,
PROP_KIND_PACKING,
PROP_KIND_CELL_PACKING,
PROP_KIND_LAYOUT
} PropKind;
static PropKind
get_prop_kind (Element *element)
{
g_assert (g_str_equal (element->element_name, "property"));
if (g_str_equal (element->parent->element_name, "packing"))
return PROP_KIND_PACKING;
else if (g_str_equal (element->parent->element_name, "layout"))
return PROP_KIND_LAYOUT;
else if (g_str_equal (element->parent->element_name, "cell-packing"))
return PROP_KIND_CELL_PACKING;
else
return PROP_KIND_OBJECT;
}
/* A number of properties unfortunately can't be omitted even
* if they are nominally set to their default value. In many
* cases, this is due to subclasses not overriding the default
@@ -165,6 +181,8 @@ needs_explicit_setting (GParamSpec *pspec,
{ "GtkRadioButton", "draw-indicator", PROP_KIND_OBJECT },
{ "GtkWidget", "hexpand", PROP_KIND_OBJECT },
{ "GtkWidget", "vexpand", PROP_KIND_OBJECT },
{ "GtkGrid", "top-attach", PROP_KIND_LAYOUT },
{ "GtkGrid", "left-attach", PROP_KIND_LAYOUT },
};
gboolean found;
gint k;
@@ -179,6 +197,7 @@ needs_explicit_setting (GParamSpec *pspec,
strcmp (pspec->name, props[k].property) == 0 &&
kind == props[k].kind)
{
g_print ("explicit: %s::%s\n", class_name, pspec->name);
found = TRUE;
break;
}
@@ -210,6 +229,10 @@ keep_for_rewrite (const char *class_name,
{ "GtkGrid", "top-attach", PROP_KIND_PACKING },
{ "GtkGrid", "width", PROP_KIND_PACKING },
{ "GtkGrid", "height", PROP_KIND_PACKING },
{ "GtkStack", "name", PROP_KIND_PACKING },
{ "GtkStack", "title", PROP_KIND_PACKING },
{ "GtkStack", "icon-name", PROP_KIND_PACKING },
{ "GtkStack", "needs-attention", PROP_KIND_PACKING },
};
gboolean found;
gint k;
@@ -225,6 +248,7 @@ keep_for_rewrite (const char *class_name,
strcmp (canonical_name, props[k].property) == 0 &&
kind == props[k].kind)
{
g_print ("keep for rewrite: %s::%s\n", class_name, canonical_name);
found = TRUE;
break;
}
@@ -309,6 +333,18 @@ canonicalize_key (gchar *key)
}
}
static struct {
const char *class;
const char *layout_manager;
} layout_managers[] = {
{ "GtkBox", "GtkBoxLayout" },
{ "GtkGrid", "GtkGridLayout" },
{ "GtkFixed", "GtkFixedLayout" },
{ "GtkFileChooserButton", "GtkBinLayout" },
{ "GtkFileChooserWidget", "GtkBinLayout" },
{ "GtkOverlay", "GtkOverlayLayout" }
};
static GParamSpec *
get_property_pspec (MyParserData *data,
const gchar *class_name,
@@ -336,9 +372,11 @@ get_property_pspec (MyParserData *data,
case PROP_KIND_OBJECT:
pspec = g_object_class_find_property (class, canonical_name);
break;
case PROP_KIND_PACKING:
pspec = NULL;
break;
case PROP_KIND_CELL_PACKING:
{
GObjectClass *cell_class;
@@ -349,6 +387,40 @@ get_property_pspec (MyParserData *data,
g_type_class_unref (cell_class);
}
break;
case PROP_KIND_LAYOUT:
{
int i;
const char *layout_manager = NULL;
pspec = NULL;
for (i = 0; i < G_N_ELEMENTS (layout_managers); i++)
{
if (g_str_equal (layout_managers[i].class, class_name))
{
layout_manager = layout_managers[i].layout_manager;
break;
}
}
if (layout_manager)
{
GtkLayoutManagerClass *layout_manager_class;
layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (g_type_class_ref (g_type_from_name (layout_manager)));
if (layout_manager_class->layout_child_type != G_TYPE_INVALID)
{
GObjectClass *layout_child_class;
layout_child_class = g_type_class_ref (layout_manager_class->layout_child_type);
pspec = g_object_class_find_property (layout_child_class, canonical_name);
g_type_class_unref (layout_child_class);
}
g_type_class_unref (layout_manager_class);
}
}
break;
default:
g_assert_not_reached ();
}
@@ -358,8 +430,11 @@ get_property_pspec (MyParserData *data,
return pspec;
}
static const char *get_class_name (Element *element);
static gboolean
value_is_default (MyParserData *data,
value_is_default (Element *element,
MyParserData *data,
GParamSpec *pspec,
const gchar *value_string)
{
@@ -377,7 +452,26 @@ value_is_default (MyParserData *data,
ret = FALSE;
}
else
ret = g_param_value_defaults (pspec, &value);
{
/* GtkWidget::visible has a 'smart' default */
if (pspec->owner_type == GTK_TYPE_WIDGET &&
g_str_equal (pspec->name, "visible"))
{
const char *class_name = get_class_name (element);
GType type = g_type_from_name (class_name);
gboolean default_value;
if (g_type_is_a (type, GTK_TYPE_ROOT) ||
g_type_is_a (type, GTK_TYPE_POPOVER))
default_value = FALSE;
else
default_value = TRUE;
ret = g_value_get_boolean (&value) == default_value;
}
else
ret = g_param_value_defaults (pspec, &value);
}
g_value_reset (&value);
@@ -470,11 +564,7 @@ property_is_boolean (Element *element,
int i;
PropKind kind;
if (g_str_equal (element->parent->element_name, "packing"))
kind = PROP_KIND_PACKING;
else
kind = PROP_KIND_OBJECT;
kind = get_prop_kind (element);
class_name = get_class_name (element);
property_name = "";
@@ -504,13 +594,7 @@ property_can_be_omitted (Element *element,
GParamSpec *pspec;
PropKind kind;
if (g_str_equal (element->parent->element_name, "packing"))
kind = PROP_KIND_PACKING;
else if (g_str_equal (element->parent->element_name, "cell-packing"))
kind = PROP_KIND_CELL_PACKING;
else
kind = PROP_KIND_OBJECT;
kind = get_prop_kind (element);
class_name = get_class_name (element);
property_name = "";
value_string = element->data;
@@ -528,7 +612,7 @@ property_can_be_omitted (Element *element,
property_name = (const gchar *)element->attribute_values[i];
}
if (data->convert3to4 &&
if (data->convert3to4 &&
keep_for_rewrite (class_name, property_name, kind))
return FALSE; /* keep, will be rewritten */
@@ -545,9 +629,10 @@ property_can_be_omitted (Element *element,
const char *kind_str[] = {
"",
"Packing ",
"Cell "
"Cell ",
"Layout "
};
g_printerr (_("%s: %sproperty %s::%s not found\n"),
data->input_filename, kind_str[kind], class_name, property_name);
return FALSE;
@@ -556,7 +641,7 @@ property_can_be_omitted (Element *element,
if (needs_explicit_setting (pspec, kind))
return FALSE;
return value_is_default (data, pspec, value_string);
return value_is_default (element, data, pspec, value_string);
}
static gboolean
@@ -587,10 +672,7 @@ property_has_been_removed (Element *element,
gint i, k;
PropKind kind;
if (g_str_equal (element->parent->element_name, "packing"))
kind = PROP_KIND_PACKING;
else
kind = PROP_KIND_OBJECT;
kind = get_prop_kind (element);
class_name = get_class_name (element);
property_name = "";
@@ -1246,6 +1328,7 @@ rewrite_grid_layout (Element *element,
}
}
/* returns TRUE to remove the element from the parent */
static gboolean
simplify_element (Element *element,
MyParserData *data)
@@ -1282,58 +1365,6 @@ simplify_element (Element *element,
property_can_be_omitted (element, data))
return TRUE;
if (data->convert3to4)
{
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkStack"))
rewrite_stack (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkAssistant"))
rewrite_assistant (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkNotebook"))
rewrite_notebook (element, data);
if (g_str_equal (element->element_name, "object") &&
(g_str_equal (get_class_name (element), "GtkActionBar") ||
g_str_equal (get_class_name (element), "GtkHeaderBar")))
rewrite_pack_type (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkPopoverMenu"))
rewrite_child_prop_to_prop (element, data, "submenu", "name");
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkToolbar"))
rewrite_child_prop_to_prop (element, data, "expand", "expand-item");
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkToolbar"))
rewrite_child_prop_to_prop (element, data, "homogeneous", "homogeneous");
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkPaned"))
rewrite_paned (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkOverlay"))
rewrite_layout_props (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkGrid"))
rewrite_grid_layout (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkFixed"))
rewrite_layout_props (element, data);
if (g_str_equal (element->element_name, "property") &&
property_has_been_removed (element, data))
return TRUE;
}
return FALSE;
}
@@ -1343,6 +1374,154 @@ simplify_tree (MyParserData *data)
simplify_element (data->root, data);
}
static gboolean
rewrite_element (Element *element,
MyParserData *data)
{
GList *l;
l = element->children;
while (l)
{
GList *next = l->next;
Element *child = l->data;
if (rewrite_element (child, data))
{
element->children = g_list_remove (element->children, child);
free_element (child);
}
l = next;
}
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkStack"))
rewrite_stack (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkAssistant"))
rewrite_assistant (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkNotebook"))
rewrite_notebook (element, data);
if (g_str_equal (element->element_name, "object") &&
(g_str_equal (get_class_name (element), "GtkActionBar") ||
g_str_equal (get_class_name (element), "GtkHeaderBar")))
rewrite_pack_type (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkPopoverMenu"))
rewrite_child_prop_to_prop (element, data, "submenu", "name");
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkToolbar"))
rewrite_child_prop_to_prop (element, data, "expand", "expand-item");
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkToolbar"))
rewrite_child_prop_to_prop (element, data, "homogeneous", "homogeneous");
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkPaned"))
rewrite_paned (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkOverlay"))
rewrite_layout_props (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkGrid"))
rewrite_grid_layout (element, data);
if (g_str_equal (element->element_name, "object") &&
g_str_equal (get_class_name (element), "GtkFixed"))
rewrite_layout_props (element, data);
if (g_str_equal (element->element_name, "property") &&
property_has_been_removed (element, data))
return TRUE;
return FALSE;
}
static void
rewrite_tree (MyParserData *data)
{
rewrite_element (data->root, data);
}
/* For properties which have changed their default
* value between 3 and 4, we make sure that their
* old default value is present in the tree before
* simplifying it.
*
* So far, this is just GtkWidget::visible,
* changing its default from 0 to 1.
*/
static void
add_old_default_properties (Element *element,
MyParserData *data)
{
const char *class_name;
GType type;
if (!g_str_equal (element->element_name, "object"))
return;
class_name = get_class_name (element);
type = g_type_from_name (class_name);
if (g_type_is_a (type, GTK_TYPE_WIDGET))
{
GList *l;
gboolean has_visible = FALSE;
for (l = element->children; l; l = l->next)
{
Element *prop = l->data;
const char *name = get_attribute_value (prop, "name");
if (g_str_equal (prop->element_name, "property") &&
g_str_equal (name, "visible"))
has_visible = TRUE;
}
if (!has_visible)
{
Element *new_prop = g_new0 (Element, 1);
new_prop->parent = element;
new_prop->element_name = g_strdup ("property");
new_prop->attribute_names = g_new0 (char *, 2);
new_prop->attribute_names[0] = g_strdup ("name");
new_prop->attribute_values = g_new0 (char *, 2);
new_prop->attribute_values[0] = g_strdup ("visible");
new_prop->data = g_strdup ("0");
element->children = g_list_prepend (element->children, new_prop);
}
}
}
static void
enhance_element (Element *element,
MyParserData *data)
{
GList *l;
add_old_default_properties (element, data);
for (l = element->children; l; l = l->next)
{
Element *child = l->data;
enhance_element (child, data);
}
}
static void
enhance_tree (MyParserData *data)
{
enhance_element (data->root, data);
}
static void
dump_element (Element *element,
FILE *output,
@@ -1384,7 +1563,7 @@ dump_element (Element *element,
g_fprintf (output, "</%s>\n", element->element_name);
}
else
g_fprintf (output, "/>\n");
g_fprintf (output, "/>\n");
}
static void
@@ -1444,6 +1623,11 @@ simplify_file (const char *filename,
data.builder = gtk_builder_new ();
if (data.convert3to4)
{
enhance_tree (&data);
rewrite_tree (&data);
}
simplify_tree (&data);
dump_tree (&data);
+1
View File
@@ -10,6 +10,7 @@
<child>
<object class="GtkSearchEntry" id="search_entry">
<signal name="search-changed" handler="search_changed"/>
<signal name="stop-search" handler="stop_search"/>
</object>
</child>
<child>
+1 -1
View File
@@ -1,5 +1,5 @@
project('gtk', 'c',
version: '3.94.0',
version: '3.96.0',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
+21 -36
View File
@@ -81,28 +81,6 @@ static GtkCupsRequestStateFunc get_states[] = {
_get_read_data
};
#ifndef HAVE_CUPS_API_1_6
#define ippSetOperation(ipp_request, ipp_op_id) ipp_request->request.op.operation_id = ipp_op_id
#define ippSetRequestId(ipp_request, ipp_rq_id) ipp_request->request.op.request_id = ipp_rq_id
#define ippSetState(ipp_request, ipp_state) ipp_request->state = ipp_state
#define ippGetString(attr, index, foo) attr->values[index].string.text
#define ippGetCount(attr) attr->num_values
int
ippSetVersion (ipp_t *ipp,
int major,
int minor)
{
if (!ipp || major < 0 || minor < 0)
return 0;
ipp->request.any.version[0] = major;
ipp->request.any.version[1] = minor;
return 1;
}
#endif
static void
gtk_cups_result_set_error (GtkCupsResult *result,
GtkCupsErrorType error_type,
@@ -168,10 +146,10 @@ gtk_cups_request_new_with_username (http_t *connection,
}
else
{
request->http = NULL;
request->http = httpConnectEncrypt (request->server,
ippPort (),
cupsEncryption ());
request->http = httpConnect2 (request->server, ippPort (),
NULL, AF_UNSPEC,
cupsEncryption (),
1, 30000, NULL);
if (request->http)
httpBlocking (request->http, 0);
@@ -686,10 +664,10 @@ _connect (GtkCupsRequest *request)
if (request->http == NULL)
{
request->http = httpConnectEncrypt (request->server,
ippPort (),
cupsEncryption ());
request->http = httpConnect2 (request->server, ippPort (),
NULL, AF_UNSPEC,
cupsEncryption (),
1, 30000, NULL);
if (request->http == NULL)
request->attempts++;
@@ -741,7 +719,11 @@ _post_send (GtkCupsRequest *request)
if (httpPost (request->http, request->resource))
{
if (httpReconnect (request->http))
int res;
res = httpReconnect2 (request->http, 30000, NULL);
if (res)
{
request->state = GTK_CUPS_POST_DONE;
request->poll_state = GTK_CUPS_HTTP_IDLE;
@@ -1039,7 +1021,7 @@ _post_check (GtkCupsRequest *request)
}
if (auth_result ||
httpReconnect (request->http))
httpReconnect2 (request->http, 30000, NULL))
{
/* if the password has been used, reset password_state
* so that we ask for a new one next time around
@@ -1098,7 +1080,7 @@ _post_check (GtkCupsRequest *request)
request->state = GTK_CUPS_POST_CONNECT;
/* Reconnect... */
httpReconnect (request->http);
httpReconnect2 (request->http, 30000, NULL);
/* Upgrade with encryption... */
httpEncryption (request->http, HTTP_ENCRYPT_REQUIRED);
@@ -1226,7 +1208,10 @@ _get_send (GtkCupsRequest *request)
if (httpGet (request->http, request->resource))
{
if (httpReconnect (request->http))
int reconnect;
reconnect = httpReconnect2 (request->http, 30000, NULL);
if (reconnect)
{
request->state = GTK_CUPS_GET_DONE;
request->poll_state = GTK_CUPS_HTTP_IDLE;
@@ -1335,7 +1320,7 @@ _get_check (GtkCupsRequest *request)
}
if (auth_result ||
httpReconnect (request->http))
httpReconnect2 (request->http, 30000, NULL))
{
/* if the password has been used, reset password_state
* so that we ask for a new one next time around
@@ -1367,7 +1352,7 @@ _get_check (GtkCupsRequest *request)
request->state = GTK_CUPS_GET_CONNECT;
/* Reconnect... */
httpReconnect (request->http);
httpReconnect2 (request->http, 30000, NULL);
/* Upgrade with encryption... */
httpEncryption (request->http, HTTP_ENCRYPT_REQUIRED);
+37 -173
View File
@@ -24,13 +24,12 @@
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
/* Cups 1.6 deprecates ppdFindAttr(), ppdFindCustomOption(),
* ppdFirstCustomParam(), and ppdNextCustomParam() among others. This
* turns off the warning so that it will compile.
*/
#ifdef HAVE_CUPS_API_1_6
# define _PPD_DEPRECATED
#endif
#define _PPD_DEPRECATED
#include <cups/cups.h>
#include <cups/language.h>
@@ -71,7 +70,6 @@ typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass;
#define _CUPS_MAX_ATTEMPTS 10
#define _CUPS_MAX_CHUNK_SIZE 8192
#ifdef HAVE_CUPS_API_1_6
#define AVAHI_IF_UNSPEC -1
#define AVAHI_PROTO_INET 0
#define AVAHI_PROTO_INET6 1
@@ -81,7 +79,6 @@ typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass;
#define AVAHI_SERVER_IFACE "org.freedesktop.Avahi.Server"
#define AVAHI_SERVICE_BROWSER_IFACE "org.freedesktop.Avahi.ServiceBrowser"
#define AVAHI_SERVICE_RESOLVER_IFACE "org.freedesktop.Avahi.ServiceResolver"
#endif
/* define this to see warnings about ignored ppd options */
#undef PRINT_IGNORED_OPTIONS
@@ -143,14 +140,14 @@ struct _GtkPrintBackendCups
#ifdef HAVE_COLORD
CdClient *colord_client;
#endif
#ifdef HAVE_CUPS_API_1_6
GDBusConnection *dbus_connection;
gchar *avahi_default_printer;
guint avahi_service_browser_subscription_id;
guint avahi_service_browser_subscription_ids[2];
gchar *avahi_service_browser_paths[2];
GCancellable *avahi_cancellable;
#endif
char *avahi_default_printer;
guint avahi_service_browser_subscription_id;
guint avahi_service_browser_subscription_ids[2];
char *avahi_service_browser_paths[2];
GCancellable *avahi_cancellable;
gboolean secrets_service_available;
guint secrets_service_watch_id;
GCancellable *secrets_service_cancellable;
@@ -228,9 +225,7 @@ static gboolean is_address_local (const gchar
static gboolean request_auth_info (gpointer data);
static void lookup_auth_info (gpointer data);
#ifdef HAVE_CUPS_API_1_6
static void avahi_request_printer_list (GtkPrintBackendCups *cups_backend);
#endif
static void secrets_service_appeared_cb (GDBusConnection *connection,
const gchar *name,
@@ -272,51 +267,6 @@ g_io_module_query (void)
return g_strdupv (eps);
}
/* CUPS 1.6 Getter/Setter Functions CUPS 1.6 makes private most of the
* IPP structures and enforces access via new getter functions, which
* are unfortunately not available in earlier versions. We define
* below those getter functions as macros for use when building
* against earlier CUPS versions.
*/
#ifndef HAVE_CUPS_API_1_6
#define ippGetOperation(ipp_request) ipp_request->request.op.operation_id
#define ippGet:Integer(attr, index) attr->values[index].integer
#define ippGetBoolean(attr, index) attr->values[index].boolean
#define ippGetString(attr, index, foo) attr->values[index].string.text
#define ippGetValueTag(attr) attr->value_tag
#define ippGetName(attr) attr->name
#define ippGetCount(attr) attr->num_values
#define ippGetGroupTag(attr) attr->group_tag
#define ippGetCollection(attr, index) attr->values[index].collection
static int
ippGetRange (ipp_attribute_t *attr,
int element,
int *upper)
{
*upper = attr->values[element].range.upper;
return (attr->values[element].range.lower);
}
static ipp_attribute_t *
ippFirstAttribute (ipp_t *ipp)
{
if (!ipp)
return (NULL);
return (ipp->current = ipp->attrs);
}
static ipp_attribute_t *
ippNextAttribute (ipp_t *ipp)
{
if (!ipp || !ipp->current)
return (NULL);
return (ipp->current = ipp->current->next);
}
#endif
/*
* GtkPrintBackendCups
*/
@@ -737,10 +687,13 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
cups_printer = GTK_PRINTER_CUPS (gtk_print_job_get_printer (job));
settings = gtk_print_job_get_settings (job);
#ifdef HAVE_CUPS_API_1_6
if (cups_printer->avahi_browsed)
{
http = httpConnect (cups_printer->hostname, cups_printer->port);
http = httpConnect2 (cups_printer->hostname, cups_printer->port,
NULL, AF_UNSPEC,
HTTP_ENCRYPTION_IF_REQUESTED,
1, 30000,
NULL);
if (http)
{
request = gtk_cups_request_new_with_username (http,
@@ -779,7 +732,6 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
}
}
else
#endif
{
request = gtk_cups_request_new_with_username (NULL,
GTK_CUPS_POST,
@@ -889,9 +841,7 @@ void overwrite_and_free (gpointer data)
static void
gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
{
#ifdef HAVE_CUPS_API_1_6
gint i;
#endif
int i;
backend_cups->list_printers_poll = FALSE;
backend_cups->got_default_printer = FALSE;
@@ -912,7 +862,6 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
backend_cups->colord_client = cd_client_new ();
#endif
#ifdef HAVE_CUPS_API_1_6
backend_cups->dbus_connection = NULL;
backend_cups->avahi_default_printer = NULL;
backend_cups->avahi_service_browser_subscription_id = 0;
@@ -921,7 +870,6 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
backend_cups->avahi_service_browser_paths[i] = NULL;
backend_cups->avahi_service_browser_subscription_ids[i] = 0;
}
#endif
cups_get_local_default_printer (backend_cups);
@@ -957,11 +905,9 @@ gtk_print_backend_cups_finalize (GObject *object)
g_object_unref (backend_cups->colord_client);
#endif
#ifdef HAVE_CUPS_API_1_6
g_clear_object (&backend_cups->avahi_cancellable);
g_clear_pointer (&backend_cups->avahi_default_printer, g_free);
g_clear_object (&backend_cups->dbus_connection);
#endif
g_clear_object (&backend_cups->secrets_service_cancellable);
if (backend_cups->secrets_service_watch_id != 0)
@@ -976,9 +922,7 @@ static void
gtk_print_backend_cups_dispose (GObject *object)
{
GtkPrintBackendCups *backend_cups;
#ifdef HAVE_CUPS_API_1_6
gint i;
#endif
int i;
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
@@ -994,7 +938,6 @@ gtk_print_backend_cups_dispose (GObject *object)
g_source_remove (backend_cups->default_printer_poll);
backend_cups->default_printer_poll = 0;
#ifdef HAVE_CUPS_API_1_6
g_cancellable_cancel (backend_cups->avahi_cancellable);
for (i = 0; i < 2; i++)
@@ -1030,7 +973,6 @@ gtk_print_backend_cups_dispose (GObject *object)
backend_cups->avahi_service_browser_subscription_id);
backend_cups->avahi_service_browser_subscription_id = 0;
}
#endif
backend_parent_class->dispose (object);
}
@@ -1784,18 +1726,8 @@ cups_request_job_info_cb (GtkPrintBackendCups *print_backend,
state = 0;
#ifdef HAVE_CUPS_API_1_6
attr = ippFindAttribute (response, "job-state", IPP_TAG_ENUM);
state = ippGetInteger (attr, 0);
#else
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
if (!attr->name)
continue;
_CUPS_MAP_ATTR_INT (attr, state, "job-state");
}
#endif
done = FALSE;
switch (state)
@@ -2031,9 +1963,7 @@ typedef struct
gboolean default_printer;
gboolean got_printer_type;
gboolean remote_printer;
#ifdef HAVE_CUPS_API_1_6
gboolean avahi_printer;
#endif
gchar **auth_info_required;
gint default_number_up;
guchar ipp_version_major;
@@ -2464,13 +2394,11 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
char *cups_server; /* CUPS server */
#ifdef HAVE_COLORD
#ifdef HAVE_CUPS_API_1_6
if (info->avahi_printer)
cups_printer = gtk_printer_cups_new (info->printer_name,
backend,
NULL);
else
#endif
cups_printer = gtk_printer_cups_new (info->printer_name,
backend,
cups_backend->colord_client);
@@ -2546,9 +2474,7 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0)
gtk_printer_set_is_default (printer, TRUE);
#ifdef HAVE_CUPS_API_1_6
cups_printer->avahi_browsed = info->avahi_printer;
#endif
gtk_print_backend_add_printer (backend, printer);
return printer;
@@ -2727,7 +2653,6 @@ set_default_printer (GtkPrintBackendCups *cups_backend,
}
}
#ifdef HAVE_CUPS_API_1_6
static void
cups_request_printer_info_cb (GtkPrintBackendCups *cups_backend,
GtkCupsResult *result,
@@ -2850,7 +2775,7 @@ cups_request_printer_info (const gchar *printer_uri,
GtkCupsRequest *request;
http_t *http;
http = httpConnect (host, port);
http = httpConnect2 (host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
if (http)
{
request = gtk_cups_request_new_with_username (http,
@@ -2918,9 +2843,7 @@ find_printer_by_uuid (GtkPrintBackendCups *backend,
printer_uuid += 5;
printer_uuid = g_strndup (printer_uuid, 36);
#if GLIB_CHECK_VERSION(2, 52, 0)
if (g_uuid_string_is_valid (printer_uuid))
#endif
{
if (g_strcmp0 (printer_uuid, UUID) == 0)
{
@@ -3493,7 +3416,6 @@ avahi_request_printer_list (GtkPrintBackendCups *cups_backend)
cups_backend->avahi_cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SYSTEM, cups_backend->avahi_cancellable, avahi_create_browsers, cups_backend);
}
#endif
static void
cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
@@ -3542,7 +3464,6 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
removed_printer_checklist = gtk_print_backend_get_printer_list (backend);
response = gtk_cups_result_get_response (result);
#ifdef HAVE_CUPS_API_1_6
for (attr = ippFirstAttribute (response); attr != NULL;
attr = ippNextAttribute (response))
{
@@ -3558,42 +3479,21 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
if (attr == NULL)
break;
while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
{
cups_printer_handle_attribute (cups_backend, attr, info);
attr = ippNextAttribute (response);
}
#else
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
GtkPrinter *printer;
gboolean status_changed = FALSE;
GList *node;
PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
info->default_number_up = 1;
/* Skip leading attributes until we hit a printer...
*/
while (attr != NULL && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
attr = attr->next;
if (attr == NULL)
break;
while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
{
cups_printer_handle_attribute (cups_backend, attr, info);
attr = attr->next;
}
#endif
{
cups_printer_handle_attribute (cups_backend, attr, info);
attr = ippNextAttribute (response);
}
if (info->printer_name == NULL ||
(info->printer_uri == NULL && info->member_uris == NULL))
{
if (attr == NULL)
break;
else
continue;
}
{
if (attr == NULL)
break;
else
continue;
}
if (info->got_printer_type)
{
@@ -3691,9 +3591,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
{
for (iter = removed_printer_checklist; iter; iter = iter->next)
{
#ifdef HAVE_CUPS_API_1_6
if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
#endif
{
mark_printer_inactive (GTK_PRINTER (iter->data), backend);
list_has_changed = TRUE;
@@ -3715,12 +3613,8 @@ done:
g_free (remote_default_printer);
}
#ifdef HAVE_CUPS_API_1_6
if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL)
{
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
#endif
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
static void
@@ -3809,9 +3703,7 @@ cups_get_printer_list (GtkPrintBackend *backend)
g_source_set_name_by_id (cups_backend->list_printers_poll, "[gtk] cups_request_printer_list");
}
#ifdef HAVE_CUPS_API_1_6
avahi_request_printer_list (cups_backend);
#endif
}
}
@@ -3847,26 +3739,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
GTK_PRINTER_CUPS (printer)->reading_ppd = FALSE;
print_backend->reading_ppds--;
#ifndef HAVE_CUPS_API_1_6
if (gtk_cups_result_is_error (result))
{
gboolean success = FALSE;
/* If we get a 404 then it is just a raw printer without a ppd
and not an error. */
if ((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) &&
(gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND))
{
gtk_printer_set_has_details (printer, TRUE);
success = TRUE;
}
g_signal_emit_by_name (printer, "details-acquired", success);
return;
}
#endif
if (!gtk_cups_result_is_error (result))
{
/* let ppdOpenFd take over the ownership of the open file */
@@ -3876,7 +3748,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
ppdMarkDefaults (data->printer->ppd_file);
}
#ifdef HAVE_CUPS_API_1_6
fstat (g_io_channel_unix_get_fd (data->ppd_io), &data_info);
/*
* Standalone Avahi printers and raw printers don't have PPD files or have
@@ -3896,7 +3767,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
return;
}
#endif
gtk_printer_set_has_details (printer, TRUE);
g_signal_emit_by_name (printer, "details-acquired", TRUE);
@@ -3922,11 +3792,7 @@ cups_request_ppd (GtkPrinter *printer)
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
if (cups_printer->remote
#ifdef HAVE_CUPS_API_1_6
&& !cups_printer->avahi_browsed
#endif
)
if (cups_printer->remote && !cups_printer->avahi_browsed)
{
GtkCupsConnectionState state;
@@ -3960,9 +3826,10 @@ cups_request_ppd (GtkPrinter *printer)
}
}
http = httpConnectEncrypt (cups_printer->hostname,
cups_printer->port,
cupsEncryption ());
http = httpConnect2 (cups_printer->hostname, cups_printer->port,
NULL, AF_UNSPEC,
cupsEncryption (),
1, 30000, NULL);
data = g_new0 (GetPPDData, 1);
@@ -4266,13 +4133,14 @@ cups_request_default_printer_cb (GtkPrintBackendCups *print_backend,
response = gtk_cups_result_get_response (result);
if ((attr = ippFindAttribute (response, "printer-name", IPP_TAG_NAME)) != NULL)
print_backend->default_printer = g_strdup (ippGetString (attr, 0, NULL));
print_backend->default_printer = g_strdup (ippGetString (attr, 0, NULL));
print_backend->got_default_printer = TRUE;
if (print_backend->default_printer != NULL)
{
printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (print_backend), print_backend->default_printer);
printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (print_backend),
print_backend->default_printer);
if (printer != NULL)
{
gtk_printer_set_is_default (printer, TRUE);
@@ -4325,11 +4193,7 @@ cups_printer_request_details (GtkPrinter *printer)
if (!cups_printer->reading_ppd &&
gtk_printer_cups_get_ppd (cups_printer) == NULL)
{
if (cups_printer->remote
#ifdef HAVE_CUPS_API_1_6
&& !cups_printer->avahi_browsed
#endif
)
if (cups_printer->remote && !cups_printer->avahi_browsed)
{
if (cups_printer->get_remote_ppd_poll == 0)
{
+4 -4
View File
@@ -115,12 +115,10 @@ gtk_printer_cups_init (GtkPrinterCups *printer)
printer->remote_cups_connection_test = NULL;
printer->auth_info_required = NULL;
printer->default_number_up = 1;
#ifdef HAVE_CUPS_API_1_6
printer->avahi_browsed = FALSE;
printer->avahi_name = NULL;
printer->avahi_type = NULL;
printer->avahi_domain = NULL;
#endif
printer->ipp_version_major = 1;
printer->ipp_version_minor = 1;
printer->supports_copies = FALSE;
@@ -176,17 +174,19 @@ gtk_printer_cups_finalize (GObject *object)
g_object_unref (printer->colord_profile);
#endif
#ifdef HAVE_CUPS_API_1_6
g_free (printer->avahi_name);
g_free (printer->avahi_type);
g_free (printer->avahi_domain);
#endif
g_strfreev (printer->covers);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (printer->ppd_file)
ppdClose (printer->ppd_file);
G_GNUC_END_IGNORE_DEPRECATIONS
g_free (printer->media_default);
g_list_free_full (printer->media_supported, g_free);
g_list_free_full (printer->media_size_supported, g_free);
+6 -5
View File
@@ -81,6 +81,7 @@ struct _GtkPrinterCups
guint get_remote_ppd_poll;
gint get_remote_ppd_attempts;
GtkCupsConnectionTest *remote_cups_connection_test;
#ifdef HAVE_COLORD
CdClient *colord_client;
CdDevice *colord_device;
@@ -89,12 +90,12 @@ struct _GtkPrinterCups
gchar *colord_title;
gchar *colord_qualifier;
#endif
#ifdef HAVE_CUPS_API_1_6
gboolean avahi_browsed;
gchar *avahi_name;
gchar *avahi_type;
gchar *avahi_domain;
#endif
char *avahi_name;
char *avahi_type;
char *avahi_domain;
guchar ipp_version_major;
guchar ipp_version_minor;
gboolean supports_copies;
+2 -6
View File
@@ -26,11 +26,7 @@ if enable_cups
cups_major_version = cc.compute_int('CUPS_VERSION_MAJOR', prefix : '#include <cups/cups.h>')
cups_minor_version = cc.compute_int('CUPS_VERSION_MINOR', prefix : '#include <cups/cups.h>')
message('Found CUPS version: @0@.@1@'.format(cups_major_version, cups_minor_version))
if cups_major_version > 1 or cups_minor_version >= 2
if cups_major_version > 1 or cups_minor_version >= 6
cdata.set('HAVE_CUPS_API_1_6', 1)
endif
if cups_major_version >= 2
if cc.compiles('#include <cups/http.h> \n http_t http; char *s = http.authstring;')
cdata.set('HAVE_HTTP_AUTHSTRING', 1,
description :'Define if cups http_t authstring field is accessible')
@@ -42,7 +38,7 @@ if enable_cups
print_backends += ['cups']
else
error('Need CUPS version >= 1.2')
error('Need CUPS version >= 2.0')
endif
else
error('Cannot find CUPS headers in default prefix.')

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