Compare commits

..

119 Commits

Author SHA1 Message Date
Matthias Clasen
e16c836f60 curve2: Show osculating circles 2020-12-27 00:26:44 -05:00
Matthias Clasen
55bfc167e3 Add gsk_path_measure_get_curvature 2020-12-27 00:26:44 -05:00
Matthias Clasen
5516ec2bf0 Add an interactive path test
This one is for interactive exploring of svg paths.

You can enter an SVG path in the entry and hit Enter
to see how GSK renders it. If you click the button
in the headerbar, you can see what GTK thinks the
closest point, tangent and distance are wrt. to the
mouse position, and the bounding box of the path.

There's also stroke parameters to play with.
2020-12-27 00:26:44 -05:00
Matthias Clasen
7e7d1987a3 xxx: Make gsk_stroke_to_cairo public
It comes in handy, and does no harm.
2020-12-27 00:26:44 -05:00
Matthias Clasen
304c3055ad Add a path editor demo
Add a simple demo for editing a poly-Bezier curve.
2020-12-27 00:26:44 -05:00
Matthias Clasen
226f556cf8 Implement gsk_path_offset
Implement offsetting of paths by reusing the
infrastructure of the stroker.
2020-12-27 00:10:08 -05:00
Matthias Clasen
be7fead1fb Add gsk_path_offset
Add a function that takes a path, and offsets it
by some distance, applying line-join parameters
as needed.

This commit just adds the api, the implementation
will be in the following commit.
2020-12-27 00:10:08 -05:00
Matthias Clasen
b871c2a3cb stroker: Cleanups
Move some utility functions around.
2020-12-26 23:57:41 -05:00
Matthias Clasen
7c67a9c76a stroker: Implement arcs
Implement arced joins as specified in SVG2.
2020-12-26 23:57:41 -05:00
Matthias Clasen
427e185bcf Add GSK_LINE_JOIN_ARCS
Implementation will follow.
2020-12-26 23:57:41 -05:00
Matthias Clasen
30552e9988 xxx: assorted fixes for special contours
Fix winding numbers, and strokes wrt to direction.
2020-12-26 23:57:41 -05:00
Matthias Clasen
08d8d6c029 Add another stroker test
Check that the outlines of random paths look as
expected. We currently have to exclude paths where
points get too close to each other.
2020-12-26 23:57:41 -05:00
Matthias Clasen
61a84956d4 Add basic tests for strokes
Add tests to check that any point on a path is
always at most half the line-width away from the
stroke path with that line-width.
2020-12-26 23:57:41 -05:00
Matthias Clasen
e44780923a Implement stroking
Implement gsk_contour_default_add_stroke, which takes a contour
and stroke parameters, and adds contours to a path builder for
the outline that woul be produced by stroking the path with these
parameters.

The current implementation does not try to handle short segments
in the vicinity of sharp joins in any special way, so there can
be some artifacts in that situation.
2020-12-26 23:57:41 -05:00
Matthias Clasen
dd1a2e0396 Special-case circles for strokes
The outline of a circle is just two circles.
2020-12-26 23:57:41 -05:00
Matthias Clasen
0100c33b71 Special-case rects for strokes
In many cases, the outline of a rectangle is just
two rectangles.
2020-12-26 23:57:41 -05:00
Matthias Clasen
8b8197a662 Add gsk_path_stroke
Add the plumbing that will let us do special-case stroking
for rectangles, circles and other special contours. There
is no implementation yet.
2020-12-26 23:57:41 -05:00
Matthias Clasen
e293f10fa1 Add gsk_curve_get_curvature
This will be used in the stroker.
2020-12-26 23:56:26 -05:00
Matthias Clasen
3a4c3c3d8c Add gsk_curve_get_normal
Its easy but thats no reason not to have this api.
2020-12-26 23:56:26 -05:00
Matthias Clasen
944735071e Add a test for gsk_curve_offset
The stroker relies on offsetting.
This only tests a few very simple cases.
2020-12-26 23:56:26 -05:00
Matthias Clasen
91356de96a Add a test for gsk_curve_reverse
The stroker relies on this working.
2020-12-26 23:56:26 -05:00
Matthias Clasen
3f29c50800 Add a test for tangents of degenerate curves
The stroker relies on these to work.
2020-12-26 23:56:26 -05:00
Matthias Clasen
59b1f9e7b1 curve: Handle degenerate cases
Nothing prevents control points from being identical,
and if that happens, some of our constructions involving
tangents and normals break down. Handle these cases in
get_{start,end}_tangent and offset, for the case of
cubics.
2020-12-26 23:56:26 -05:00
Matthias Clasen
dd3cf83a35 Add gsk_curve_reverse
This will be used in stroking.
2020-12-26 23:56:26 -05:00
Matthias Clasen
7f8a9e5543 Add gsk_curve_offset
This method creates an offset curve from an existing
curve by just moving the control points laterally.

This will be used in stroking.
2020-12-26 23:56:26 -05:00
Matthias Clasen
8523c6cb2d Add conic decomposition tests
We don't have good error bounds here, unfortunately.
2020-12-26 23:56:26 -05:00
Matthias Clasen
49b25424c5 path: support conic->curve in foreach 2020-12-26 23:56:26 -05:00
Matthias Clasen
db2046cb67 Add gsk_curve_decompose_curve
This is mainly useful for decomposing a conic into
cubics. The criterion here for terminating the
subdivision is very improvised.
2020-12-26 23:56:26 -05:00
Matthias Clasen
61264165ff Add a performance test for curve eval
All curve types are equally fast here.
2020-12-26 23:56:26 -05:00
Matthias Clasen
7b3d283fc0 Add a performance test for curve intersection
This shows how much more expensive curve
intersections are.
2020-12-26 23:56:26 -05:00
Matthias Clasen
44ffed0283 Add curve split tests 2020-12-26 23:56:26 -05:00
Matthias Clasen
e91ec1f26f Add another intersection testcase
This tests horizontal line/conic intersection,
which failed before the fix in the previous commit.
2020-12-26 23:56:26 -05:00
Matthias Clasen
eace55daa6 xxx: work around bounding box problems
graphene_rect_intersect returns FALSE when you
intersect the bounding boxes of axis-aligned
lines, so we never find intersections with those.

Make things better by making the bounding boxes worse.
2020-12-26 23:56:26 -05:00
Matthias Clasen
097e58558b Add curve intersection tests
These tests check that gsk_curve_intersect finds
the intersections we want.
2020-12-26 23:56:26 -05:00
Matthias Clasen
f0acb0f073 Add gsk_curve_intersect
Add a way to find the intersections of two curves.
This will be used in stroking.
2020-12-26 23:56:25 -05:00
Matthias Clasen
b779ba19ca Add gsk_curve_get_bounds
Add getters for bounding boxes of curves.
2020-12-26 23:56:25 -05:00
Matthias Clasen
aa0f1ce956 Only test conic weights between 1/20 and 20
The rest just give us no end of numeric trouble.
2020-12-26 23:56:25 -05:00
Benjamin Otte
e9d01c1a63 Ottie: Add ottie-editor 2020-12-27 01:12:11 +01:00
Benjamin Otte
e235392894 ottie: Add a snapshot testsuite test
The test takes a lottie file and a timestamp in seconds and produces a
rendernode at that timestamp.

It then serializes that node and compares it via diff(1) with a file
containing the expected output.

This is a lot stricter than it needs to be (because different node files
can generate the same output and updates to the rendering pipeline can
break everything) but I chose this method on purpose because it does a
good job at guarding against accidental changes in other parts of the
code.

It's also better than comparing image output because it avoids
antialiasing artifacts when using curves and things like that.
2020-12-27 01:12:11 +01:00
Benjamin Otte
73904f3034 ottie: Add a command-line tool
Supports:

 * Taking a screenie:
   ottie image file.lottie image.png

 * Recording a rendernode:
   ottie node file.lottie render.node

 * Encoding an image:
   ottie video file.lottie video.webm
2020-12-27 01:12:11 +01:00
Benjamin Otte
c2ed71af7a Ottie: Add 2020-12-27 01:12:11 +01:00
Benjamin Otte
aa2f6345c8 path: Add gsk_path_builder_add_ellipse() 2020-12-27 00:31:18 +01:00
Benjamin Otte
cef1bc9098 path: Change semantics of gtk_path_builder_add_segment()
Allow start >= end to mean that the path continues at the beginning
after reaching the end until it reaches the point at @end.
2020-12-27 00:31:18 +01:00
Benjamin Otte
828ccc51d9 path: Add gsk_path_measure_is_closed () 2020-12-27 00:31:18 +01:00
Benjamin Otte
8397d10c20 path: Add gsk_path_measure_restrict_to_contour() 2020-12-27 00:31:18 +01:00
Matthias Clasen
78d06e58d0 Add gsk_path_measure_get_{path,tolerance}
These are just nice apis to have and avoid having to carry
these around as extra arguments in many places.

This was showing up as inconvenience in writing tests
for the measure apis.
2020-12-27 00:31:18 +01:00
Benjamin Otte
a5e13cc96b xxx path)_fill 2020-12-27 00:31:18 +01:00
Matthias Clasen
776dc54c8a Add gsk_path_get_stroke_bounds
A relatively cheap way to get bounds for the area
that would be affected by stroking a path.
2020-12-27 00:31:18 +01:00
Benjamin Otte
ee6879fba8 testsuite: Add tests for the dasher 2020-12-27 00:31:18 +01:00
Benjamin Otte
14f9395476 path: Add a foreach function that dashes a path 2020-12-27 00:31:18 +01:00
Benjamin Otte
1349cf2454 path: Deal with non-uniformness of progress parameter
The progress is non-uniform, so simple translation of progress doesn't work.
So check if larger and smaller values inch closer towards minimal distance.
2020-12-27 00:31:18 +01:00
Benjamin Otte
d47ebd388c path: Always decompose conics into at least 2 segments
Conics are evil in that their parameter skews towards the center, and if
it's a very flat conic (weight almost equal to 0), then we'd approximate
it with a single segment and not subdivide, which would cause the
parameter to be wildly off around 0.25 or 0.75.

And that would cause offset calculations to fail.
2020-12-27 00:31:18 +01:00
Matthias Clasen
61214221b3 testsuite Add curve tangent tests 2020-12-27 00:31:18 +01:00
Benjamin Otte
7eb4ed8f86 testsuite: Add a test for the conic that got us segment() 2020-12-27 00:31:18 +01:00
Benjamin Otte
92b472fec1 path: Add gsk_curve_segment()
Using split() twice with scaled t values does not work with conics.
2020-12-27 00:31:18 +01:00
Benjamin Otte
7a6b008479 testsuite: Add a test for gsk_curve_decompose() 2020-12-27 00:31:18 +01:00
Benjamin Otte
d8c26172a5 testuite: Add tests for gsk_curve_get_tangent() 2020-12-27 00:31:18 +01:00
Matthias Clasen
da835321a5 testuite: Add tests for gsk_curve_get_point()
Add a few tests for gsk_curve_get_point().

Since GskCurve is not public api, we add gskcurve.c
as source to the test binary.
2020-12-27 00:31:18 +01:00
Benjamin Otte
30635d1cac curve: Split eval() into get_point() and get_tangent()
That's more in line with the get_start/end_point/tangent() functions.

Plus, those calls are independent and we usually want one or the other.
2020-12-27 00:31:18 +01:00
Matthias Clasen
a60b72ba58 Add gsk_curve_get_{start,end}_tangent
Add a way to get the tangents at the start and end of the curve.
This will be used in stroking.
2020-12-27 00:31:18 +01:00
Benjamin Otte
36347892d8 testsuite: Add conics to the random paths 2020-12-27 00:31:18 +01:00
Benjamin Otte
924f0bc2c5 path: Add GskCurve
GskCurve is an abstraction for path operations. It's essentially a
collection of vfuncs per GskPathOperation.

GskStandardContour has been ported to use it where appropriate.
2020-12-27 00:31:18 +01:00
Benjamin Otte
23c5318de1 path: Introduce gskpathop
A gskpathop is a pointer to a graphene_point_t* with the low bits used
to encode the GskPathOperation. It's an easy way to introduce API for
operations.

So far it's just used to replace GskStandardOperation.
2020-12-27 00:31:18 +01:00
Benjamin Otte
678405bd22 WIP: css: Replace border rendering code with GskPath
The weight is wrong still, I need to compute the correct one to get real
45deg circle corners and not just roughly correct ones.
2020-12-27 00:31:18 +01:00
Benjamin Otte
946b76881b WIP: pathbuilder: Add gsk_path_builder_add_rounded_rect()
It works, but does not use a custom contour yet.
2020-12-27 00:31:18 +01:00
Benjamin Otte
061683344f path: Add conic curves
So far this just adds the API, if you use it, you'll get lots of
g_warnings().

This will be fixed in future commits.
2020-12-27 00:31:18 +01:00
Benjamin Otte
af9a85616d path: Rename to gtk_path_builder_add_segment()
It's about bulding paths, not about measuring them.
2020-12-27 00:31:18 +01:00
Benjamin Otte
0f332de3d3 path: Split contours into their own file
I'm not sure I want to keep all contours in one file, but for now that's
how it is.
2020-12-27 00:31:18 +01:00
Benjamin Otte
15e8f2bacc path: Make all private contour APIs take a GskContour
... instead of a path, index tuple.
2020-12-27 00:31:18 +01:00
Benjamin Otte
25f9eadb0d stroke: Add support for dashes
... and hook it up in the node parser and for Cairo rendering.
2020-12-27 00:31:18 +01:00
Matthias Clasen
ced2959cdd gsk: Implement parsing fill and stroke nodes
Make serialization and deserialization work for stroke and
fill nodes.
2020-12-27 00:31:18 +01:00
Benjamin Otte
3c363f00d5 path: Add flags to gsk_path_foreach()
This way we can default to the siplest possible foreach() output - like
cairo_copy_path_flat() decomposing everything into lines - and add flags
to get more and more fancy.

This will be useful to have conics automatically decomposed for Cairo
drawing or if we want to add more line types in the future.
2020-12-27 00:31:18 +01:00
Benjamin Otte
a9ad37ed89 testsuite: Add an in_fill() test 2020-12-27 00:31:18 +01:00
Matthias Clasen
acdf04287d Implement gsk_path_measure_in_fill
Implement this in the obvious way, using the decomposed form
of standard contours. Since the decomposed form is part of the
measure object, this api moves from gsk_path_in_fill to
gsk_path_measure_in_fill.
2020-12-27 00:31:18 +01:00
Benjamin Otte
34725c1207 testsuite: Add a parsing test
This test includes an implementation of a gsk_path_equal() func with
a tolerance that is necessary because parsing does not always work
100% exactly due to floating point rounding, so we can't just
compare the to_string() output.
2020-12-27 00:31:18 +01:00
Matthias Clasen
cb10cf07e6 path: Special-case rects and circles
Write out the commands for rects and circles in a special
way, and add code in the parser to recognize this, so we
can successfully round-trip these through the SVG path format.

The special way - for people who want to use it for debugging -
for now is that we use uppercase "Z" to close standard paths, but
lowercase "z" to close our special paths.

A test is included, but the random path serializations should take care
of it, too.
2020-12-27 00:31:18 +01:00
Matthias Clasen
a7ba2bde86 path: Fix serialization for circles
The svg A can not do a full circle, since it is a two point
parametrization - if the start and end point are the same,
it draws nothing. So, use two arcs.
2020-12-27 00:31:18 +01:00
Benjamin Otte
87b3cb1df8 testsuite: Add librsvg path tests 2020-12-27 00:31:18 +01:00
Matthias Clasen
2478963cbb path: Implement gsk_path_parse
Implement the SVG path syntax to read back the strings
that we generate when serializing paths. The tests for
this code are taken from librsvg.

This includes an elliptical arc implementation according
to the SVG spec. The code is mostly taken from librsvg,
but pretty directly follows the SVG spec implementation
notes. We don't export this, since the parametrization
is inconvenient. We do want an arc_to API, but
these are not the arcs we are looking for.
2020-12-27 00:31:18 +01:00
Matthias Clasen
abbbaef7e8 path: Implement SVG arcs
This is elliptical arc implementation according to the SVG spec.
The code is mostly taken from librsvg, but pretty directly
follows the SVG spec implementation notes.

We don't export this, since the parametrization is inconvenient.
We do want an arc_to API, but these are not the arcs we are
looking for.

It will be used in parsing SVG path syntax.
2020-12-27 00:31:18 +01:00
Matthias Clasen
69177416a0 stroke: Add miter limit
Add a miter limit to GskStroke. This will be needed to
fully implement line joins.

Also introduce the GSK_LINE_JOIN_MITER_CLIP value,
following SVG 2.0. cairo does not have it, so translate
it to plain miter when using cairo.
2020-12-27 00:31:18 +01:00
Matthias Clasen
ff47bfdbcf Documentation typo fixes 2020-12-27 00:31:18 +01:00
Benjamin Otte
120e449bdd testsuite: Add relative path functions
They're making the paths slightly weirder, but they test public API, so
woohoo!
2020-12-27 00:31:18 +01:00
Benjamin Otte
237c37f6c2 pathbuilder: Add relative path commands
And gsk_path_builder_get_current_point().

They will be needed by the string parser.
2020-12-27 00:31:18 +01:00
Benjamin Otte
683729c388 path: Add GSK_CIRCLE_POINT_INIT() to initialize points on the circle
This is just splitting out a commonly done operation into a macro.
2020-12-27 00:31:18 +01:00
Benjamin Otte
9fe71e7dae pathbuilder: Redo semantics for starting curves
We now always have a "current point" which is either the last point an
operation was made to, or (0, 0) if no drawing operation has
been made yet.

Adding a contour of any kind to the builder will always update the
current point to that contour's end point.
2020-12-27 00:31:18 +01:00
Benjamin Otte
c74970e6c1 xxx: demo 2020-12-27 00:31:18 +01:00
Benjamin Otte
5225d01504 path: Split GskPathBuilder into its own file
... and add missing API docs.
2020-12-27 00:31:18 +01:00
Benjamin Otte
916d950069 testsuite: Add a test using get_point() and get_closest_point() 2020-12-27 00:31:18 +01:00
Benjamin Otte
76d6fed248 testsuite: Add a test for get_point() 2020-12-27 00:31:18 +01:00
Benjamin Otte
7ff6235ae6 testsuite: Update create_random_path()
1. Allow specifying the max number of contours
2. Be smarter about creating the paths:
   With 10% chance, create a "weird" path like the empty one or only
   points or things like that.
   Otherwise create a bunch of contours, with 2/3 a standard contour,
   with 1/3 a predetermined one.
2020-12-27 00:31:18 +01:00
Benjamin Otte
9b957c26cb gtk-demo: Add cute maze demo 2020-12-27 00:31:18 +01:00
Benjamin Otte
445b2382e6 testsuite: Add tests for gsk_path_measure_get_closest_point() 2020-12-27 00:31:18 +01:00
Benjamin Otte
790a4201c3 path: Add gsk_path_measure_get_closest_point()
... and gsk_path_measure_get_closest_point_full().

Those 2 functions allow finding the closest point on a path to a given
point.
2020-12-27 00:31:18 +01:00
Benjamin Otte
00b9af65b5 spline: Use Skia's tolerance checks
This avoids measuring being too far off (it's still off, but it's less
than a percent now.
2020-12-27 00:31:18 +01:00
Benjamin Otte
f7c367338c testsuite: Add tests for gsk_path_measure_add_segment() 2020-12-27 00:31:18 +01:00
Benjamin Otte
5d69887618 gtk-demo: Add a text-on-path demo 2020-12-27 00:31:18 +01:00
Benjamin Otte
b658c26a3e xxx: path_fill demo 2020-12-27 00:31:18 +01:00
Benjamin Otte
e4c147cf2f path: Add gsk_path_measure_get_point()
Allows querying the coordinates and direction of any specific point on a
path.
2020-12-27 00:31:18 +01:00
Matthias Clasen
fc2c6f1566 path: Add gsk_path_add_circle()
Adds a circle contour, too.
2020-12-27 00:31:18 +01:00
Benjamin Otte
b0d6130905 pathmeasure: Implement support for beziers
Instead of treating bezier curves as lines, we properly decompose them
into line segments now so that we can treat those as lines.
2020-12-27 00:31:18 +01:00
Benjamin Otte
a0b9238a15 path: Implement gsk_path_to_cairo() using foreach() 2020-12-27 00:31:18 +01:00
Benjamin Otte
801c63494c path: Add gsk_path_foreach() 2020-12-27 00:31:17 +01:00
Benjamin Otte
d2cfe74140 path: Collect flags
We don't need them yet, but maybe later.
2020-12-27 00:31:17 +01:00
Benjamin Otte
a3ac003546 testsuite: Add path tests 2020-12-27 00:31:17 +01:00
Benjamin Otte
483a4773cd pathmeasure: Add gsk_path_measure_add_segment()
This allows chunking paths, weeee.
2020-12-27 00:31:17 +01:00
Benjamin Otte
c82ad0214e path: Add gsk_path_builder_add_path() 2020-12-27 00:31:17 +01:00
Benjamin Otte
207feeb7a9 gsk: Add GskPathMeasure
An object to do measuring operations on paths - determining their
length, cutting off subpaths, things like that.
2020-12-27 00:31:17 +01:00
Benjamin Otte
9a2e4ac9a9 path: Change data structure for standard path
Instead of the Cairo method and imitating cairo_path_data_t, use the
Skia method and keep points and operations separate.

That way we get a points array that includes the starting point -
because it's always the end point of the previous operation.
2020-12-27 00:31:17 +01:00
Benjamin Otte
2bd3aa3cbe popover: Use fill and stroke nodes instead of Cairo
... to render the arrow.

The arrow should really be turned into a real thing - maybe an icon?
2020-12-27 00:31:17 +01:00
Benjamin Otte
118e41f432 snapshot: Add gtk_snapshot_push_stroke() 2020-12-27 00:31:17 +01:00
Benjamin Otte
2d7897a769 gsk: Add GskStrokeNode 2020-12-27 00:31:17 +01:00
Benjamin Otte
c279e1aa1e gsk: Add GskStroke
It's unused in this commit. This just prepares the new object.
2020-12-27 00:31:17 +01:00
Benjamin Otte
3c91d0be91 demos: Add a simple demo filling a path 2020-12-27 00:31:17 +01:00
Benjamin Otte
e7bbed54b5 snapshot: Add gtk_snapshot_push_fill() 2020-12-27 00:31:17 +01:00
Benjamin Otte
4eb7d68970 gsk: Add GskFillNode
Take a rendernode as source and a GskPath and fill the region in the
path just like cairo_fill() would.
2020-12-27 00:31:17 +01:00
Benjamin Otte
98337f7115 gsk: Add GskPath 2020-12-27 00:31:17 +01:00
Benjamin Otte
08ee6c7acf mediafile: Load extension at startup with GTK_MEDIA
When the GTK_MEDIA env var is set, check at startup that it works, not
only when the first MeidaFile is instantiated.

This has the fortunate side effect that it prints help output for
GTK_MEDIA=help at startup, too.
2020-12-27 00:31:17 +01:00
Benjamin Otte
c815496fe3 gtk: Build as static library first
This allows linking against the static libgtk from the testsuite.

We build the dynamic library by linking all the static libraries into
the final product.
2020-12-27 00:31:16 +01:00
5310 changed files with 1392481 additions and 643667 deletions

View File

@@ -1,10 +1,9 @@
# See https://www.apertis.org/policies/coding_conventions/#code-formatting # See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
BasedOnStyle: GNU BasedOnStyle: GNU
AlwaysBreakAfterDefinitionReturnType: All AlwaysBreakAfterDefinitionReturnType: All
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BinPackParameters: false BinPackParameters: false
SpaceAfterCStyleCast: true SpaceAfterCStyleCast: true
PointerAlignment: Right
# Our column limit is actually 80, but setting that results in clang-format # Our column limit is actually 80, but setting that results in clang-format
# making a lot of dubious hanging-indent choices; disable it and assume the # making a lot of dubious hanging-indent choices; disable it and assume the
# developer will line wrap appropriately. clang-format will still check # developer will line wrap appropriately. clang-format will still check

View File

@@ -1,32 +0,0 @@
# SPDX-FileCopyrightText: 2021 The GTK Authors
# SPDX-License-Identifier: CC0-1.0
root = true
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
[*.[ch]]
indent_size = 2
indent_style = space
insert_final_newline = true
# For the legacy tabs which still exist in the code:
tab_width = 8
[*.ui]
indent_size = 2
indent_style = space
insert_final_newline = true
[*.xml]
indent_size = 2
indent_style = space
[meson.build]
indent_size = 2
indent_style = space
[*.md]
max_line_length = 80

View File

@@ -1,2 +0,0 @@
[flake8]
ignore = E501

1
.gitignore vendored
View File

@@ -1,2 +1 @@
/subprojects/*/ /subprojects/*/
.flatpak-builder/

View File

@@ -3,12 +3,10 @@ include:
file: 'flatpak/flatpak_ci_initiative.yml' file: 'flatpak/flatpak_ci_initiative.yml'
stages: stages:
- check
- build - build
- analysis - analysis
- docs - docs
- flatpak - flatpak
- publish
- deploy - deploy
.cache-paths: &cache-paths .cache-paths: &cache-paths
@@ -22,39 +20,25 @@ stages:
# Common variables # Common variables
variables: variables:
COMMON_MESON_FLAGS: "-Dwerror=true -Dcairo:werror=false -Dgi-docgen:werror=false -Dgraphene:werror=false -Dlibepoxy:werror=false -Dlibsass:werror=false -Dpango:werror=false -Dsassc:werror=false -Dgdk-pixbuf:werror=false -Dglib:werror=false -Dlibcloudproviders:werror=false -Dlibpng:werror=false -Dlibtiff:werror=false -Dsysprof:werror=false -Dwayland-protocols:werror=false -Dharfbuzz:werror=false -Dfreetype2:werror=false -Dfontconfig:werror=false -Dfribidi:werror=false -Dlibffi:werror=false -Dlibjpeg-turbo:werror=false -Dmutest:werror=false -Dpixman:werror=false -Dproxy-libintl:werror=false" COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false -Dpango:werror=false -Dgtk-doc:werror=false -Dwayland-protocols:werror=false -Dsysprof:werror=false"
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true" BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true -Dintrospection=enabled" FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3 MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v49" FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v25"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v25"
workflow: .only-default:
rules: only:
# run merge request pipelines - branches
- if: $CI_PIPELINE_SOURCE == "merge_request_event" except:
# do not run branch pipelines if corresponding merge requests exist... - tags
# (this avoids duplicate pipelines)
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
# ...but otherwise run branch pipelines
- if: $CI_COMMIT_BRANCH
# run tag pipelines
- if: $CI_COMMIT_TAG
default:
retry:
max: 2
when:
- 'runner_system_failure'
- 'stuck_or_timeout_failure'
- 'scheduler_failure'
- 'api_failure'
interruptible: true
style-check-diff: style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE image: $FEDORA_IMAGE
stage: check stage: .pre
when: manual allow_failure: true
script: script:
- .gitlab-ci/run-style-check-diff.sh - .gitlab-ci/run-style-check-diff.sh
@@ -66,8 +50,6 @@ style-check-diff:
junit: junit:
- "${CI_PROJECT_DIR}/_build/report-x11.xml" - "${CI_PROJECT_DIR}/_build/report-x11.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland.xml" - "${CI_PROJECT_DIR}/_build/report-wayland.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_gl.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_gles2.xml"
- "${CI_PROJECT_DIR}/_build/report-broadway.xml" - "${CI_PROJECT_DIR}/_build/report-broadway.xml"
name: "gtk-${CI_COMMIT_REF_NAME}" name: "gtk-${CI_COMMIT_REF_NAME}"
paths: paths:
@@ -75,17 +57,17 @@ style-check-diff:
- "${CI_PROJECT_DIR}/_build/report*.xml" - "${CI_PROJECT_DIR}/_build/report*.xml"
- "${CI_PROJECT_DIR}/_build/report*.html" - "${CI_PROJECT_DIR}/_build/report*.html"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png" - "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.node"
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png" - "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.node"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap" - "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
- "${CI_PROJECT_DIR}/_build/testsuite/headless/*/*.log"
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
cache: cache:
key: "$CI_JOB_NAME" key: "$CI_JOB_NAME"
paths: paths:
- _ccache/ - _ccache/
- subprojects/gdk-pixbuf/
- subprojects/glib/
- subprojects/graphene/
- subprojects/libepoxy/
- subprojects/pango/
fedora-x86_64: fedora-x86_64:
extends: .build-fedora-default extends: .build-fedora-default
@@ -94,20 +76,13 @@ fedora-x86_64:
variables: variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both" EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script: script:
- .gitlab-ci/show-info-linux.sh - meson subprojects update
- export PATH="$HOME/.local/bin:$PATH" - meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- meson subprojects download
- meson subprojects update --reset
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
_build _build
- meson compile -C _build - ninja -C _build
- .gitlab-ci/run-tests.sh _build x11 gtk - .gitlab-ci/run-tests.sh _build x11
# only repeat test runs that are likely affected by test setups - .gitlab-ci/run-tests.sh _build wayland
- .gitlab-ci/run-tests.sh _build wayland_gl gtk:gdk,gtk:gsk-gl - .gitlab-ci/run-tests.sh _build broadway
release-build: release-build:
extends: .build-fedora-default extends: .build-fedora-default
@@ -116,70 +91,34 @@ release-build:
variables: variables:
EXTRA_MESON_FLAGS: "--buildtype=release" EXTRA_MESON_FLAGS: "--buildtype=release"
script: script:
- .gitlab-ci/show-info-linux.sh - meson subprojects update
- export PATH="$HOME/.local/bin:$PATH" - meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- meson subprojects download
- meson subprojects update --reset
- mkdir _install
- meson setup
--prefix=${CI_PROJECT_DIR}/_install
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
_build _build
- meson compile -C _build - ninja -C _build
- meson install -C _build - .gitlab-ci/run-tests.sh _build x11
- PKG_CONFIG_PATH=${CI_PROJECT_DIR}/_install/lib64/pkgconfig:${CI_PROJECT_DIR}/_install/share/pkgconfig meson setup _build_hello examples/hello
- LD_LIBRARY_PATH=${CI_PROJECT_DIR}/_install/lib64 meson compile -C _build_hello
- .gitlab-ci/run-tests.sh _build wayland gtk
# only repeat test runs that are likely affected by test setups
- .gitlab-ci/run-tests.sh _build wayland_gles2 gtk:gdk,gtk:gsk-gl
fedora-clang: installed-tests:
extends: .build-fedora-default extends: .build-fedora-default
stage: build stage: build
needs: [] needs: []
variables: variables:
EXTRA_MESON_FLAGS: "--buildtype=release" EXTRA_MESON_FLAGS: "--prefix=/usr --libdir=/usr/lib64 -Dinstall-tests=true"
G_TEST_ACCESSIBLE: 1
script: script:
- .gitlab-ci/show-info-linux.sh - meson subprojects update
- export PATH="$HOME/.local/bin:$PATH" - meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- export CC=clang
- meson subprojects download
- meson subprojects update --reset
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
_build _build
- meson compile -C _build - ninja -C _build
- sudo ninja -C _build install
- dbus-run-session xvfb-run -a -s "-screen 0 1024x768x24"
gnome-desktop-testing-runner
--report-directory=_build/installed-tests-report/failed/
--parallel=0
gtk-4.0
artifacts:
paths:
- "_build/installed-tests-report/"
fedora-mingw64:
extends: .build-fedora-default
stage: build
needs: []
before_script:
- sudo dnf install -y
mingw64-filesystem
mingw64-gcc
mingw64-binutils
mingw64-cairo
mingw64-gdk-pixbuf
mingw64-gstreamer1-plugins-bad-free
mingw64-glib2
mingw64-libepoxy
mingw64-pango
# mingw64-graphene (rawhide)
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=1.0
- meson subprojects download
- meson subprojects update --reset
- meson -Dintrospection=disabled -Dgraphene:introspection=disabled _build
- meson compile -C _build
.mingw-defaults: .mingw-defaults:
stage: build stage: build
@@ -204,84 +143,9 @@ msys2-mingw64:
variables: variables:
MSYSTEM: "MINGW64" MSYSTEM: "MINGW64"
CHERE_INVOKING: "yes" CHERE_INVOKING: "yes"
artifacts:
when: always
expose_as: 'Windows_DLL_MSYS2_64_bit_toolchain'
paths:
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
macos:
rules:
# Do not run in forks as the runner is not available there.
# (except for dehesselle who maintains the runner)
- if: $CI_PROJECT_NAMESPACE != "GNOME" && $CI_PROJECT_NAMESPACE != "dehesselle"
when: never
- if: $RUNNER == "macosintel"
variables:
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
NINJA_PKG: $CI_API_V4_URL/projects/30745/packages/generic/ninja_macos/v1.11.1.1+9/ninja-1.11.1.1-cp38-cp38-macosx_11_0_x86_64.whl
when: manual
allow_failure: true
- if: $RUNNER == "macosarm"
variables:
SDKROOT: /opt/sdks/MacOSX11.3.sdk
NINJA_PKG: ninja==1.11.1.1
stage: build
parallel:
matrix:
- RUNNER: [ "macosintel", "macosarm" ]
tags:
- ${RUNNER}
needs: []
variables:
EXTRA_MESON_FLAGS: ""
BACKEND_FLAGS: "-Dx11-backend=false -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dmedia-gstreamer=disabled -Dintrospection=enabled -Dgobject-introspection:werror=false"
TMPDIR: /Users/Shared/work/tmp
PIP_CACHE_DIR: /Users/Shared/build/cache
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
before_script:
- .gitlab-ci/show-info-macos.sh
- python3 -m venv .venv
# Building the introspection feature requires pkg-config and bison.
- curl -L $CI_API_V4_URL/projects/30437/packages/generic/pkgconfig/v0.29.2+10/pkg-config-0.29.2+10_$(uname -m).tar.xz | tar -C .venv -xJ
- curl -L $CI_API_V4_URL/projects/30438/packages/generic/bison/v3.8.2+3/bison-3.8.2+3_$(uname -m).tar.xz | tar -C .venv -xJ
- source .venv/bin/activate
- pip3 install meson==1.3.2 $NINJA_PKG
# We're not setting up ccache here on purpose as it accelerates the build
# so much that it triggers race conditions in the gobject-introspection
# subproject.
script:
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
_build
- meson compile -C _build
artifacts:
when: always
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
vs2017-x64:
# TODO: Uncomment this when ready to merge.
# rules:
# - if: $CI_PROJECT_NAMESPACE == "GNOME"
stage: build
tags:
- win32-ps
needs: []
script:
- .gitlab-ci/test-msvc.bat
artifacts:
when: always
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
.flatpak-defaults: .flatpak-defaults:
image: "quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master" image: $FLATPAK_IMAGE
stage: flatpak stage: flatpak
allow_failure: true allow_failure: true
tags: tags:
@@ -291,104 +155,73 @@ vs2017-x64:
- "${APPID}-dev.flatpak" - "${APPID}-dev.flatpak"
- 'repo.tar' - 'repo.tar'
expire_in: 1 day expire_in: 1 day
rules:
# Only build Flatpak bundles automatically on main
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH != "main"
when: "manual"
script: script:
- bash -x ./.gitlab-ci/flatpak-build.sh "${APPID}" - bash -x ./.gitlab-ci/flatpak-build.sh "${APPID}"
flatpak:demo: # Manual jobs, for branches and MRs
extends: '.flatpak-defaults' .flatpak-manual:
extends: .flatpak-defaults
when: manual
# Only build Flatpak bundles automatically on master
.flatpak-master:
extends: .flatpak-defaults
only:
- master
flatpak-manual:demo:
extends: .flatpak-manual
needs: [] needs: []
variables: variables:
APPID: org.gtk.Demo4 APPID: org.gtk.Demo4
flatpak:demo:aarch64: flatpak-master:demo:
extends: '.flatpak-defaults' extends: .flatpak-master
needs: [] needs: []
tags:
- flatpak-aarch64
variables: variables:
APPID: org.gtk.Demo4 APPID: org.gtk.Demo4
flatpak:widget-factory: flatpak-manual:widget-factory:
extends: '.flatpak-defaults' extends: .flatpak-manual
needs: [] needs: []
variables: variables:
APPID: org.gtk.WidgetFactory4 APPID: org.gtk.WidgetFactory4
flatpak:widget-factory:aarch64: flatpak-master:widget-factory:
extends: '.flatpak-defaults' extends: .flatpak-master
needs: [] needs: []
tags:
- flatpak-aarch64
variables: variables:
APPID: org.gtk.WidgetFactory4 APPID: org.gtk.WidgetFactory4
flatpak:icon-browser: flatpak-manual:icon-browser:
extends: '.flatpak-defaults' extends: .flatpak-manual
needs: [] needs: []
variables: variables:
APPID: org.gtk.IconBrowser4 APPID: org.gtk.IconBrowser4
flatpak:icon-browser:aarch64: flatpak-master:icon-browser:
extends: '.flatpak-defaults' extends: .flatpak-master
needs: [] needs: []
tags:
- flatpak-aarch64
variables: variables:
APPID: org.gtk.IconBrowser4 APPID: org.gtk.IconBrowser4
flatpak:node-editor:
extends: '.flatpak-defaults'
needs: []
variables:
APPID: org.gtk.gtk4.NodeEditor
flatpak:node-editor:aarch64:
extends: '.flatpak-defaults'
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.gtk4.NodeEditor
# Publish the demo apps to the GNOME Nightly repo # Publish the demo apps to the GNOME Nightly repo
# https://wiki.gnome.org/Apps/Nightly # https://wiki.gnome.org/Apps/Nightly
# https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/DevOps-with-Flatpak # https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/DevOps-with-Flatpak
nightly demo: nightly demo:
extends: '.publish_nightly' extends: '.publish_nightly'
needs: ['flatpak:demo'] dependencies: ['flatpak-master:demo']
needs: ['flatpak-master:demo']
nightly demo aarch64:
extends: '.publish_nightly'
needs: ['flatpak:demo:aarch64']
nightly factory: nightly factory:
extends: '.publish_nightly' extends: '.publish_nightly'
needs: ['flatpak:widget-factory'] dependencies: ['flatpak-master:widget-factory']
needs: ['flatpak-master:widget-factory']
nightly factory aarch64:
extends: '.publish_nightly'
needs: ['flatpak:widget-factory:aarch64']
nightly icon-browser: nightly icon-browser:
extends: '.publish_nightly' extends: '.publish_nightly'
needs: ['flatpak:icon-browser'] dependencies: ['flatpak-master:icon-browser']
needs: ['flatpak-master:icon-browser']
nightly icon-browser aarch64:
extends: '.publish_nightly'
needs: ['flatpak:icon-browser:aarch64']
nightly node-editor:
extends: '.publish_nightly'
needs: ['flatpak:node-editor']
nightly node-editor aarch64:
extends: '.publish_nightly'
needs: ['flatpak:node-editor:aarch64']
static-scan: static-scan:
image: $FEDORA_IMAGE image: $FEDORA_IMAGE
@@ -397,21 +230,15 @@ static-scan:
variables: variables:
EXTRA_MESON_FLAGS: "--buildtype=debug" EXTRA_MESON_FLAGS: "--buildtype=debug"
script: script:
- export PATH="$HOME/.local/bin:$PATH" - meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _scan_build
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
_scan_build
- ninja -C _scan_build scan-build - ninja -C _scan_build scan-build
artifacts: artifacts:
paths: paths:
- _scan_build/meson-logs - _scan_build/meson-logs
allow_failure: true allow_failure: true
# Run tests with the address sanitizer. We need to turn off introspection # Run tests with the address sanitizer. We need to turn off introspection,
# and f16c, since they are incompatible with asan # since it is incompatible with asan
asan-build: asan-build:
image: $FEDORA_IMAGE image: $FEDORA_IMAGE
tags: [ asan ] tags: [ asan ]
@@ -419,65 +246,38 @@ asan-build:
needs: [] needs: []
variables: variables:
script: script:
- export PATH="$HOME/.local/bin:$PATH" - CC=clang meson --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled _build
- CC=clang meson setup
--buildtype=debugoptimized
-Db_sanitize=address
-Db_lundef=false
-Dbuild-demos=false
-Dbuild-tests=false
-Dbuild-examples=false
-Dintrospection=disabled
-Df16c=disabled
_build
- ninja -C _build - ninja -C _build
- .gitlab-ci/run-tests.sh _build wayland gtk - .gitlab-ci/run-tests.sh _build wayland
artifacts:
paths:
- _build/meson-logs
allow_failure: true
reference: reference:
image: $FEDORA_IMAGE image: $DOCS_IMAGE
stage: docs stage: docs
needs: [] needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script: script:
- export PATH="$HOME/.local/bin:$PATH" - meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} -Dgtk_doc=true _build
- meson setup - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
${COMMON_MESON_FLAGS}
--buildtype=release
--force-fallback-for=gdk-pixbuf,pango
-Dintrospection=enabled
-Ddocumentation=true
-Dgdk-pixbuf:gtk_doc=true
-Dpango:documentation=true
-Dbuild-demos=false
-Dbuild-examples=false
-Dbuild-tests=false
-Dbuild-testsuite=false
_build
- meson compile -C _build
- mkdir -p _reference/ - mkdir -p _reference/
- mv _build/docs/reference/gdk/gdk4/ _reference/gdk4/ - mv _build/docs/reference/gdk/html/ _reference/gdk/
- mv _build/docs/reference/gdk/gdk4-x11/ _reference/gdk4-x11/ - mv _build/docs/reference/gsk/html/ _reference/gsk/
- mv _build/docs/reference/gdk/gdk4-wayland/ _reference/gdk4-wayland/ - mv _build/docs/reference/gtk/html/ _reference/gtk/
- mv _build/docs/reference/gsk/gsk4/ _reference/gsk4/
- mv _build/docs/reference/gtk/gtk4/ _reference/gtk4/
- mv _build/subprojects/pango/docs/Pango/ _reference/Pango/
- mv _build/subprojects/pango/docs/PangoCairo/ _reference/PangoCairo/
- mv _build/subprojects/pango/docs/PangoFc/ _reference/PangoFc/
- mv _build/subprojects/pango/docs/PangoFT2/ _reference/PangoFT2/
- mv _build/subprojects/pango/docs/PangoOT/ _reference/PangoOT/
- mv _build/subprojects/pango/docs/PangoXft/ _reference/PangoXft/
- mv _build/subprojects/gdk-pixbuf/docs/gdk-pixbuf/ _reference/gdk-pixbuf/
- mv _build/subprojects/gdk-pixbuf/docs/gdk-pixdata/ _reference/gdk-pixdata/
artifacts: artifacts:
paths: paths:
- _reference - _reference
publish-docs: pages:
image: fedora:latest stage: deploy
stage: publish
interruptible: false
needs: ['reference'] needs: ['reference']
script: script:
- "curl -X POST -F token=${PAGES_TRIGGER_TOKEN} -F ref=docs-gtk-org https://gitlab.gnome.org/api/v4/projects/665/trigger/pipeline" - mv _reference/ public/
rules: artifacts:
- if: $CI_COMMIT_REF_NAME == "main" paths:
- public
only:
- master

View File

@@ -14,14 +14,11 @@ Each Docker image has a tag composed of two parts:
See the [container registry][registry] for the available images for each See the [container registry][registry] for the available images for each
branch, as well as their available versions. branch, as well as their available versions.
Note that using `latest` as version number will overwrite the most
recently uploaded image in the registry.
### Checklist for Updating a CI image ### Checklist for Updating a CI image
- [ ] Update the `${image}.Dockerfile` file with the dependencies - [ ] Update the `${image}.Dockerfile` file with the dependencies
- [ ] Run `./run-docker.sh build --base ${image} --version ${number}` - [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --version ${number}` - [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
once the Docker image is built; you may need to log in by using once the Docker image is built; you may need to log in by using
`docker login` or `podman login` `docker login` or `podman login`
- [ ] Update the `image` keys in the `.gitlab-ci.yml` file with the new - [ ] Update the `image` keys in the `.gitlab-ci.yml` file with the new
@@ -33,8 +30,8 @@ recently uploaded image in the registry.
- [ ] Write a new `${image}.Dockerfile` with the instructions to set up - [ ] Write a new `${image}.Dockerfile` with the instructions to set up
a build environment a build environment
- [ ] Add the `pip3 install meson` incantation - [ ] Add the `pip3 install meson` incantation
- [ ] Run `./run-docker.sh build --base ${image} --version ${number}` - [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --version ${number}` - [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image - [ ] Add the new job to `.gitlab-ci.yml` referencing the image
- [ ] Open a merge request with your changes and let it run - [ ] Open a merge request with your changes and let it run

View File

@@ -0,0 +1,91 @@
FROM fedora:31
RUN dnf -y install \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
ccache \
clang \
clang-analyzer \
colord-devel \
cups-devel \
dbus-daemon \
dbus-x11 \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
elfutils-libelf-devel \
fribidi-devel \
gcc \
gcc-c++ \
gdk-pixbuf2-devel \
gdk-pixbuf2-modules \
gettext \
git \
glib2-devel \
glib2-static \
glibc-devel \
glibc-headers \
gnome-desktop-testing \
gobject-introspection-devel \
graphene-devel \
gstreamer1-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
gtk-doc \
hicolor-icon-theme \
iso-codes \
itstool \
json-glib-devel \
lcov \
libasan \
libattr-devel \
libcloudproviders-devel \
libepoxy-devel \
libffi-devel \
libmount-devel \
librsvg2 \
libselinux-devel \
libubsan \
libXcomposite-devel \
libXcursor-devel \
libXcursor-devel \
libXdamage-devel \
libXfixes-devel \
libXi-devel \
libXinerama-devel \
libxkbcommon-devel \
libXrandr-devel \
libXrender-devel \
libXtst-devel \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
mesa-libwayland-egl-devel \
ninja-build \
pango-devel \
pcre-devel \
pcre-static \
python3 \
python3-jinja2 \
python3-pip \
python3-pygments \
python3-wheel \
redhat-rpm-config \
sassc \
systemtap-sdt-devel \
vulkan-devel \
wayland-devel \
wayland-protocols-devel \
weston \
weston-libs \
which \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson==0.55.3

View File

@@ -0,0 +1,12 @@
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v25
RUN dnf -y install pandoc
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8

View File

@@ -1,105 +1,4 @@
FROM fedora:39 FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v25
RUN dnf -y install \
adwaita-icon-theme \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
ccache \
clang \
clang-analyzer \
clang-tools-extra \
colord-devel \
cups-devel \
dbus-daemon \
dbus-x11 \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
elfutils-libelf-devel \
expat-devel \
fribidi-devel \
gcc \
gcc-c++ \
gdk-pixbuf2-devel \
gdk-pixbuf2-modules \
gettext \
git \
glib2-devel \
glib2-static \
glibc-devel \
glibc-headers \
glslc \
gnupg2 \
gobject-introspection-devel \
graphene-devel \
graphviz \
gstreamer1-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
hicolor-icon-theme \
iso-codes \
itstool \
json-glib-devel \
lcov \
libasan \
libattr-devel \
libcloudproviders-devel \
libepoxy-devel \
libffi-devel \
libjpeg-turbo-devel \
libmount-devel \
libpng-devel \
librsvg2 \
libselinux-devel \
libtiff-devel \
libubsan \
libXcomposite-devel \
libXcursor-devel \
libXcursor-devel \
libXdamage-devel \
libXfixes-devel \
libXi-devel \
libXinerama-devel \
libxkbcommon-devel \
libXrandr-devel \
libXrender-devel \
libXtst-devel \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
mesa-libGLES-devel \
meson \
mutter \
ninja-build \
pango-devel \
pcre-devel \
pcre-static \
pipewire \
pipewire-gstreamer \
python3 \
python3-docutils \
python3-gobject \
python3-jinja2 \
python3-markdown \
python3-packaging \
python3-pip \
python3-pydbus \
python3-pygments \
python3-typogrify \
python3-wheel \
redhat-rpm-config \
sassc \
vulkan-devel \
wayland-devel \
wayland-protocols-devel \
weston \
weston-libs \
which \
wireplumber \
xorg-x11-server-Xvfb \
&& dnf clean all
# Enable sudo for wheel users # Enable sudo for wheel users
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers

View File

@@ -16,18 +16,17 @@ flatpak-builder \
flatpak build ${builddir} meson \ flatpak build ${builddir} meson \
--prefix=/app \ --prefix=/app \
--libdir=/app/lib \ --libdir=/app/lib \
--buildtype=debugoptimized \ --buildtype=release \
-Dx11-backend=true \ -Dx11-backend=true \
-Dwayland-backend=true \ -Dwayland-backend=true \
-Dprint-backends=file \
-Dbuild-tests=false \ -Dbuild-tests=false \
-Dbuild-testsuite=false \
-Dbuild-examples=false \ -Dbuild-examples=false \
-Dintrospection=disabled \ -Dintrospection=disabled \
-Dbuild-demos=true \ -Ddemos=true \
-Dprofile=devel \
_flatpak_build _flatpak_build
flatpak build --env=CI_COMMIT_SHORT_SHA=$CI_COMMIT_SHORT_SHA ${builddir} ninja -C _flatpak_build install flatpak build ${builddir} ninja -C _flatpak_build install
flatpak-builder \ flatpak-builder \
--user --disable-rofiles-fuse \ --user --disable-rofiles-fuse \
@@ -43,6 +42,6 @@ flatpak build-bundle \
${appid} ${appid}
# to be consumed by the nightly publish jobs # to be consumed by the nightly publish jobs
if [[ $CI_COMMIT_BRANCH == main ]]; then if [[ $CI_COMMIT_BRANCH == master ]]; then
tar cf repo.tar ${repodir} tar cf repo.tar ${repodir}
fi fi

View File

@@ -185,8 +185,6 @@ ul.images li {
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li> <li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
<li><img alt="out" src="{{ failure.image_data.out }}" /></li> <li><img alt="out" src="{{ failure.image_data.out }}" /></li>
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li> <li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
<li><a href="{{ failure.image_data.refnode }}">ref node</a></li>
<li><a href="{{ failure.image_data.outnode }}">out node</a></li>
</ul> </ul>
{% endif %} {% endif %}
</li> </li>
@@ -270,7 +268,7 @@ aparser.add_argument('--job-id', metavar='ID',
default=None) default=None)
aparser.add_argument('--branch', metavar='NAME', aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested', help='Branch of the project being tested',
default='main') default='master')
aparser.add_argument('--output', metavar='FILE', aparser.add_argument('--output', metavar='FILE',
help='The output HTML file, stdout by default', help='The output HTML file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'), type=argparse.FileType('w', encoding='UTF-8'),
@@ -313,8 +311,6 @@ for line in args.infile:
image_data = { image_data = {
'ref': os.path.join(args.reftest_output_dir, '{}.ref.png'.format(basename)), 'ref': os.path.join(args.reftest_output_dir, '{}.ref.png'.format(basename)),
'out': os.path.join(args.reftest_output_dir, '{}.out.png'.format(basename)), 'out': os.path.join(args.reftest_output_dir, '{}.out.png'.format(basename)),
'refnode': os.path.join(args.reftest_output_dir, '{}.ref.node'.format(basename)),
'outnode': os.path.join(args.reftest_output_dir, '{}.out.node'.format(basename)),
'diff': os.path.join(args.reftest_output_dir, '{}.diff.png'.format(basename)), 'diff': os.path.join(args.reftest_output_dir, '{}.diff.png'.format(basename)),
} }
@@ -324,7 +320,7 @@ for line in args.infile:
units.append(unit) units.append(unit)
report = {} report = {}
report['date'] = datetime.datetime.now(datetime.UTC) report['date'] = datetime.datetime.utcnow()
report['locale_date'] = report['date'].strftime("%c") report['locale_date'] = report['date'].strftime("%c")
report['project_name'] = args.project_name report['project_name'] = args.project_name
report['backend'] = args.backend report['backend'] = args.backend

View File

@@ -27,7 +27,7 @@ aparser.add_argument('--job-id', metavar='ID',
default='Unknown') default='Unknown')
aparser.add_argument('--branch', metavar='NAME', aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested', help='Branch of the project being tested',
default='main') default='master')
aparser.add_argument('--output', metavar='FILE', aparser.add_argument('--output', metavar='FILE',
help='The output file, stdout by default', help='The output file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'), type=argparse.FileType('w', encoding='UTF-8'),
@@ -44,7 +44,7 @@ outfile = args.output
testsuites = ET.Element('testsuites') testsuites = ET.Element('testsuites')
testsuites.set('id', '{}/{}'.format(args.job_id, args.branch)) testsuites.set('id', '{}/{}'.format(args.job_id, args.branch))
testsuites.set('package', args.project_name) testsuites.set('package', args.project_name)
testsuites.set('timestamp', datetime.datetime.now(datetime.UTC).isoformat(timespec='minutes')) testsuites.set('timestamp', datetime.datetime.utcnow().isoformat(timespec='minutes'))
suites = {} suites = {}
for line in args.infile: for line in args.infile:

View File

@@ -1,154 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
/**
* RedHat Fonts taken from https://github.com/RedHatOfficial/RedHatFont
* License: SIL Open Font License 1.1 http://scripts.sil.org/OFL
*/
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&family=Red+Hat+Display:ital,wght@0,400;0,500;0,700;0,900;1,400;1,500;1,700;1,900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600&display=swap');
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Regular.woff2") format("woff2"),
url("RedHatDisplay-Regular.woff") format("woff");
font-style: normal;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-RegularItalic.woff2") format("woff2"),
url("RedHatDisplay-RegularItalic.woff") format("woff");
font-style: italic;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Medium.woff2") format("woff2"),
url("RedHatDisplay-Medium.woff") format("woff");
font-style: normal;
font-weight: 500;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-MediumItalic.woff2") format("woff2"),
url("RedHatDisplay-MediumItalic.woff") format("woff");
font-style: italic;
font-weight: 500;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Bold.woff2") format("woff2"),
url("RedHatDisplay-Bold.woff") format("woff");
font-style: normal;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-BoldItalic.woff2") format("woff2"),
url("RedHatDisplay-BoldItalic.woff") format("woff");
font-style: italic;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Black.woff2") format("woff2"),
url("RedHatDisplay-Black.woff") format("woff");
font-style: normal;
font-weight: 900;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-BlackItalic.woff2") format("woff2"),
url("RedHatDisplay-BlackItalic.woff") format("woff");
font-style: italic;
font-weight: 900;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-Regular.woff2") format("woff2"),
url("RedHatText-Regular.woff") format("woff");
font-style: normal;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-RegularItalic.woff2") format("woff2"),
url("RedHatText-RegularItalic.woff") format("woff");
font-style: italic;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-Medium.woff2") format("woff2"),
url("RedHatText-Medium.woff") format("woff");
font-style: normal;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-MediumItalic.woff2") format("woff2"),
url("RedHatText-MediumItalic.woff") format("woff");
font-style: italic;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-Bold.woff2") format("woff2"),
url("RedHatText-Bold.woff") format("woff");
font-style: normal;
font-weight: 900;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-BoldItalic.woff2") format("woff2"),
url("RedHatText-BoldItalic.woff") format("woff");
font-style: italic;
font-weight: 900;
font-display: fallback;
}

View File

@@ -1,138 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
id="svg6843"
sodipodi:version="0.32"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
version="1.0"
sodipodi:docname="gtk-logo.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="/home/ebassi/Pictures/gtk-logo-256.png"
inkscape:export-xdpi="192"
inkscape:export-ydpi="192">
<defs
id="defs6845">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="-50 : 600 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="700 : 600 : 1"
inkscape:persp3d-origin="300 : 400 : 1"
id="perspective13" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="69.874353"
inkscape:cy="64.313526"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
width="128px"
height="128px"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid7947" />
</sodipodi:namedview>
<metadata
id="metadata6848">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:date />
<dc:creator>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:publisher>
<dc:identifier />
<dc:source />
<dc:relation />
<dc:language />
<dc:subject>
<rdf:Bag />
</dc:subject>
<dc:coverage />
<dc:description />
<dc:contributor>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="" />
</cc:Work>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
sodipodi:nodetypes="ccccc"
id="path6976"
d="M 20.88413,30.82696 L 53.816977,55.527708 L 107.33282,39.060543 L 70.587303,17.177763 L 20.88413,30.82696 z"
style="fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
<path
id="path6978"
d="M 22.94243,82.287118 L 20.88413,30.82696 L 53.816977,55.527708 L 53.816977,111.10486 L 22.94243,82.287118 z"
style="fill:#e40000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
<path
id="path6980"
d="M 53.816977,111.10486 L 103.21619,90.5207 L 107.33282,39.060543 L 53.816977,55.527708 L 53.816977,111.10486 z"
style="fill:#7fe719;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
<path
sodipodi:nodetypes="ccc"
id="path6982"
d="M 23.216626,81.319479 L 70.48573,67.361442 L 103.38422,90.444516"
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
id="path6984"
d="M 70.434539,17.875593 L 70.434539,66.984877"
style="opacity:1;fill:#babdb6;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -1,149 +0,0 @@
<!--
SPDX-FileCopyrightText: 2021 GNOME Foundation
SPDX-License-Identifier: LGPL-2.1-or-later
-->
<!DOCTYPE html>
<html lang="en">
<head>
<title>GTK Documentation</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8" />
<meta property="og:site_name" content="https://docs.gtk.org"/>
<meta property="og:title" content="GTK Documentation"/>
<meta property="og:url" content="https://docs.gtk.org"/>
<meta property="og:type" content="website"/>
<meta property="og:description" content="API reference for GTK"/>
<meta name="twitter:title" content="GTK Documentation"/>
<meta name="twitter:url" content="https://docs.gtk.org"/>
<meta name="twitter:card" content="summary"/>
<link rel="canonical" href="https://docs.gtk.org"/>
<link rel="stylesheet" href="style.css" type="text/css" />
<script src="main.js"></script>
<!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>
<body>
<div id="body-wrapper" tabindex="-1">
<nav class="sidebar">
<div class="section">
<img src="gtk-logo.svg" class="logo"/>
</div>
<div class="section">
<h5>Sections</h5>
<div class="links">
<a href="#user-interface">User interface</a>
<a href="#core-libraries">Core libraries</a>
</div>
</div>
</nav>
<button id="btn-to-top" class="hidden"><span class="up-arrow"></span></button>
<section id="main" class="content">
<header>
<h1>GTK Documentation</h1>
</header>
<div class="toggle-wrapper">
<h4 id="user-interface">
User interface
<a href="#user-interface" class="anchor"></a>
</h4>
<div class="docblock">
<h5 id="gdk">GTK</h5>
<p>GTK is the primary library used to construct user interfaces. It
provides user interface controls and signal callbacks to respond to
user actions.</p>
<p><a href="https://docs.gtk.org/gtk4/">GTK API reference</a></p>
</div>
<div class="docblock">
<h5 id="gdk">GSK</h5>
<p>An intermediate layer which provides a rendering API implemented using Cairo, OpenGL or Vulkan.</p>
<p><a href="https://docs.gtk.org/gsk4/">GSK API reference</a></p>
</div>
<div class="docblock">
<h5 id="gdk">GDK</h5>
<p>An intermediate layer which isolates GTK from the details of the windowing system.</p>
<p><a href="https://docs.gtk.org/gdk4/">GDK API reference</a></p>
</div>
<div class="docblock">
<h5 id="pango">Pango</h5>
<p>Pango is the core text and font handling library used in GTK
applications. It has extensive support for the different writing
systems used throughout the world.</p>
<p><a href="https://docs.gtk.org/Pango/">Pango API reference</a></p>
</div>
<div class="docblock">
<h5 id="gdk-pixbuf">GdkPixbuf</h5>
<p>GdkPixbuf is a library for image loading and manipulation.</p>
<p><a href="https://docs.gtk.org/gdk-pixbuf/">GdkPixbuf API reference</a></p>
</div>
<div class="docblock">
<h5 id="cairo">Cairo</h5>
<p>Cairo is a 2D graphics library with support for multiple output
devices. It is designed to produce consistent, high quality output
on all media.</p>
<p><a href="https://www.cairographics.org/manual/" class="external">Cairo API reference</a></p>
</div>
</div>
<div class="toggle-wrapper">
<h4 id="core-libraries" style="display:flex;">
Core libraries
<a href="#core-libraries" class="anchor"></a>
</h4>
<div class="docblock">
<h5 id="glib">GLib</h5>
<p>GLib provides the core application building blocks for libraries
and applications written in C. It provides common data types
used in GTK, the main loop implementation, and a large set of
utility functions for strings and general portability across
different platforms.</p>
<p><a href="https://developer.gnome.org/glib/" class="external">GLib API reference</a></p>
</div>
<div class="docblock">
<h5 id="gobject">GObject</h5>
<p>GObject provides the object system used by GTK.</p>
<p><a href="https://developer.gnome.org/gobject/" class="external">GObject API reference</a></p>
</div>
<div class="docblock">
<h5 id="gio">GIO</h5>
<p>GIO provides a portable, modern and easy-to-use file system
abstraction API for accessing local and remote files; a set of
low and high level abstractions over the <a href="https://www.freedesktop.org/wiki/Software/dbus/" class="external">DBus</a>
IPC specification; an application settings API; portable networking
abstractions; and additional utilities for writing asynchronous
operations without blocking the user interface of your application.</p>
<p><a href="https://developer.gnome.org/gio/" class="external">GIO API reference</a></p>
</div>
</div>
</section>
<footer>
</footer>
</div>
</body>
</html>

View File

@@ -1,140 +0,0 @@
// SPDX-FileCopyrightText: 2021 GNOME Foundation
//
// SPDX-License-Identifier: LGPL-2.1-or-later
// eslint-disable-next-line no-unused-vars
function hasClass(elem, className) {
return elem && elem.classList && elem.classList.contains(className);
}
// eslint-disable-next-line no-unused-vars
function addClass(elem, className) {
if (!elem || !elem.classList) {
return;
}
elem.classList.add(className);
}
// eslint-disable-next-line no-unused-vars
function removeClass(elem, className) {
if (!elem || !elem.classList) {
return;
}
elem.classList.remove(className);
}
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
function onEach(arr, func, reversed) {
if (arr && arr.length > 0 && func) {
var length = arr.length;
var i;
if (reversed !== true) {
for (i = 0; i < length; ++i) {
if (func(arr[i]) === true) {
return true;
}
}
} else {
for (i = length - 1; i >= 0; --i) {
if (func(arr[i]) === true) {
return true;
}
}
}
}
return false;
}
function onEachLazy(lazyArray, func, reversed) {
return onEach(
Array.prototype.slice.call(lazyArray),
func,
reversed);
}
// eslint-disable-next-line no-unused-vars
function hasOwnProperty(obj, property) {
return Object.prototype.hasOwnProperty.call(obj, property);
}
window.addEventListener("load", function() {
"use strict;"
var main = document.getElementById("main");
var btnToTop = document.getElementById("btn-to-top");
function labelForToggleButton(isCollapsed) {
if (isCollapsed) {
return "+";
}
return "\u2212";
}
function createToggle(isCollapsed) {
var toggle = document.createElement("a");
toggle.href = "javascript:void(0)";
toggle.className = "collapse-toggle";
toggle.innerHTML = "[<span class=\"inner\">"
+ labelForToggleButton(isCollapsed)
+ "</span>]";
return toggle;
}
function toggleClicked() {
if (hasClass(this, "collapsed")) {
removeClass(this, "collapsed");
this.innerHTML = "[<span class=\"inner\">"
+ labelForToggleButton(false)
+ "</span>]";
onEachLazy(this.parentNode.getElementsByClassName("docblock"), function(e) {
removeClass(e, "hidden");
});
} else {
addClass(this, "collapsed");
this.innerHTML = "[<span class=\"inner\">"
+ labelForToggleButton(true)
+ "</span>]";
onEachLazy(this.parentNode.getElementsByClassName("docblock"), function(e) {
addClass(e, "hidden");
});
}
}
onEachLazy(document.getElementsByClassName("toggle-wrapper"), function(e) {
let sectionHeader = e.querySelector(".section-header");
let fragmentMatches = sectionHeader !== null && location.hash === "#" + sectionHeader.getAttribute('id');
collapsedByDefault = hasClass(e, "default-hide") && !fragmentMatches;
var toggle = createToggle(collapsedByDefault);
toggle.onclick = toggleClicked;
e.insertBefore(toggle, e.firstChild);
if (collapsedByDefault) {
addClass(toggle, "collapsed");
onEachLazy(e.getElementsByClassName("docblock"), function(d) {
addClass(d, "hidden");
});
}
});
function scrollBackTop(e) {
e.preventDefault();
window.scroll({
top: 0,
behavior: 'smooth',
});
}
function toggleScrollButton() {
if (window.scrollY < 400) {
addClass(btnToTop, "hidden");
} else {
removeClass(btnToTop, "hidden");
}
}
window.onscroll = toggleScrollButton;
btnToTop.onclick = scrollBackTop;
}, false);

View File

@@ -1,747 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
@import url("fonts.css");
/*********************************
* LIGHT THEME
*********************************/
:root {
/* colors */
--text-color: #333;
--text-color-muted: #999;
--primary: rgb(28, 118, 228);
--body-bg: #fff;
--sidebar-primary: rgb(144, 194, 255);
--sidebar-bg: #151515;
--sidebar-selected-bg: var(--primary);
--sidebar-text-color: #fafafa;
--sidebar-padding: 1.5em;
/* boxes, e.g. code blocks */
--box-bg: rgba(135, 135, 135, 0.085);
--box-radius: 0.35rem;
--box-padding: 0.75rem;
--box-margin: 0.75rem 0;
--box-text-color: #111;
/* typography */
--body-font-family: "Noto Serif",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
--body-font-scale: 0.95;
--body-font-size: calc(var(--body-font-scale) * clamp(16px, 1vw, 20px));
--body-font-weight: normal;
--monospace-font-family: "Source Code Pro", monospace;
--monospace-font-size: calc(0.86 * var(--body-font-size)); /* Monospace fonts are very different in terms of font-sizes. Adjust this value to scale it */
--heading-font-family: "Red Hat Display", var(--body-font-family);
--heading-weight: 900;
--heading-font-scale: 1.05;
--heading-small-font-family: var(--heading-font-family);
--heading-small-weight: 600;
--heading-small-font-scale: 1;
--heading-table-font-family: var(--heading-font-family);
--heading-table-weight: 600;
--heading-docblock-color: #6d6d6d; /* docblocks have headings from source comments. we want them to differ.*/
--heading-docblock-scale: 0.9; /* docblocks have headings from source comments. we want them to differ.*/
--symbol-font-family: var(--heading-font-family);
--symbol-font-weight: 500;
--symbol-font-scale: 1;
--table-font-size: 0.92em; /* Tables often contain lots information. It's better to scale them down a big to get more sutff fitted inside */
/* misc */
--prefered-content-width: 90ch; /* The preferred width for the readable content */
--anchor-sign: "#";
}
/*********************************
* DARK THEME (overrides)
*********************************/
@media (prefers-color-scheme: dark) {
:root {
--primary: rgb(144, 194, 255);
--text-color: #f6f6f6;
--text-color-muted: #686868;
--body-bg: #121212;
--sidebar-primary: rgb(144, 194, 255);
--sidebar-bg: #1e1e1e;
--sidebar-selected-bg: rgb(17, 112, 228);
--sidebar-text-color: #fafafa;
--box-bg: rgba(135, 135, 135, 0.1);
--box-text-color: #fff;
--heading-docblock-color: #b7b7b7;
}
/* fix dark theme syntax highlighting with a filter (for now) */
.highlight pre span {
filter: brightness(6);
}
}
/*********************************
* GENERAL STYLING
*********************************/
*,
*:before,
*:after {
box-sizing: border-box;
}
::-moz-selection {
color: white;
background: var(--primary);
}
::selection {
color: white;
background: var(--primary);
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(128, 128, 128, 0.6);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(128, 128, 128, 1);
}
::-webkit-scrollbar-track {
background: rgba(128, 128, 128, 0.15);
}
* {
scrollbar-width: initial;
}
body {
font: 16px/1.5 var(--body-font-family);
font-weight: var(--body-font-weight);
font-size: var(--body-font-size);
margin: 0;
padding: 0;
position: relative;
-webkit-font-feature-settings: "kern", "liga";
-moz-font-feature-settings: "kern", "liga";
font-feature-settings: "kern", "liga";
color: var(--text-color);
background: var(--body-bg);
}
h1, h2, h3, h4, h5, h6 {
font-family: var(--heading-font-family);
font-weight: var(--heading-weight);
margin: 1.75em 0 0.75em 0;
display: flex;
align-items: center;
}
h1 {
font-size: calc(1.75em * var(--heading-font-scale));
}
header h1 {
margin-top: 0;
}
h2 {
font-size: calc(1.4em * var(--heading-font-scale));
}
h3 {
font-size: calc(1.2em * var(--heading-font-scale));
}
header h3 {
color: var(--text-color-muted);
margin-bottom: 0;
}
h4, h5 {
font-size: calc(1em * var(--heading-font-scale));
}
h6 {
font-size: calc(1em * var(--heading-small-font-scale));
font-family: var(--heading-small-font-family);
font-weight: var(--heading-small-weight);
}
ol, ul {
padding-left: 1rem;
}
ul ul, ol ul, ul ol, ol ol {
margin-bottom: .6em;
}
p {
margin: 0 0 .6em 0;
}
a {
color: var(--primary);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
summary {
outline: none;
}
blockquote {
border-left: 3px solid var(--primary);
background: var(--box-bg);
padding: var(--box-padding);
border-radius: var(--box-radius);
margin: var(--box--margin);
}
code,
pre {
font-family: var(--monospace-font-family);
font-size: var(--monospace-font-size);
color: var(--box-text-color);
}
pre {
background: var(--box-bg);
padding: var(--box-padding);
border-radius: var(--box-radius);
overflow: auto;
}
code {
background: var(--box-bg);
padding: 0 0.35em;
border-radius: 0.35rem;
word-break: break-word;
}
a > code {
color: var(--primary);
}
pre pre,
pre code {
padding: 0;
margin: 0;
font-size: 1em;
background: none;
color: inherit;
}
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
font-family: inherit;
font-weight: inherit;
font-size: 0.85em;
}
strong, b {
font-weight: 600;
}
/* fix unwanted margins in tables, code, lists and blockquotes */
li > *:first-child,
li > *:first-child > *:first-child,
li > *:first-child > *:first-child > *:first-child,
td > *:first-child,
td > *:first-child > *:first-child,
td > *:first-child > *:first-child > *:first-child,
pre > *:first-child,
pre > *:first-child > *:first-child,
pre > *:first-child > *:first-child > *:first-child,
blockquote > *:first-child,
blockquote > *:first-child > *:first-child,
blockquote > *:first-child > *:first-child > *:first-child {
margin-top: 0;
}
li > *:last-child,
li > *:last-child > *:last-child,
li > *:last-child > *:last-child > *:last-child,
td > *:last-child,
td > *:last-child > *:last-child,
td > *:last-child > *:last-child > *:last-child,
pre > *:last-child,
pre > *:last-child > *:last-child,
pre > *:last-child > *:last-child > *:last-child,
blockquote > *:last-child,
blockquote > *:last-child > *:last-child,
blockquote > *:last-child > *:last-child > *:last-child {
margin-bottom: 0;
}
/*********************************
* PAGE STRUCTURE
*********************************/
#body-wrapper {
display: flex;
flex-wrap: nowrap;
flex-direction: row;
}
#body-wrapper:focus {
outline: none;
}
#main {
position: relative;
flex-grow: 1;
min-width: 0;
box-shadow: 0 0 134px rgba(0, 0, 0, 0.1);
}
footer {
width: 100%;
display: none;
}
/*********************************
* Button
*********************************/
#btn-to-top {
position: fixed;
bottom: 12px;
right: 32px;
z-index: 1000;
border-radius: 50%;
width: 42px;
height: 42px;
border: 1px solid var(--primary);
background: var(--box-bg);
color: var(--text-color);
cursor: pointer;
text-transform: none;
}
#btn-to-top > .up-arrow:after {
content: "🡅"
}
/*********************************
* SIDEBAR
*********************************/
.sidebar {
scrollbar-width: thin;
background: var(--sidebar-bg);
border-right: 1px solid var(--sidebar-bg);
min-width: 40ch;
padding: var(--sidebar-padding);
color: var(--sidebar-text-color);
position: sticky;
top: 0;
z-index: 2;
height: 100vh;
overflow-y: auto;
}
.sidebar a,
.sidebar a:hover {
text-decoration: none;
}
.sidebar .logo {
display: block;
margin: 2rem auto 0 auto;
width: 70%;
}
.sidebar .section > ul > li {
margin-right: -10px;
}
.sidebar .section h3, .sidebar .section h5 {
text-align: left;
padding-left: 0.5rem;
padding-right: 0.5rem;
font-weight: var(--heading-weight);
}
.sidebar .section h5 {
font-size: 1em;
margin-bottom: 0.5em;
}
.sidebar .namespace > h3 {
margin-bottom: 0;
padding: 0;
font-size: 1.5em;
text-transform: uppercase;
font-weight: 900;
}
.sidebar .namespace > p {
font-size: 0.9em;
opacity: 0.8;
padding-left: 0.5rem;
}
.sidebar .section {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.sidebar .links {
margin-bottom: 1rem;
}
.sidebar .section a {
display: block;
text-overflow: ellipsis;
overflow: hidden;
transition: background-color 150ms ease;
color: var(--sidebar-primary);
border-radius: var(--box-radius);
padding: 0.2rem 0.5rem;
margin-bottom: 0.15rem;
}
.sidebar .section a:hover {
background-color: rgba(127, 127, 127, 0.2);
color: var(--sidebar-text-color);
}
.sidebar .section a.current {
background-color: var(--sidebar-selected-bg);
color: white;
}
.sidebar .search {
box-sizing: border-box;
text-align: center;
}
.sidebar .search input[type="text"] {
border-color: transparent;
width: 100%;
border: 1px solid #ccc;
border-radius: 50px;
padding: 6px 12px;
display: inline-block;
font-size: 80%;
box-shadow: inset 0 1px 3px #ddd;
transition: border .3s linear;
}
/*********************************
* ANCHORS & TOGGLERS
*********************************/
.anchor,
.md-anchor {
position: relative;
z-index: 1;
text-decoration: none;
padding: 0 0.5em;
color: var(--text-color-muted);
}
.anchor:hover,
.md-anchor:hover {
color: var(--primary);
}
.anchor:not([href]),
.md-anchor:not([href]) {
display: none;
}
.anchor:before,
.md-anchor:before {
content: var(--anchor-sign); /*'§'*/
}
.toggle-wrapper {
position: relative;
}
.collapse-toggle {
position: absolute;
right: 0;
left: -2em;
white-space: nowrap;
text-decoration: none;
font-size: 0.8em;
color: transparent;
}
.collapse-toggle > .inner {
width: 1rem;
height: 1rem;
border-radius: calc(0.75 * var(--box-radius));
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
vertical-align: middle;
color: var(--box-text-color);
position: relative;
left: -0.25rem;
font-family: monospace;
font-size: 0.7rem;
font-weight: bold;
background: var(--box-bg);
}
/*********************************
* UTILITY
*********************************/
.deprecated > h6 > a {
opacity: 0.65;
}
.hidden {
display: none !important;
}
/*********************************
* CONTENT STYLING
*********************************/
.content {
padding: 2em 4em;
overflow: visible;
max-width: calc(var(--prefered-content-width) + 8em);
}
.content table:not(.table-display) {
border-spacing: 0 0.25rem;
}
.content td {
vertical-align: top;
}
.content td:first-child {
padding-right: 1rem;
}
.content td p:first-child {
margin-top: 0;
}
.content td h1, .content td h2 {
margin-left: 0;
font-size: 1.1em;
}
.content tr:first-child td {
border-top: 0;
}
kbd {
display: inline-block;
padding: 3px 5px;
font: 15px monospace;
line-height: 10px;
vertical-align: middle;
border: solid 1px;
border-radius: 3px;
box-shadow: inset 0 -1px 0;
cursor: default;
}
.content tr:first-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.35);
}
.content td {
vertical-align: top;
}
.content td:first-child {
padding-right: 1rem;
}
.content td p:first-child {
margin-top: 0;
}
.content td h4, .content td h5 {
margin-left: 0;
font-size: 1.1em;
}
.content tr:first-child td {
border-top: 0;
}
.srclink {
color: var(--text-color-muted);
font-size: 1rem;
font-weight: var(--body-font-weight);
flex-grow: 0;
text-decoration: none;
margin-left: auto;
position: relative;
z-index: 1;
}
.meta tr > td:not(:first-child) {
width: 100%;
}
.meta tr > td:first-child {
white-space: nowrap;
}
/*********************************
* DOCBLOCK STYLING
*********************************/
.docblock {
position: relative;
text-align: left;
}
.docblock h1 {
font-size: calc(1.3em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h2 {
font-size: calc(1.2em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h3 {
font-size: calc(1.1em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h4 {
font-size: calc(1.05em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h1,
.docblock h2,
.docblock h3,
.docblock h4,
.docblock h5,
.docblock h6 {
color: var(--heading-docblock-color)
}
.docblock table {
margin: .25em 0;
max-width: 100%;
font-size: var(--table-font-size);
}
.docblock table td {
padding: .25em;
}
.docblock table th {
padding: .25em;
text-align: left;
font-family: var(--heading-table-font-family);
font-weight: var(--heading-table-weight);
}
.docblock table tr th:first-child,
.docblock table tr td:first-child {
padding-left: 0;
}
.docblock table tr th:last-child,
.docblock table tr td:last-child {
padding-right: 0;
}
table.enum-members,
table.results {
border-radius: var(--box-radius);
border: 1px solid var(--text-color-muted);
border-spacing: 0 0 !important;
font-size: 80%;
}
table.enum-members tr th,
table.results tr th {
border-top-color: var(--body-bg);
background-color: var(--box-bg);
border-bottom: 1px solid var(--text-color-muted);
}
table.enum-members tr th:first-child,
table.enum-members tr td:first-child {
min-width: 25em;
padding-left: .5em;
}
table.results tr th:first-child,
table.results tr td:first-child {
padding-left: .5em;
}
table.enum-members tr th:last-child,
table.enum-members tr td:last-child,
table.results tr th:last-child,
table.results tr td:last-child {
max-width: 35em;
padding-right: .5em;
}
table.results tr td code {
font-size: 100%;
}
.docblock ul li,
.docblock ol li {
padding-top: 0.15rem;
padding-bottom: 0.15rem;
}
.docblock ul.type {
list-style: none;
}
.docblock ul.type li::before {
content: "»";
color: var(--text-color);
display: inline-block;
width: 1em;
margin-left: -1em;
}
/**************************
RESPONSIVENESS
**************************/
@media (max-width: 700px) {
body {
padding-top: 0px;
}
#body-wrapper {
flex-direction: column;
overflow: hidden;
}
#main {
width: 100%;
padding: 2rem;
}
.sidebar {
position: static;
height: initial;
order: 1;
}
}

View File

@@ -23,7 +23,6 @@ push=0
list=0 list=0
print_help=0 print_help=0
no_login=0 no_login=0
no_cache=0
while (($# > 0)); do while (($# > 0)); do
case "${1%%=*}" in case "${1%%=*}" in
@@ -33,9 +32,8 @@ while (($# > 0)); do
list) list=1;; list) list=1;;
help) print_help=1;; help) print_help=1;;
--base|-b) read_arg base "$@" || shift;; --base|-b) read_arg base "$@" || shift;;
--version|-v) read_arg base_version "$@" || shift;; --base-version) read_arg base_version "$@" || shift;;
--no-login) no_login=1;; --no-login) no_login=1;;
--no-cache) no_cache=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;; *) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac esac
shift shift
@@ -105,21 +103,11 @@ TAG="${REGISTRY}/gnome/gtk/${base}:${base_version}"
if [ $build == 1 ]; then if [ $build == 1 ]; then
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}" echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
if [ $no_cache == 0 ]; then ${CMD} build \
${CMD} build \ ${format} \
${format} \ --build-arg HOST_USER_ID="$UID" \
--build-arg HOST_USER_ID="$UID" \ --tag "${TAG}" \
--tag "${TAG}" \ --file "${base}.Dockerfile" .
--file "${base}.Dockerfile" .
else
${CMD} build \
${format} \
--no-cache \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
fi
exit $? exit $?
fi fi
@@ -138,8 +126,7 @@ if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}" echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
${CMD} run \ ${CMD} run \
--rm \ --rm \
--userns=keep-id \ --volume "$(pwd)/..:/home/user/app" \
--volume "$(pwd)/..:/home/user/app:rw,z" \
--workdir "/home/user/app" \ --workdir "/home/user/app" \
--tty \ --tty \
--interactive "${TAG}" \ --interactive "${TAG}" \

View File

@@ -1,32 +0,0 @@
#!/usr/bin/sh
#
builddir=$1
suite=$2
unit=$3
echo "** builddir: ${builddir}"
echo "** suite: ${suite}"
echo "** unit: ${unit}"
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
weston --backend=headless-backend.so --socket=wayland-5 --idle-time=0 &
compositor=$!
export WAYLAND_DISPLAY=wayland-5
meson test -C ${builddir} \
--print-errorlogs \
--setup=wayland \
--suite=${suite} \
--no-suite=failing \
--no-suite=flaky \
--no-suite=wayland_failing \
--no-suite=gsk-compare-broadway \
--verbose \
"${unit}"
exit_code=$?
kill ${compositor}
exit ${exit_code}

View File

@@ -2,43 +2,25 @@
set -e set -e
ancestor_horizon=31 # days (one month) # We need to add a new remote for the upstream master, since this script could
# be running in a personal fork of the repository which has out of date branches.
# Recently, git is picky about directory ownership. Tell it not to worry. if [ "${CI_PROJECT_NAMESPACE}" != "GNOME" ]; then
git config --global --add safe.directory "$PWD" echo "Retrieving the current upstream repository from ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}..."
# We need to add a new remote for the upstream target branch, since this script
# could be running in a personal fork of the repository which has out of date
# branches.
#
# Limit the fetch to a certain date horizon to limit the amount of data we get.
# If the branch was forked from origin/main before this horizon, it should
# probably be rebased.
if ! git ls-remote --exit-code upstream >/dev/null 2>&1 ; then
git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git
git fetch upstream
ORIGIN="upstream"
else
echo "Reusing the existing repository on ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}"
ORIGIN="origin"
fi fi
# Work out the newest common ancestor between the detached HEAD that this CI job # Work out the newest common ancestor between the detached HEAD that this CI job
# has checked out, and the upstream target branch (which will typically be # has checked out, and the upstream target branch (which will typically be
# `upstream/main` or `upstream/glib-2-62`). # `upstream/master` or `upstream/gtk-3-24`).
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` or `${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}` #
# are only defined if were running in a merge request pipeline, # `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if were running in
# fall back to `${CI_DEFAULT_BRANCH}` or `${CI_COMMIT_BRANCH}` respectively # a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise.
# otherwise. newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${ORIGIN}/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1)
source_branch="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-${CI_COMMIT_BRANCH}}"
target_branch="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}"
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" origin "${source_branch}"
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" upstream "${target_branch}"
newest_common_ancestor_sha=$(git merge-base upstream/${target_branch} origin/${source_branch})
if [ -z "${newest_common_ancestor_sha}" ]; then
echo "Couldnt find common ancestor with upstream main branch. This typically"
echo "happens if you branched from main a long time ago. Please update"
echo "your clone, rebase, and re-push your branch."
exit 1
fi
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1 git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1
exit_status=$? exit_status=$?
@@ -54,7 +36,7 @@ exit_status=$?
echo "" echo ""
echo "Note that clang-format output is advisory and cannot always match the" echo "Note that clang-format output is advisory and cannot always match the"
echo "GTK coding style, documented at:" echo "GTK coding style, documented at:"
echo " https://gitlab.gnome.org/GNOME/gtk/blob/main/docs/CODING-STYLE.md" echo " https://gitlab.gnome.org/GNOME/gtk/blob/master/docs/CODING-STYLE"
echo "Warnings from this tool can be ignored in favour of the documented " echo "Warnings from this tool can be ignored in favour of the documented "
echo "coding style, or in favour of matching the style of existing" echo "coding style, or in favour of matching the style of existing"
echo "surrounding code." echo "surrounding code."

View File

@@ -1,31 +1,23 @@
#!/bin/bash #!/bin/bash
set -x set +x
set +e set +e
srcdir=$( pwd ) srcdir=$( pwd )
builddir=$1 builddir=$1
setup=$2 backend=$2
suite=$3
multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
# Ignore memory leaks lower in dependencies # Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:detect_leaks=0:allocator_may_return_null=1 export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
export G_SLICE=always-malloc
case "${setup}" in case "${backend}" in
x11*) x11)
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \ xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
meson test -C ${builddir} \ meson test -C ${builddir} \
--quiet \ --timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--timeout-multiplier "${multiplier}" \
--print-errorlogs \ --print-errorlogs \
--setup=${setup} \ --setup=${backend} \
--suite=${suite//,/ --suite=} \ --suite=gtk \
--no-suite=failing \
--no-suite=${setup}_failing \
--no-suite=flaky \
--no-suite=headless \
--no-suite=gsk-compare-broadway --no-suite=gsk-compare-broadway
# Store the exit code for the CI run, but always # Store the exit code for the CI run, but always
@@ -33,7 +25,7 @@ case "${setup}" in
exit_code=$? exit_code=$?
;; ;;
wayland*) wayland)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)" export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
weston --backend=headless-backend.so --socket=wayland-5 --idle-time=0 & weston --backend=headless-backend.so --socket=wayland-5 --idle-time=0 &
@@ -41,22 +33,17 @@ case "${setup}" in
export WAYLAND_DISPLAY=wayland-5 export WAYLAND_DISPLAY=wayland-5
meson test -C ${builddir} \ meson test -C ${builddir} \
--quiet \ --timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--timeout-multiplier "${multiplier}" \
--print-errorlogs \ --print-errorlogs \
--setup=${setup} \ --setup=${backend} \
--suite=${suite//,/ --suite=} \ --suite=gtk \
--no-suite=failing \
--no-suite=${setup}_failing \
--no-suite=flaky \
--no-suite=headless \
--no-suite=gsk-compare-broadway --no-suite=gsk-compare-broadway
exit_code=$?
exit_code=$?
kill ${compositor} kill ${compositor}
;; ;;
broadway*) broadway)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)" export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
${builddir}/gdk/broadway/gtk4-broadwayd :5 & ${builddir}/gdk/broadway/gtk4-broadwayd :5 &
@@ -64,42 +51,32 @@ case "${setup}" in
export BROADWAY_DISPLAY=:5 export BROADWAY_DISPLAY=:5
meson test -C ${builddir} \ meson test -C ${builddir} \
--quiet \ --timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--timeout-multiplier "${multiplier}" \
--print-errorlogs \ --print-errorlogs \
--setup=${setup} \ --setup=${backend} \
--suite=${suite//,/ --suite=} \ --suite=gtk \
--no-suite=failing \
--no-suite=${setup}_failing \
--no-suite=flaky \
--no-suite=headless \
--no-suite=gsk-compare-opengl --no-suite=gsk-compare-opengl
# don't let Broadway failures fail the run, for now
exit_code=0
kill ${server} kill ${server}
;; ;;
*)
echo "Failed to add ${setup} to .gitlab-ci/run-tests.sh"
exit 1
;;
esac esac
cd ${builddir} cd ${builddir}
$srcdir/.gitlab-ci/meson-junit-report.py \ $srcdir/.gitlab-ci/meson-junit-report.py \
--project-name=gtk \ --project-name=gtk \
--backend="${setup}" \ --backend=${backend} \
--job-id="${CI_JOB_NAME}" \ --job-id="${CI_JOB_NAME}" \
--output="report-${setup}.xml" \ --output=report-${backend}.xml \
"meson-logs/testlog-${setup}.json" meson-logs/testlog-${backend}.json
$srcdir/.gitlab-ci/meson-html-report.py \ $srcdir/.gitlab-ci/meson-html-report.py \
--project-name=gtk \ --project-name=gtk \
--backend="${setup}" \ --backend=${backend} \
--job-id="${CI_JOB_NAME}" \ --job-id="${CI_JOB_NAME}" \
--reftest-output-dir="testsuite/reftests/output/${setup}" \ --reftest-output-dir="testsuite/reftests/output/${backend}" \
--output="report-${setup}.html" \ --output=report-${backend}.html \
"meson-logs/testlog-${setup}.json" meson-logs/testlog-${backend}.json
exit $exit_code exit $exit_code

View File

@@ -1,5 +0,0 @@
#! /bin/sh
. /etc/os-release
echo $PRETTY_NAME

View File

@@ -1,13 +0,0 @@
#!/bin/bash
set -eux -o pipefail
xcodebuild -version || :
if [ -z "$SDKROOT" ]; then
xcodebuild -showsdks || :
else
echo "SDKROOT = $SDKROOT"
fi
system_profiler SPSoftwareDataType || :

View File

@@ -15,7 +15,7 @@ meson \
-Dx11-backend=true \ -Dx11-backend=true \
-Dwayland-backend=true \ -Dwayland-backend=true \
-Dbroadway-backend=true \ -Dbroadway-backend=true \
-Dvulkan=enabled \ -Dvulkan=yes \
-Dprofiler=true \ -Dprofiler=true \
--werror \ --werror \
${EXTRA_MESON_FLAGS:-} \ ${EXTRA_MESON_FLAGS:-} \

View File

@@ -1,14 +0,0 @@
@echo on
:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the
:: specified build architecture
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
@echo on
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson~=0.64 || goto :error
meson setup -Dbackend_max_links=1 -Ddebug=false -Dmedia-gstreamer=disabled -Dvulkan=disabled _build || goto :error
ninja -C _build || goto :error
goto :EOF
:error
exit /b 1

View File

@@ -15,9 +15,9 @@ pacman --noconfirm -Suy
pacman --noconfirm -S --needed \ pacman --noconfirm -S --needed \
base-devel \ base-devel \
git \ git \
mingw-w64-$MSYS2_ARCH-cc \ mingw-w64-$MSYS2_ARCH-toolchain \
mingw-w64-$MSYS2_ARCH-ccache \ mingw-w64-$MSYS2_ARCH-ccache \
mingw-w64-$MSYS2_ARCH-pkgconf \ mingw-w64-$MSYS2_ARCH-pkg-config \
mingw-w64-$MSYS2_ARCH-gobject-introspection \ mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-meson \ mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \ mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \
@@ -30,25 +30,41 @@ pacman --noconfirm -S --needed \
mingw-w64-$MSYS2_ARCH-libepoxy \ mingw-w64-$MSYS2_ARCH-libepoxy \
mingw-w64-$MSYS2_ARCH-pango \ mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-fribidi \ mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \ mingw-w64-$MSYS2_ARCH-gst-plugins-bad \
mingw-w64-$MSYS2_ARCH-shared-mime-info \ mingw-w64-$MSYS2_ARCH-shared-mime-info
mingw-w64-$MSYS2_ARCH-python-gobject \
mingw-w64-$MSYS2_ARCH-shaderc \
mingw-w64-$MSYS2_ARCH-vulkan \
mingw-w64-$MSYS2_ARCH-vulkan-headers
mkdir -p _ccache mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)" export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
# https://gitlab.gnome.org/GNOME/gtk/-/issues/2243
# https://gitlab.gnome.org/GNOME/gtk/-/issues/3002
if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
git clone https://gitlab.gnome.org/GNOME/glib.git _glib
meson setup _glib_build _glib
meson compile -C _glib_build
meson install -C _glib_build
fi
pkg-config --modversion glib-2.0
if ! pkg-config --atleast-version=1.47.0 pango; then
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
meson setup _pango_build _pango
meson compile -C _pango_build
meson install -C _pango_build
fi
pkg-config --modversion pango
# Build # Build
ccache --zero-stats ccache --zero-stats
ccache --show-stats ccache --show-stats
export CCACHE_DISABLE=true export CCACHE_DISABLE=true
meson setup \ meson \
-Dx11-backend=false \ -Dx11-backend=false \
-Dwayland-backend=false \ -Dwayland-backend=false \
-Dwin32-backend=true \ -Dwin32-backend=true \
-Dvulkan=disabled \
-Dintrospection=enabled \ -Dintrospection=enabled \
-Dgtk:werror=true \ -Dgtk:werror=true \
_build _build
@@ -56,5 +72,3 @@ unset CCACHE_DISABLE
ninja -C _build ninja -C _build
ccache --show-stats ccache --show-stats
tar zcf _build/gtkdll.tar.gz _build/gtk/libgtk*.dll

View File

@@ -1,13 +1,4 @@
<!--
Please, read the CONTRIBUTING.md guide on how to file a new issue.
https://gitlab.gnome.org/GNOME/gtk/-/blob/main/CONTRIBUTING.md
-->
## Steps to reproduce ## Steps to reproduce
<!--
Please, explain the sequence of actions necessary to reproduce the
bug
-->
1. ... 1. ...
2. ... 2. ...
@@ -41,8 +32,5 @@
## Additional information ## Additional information
<!-- <!--
- Screenshots or screen recordings are useful for visual errors - Screenshots or screen recordings are useful for visual errors
- Attaching a screenshot or a video without explaining the current
behavior and the actions necessary to reproduce the bug will lead
to the bug being closed
- Please report any warning or message printed on the terminal - Please report any warning or message printed on the terminal
--> -->

View File

@@ -1,14 +1,4 @@
<!--
Please, read the CONTRIBUTING.md guide on how to file a new issue.
https://gitlab.gnome.org/GNOME/gtk/-/blob/main/CONTRIBUTING.md
-->
## Steps to reproduce ## Steps to reproduce
<!--
Please, explain the sequence of actions necessary to reproduce the
crash
-->
1. ... 1. ...
2. ... 2. ...

45
AUTHORS
View File

@@ -7,7 +7,7 @@ Peter Mattis <petm@xcf.berkeley.edu>
Spencer Kimball <spencer@xcf.berkeley.edu> Spencer Kimball <spencer@xcf.berkeley.edu>
Josh MacDonald <jmacd@xcf.berkeley.edu> Josh MacDonald <jmacd@xcf.berkeley.edu>
The team that build GTK 2 (in alphabetical order) The Team that build GTK 2 (in alphabetical order)
------------------------------------------------- -------------------------------------------------
Shawn T. Amundson <amundson@gtk.org> Shawn T. Amundson <amundson@gtk.org>
Jerome Bolliet <bolliet@gtk.org> Jerome Bolliet <bolliet@gtk.org>
@@ -28,8 +28,9 @@ Jay Painter <jpaint@gtk.org>
Manish Singh <manish@gtk.org> Manish Singh <manish@gtk.org>
Owen Taylor <otaylor@gtk.org> Owen Taylor <otaylor@gtk.org>
The team that built GTK 3 The current team (GTK 3 and 4)
------------------------- ------------------------------
Jonas Ådahl <jadahl@gmail.com> Jonas Ådahl <jadahl@gmail.com>
Tim Bäder <mail@baedert.org> Tim Bäder <mail@baedert.org>
Emmanuele Bassi <ebassi@gnome.org> Emmanuele Bassi <ebassi@gnome.org>
@@ -39,16 +40,6 @@ Carlos Garnacho <mrgarnacho@gmail.com>
Alexander Larsson <alexl@redhat.com> Alexander Larsson <alexl@redhat.com>
Benjamin Otte <otte@gnome.org> Benjamin Otte <otte@gnome.org>
The current team (GTK 4)
------------------------
Jonas Ådahl <jadahl@gmail.com>
Emmanuele Bassi <ebassi@gnome.org>
Christian Hergert <chergert@gnome.org>
Chun-wei Fan <fanchunwei@src.gnome.org>
Matthias Clasen <mclasen@redhat.com>
Carlos Garnacho <mrgarnacho@gmail.com>
Benjamin Otte <otte@gnome.org>
There are many others who have contributed patches; we thank them, There are many others who have contributed patches; we thank them,
GTK is much better because of them. GTK is much better because of them.
@@ -58,15 +49,35 @@ Over time, GTK has incorporated some pieces of software which
started as independent projects. We list the original authors here: started as independent projects. We list the original authors here:
MS-Windows theme engine
-----------------------
Raymond Penners
Dom Lachowicz
Pixbuf theme engine
-------------------
Owen Taylor
IME input method IME input method
---------------- ----------------
Takuro Ashie Takuro Ashie
Kazuki IWAMOTO Kazuki IWAMOTO
MacOS backend
------------- Mac OS X backend
----------------
Anders Carlsson Anders Carlsson
GtkInspector (originally gtkparasite)
------------------------------------- DirectFB backend
----------------
Denis Oliver Kropp
Sven Neumann
Mike Emmel
gtkparasite
-----------
Christian Hammond Christian Hammond

View File

@@ -21,7 +21,7 @@ many things that we value:
Please, do not use the issue tracker for support questions. If you have Please, do not use the issue tracker for support questions. If you have
questions on how to use GTK effectively, you can use: questions on how to use GTK effectively, you can use:
- the `gtk` [room on matrix](https://matrix.to/#/#gtk:gnome.org) - the `#gtk` IRC channel on irc.gnome.org
- the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk) - the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk)
You can also look at the GTK tag on [Stack You can also look at the GTK tag on [Stack
@@ -35,7 +35,8 @@ The issue tracker is meant to be used for actionable issues only.
You should not open a new issue for security related questions. You should not open a new issue for security related questions.
When in doubt, follow the process for [GNOME security issues](https://security.gnome.org/). When in doubt, send an email to the [security](mailto:security@gnome.org)
mailing list.
### Bug reports ### Bug reports
@@ -43,7 +44,6 @@ If you're reporting a bug make sure to list:
0. which version of GTK are you using? 0. which version of GTK are you using?
0. which operating system are you using? 0. which operating system are you using?
0. what display and graphics driver are you using?
0. the necessary steps to reproduce the issue 0. the necessary steps to reproduce the issue
0. the expected outcome 0. the expected outcome
0. a description of the behavior; screenshots are also welcome 0. a description of the behavior; screenshots are also welcome
@@ -144,28 +144,33 @@ $ git clone https://gitlab.gnome.org/yourusername/gtk.git
$ cd gtk $ cd gtk
``` ```
**Note**: if you plan to push changes to back to the main repository and
have a GNOME account, you can skip the fork, and use the following instead:
```sh
$ git clone git@gitlab.gnome.org:GNOME/gtk.git
$ cd gtk
```
To compile the Git version of GTK on your system, you will need to To compile the Git version of GTK on your system, you will need to
configure your build using Meson: configure your build using Meson:
```sh ```sh
$ meson setup _builddir . $ meson _builddir .
$ meson compile -C _builddir $ cd _builddir
$ ninja
``` ```
Typically, you should work on your own branch: Typically, you should work on your own branch:
```sh ```sh
$ git switch -C your-branch $ git checkout -b your-branch
``` ```
Once you've finished working on the bug fix or feature, push the branch Once you've finished working on the bug fix or feature, push the branch
to the Git repository and open a new merge request, to let the GTK to the Git repository and open a new merge request, to let the GTK
maintainers review your contribution. maintainers review your contribution.
**Important**: Do **not** attach a diff or a patch file to a GitLab issue.
Patches cannot be reviewed, and do not not go through the CI pipeline. If
you wish to submit your changes to GTK, always use a merge request.
### Code reviews ### Code reviews
Each contribution is reviewed by the core developers of the GTK project. Each contribution is reviewed by the core developers of the GTK project.
@@ -208,7 +213,7 @@ Closes #1234
`git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`. `git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`.
- If your commit is addressing an issue, use the - If your commit is addressing an issue, use the
[GitLab syntax](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) [GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html)
to automatically close the issue when merging the commit with the upstream to automatically close the issue when merging the commit with the upstream
repository: repository:
@@ -238,18 +243,20 @@ people committing to GTK to follow a few rules:
code, you should always ask. If your change is minor and you've been code, you should always ask. If your change is minor and you've been
working on GTK for a while it probably isn't necessary to ask. But when working on GTK for a while it probably isn't necessary to ask. But when
in doubt, ask. Even if your change is correct, somebody may know a in doubt, ask. Even if your change is correct, somebody may know a
better way to do things. better way to do things. If you are making changes to GTK, you should
The `gtk` [room on matrix](https://matrix.to/#/#gtk:gnome.org) is also a be subscribed to the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
good place to find GTK developers to discuss changes, but if you live mailing list; this is a good place to ask about intended changes.
outside of the EU/US time zones, the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk) The `#gtk` IRC channel on irc.gnome.org is also a good place to find GTK
is the most certain and preferred method. developers to discuss changes, but if you live outside of the EU/US time
zones, an email to the gtk-devel mailing list is the most certain and
preferred method.
0. Ask _first_. 0. Ask _first_.
0. Always write a meaningful commit message. Changes without a sufficient 0. Always write a meaningful commit message. Changes without a sufficient
commit message will be reverted. commit message will be reverted.
0. Never push to the `main` branch, or any stable branches, directly; you 0. Never push to the `master` branch, or any stable branches, directly; you
should always go through a merge request, to ensure that the code is should always go through a merge request, to ensure that the code is
tested on the CI infrastructure at the very least. A merge request is tested on the CI infrastructure at the very least. A merge request is
also the proper place to get a comprehensive code review from the core also the proper place to get a comprehensive code review from the core
@@ -257,4 +264,4 @@ people committing to GTK to follow a few rules:
If you have been contributing to GTK for a while and you don't have commit If you have been contributing to GTK for a while and you don't have commit
access to the repository, you may ask to obtain it following the [GNOME account access to the repository, you may ask to obtain it following the [GNOME account
process](https://handbook.gnome.org/infrastructure/developer-access.html). process](https://wiki.gnome.org/AccountsTeam/NewAccounts).

12161
NEWS

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
GTK — The GTK toolkit GTK — The GTK toolkit
===================== =====================
[![Build status](https://gitlab.gnome.org/GNOME/gtk/badges/main/pipeline.svg)](https://gitlab.gnome.org/GNOME/gtk/-/commits/main) [![Build status](https://gitlab.gnome.org/GNOME/gtk/badges/master/pipeline.svg)](https://gitlab.gnome.org/GNOME/gtk/-/commits/master)
General information General information
------------------- -------------------
@@ -10,12 +10,10 @@ GTK is a multi-platform toolkit for creating graphical user interfaces.
Offering a complete set of widgets, GTK is suitable for projects ranging Offering a complete set of widgets, GTK is suitable for projects ranging
from small one-off projects to complete application suites. from small one-off projects to complete application suites.
GTK is a free and open-source software project. The licensing terms GTK is free software and part of the GNU Project. However, the
for GTK, the GNU LGPL, allow it to be used by all developers, including those licensing terms for GTK, the GNU LGPL, allow it to be used by all
developing proprietary software, without any license fees or royalties. developers, including those developing proprietary software, without any
license fees or royalties.
GTK is hosted by the GNOME project (thanks!) and used by a wide variety
of applications and projects.
The official download location The official download location
@@ -34,16 +32,9 @@ Discussion forum
- https://discourse.gnome.org/c/platform/core/ - https://discourse.gnome.org/c/platform/core/
Nightly documentation can be found at Nightly documentation can be found at
- Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk4/ - Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk/
- Gdk: https://gnome.pages.gitlab.gnome.org/gtk/gdk4/ - Gdk: https://gnome.pages.gitlab.gnome.org/gtk/gdk/
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk4/ - Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk/
Nightly flatpaks of our demos can be installed from the
[GNOME Nightly](https://wiki.gnome.org/Apps/Nightly) repository:
- `flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo`
- `flatpak install gnome-nightly org.gtk.Demo4`
- `flatpak install gnome-nightly org.gtk.WidgetFactory4`
- `flatpak install gnome-nightly org.gtk.IconBrowser4`
Building and installing Building and installing
----------------------- -----------------------
@@ -67,13 +58,6 @@ building for:
- [Graphene](https://github.com/ebassi/graphene) - [Graphene](https://github.com/ebassi/graphene)
- [Xkb-common](https://github.com/xkbcommon/libxkbcommon) - [Xkb-common](https://github.com/xkbcommon/libxkbcommon)
If you are building the Wayland backend, you will also need:
- Wayland-client
- Wayland-protocols
- Wayland-cursor
- Wayland-EGL
If you are building the X11 backend, you will also need: If you are building the X11 backend, you will also need:
- Xlib, and the following X extensions: - Xlib, and the following X extensions:
@@ -86,24 +70,32 @@ If you are building the X11 backend, you will also need:
- xdamage - xdamage
- xcomposite - xcomposite
If you are building the Wayland backend, you will also need:
- Wayland-client
- Wayland-protocols
- Wayland-cursor
- Wayland-EGL
Once you have all the necessary dependencies, you can build GTK by using Once you have all the necessary dependencies, you can build GTK by using
Meson: Meson:
```sh ```sh
$ meson setup _build $ meson _build .
$ meson compile -C_build $ cd _build
$ ninja
``` ```
You can run the test suite using: You can run the test suite using:
```sh ```sh
$ meson test -C_build $ meson test
``` ```
And, finally, you can install GTK using: And, finally, you can install GTK using:
``` ```
$ sudo meson install -C_build $ sudo ninja install
``` ```
Complete information about installing GTK and related libraries Complete information about installing GTK and related libraries
@@ -113,19 +105,12 @@ can be found in the file:
docs/reference/gtk/html/gtk-building.html docs/reference/gtk/html/gtk-building.html
``` ```
Or [online](https://docs.gtk.org/gtk4/building.html) Or [online](https://developer.gnome.org/gtk4/stable/gtk-building.html)
Building from git
-----------------
The GTK sources are hosted on [gitlab.gnome.org](http://gitlab.gnome.org). The main
development branch is called `main`, and stable branches are named after their minor
version, for example `gtk-4-10`.
How to report bugs How to report bugs
------------------ ------------------
Bugs should be reported on the [issues page](https://gitlab.gnome.org/GNOME/gtk/issues/). Bugs should be reported on the [issues page](https://gitlab.gnome.org/GNOME/gtk/issues/new).
In the bug report please include: In the bug report please include:
@@ -159,17 +144,14 @@ Contributing to GTK
Please, follow the [contribution guide](./CONTRIBUTING.md) to know how to Please, follow the [contribution guide](./CONTRIBUTING.md) to know how to
start contributing to GTK. start contributing to GTK.
If you want to support GTK financially, please consider donating to
the GNOME project, which runs the infrastructure hosting GTK.
Release notes Release notes
------------- -------------
The release notes for GTK are part of the migration guide in the API The release notes for GTK are part of the migration guide in the API
reference. See: reference. See:
- [3.x release notes](https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html) - [3.x release notes](https://developer.gnome.org/gtk3/unstable/gtk-migrating-2-to-3.html)
- [4.x release notes](https://docs.gtk.org/gtk4/migrating-3to4.html) - [4.x release notes](https://developer.gnome.org/gtk4/unstable/gtk-migrating-3-to-4.html)
Licensing terms Licensing terms
--------------- ---------------

View File

@@ -1,43 +0,0 @@
diff -ur lua-5.1.4/src/Makefile lua-5.1.4-new/src/Makefile
--- lua-5.1.4/src/Makefile 2008-01-19 20:37:58.000000000 +0100
+++ lua-5.1.4-new/src/Makefile 2012-02-23 18:26:43.000000000 +0100
@@ -23,6 +23,7 @@
PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
LUA_A= liblua.a
+LUA_SO= liblua.so
CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
lundump.o lvm.o lzio.o
@@ -36,7 +37,7 @@
LUAC_O= luac.o print.o
ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
+ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
ALL_A= $(LUA_A)
default: $(PLAT)
@@ -51,6 +52,11 @@
$(AR) $@ $?
$(RANLIB) $@
+$(LUA_SO): $(CORE_O) $(LIB_O)
+ $(CC) -shared -ldl -Wl,-soname,$(LUA_SO).$(V) -o $@.$(R) $? -lm $(MYLDFLAGS)
+ ln -sf $(LUA_SO).$(R) $(LUA_SO).$(V)
+ ln -sf $(LUA_SO).$(R) $(LUA_SO)
+
$(LUA_T): $(LUA_O) $(LUA_A)
$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
--- lua-5.1.4/Makefile 2008-08-12 02:40:48.000000000 +0200
+++ lua-5.1.4-new/Makefile 2012-02-23 19:06:32.000000000 +0100
@@ -53,7 +53,7 @@
all: $(PLAT)
$(PLATS) clean:
- cd src && $(MAKE) $@
+ cd src && $(MAKE) $@ V=$(V) R=$(R)
test: dummy
src/lua test/hello.lua

View File

@@ -35,16 +35,15 @@
"modules" : [ "modules" : [
{ {
"name" : "wayland", "name" : "wayland",
"buildsystem" : "meson", "buildsystem" : "autotools",
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"-Ddocumentation=false" "--disable-documentation"
], ],
"sources" : [ "sources" : [
{ {
"type" : "git", "type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git", "url" : "https://github.com/wayland-project/wayland.git"
"branch" : "main"
} }
] ]
}, },
@@ -54,7 +53,8 @@
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"--libdir=/app/lib", "--libdir=/app/lib",
"-Dtests=false" "-Dtests=false",
"-Dbenchmarks=false"
], ],
"sources" : [ "sources" : [
{ {
@@ -93,106 +93,19 @@
} }
] ]
}, },
{
"name": "boost",
"buildsystem": "simple",
"build-commands": [
"./bootstrap.sh --prefix=/app --with-libraries=date_time,filesystem,iostreams,locale,regex,system,thread,python,program_options,test,serialization",
"./b2 --build-type=minimal link=shared -j $FLATPAK_BUILDER_N_JOBS",
"./b2 --build-type=minimal link=shared install"
],
"sources": [
{
"type": "archive",
"url": "https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2",
"sha256": "475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39"
}
]
},
{
"name": "lua-5.1",
"buildsystem": "simple",
"build-commands": [
"make -j $FLATPAK_BUILDER_N_JOBS CFLAGS=\"$CFLAGS -fPIC -DLUA_USE_LINUX\" linux",
"make INSTALL_TOP=$FLATPAK_DEST TO_LIB='liblua.a liblua.so.5.1.5' install",
"ln -sf liblua.so.5.1.5 $FLATPAK_DEST/lib/liblua.so",
"ln -sf liblua.so.5.1.5 $FLATPAK_DEST/lib/liblua.so.5.1",
"install -Dm0644 etc/lua.pc $FLATPAK_DEST/lib/pkgconfig/lua.pc",
"ln -sf lua.pc $FLATPAK_DEST/lib/pkgconfig/lua51.pc",
"ln -sf lua.pc $FLATPAK_DEST/lib/pkgconfig/lua5.1.pc",
"ln -sf lua.pc $FLATPAK_DEST/lib/pkgconfig/lua-5.1.pc"
],
"sources": [
{
"type": "archive",
"url": "https://www.lua.org/ftp/lua-5.1.5.tar.gz",
"sha256": "2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333"
},
{
"type": "patch",
"path": "lua-5.1.5-so.patch"
},
{
"type": "shell",
"commands": [
"sed -i \"s|/usr/local|$FLATPAK_DEST|\" etc/lua.pc src/luaconf.h"
]
}
],
"cleanup": [
"*.a",
"/bin",
"/include",
"/lib/pkgconfig",
"/man"
]
},
{
"name" : "highlight",
"buildsystem" : "simple",
"builddir" : true,
"build-commands" : [
"sed -i -e 's#^PREFIX = /usr#PREFIX = /app#' makefile",
"make",
"make install"
],
"sources" : [
{
"type" : "archive",
"url" : "http://www.andre-simon.de/zip/highlight-4.0.tar.bz2",
"sha256" : "f40dcba26e011a2c67df874f4d9b0238c2c6b065163ce8de3d8371b9dfce864d"
}
]
},
{
"name" : "pango",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/pango.git",
"branch" : "main"
}
]
},
{ {
"name" : "gtk", "name" : "gtk",
"buildsystem" : "meson", "buildsystem" : "meson",
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"--libdir=/app/lib", "--libdir=/app/lib",
"-Dbuildtype=debugoptimized", "-Denable_vulkan=no",
"-Dprofile=devel" "-Dbuildtype=debugoptimized"
], ],
"sources" : [ "sources" : [
{ {
"type" : "git", "type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git", "url" : "https://gitlab.gnome.org/GNOME/gtk.git"
"branch" : "main"
} }
] ]
} }

View File

@@ -35,16 +35,15 @@
"modules" : [ "modules" : [
{ {
"name" : "wayland", "name" : "wayland",
"buildsystem" : "meson", "buildsystem" : "autotools",
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"-Ddocumentation=false" "--disable-documentation"
], ],
"sources" : [ "sources" : [
{ {
"type" : "git", "type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git", "url" : "https://github.com/wayland-project/wayland.git"
"branch" : "main"
} }
] ]
}, },
@@ -54,7 +53,8 @@
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"--libdir=/app/lib", "--libdir=/app/lib",
"-Dtests=false" "-Dtests=false",
"-Dbenchmarks=false"
], ],
"sources" : [ "sources" : [
{ {
@@ -93,35 +93,19 @@
} }
] ]
}, },
{
"name" : "pango",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/pango.git",
"branch" : "main"
}
]
},
{ {
"name" : "gtk", "name" : "gtk",
"buildsystem" : "meson", "buildsystem" : "meson",
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"--libdir=/app/lib", "--libdir=/app/lib",
"-Dbuildtype=debugoptimized", "-Denable_vulkan=no",
"-Dprofile=devel" "-Dbuildtype=debugoptimized"
], ],
"sources" : [ "sources" : [
{ {
"type" : "git", "type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git", "url" : "https://gitlab.gnome.org/GNOME/gtk.git"
"branch" : "main"
} }
] ]
} }

View File

@@ -35,16 +35,15 @@
"modules" : [ "modules" : [
{ {
"name" : "wayland", "name" : "wayland",
"buildsystem" : "meson", "buildsystem" : "autotools",
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"-Ddocumentation=false" "--disable-documentation"
], ],
"sources" : [ "sources" : [
{ {
"type" : "git", "type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git", "url" : "https://github.com/wayland-project/wayland.git"
"branch" : "main"
} }
] ]
}, },
@@ -54,7 +53,8 @@
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"--libdir=/app/lib", "--libdir=/app/lib",
"-Dtests=false" "-Dtests=false",
"-Dbenchmarks=false"
], ],
"sources" : [ "sources" : [
{ {
@@ -93,35 +93,19 @@
} }
] ]
}, },
{
"name" : "pango",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/pango.git",
"branch" : "main"
}
]
},
{ {
"name" : "gtk", "name" : "gtk",
"buildsystem" : "meson", "buildsystem" : "meson",
"builddir" : true, "builddir" : true,
"config-opts" : [ "config-opts" : [
"--libdir=/app/lib", "--libdir=/app/lib",
"-Dbuildtype=debugoptimized", "-Denable_vulkan=no",
"-Dprofile=devel" "-Dbuildtype=debugoptimized"
], ],
"sources" : [ "sources" : [
{ {
"type" : "git", "type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git", "url" : "https://gitlab.gnome.org/GNOME/gtk.git"
"branch" : "main"
} }
] ]
} }
@@ -130,6 +114,7 @@
"env" : { "env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''", "DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl", "GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true" "G_ENABLE_DEBUG" : "true"
} }
} }

View File

@@ -1,136 +0,0 @@
{
"app-id" : "org.gtk.gtk4.NodeEditor",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-node-editor",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs",
"--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
{
"name" : "wayland",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"-Ddocumentation=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
}
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dtests=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name" : "pango",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/pango.git",
"branch" : "main"
}
]
},
{
"name" : "gtk",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dbuildtype=debugoptimized",
"-Dprofile=devel"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git",
"branch" : "main"
}
]
}
],
"build-options" : {
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"G_ENABLE_DEBUG" : "true"
}
}
}

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env python3
import os
import shutil
import subprocess
from pathlib import PurePath
stylesheets = [
'gtk/theme/Default/Default-light.css',
'gtk/theme/Default/Default-dark.css',
'gtk/theme/Default/Default-hc.css',
'gtk/theme/Default/Default-hc-dark.css',
]
references = [
'docs/reference/gtk/gtk4',
'docs/reference/gsk/gsk4',
'docs/reference/gdk/gdk4',
'docs/reference/gdk/gdk4-wayland',
'docs/reference/gdk/gdk4-x11',
]
sourceroot = os.environ.get('MESON_SOURCE_ROOT')
buildroot = os.environ.get('MESON_BUILD_ROOT')
distroot = os.environ.get('MESON_DIST_ROOT')
for stylesheet in stylesheets:
stylesheet_path = PurePath(stylesheet)
src = PurePath(sourceroot, stylesheet_path.with_suffix('.scss'))
dst = PurePath(distroot, stylesheet_path)
subprocess.call(['sassc', '-a', '-M', '-t', 'compact', src, dst])
for reference in references:
src_path = os.path.join(buildroot, reference)
if os.path.isdir(src_path):
dst_path = os.path.join(distroot, reference)
shutil.copytree(src_path, dst_path)

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env python3
import os
import subprocess
import sys
repodir = sys.argv[1]
profile = sys.argv[2]
sys.stdout.write("/* This file is auto-generated. Do not edit. */\n")
sys.stdout.write("#pragma once\n")
sys.stdout.write("\n")
sys.stdout.write(f"#define PROFILE \"{profile}\"\n")
short_sha = os.environ.get('CI_COMMIT_SHORT_SHA')
if short_sha is None:
cmd = ["git", "-C", repodir, "rev-parse", "--short", "HEAD"]
try:
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as p:
short_sha = p.stdout.read().decode('utf-8').rstrip("\n")
except FileNotFoundError:
short_sha = ''
if profile != 'default':
short_sha = 'devel'
sys.stdout.write(f"#define VCS_TAG \"{short_sha}\"\n")

View File

@@ -1,201 +0,0 @@
#!/usr/bin/env python3
#
# SPDX-FileCopyrightText: 2022 Collabora Inc.
# 2023 Emmanuele Bassi
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Original author: Xavier Claessens <xclaesse@gmail.com>
import argparse
import textwrap
from pathlib import Path
# Disable line length warnings as wrapping the C code templates would be hard
# flake8: noqa: E501
def gen_versions_macros(args, current_major_version, current_minor_version, current_micro_version):
with args.out_path.open("w", encoding="utf-8") as ofile, args.in_path.open(
"r", encoding="utf-8"
) as ifile:
for line in ifile.readlines():
if "@GDK_VERSIONS@" in line:
ofile.write(
textwrap.dedent(
f"""\
/**
* GDK_MAJOR_VERSION:
*
* The major version component of the library's version, e.g. "1" for "1.2.3".
*/
#define GDK_MAJOR_VERSION ({current_major_version})
/**
* GDK_MINOR_VERSION:
*
* The minor version component of the library's version, e.g. "2" for "1.2.3".
*/
#define GDK_MINOR_VERSION ({current_minor_version})
/**
* GDK_MICRO_VERSION:
*
* The micro version component of the library's version, e.g. "3" for "1.2.3".
*/
#define GDK_MICRO_VERSION ({current_micro_version})
"""
)
)
for minor in range(0, current_minor_version + 2, 2):
ofile.write(
textwrap.dedent(
f"""\
/**
* GDK_VERSION_{current_major_version}_{minor}:
*
* A macro that evaluates to the {current_major_version}.{minor} version of GTK, in a format
* that can be used by the C pre-processor.
*
* Since: {current_major_version}.{minor}
*/
#define GDK_VERSION_{current_major_version}_{minor} (G_ENCODE_VERSION ({current_major_version}, {minor}))
"""
)
)
else:
ofile.write(line)
def gen_visibility_macros(args, current_major_version, current_minor_version, current_micro_version):
"""
Generates a set of macros for each minor stable version of GTK
- GDK_DEPRECATED
- GDK_DEPRECATED_IN_…
- GDK_DEPRECATED_MACRO_IN_…
- GDK_DEPRECATED_ENUMERATOR_IN_…
- GDK_DEPRECATED_TYPE_IN_…
- GDK_AVAILABLE_IN_ALL
- GDK_AVAILABLE_IN_…
- GDK_AVAILABLE_STATIC_INLINE_IN_…
- GDK_AVAILABLE_MACRO_IN_…
- GDK_AVAILABLE_ENUMERATOR_IN_…
- GDK_AVAILABLE_TYPE_IN_…
- GDK_UNAVAILABLE(maj,min)
- GDK_UNAVAILABLE_STATIC_INLINE(maj,min)
"""
ns = args.namespace
with args.out_path.open("w", encoding="utf-8") as f:
f.write(
textwrap.dedent(
f"""\
#pragma once
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined({ns}_STATIC_COMPILATION)
# define _{ns}_EXPORT __declspec(dllexport)
# define _{ns}_IMPORT __declspec(dllimport)
#elif __GNUC__ >= 4
# define _{ns}_EXPORT __attribute__((visibility("default")))
# define _{ns}_IMPORT
#else
# define _{ns}_EXPORT
# define _{ns}_IMPORT
#endif
#ifdef GTK_COMPILATION
# define _{ns}_API _{ns}_EXPORT
#else
# define _{ns}_API _{ns}_IMPORT
#endif
#define _{ns}_EXTERN _{ns}_API extern
#define {ns}_VAR _{ns}_EXTERN
#define {ns}_AVAILABLE_IN_ALL _{ns}_EXTERN
#ifdef GDK_DISABLE_DEPRECATION_WARNINGS
#define {ns}_DEPRECATED _{ns}_EXTERN
#define {ns}_DEPRECATED_FOR(f) _{ns}_EXTERN
#define {ns}_UNAVAILABLE(maj,min) _{ns}_EXTERN
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min)
#else
#define {ns}_DEPRECATED G_DEPRECATED _{ns}_EXTERN
#define {ns}_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _{ns}_EXTERN
#define {ns}_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _{ns}_EXTERN
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min) G_UNAVAILABLE(maj,min)
#endif
"""
)
)
for minor in range(0, current_minor_version + 2, 2):
f.write(
textwrap.dedent(
f"""
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_{minor}
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor} {ns}_DEPRECATED
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor}_FOR(f) {ns}_DEPRECATED_FOR (f)
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor} GDK_DEPRECATED_MACRO
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_MACRO_FOR (f)
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor} GDK_DEPRECATED_ENUMERATOR
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_ENUMERATOR_FOR (f)
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor} GDK_DEPRECATED_TYPE
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_TYPE_FOR (f)
#else
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor} _{ns}_EXTERN
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor}_FOR(f) _{ns}_EXTERN
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}_FOR(f)
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}_FOR(f)
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}_FOR(f)
#endif
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_{current_major_version}_{minor}
#define {ns}_AVAILABLE_IN_{current_major_version}_{minor} {ns}_UNAVAILABLE ({current_major_version}, {minor})
#define {ns}_AVAILABLE_STATIC_INLINE_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_STATIC_INLINE ({current_major_version}, {minor})
#define {ns}_AVAILABLE_MACRO_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_MACRO ({current_major_version}, {minor})
#define {ns}_AVAILABLE_ENUMERATOR_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_ENUMERATOR ({current_major_version}, {minor})
#define {ns}_AVAILABLE_TYPE_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_TYPE ({current_major_version}, {minor})
#else
#define {ns}_AVAILABLE_IN_{current_major_version}_{minor} _{ns}_EXTERN
#define {ns}_AVAILABLE_STATIC_INLINE_IN_{current_major_version}_{minor}
#define {ns}_AVAILABLE_MACRO_IN_{current_major_version}_{minor}
#define {ns}_AVAILABLE_ENUMERATOR_IN_{current_major_version}_{minor}
#define {ns}_AVAILABLE_TYPE_IN_{current_major_version}_{minor}
#endif
"""
)
)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("gtk_version", help="Current GLib version")
subparsers = parser.add_subparsers()
versions_parser = subparsers.add_parser(
"versions-macros", help="Generate versions macros"
)
versions_parser.add_argument("in_path", help="input file", type=Path)
versions_parser.add_argument("out_path", help="output file", type=Path)
versions_parser.set_defaults(func=gen_versions_macros)
visibility_parser = subparsers.add_parser(
"visibility-macros", help="Generate visibility macros"
)
visibility_parser.add_argument("namespace", help="Macro namespace")
visibility_parser.add_argument("out_path", help="output file", type=Path)
visibility_parser.set_defaults(func=gen_visibility_macros)
args = parser.parse_args()
version = [int(i) for i in args.gtk_version.split(".")]
args.func(args, version[0], version[1], version[2])
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python3
import os
import sys
import subprocess
if 'DESTDIR' not in os.environ:
gtk_api_version = sys.argv[1]
gtk_abi_version = sys.argv[2]
gtk_libdir = sys.argv[3]
gtk_datadir = sys.argv[4]
gtk_bindir = sys.argv[5]
gtk_moduledir = os.path.join(gtk_libdir, 'gtk-' + gtk_api_version, gtk_abi_version)
gtk_printmodule_dir = os.path.join(gtk_moduledir, 'printbackends')
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
print('Compiling GSettings schemas...')
glib_compile_schemas = subprocess.check_output(['pkg-config',
'--variable=glib_compile_schemas',
'gio-2.0']).strip()
if not os.path.exists(glib_compile_schemas):
# pkg-config variables only available since GLib 2.62.0.
glib_compile_schemas = 'glib-compile-schemas'
subprocess.call([glib_compile_schemas,
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
print('Updating icon cache...')
update_icon_cache = os.path.join(gtk_bindir, 'gtk4-update-icon-cache')
subprocess.call([update_icon_cache, '-q', '-t' ,'-f',
os.path.join(gtk_datadir, 'icons', 'hicolor')])
print('Updating module cache for print backends...')
os.makedirs(gtk_printmodule_dir, exist_ok=True)
gio_querymodules = subprocess.check_output(['pkg-config',
'--variable=gio_querymodules',
'gio-2.0']).strip()
if not os.path.exists(gio_querymodules):
# pkg-config variables only available since GLib 2.62.0.
gio_querymodules = 'gio-querymodules'
subprocess.call([gio_querymodules, gtk_printmodule_dir])
print('Updating module cache for input methods...')
os.makedirs(gtk_immodule_dir, exist_ok=True)
subprocess.call([gio_querymodules, gtk_immodule_dir])

View File

@@ -1,41 +0,0 @@
#ifndef _MSC_VER
#pragma error "This header is for Microsoft VC or clang-cl only."
#endif /* _MSC_VER */
/* Make MSVC more pedantic, this is a recommended pragma list
* from _Win32_Programming_ by Rector and Newcomer.
*/
#ifndef __clang__
#pragma warning(error:4002) /* too many actual parameters for macro */
#pragma warning(error:4003) /* not enough actual parameters for macro */
#pragma warning(1:4010) /* single-line comment contains line-continuation character */
#pragma warning(error:4013) /* 'function' undefined; assuming extern returning int */
#pragma warning(1:4016) /* no function return type; using int as default */
#pragma warning(error:4020) /* too many actual parameters */
#pragma warning(error:4021) /* too few actual parameters */
#pragma warning(error:4027) /* function declared without formal parameter list */
#pragma warning(error:4029) /* declared formal parameter list different from definition */
#pragma warning(error:4033) /* 'function' must return a value */
#pragma warning(error:4035) /* 'function' : no return value */
#pragma warning(error:4045) /* array bounds overflow */
#pragma warning(error:4047) /* different levels of indirection */
#pragma warning(error:4049) /* terminating line number emission */
#pragma warning(error:4053) /* An expression of type void was used as an operand */
#pragma warning(error:4071) /* no function prototype given */
#pragma warning(disable:4101) /* unreferenced local variable */
#pragma warning(error:4150)
/* G_NORETURN */
#pragma warning(error:4646) /* function declared with __declspec(noreturn) has non-void return type */
#pragma warning(error:4715) /* 'function': not all control paths return a value */
#pragma warning(error:4098) /* 'void' function returning a value */
#pragma warning(disable:4244) /* No possible loss of data warnings */
#pragma warning(disable:4305) /* No truncation from int to char warnings */
#pragma warning(error:4819) /* The file contains a character that cannot be represented in the current code page */
#endif /* __clang__ */
/* work around Microsoft's premature attempt to deprecate the C-Library */
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS

281
config.h.meson Normal file
View File

@@ -0,0 +1,281 @@
/* always defined to indicate that i18n is enabled */
#define ENABLE_NLS 1
/* Use structured logging */
#define G_LOG_STRUCTURED 1
/* The prefix for our gettext translation domains. */
#mesondefine GETTEXT_PACKAGE
/* Disable deprecation warnings from glib */
#mesondefine GLIB_DISABLE_DEPRECATION_WARNINGS
/* Define the location where the catalogs will be installed */
#mesondefine GTK_LOCALEDIR
/* Define to 1 if you have the `bind_textdomain_codeset' function. */
#mesondefine HAVE_BIND_TEXTDOMAIN_CODESET
/* Have the cloudproviders library */
#mesondefine HAVE_CLOUDPROVIDERS
/* define if we have colord */
#mesondefine HAVE_COLORD
/* Define to 1 if you have the <crt_externs.h> header file. */
#mesondefine HAVE_CRT_EXTERNS_H
/* Define to 1 if you have the `dcgettext' function. */
#mesondefine HAVE_DCGETTEXT
/* Define to 1 if you have the <dlfcn.h> header file. */
#mesondefine HAVE_DLFCN_H
/* Have the ffmpeg library */
#mesondefine HAVE_FFMPEG
/* Define to 1 if you have the <ftw.h> header file. */
#mesondefine HAVE_FTW_H
/* Define to 1 if you have the `getpagesize' function. */
#mesondefine HAVE_GETPAGESIZE
/* Define to 1 if you have the `getresuid' function. */
#mesondefine HAVE_GETRESUID
/* Define if gio-unix is available */
#mesondefine HAVE_GIO_UNIX
/* Define if GStreamer support is available */
#mesondefine HAVE_GSTREAMER
/* Define to 1 if you have the <inttypes.h> header file. */
#mesondefine HAVE_INTTYPES_H
/* Define to 1 if the system has the type `IPrintDialogCallback'. */
#mesondefine HAVE_IPRINTDIALOGCALLBACK
/* Define to 1 if you have the <locale.h> header file. */
#mesondefine HAVE_LOCALE_H
/* Define to 1 if you have the `lstat' function. */
#mesondefine HAVE_LSTAT
/* Define to 1 if you have the `mallinfo' function. */
#mesondefine HAVE_MALLINFO
/* Define to 1 if you have the <memory.h> header file. */
#mesondefine HAVE_MEMORY_H
/* Define to 1 if you have the `mkstemp' function. */
#mesondefine HAVE_MKSTEMP
/* Define to 1 if you have the `mlock` function. */
#mesondefine HAVE_MLOCK
/* Define to 1 if you have a working `mmap' system call. */
#mesondefine HAVE_MMAP
/* Define to 1 if you have the `posix_fallocate' function. */
#mesondefine HAVE_POSIX_FALLOCATE
/* Have the Xrandr extension library */
#mesondefine HAVE_RANDR
/* Have the Xrandr 1.5 extension library */
#mesondefine HAVE_RANDR15
/* Define to 1 if you have the `sincos' function. */
#mesondefine HAVE_SINCOS
/* Define to 1 if you have the <stdint.h> header file. */
#mesondefine HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#mesondefine HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#mesondefine HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#mesondefine HAVE_STRING_H
/* Define to 1 if you have the <sys/mman.h> header file. */
#mesondefine HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/param.h> header file. */
#mesondefine HAVE_SYS_PARAM_H
/* Have the sysprof-capture library */
#mesondefine HAVE_SYSPROF
/* Define to 1 if you have the <sys/stat.h> header file. */
#mesondefine HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#mesondefine HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#mesondefine HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#mesondefine HAVE_UNISTD_H
/* Have the XCOMPOSITE X extension */
#mesondefine HAVE_XCOMPOSITE
/* Have the Xcursor library */
#mesondefine HAVE_XCURSOR
/* Have the XDAMAGE X extension */
#mesondefine HAVE_XDAMAGE
/* Have the XFIXES X extension */
#mesondefine HAVE_XFIXES
/* Define to 1 if XFree Xinerama is available */
#mesondefine HAVE_XFREE_XINERAMA
/* Have XGenericEvent */
#mesondefine HAVE_XGENERICEVENTS
/* Define to use XKB extension */
#mesondefine HAVE_XKB
/* Have the SYNC extension library */
#mesondefine HAVE_XSYNC
/* Define to 1 if you have the `_lock_file' function */
#mesondefine HAVE__LOCK_FILE
/* Define to 1 if you have the `flockfile' function */
#mesondefine HAVE_FLOCKFILE
/* Define if _NL_MEASUREMENT_MEASUREMENT is available */
#mesondefine HAVE__NL_MEASUREMENT_MEASUREMENT
/* Define if _NL_PAPER_HEIGHT is available */
#mesondefine HAVE__NL_PAPER_HEIGHT
/* Define if _NL_PAPER_WIDTH is available */
#mesondefine HAVE__NL_PAPER_WIDTH
/* Define if _NL_TIME_FIRST_WEEKDAY is available */
#mesondefine HAVE__NL_TIME_FIRST_WEEKDAY
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#mesondefine LT_OBJDIR
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#mesondefine NO_MINUS_C_MINUS_O
/* Define to the address where bug reports for this package should be sent. */
#mesondefine PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#mesondefine PACKAGE_NAME
/* Define to the full name and version of this package. */
#mesondefine PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#mesondefine PACKAGE_TARNAME
/* Define to the home page for this package. */
#mesondefine PACKAGE_URL
/* Define to the version of this package. */
#mesondefine PACKAGE_VERSION
/* Use NSBundle functions to determine load paths for libraries, translations,
etc. */
#mesondefine QUARTZ_RELOCATION
/* Define to 1 if you have the ANSI C header files. */
#mesondefine STDC_HEADERS
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Define to 1 if XInput 2.2 is available */
#mesondefine XINPUT_2_2
/* Define to 1 if the X Window System is missing or not being used. */
#mesondefine X_DISPLAY_MISSING
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#mesondefine _FILE_OFFSET_BITS
/* defines how to decorate public symbols while building */
#mesondefine _GDK_EXTERN
/* Define for large files, on AIX-style hosts. */
#mesondefine _LARGE_FILES
/* Define to 1 if on MINIX. */
#mesondefine _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#mesondefine _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#mesondefine _POSIX_SOURCE
/* Define to `int' if <sys/types.h> doesn't define. */
#mesondefine gid_t
/* Define to `int' if <sys/types.h> doesn't define. */
#mesondefine uid_t
/* Define to 1 if linux/memfd.h exists */
#mesondefine HAVE_LINUX_MEMFD_H
#mesondefine HAVE_LINUX_INPUT_H
#mesondefine HAVE_DEV_EVDEV_INPUT_H
#mesondefine GTK_SYSCONFDIR
#mesondefine GTK_LOCALEDIR
#mesondefine GTK_DATADIR
#mesondefine GTK_LIBDIR
#mesondefine GTK_PRINT_BACKENDS
#mesondefine HAVE_CAIRO_SCRIPT_INTERPRETER
#mesondefine HAVE_HARFBUZZ
#mesondefine HAVE_PANGOFT
#mesondefine ISO_CODES_PREFIX
/* Define if tracker3 is available */
#mesondefine HAVE_TRACKER3

View File

@@ -202,36 +202,43 @@ constraint_editor_window_load (ConstraintEditorWindow *self,
} }
static void static void
open_response_cb (GObject *source, open_response_cb (GtkNativeDialog *dialog,
GAsyncResult *result, int response,
void *user_data) ConstraintEditorWindow *self)
{ {
GtkFileDialog *dialog = GTK_FILE_DIALOG (source); gtk_native_dialog_hide (dialog);
ConstraintEditorWindow *self = user_data;
GFile *file;
file = gtk_file_dialog_open_finish (dialog, result, NULL); if (response == GTK_RESPONSE_ACCEPT)
if (file)
{ {
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
constraint_editor_window_load (self, file); constraint_editor_window_load (self, file);
g_object_unref (file); g_object_unref (file);
} }
gtk_native_dialog_destroy (dialog);
} }
static void static void
open_cb (GtkWidget *button, open_cb (GtkWidget *button,
ConstraintEditorWindow *self) ConstraintEditorWindow *self)
{ {
GtkFileDialog *dialog; GtkFileChooserNative *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new (); dialog = gtk_file_chooser_native_new ("Open file",
gtk_file_dialog_set_title (dialog, "Open file"); GTK_WINDOW (self),
cwd = g_file_new_for_path ("."); GTK_FILE_CHOOSER_ACTION_OPEN,
gtk_file_dialog_set_initial_folder (dialog, cwd); "_Load",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd); g_object_unref (cwd);
gtk_file_dialog_open (dialog, GTK_WINDOW (self), NULL, open_response_cb, self);
g_object_unref (dialog); g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
} }
static void static void
@@ -287,23 +294,22 @@ serialize_model (GListModel *list)
static void static void
save_response_cb (GObject *source, save_response_cb (GtkNativeDialog *dialog,
GAsyncResult *result, int response,
void *user_data) ConstraintEditorWindow *self)
{ {
GtkFileDialog *dialog = GTK_FILE_DIALOG (source); gtk_native_dialog_hide (dialog);
ConstraintEditorWindow *self = user_data;
GFile *file;
file = gtk_file_dialog_save_finish (dialog, result, NULL); if (response == GTK_RESPONSE_ACCEPT)
if (file)
{ {
GListModel *model; GListModel *model;
GFile *file;
char *text; char *text;
GError *error = NULL; GError *error = NULL;
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view)); model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
text = serialize_model (model); text = serialize_model (model);
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_file_replace_contents (file, text, strlen (text), g_file_replace_contents (file, text, strlen (text),
NULL, FALSE, NULL, FALSE,
G_FILE_CREATE_NONE, G_FILE_CREATE_NONE,
@@ -312,46 +318,54 @@ save_response_cb (GObject *source,
&error); &error);
if (error != NULL) if (error != NULL)
{ {
GtkAlertDialog *alert; GtkWidget *message_dialog;
alert = gtk_alert_dialog_new ("Saving failed"); message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
gtk_alert_dialog_set_detail (alert, error->message); GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
gtk_alert_dialog_show (alert, GTK_MESSAGE_INFO,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)))); GTK_BUTTONS_OK,
g_object_unref (alert); "Saving failed");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
"%s", error->message);
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (message_dialog);
g_error_free (error); g_error_free (error);
} }
g_free (text); g_free (text);
g_object_unref (file); g_object_unref (file);
} }
gtk_native_dialog_destroy (dialog);
} }
static void static void
save_cb (GtkWidget *button, save_cb (GtkWidget *button,
ConstraintEditorWindow *self) ConstraintEditorWindow *self)
{ {
GtkFileDialog *dialog; GtkFileChooserNative *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new (); dialog = gtk_file_chooser_native_new ("Save constraints",
gtk_file_dialog_set_title (dialog, "Save constraints"); GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
cwd = g_file_new_for_path ("."); GTK_FILE_CHOOSER_ACTION_SAVE,
gtk_file_dialog_set_initial_folder (dialog, cwd); "_Save",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd); g_object_unref (cwd);
gtk_file_dialog_save (dialog,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))), g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
NULL, gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
save_response_cb, self);
g_object_unref (dialog);
} }
static void static void
constraint_editor_window_dispose (GObject *object) constraint_editor_window_finalize (GObject *object)
{ {
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_WINDOW_TYPE); //ConstraintEditorWindow *self = (ConstraintEditorWindow *)object;
G_OBJECT_CLASS (constraint_editor_window_parent_class)->dispose (object); G_OBJECT_CLASS (constraint_editor_window_parent_class)->finalize (object);
} }
static int child_counter; static int child_counter;
@@ -426,7 +440,7 @@ edit_constraint (ConstraintEditorWindow *win,
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win); g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
gtk_window_present (GTK_WINDOW (window)); gtk_widget_show (window);
} }
static void static void
@@ -459,7 +473,7 @@ edit_guide (ConstraintEditorWindow *win,
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor)); gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win); g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
gtk_window_present (GTK_WINDOW (window)); gtk_widget_show (window);
} }
static void static void
@@ -483,9 +497,7 @@ constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class); GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
g_type_ensure (CONSTRAINT_VIEW_TYPE); object_class->finalize = constraint_editor_window_finalize;
object_class->dispose = constraint_editor_window_dispose;
gtk_widget_class_set_template_from_resource (widget_class, gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui"); "/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui");

View File

@@ -20,7 +20,6 @@
#include "config.h" #include "config.h"
#include "constraint-editor.h" #include "constraint-editor.h"
#include "constraint-view.h"
struct _ConstraintEditor struct _ConstraintEditor
{ {
@@ -65,7 +64,7 @@ static const char *
get_target_name (GtkConstraintTarget *target) get_target_name (GtkConstraintTarget *target)
{ {
if (target == NULL) if (target == NULL)
return "Super"; return "super";
else if (GTK_IS_WIDGET (target)) else if (GTK_IS_WIDGET (target))
return gtk_widget_get_name (GTK_WIDGET (target)); return gtk_widget_get_name (GTK_WIDGET (target));
else if (GTK_IS_CONSTRAINT_GUIDE (target)) else if (GTK_IS_CONSTRAINT_GUIDE (target))
@@ -79,29 +78,62 @@ constraint_target_combo (GListModel *model,
GtkWidget *combo, GtkWidget *combo,
gboolean is_source) gboolean is_source)
{ {
GtkStringList *targets;
int i; int i;
targets = gtk_string_list_new (NULL); gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "super", "Super");
gtk_string_list_append (targets, "Super");
if (model) if (model)
{ {
for (i = 0; i < g_list_model_get_n_items (model); i++) for (i = 0; i < g_list_model_get_n_items (model); i++)
{ {
GObject *item = g_list_model_get_object (model, i); GObject *item = g_list_model_get_object (model, i);
const char *name;
if (GTK_IS_CONSTRAINT (item)) if (GTK_IS_CONSTRAINT (item))
continue; continue;
gtk_string_list_append (targets, get_target_name (GTK_CONSTRAINT_TARGET (item))); name = get_target_name (GTK_CONSTRAINT_TARGET (item));
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), name, name);
g_object_unref (item); g_object_unref (item);
} }
} }
}
gtk_drop_down_set_model (GTK_DROP_DOWN (combo), G_LIST_MODEL (targets)); static void
g_object_unref (targets); constraint_attribute_combo (GtkWidget *combo,
gboolean is_source)
{
if (is_source)
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "none", "None");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "left", "Left");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "right", "Right");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "top", "Top");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "bottom", "Bottom");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "start", "Start");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "end", "End");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "width", "Width");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "height", "Height");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-x", "Center X");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-y", "Center Y");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "baseline", "Baseline");
}
static void
constraint_relation_combo (GtkWidget *combo)
{
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "le", "");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "eq", "=");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "ge", "");
}
static void
constraint_strength_combo (GtkWidget *combo)
{
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
} }
static gpointer static gpointer
@@ -113,7 +145,7 @@ get_target (GListModel *model,
if (id == NULL) if (id == NULL)
return NULL; return NULL;
if (strcmp ("Super", id) == 0) if (strcmp ("super", id) == 0)
return NULL; return NULL;
for (i = 0; i < g_list_model_get_n_items (model); i++) for (i = 0; i < g_list_model_get_n_items (model); i++)
@@ -137,65 +169,16 @@ get_target (GListModel *model,
return NULL; return NULL;
} }
static void
select_target (GtkDropDown *combo,
const char *target_name)
{
GListModel *model = gtk_drop_down_get_model (combo);
for (unsigned int i = 0; i < g_list_model_get_n_items (model); i++)
{
GtkStringObject *s = g_list_model_get_item (model, i);
g_object_unref (s);
if (strcmp (target_name, gtk_string_object_get_string (s)) == 0)
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), i);
return;
}
}
}
static GtkConstraintAttribute static GtkConstraintAttribute
get_attr (unsigned int id) get_target_attr (const char *id)
{ {
switch (id) GtkConstraintAttribute attr;
{ GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
case 0: return GTK_CONSTRAINT_ATTRIBUTE_NONE; GEnumValue *value = g_enum_get_value_by_nick (class, id);
case 1: return GTK_CONSTRAINT_ATTRIBUTE_LEFT; attr = value->value;
case 2: return GTK_CONSTRAINT_ATTRIBUTE_RIGHT; g_type_class_unref (class);
case 3: return GTK_CONSTRAINT_ATTRIBUTE_TOP;
case 4: return GTK_CONSTRAINT_ATTRIBUTE_BOTTOM;
case 5: return GTK_CONSTRAINT_ATTRIBUTE_START;
case 6: return GTK_CONSTRAINT_ATTRIBUTE_END;
case 7: return GTK_CONSTRAINT_ATTRIBUTE_WIDTH;
case 8: return GTK_CONSTRAINT_ATTRIBUTE_HEIGHT;
case 9: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_X;
case 10: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y;
case 11: return GTK_CONSTRAINT_ATTRIBUTE_BASELINE;
default: g_assert_not_reached ();
}
}
static unsigned int return attr;
get_attr_id (GtkConstraintAttribute attr)
{
switch (attr)
{
case GTK_CONSTRAINT_ATTRIBUTE_NONE: return 0;
case GTK_CONSTRAINT_ATTRIBUTE_LEFT: return 1;
case GTK_CONSTRAINT_ATTRIBUTE_RIGHT: return 2;
case GTK_CONSTRAINT_ATTRIBUTE_TOP: return 3;
case GTK_CONSTRAINT_ATTRIBUTE_BOTTOM: return 4;
case GTK_CONSTRAINT_ATTRIBUTE_START: return 5;
case GTK_CONSTRAINT_ATTRIBUTE_END: return 6;
case GTK_CONSTRAINT_ATTRIBUTE_WIDTH: return 7;
case GTK_CONSTRAINT_ATTRIBUTE_HEIGHT: return 8;
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_X: return 9;
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y: return 10;
case GTK_CONSTRAINT_ATTRIBUTE_BASELINE: return 11;
default: g_assert_not_reached ();
}
} }
static const char * static const char *
@@ -210,27 +193,15 @@ get_attr_nick (GtkConstraintAttribute attr)
} }
static GtkConstraintRelation static GtkConstraintRelation
get_relation (unsigned int id) get_relation (const char *id)
{ {
switch (id) GtkConstraintRelation relation;
{ GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
case 0: return GTK_CONSTRAINT_RELATION_LE; GEnumValue *value = g_enum_get_value_by_nick (class, id);
case 1: return GTK_CONSTRAINT_RELATION_EQ; relation = value->value;
case 2: return GTK_CONSTRAINT_RELATION_GE; g_type_class_unref (class);
default: g_assert_not_reached ();
}
}
static unsigned int return relation;
get_relation_id (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE: return 0;
case GTK_CONSTRAINT_RELATION_EQ: return 1;
case GTK_CONSTRAINT_RELATION_GE: return 2;
default: g_assert_not_reached ();
}
} }
static const char * static const char *
@@ -261,29 +232,15 @@ get_relation_display_name (GtkConstraintRelation relation)
} }
static GtkConstraintStrength static GtkConstraintStrength
get_strength (unsigned int id) get_strength (const char *id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK;
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM;
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
default: g_assert_not_reached ();
}
}
static unsigned int
get_strength_id (GtkConstraintStrength strength)
{ {
switch (strength) GtkConstraintStrength strength;
{ GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0; GEnumValue *value = g_enum_get_value_by_nick (class, id);
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1; strength = value->value;
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2; g_type_class_unref (class);
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
default: g_assert_not_reached (); return strength;
}
} }
static const char * static const char *
@@ -335,7 +292,7 @@ static void
create_constraint (GtkButton *button, create_constraint (GtkButton *button,
ConstraintEditor *editor) ConstraintEditor *editor)
{ {
gpointer obj; const char *id;
gpointer target; gpointer target;
GtkConstraintAttribute target_attr; GtkConstraintAttribute target_attr;
gpointer source; gpointer source;
@@ -346,27 +303,25 @@ create_constraint (GtkButton *button,
int strength; int strength;
GtkConstraint *constraint; GtkConstraint *constraint;
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target)); id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
if (obj) target = get_target (editor->model, id);
target = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj))); id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
else target_attr = get_target_attr (id);
target = NULL;
target_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->target_attr)));
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source)); id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
if (obj) source = get_target (editor->model, id);
source = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj))); id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
else source_attr = get_target_attr (id);
source = NULL;
source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN(editor->source_attr)));
relation = get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation))); id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->relation));
relation = get_relation (id);
multiplier = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)), NULL); multiplier = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)), NULL);
constant = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->constant)), NULL); constant = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->constant)), NULL);
strength = get_strength (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength))); id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->strength));
strength = get_strength (id);
constraint = gtk_constraint_new (target, target_attr, constraint = gtk_constraint_new (target, target_attr,
relation, relation,
@@ -381,9 +336,12 @@ create_constraint (GtkButton *button,
static void static void
source_attr_changed (ConstraintEditor *editor) source_attr_changed (ConstraintEditor *editor)
{ {
if (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr))) == GTK_CONSTRAINT_ATTRIBUTE_NONE) const char *id;
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
if (strcmp (id, "none") == 0)
{ {
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source), GTK_INVALID_LIST_POSITION); gtk_combo_box_set_active (GTK_COMBO_BOX (editor->source), -1);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), ""); gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "");
gtk_widget_set_sensitive (editor->source, FALSE); gtk_widget_set_sensitive (editor->source, FALSE);
gtk_widget_set_sensitive (editor->multiplier, FALSE); gtk_widget_set_sensitive (editor->multiplier, FALSE);
@@ -449,7 +407,7 @@ update_preview (ConstraintEditor *editor)
GString *str; GString *str;
const char *name; const char *name;
const char *attr; const char *attr;
const char *relation; char *relation;
const char *multiplier; const char *multiplier;
const char *constant; const char *constant;
double c, m; double c, m;
@@ -459,22 +417,23 @@ update_preview (ConstraintEditor *editor)
str = g_string_new (""); str = g_string_new ("");
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target)))); name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected ((GTK_DROP_DOWN (editor->target_attr))))); attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
relation = get_relation_nick (get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation)))); relation = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (editor->relation));
if (name == NULL) if (name == NULL)
name = "[ ]"; name = "[ ]";
g_string_append_printf (str, "%s.%s %s ", name, attr, relation); g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
g_free (relation);
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant)); constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
c = g_ascii_strtod (constant, NULL); c = g_ascii_strtod (constant, NULL);
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr)))); attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
if (strcmp (attr, "none") != 0) if (strcmp (attr, "none") != 0)
{ {
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source)))); name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)); multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier));
m = g_ascii_strtod (multiplier, NULL); m = g_ascii_strtod (multiplier, NULL);
@@ -502,18 +461,12 @@ update_preview (ConstraintEditor *editor)
static void static void
update_button (ConstraintEditor *editor) update_button (ConstraintEditor *editor)
{ {
gpointer obj; const char *target = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
const char *target; const char *source = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
const char *source; const char *source_attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
GtkConstraintAttribute source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr)));
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target)); if (target &&
target = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL; (source || (source_attr && get_target_attr (source_attr) == GTK_CONSTRAINT_ATTRIBUTE_NONE)))
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source));
source = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL;
if (target && (source || (source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)))
gtk_widget_set_sensitive (editor->button, TRUE); gtk_widget_set_sensitive (editor->button, TRUE);
else else
gtk_widget_set_sensitive (editor->button, FALSE); gtk_widget_set_sensitive (editor->button, FALSE);
@@ -531,7 +484,12 @@ constraint_editor_constructed (GObject *object)
ConstraintEditor *editor = CONSTRAINT_EDITOR (object); ConstraintEditor *editor = CONSTRAINT_EDITOR (object);
constraint_target_combo (editor->model, editor->target, FALSE); constraint_target_combo (editor->model, editor->target, FALSE);
constraint_attribute_combo (editor->target_attr, FALSE);
constraint_relation_combo (editor->relation);
constraint_target_combo (editor->model, editor->source, TRUE); constraint_target_combo (editor->model, editor->source, TRUE);
constraint_attribute_combo (editor->source_attr, TRUE);
constraint_strength_combo (editor->strength);
if (editor->constraint) if (editor->constraint)
{ {
@@ -539,24 +497,30 @@ constraint_editor_constructed (GObject *object)
GtkConstraintAttribute attr; GtkConstraintAttribute attr;
GtkConstraintRelation relation; GtkConstraintRelation relation;
GtkConstraintStrength strength; GtkConstraintStrength strength;
const char *nick;
char *val; char *val;
double multiplier; double multiplier;
double constant; double constant;
target = gtk_constraint_get_target (editor->constraint); target = gtk_constraint_get_target (editor->constraint);
select_target (GTK_DROP_DOWN (editor->target), get_target_name (target)); nick = get_target_name (target);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target), nick);
attr = gtk_constraint_get_target_attribute (editor->constraint); attr = gtk_constraint_get_target_attribute (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (attr)); nick = get_attr_nick (attr);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), nick);
target = gtk_constraint_get_source (editor->constraint); target = gtk_constraint_get_source (editor->constraint);
select_target (GTK_DROP_DOWN (editor->source), get_target_name (target)); nick = get_target_name (target);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source), nick);
attr = gtk_constraint_get_source_attribute (editor->constraint); attr = gtk_constraint_get_source_attribute (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (attr)); nick = get_attr_nick (attr);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), nick);
relation = gtk_constraint_get_relation (editor->constraint); relation = gtk_constraint_get_relation (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (relation)); nick = get_relation_nick (relation);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), nick);
multiplier = gtk_constraint_get_multiplier (editor->constraint); multiplier = gtk_constraint_get_multiplier (editor->constraint);
val = g_strdup_printf ("%g", multiplier); val = g_strdup_printf ("%g", multiplier);
@@ -569,16 +533,17 @@ constraint_editor_constructed (GObject *object)
g_free (val); g_free (val);
strength = gtk_constraint_get_strength (editor->constraint); strength = gtk_constraint_get_strength (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength)); nick = get_strength_nick (strength);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply"); gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
} }
else else
{ {
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT)); gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), "left");
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT)); gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), "left");
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (GTK_CONSTRAINT_RELATION_EQ)); gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), "eq");
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_REQUIRED)); gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), "required");
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1.0"); gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1.0");
gtk_editable_set_text (GTK_EDITABLE (editor->constant), "0.0"); gtk_editable_set_text (GTK_EDITABLE (editor->constant), "0.0");
@@ -642,11 +607,10 @@ constraint_editor_dispose (GObject *object)
{ {
ConstraintEditor *self = (ConstraintEditor *)object; ConstraintEditor *self = (ConstraintEditor *)object;
g_clear_pointer (&self->grid, gtk_widget_unparent);
g_clear_object (&self->model); g_clear_object (&self->model);
g_clear_object (&self->constraint); g_clear_object (&self->constraint);
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_TYPE);
G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object); G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object);
} }

View File

@@ -1,21 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<object class="GtkStringList" id="targets">
<items>
<item>None</item>
<item>Left</item>
<item>Right</item>
<item>Top</item>
<item>Bottom</item>
<item>Start</item>
<item>End</item>
<item>Width</item>
<item>Height</item>
<item>Center X</item>
<item>Center Y</item>
<item>Baseline</item>
</items>
</object>
<template class="ConstraintEditor" parent="GtkWidget"> <template class="ConstraintEditor" parent="GtkWidget">
<child> <child>
<object class="GtkGrid" id="grid"> <object class="GtkGrid" id="grid">
@@ -35,9 +19,9 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkDropDown" id="target"> <object class="GtkComboBoxText" id="target">
<signal name="notify::selected" handler="update_preview" swapped="yes"/> <signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/> <signal name="changed" handler="update_button" swapped="yes"/>
<layout> <layout>
<property name="column">1</property> <property name="column">1</property>
<property name="row">1</property> <property name="row">1</property>
@@ -45,9 +29,8 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkDropDown" id="target_attr"> <object class="GtkComboBoxText" id="target_attr">
<property name="model">targets</property> <signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<layout> <layout>
<property name="column">2</property> <property name="column">2</property>
<property name="row">1</property> <property name="row">1</property>
@@ -64,17 +47,8 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkDropDown" id="relation"> <object class="GtkComboBoxText" id="relation">
<signal name="notify::selected" handler="update_preview" swapped="yes"/> <signal name="changed" handler="update_preview" swapped="yes"/>
<property name="model">
<object class="GtkStringList">
<items>
<item>≤</item>
<item>=</item>
<item>≥</item>
</items>
</object>
</property>
<layout> <layout>
<property name="column">1</property> <property name="column">1</property>
<property name="row">2</property> <property name="row">2</property>
@@ -91,9 +65,9 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkDropDown" id="source"> <object class="GtkComboBoxText" id="source">
<signal name="notify::selected" handler="update_preview" swapped="yes"/> <signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/> <signal name="changed" handler="update_button" swapped="yes"/>
<layout> <layout>
<property name="column">1</property> <property name="column">1</property>
<property name="row">3</property> <property name="row">3</property>
@@ -101,11 +75,10 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkDropDown" id="source_attr"> <object class="GtkComboBoxText" id="source_attr">
<property name="model">targets</property> <signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_preview" swapped="yes"/> <signal name="changed" handler="source_attr_changed" swapped="yes"/>
<signal name="notify::selected" handler="source_attr_changed" swapped="yes"/> <signal name="changed" handler="update_button" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/>
<layout> <layout>
<property name="column">2</property> <property name="column">2</property>
<property name="row">3</property> <property name="row">3</property>
@@ -158,17 +131,7 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkDropDown" id="strength"> <object class="GtkComboBoxText" id="strength">
<property name="model">
<object class="GtkStringList">
<items>
<item>Weak</item>
<item>Medium</item>
<item>Strong</item>
<item>Required</item>
</items>
</object>
</property>
<layout> <layout>
<property name="column">1</property> <property name="column">1</property>
<property name="row">6</property> <property name="row">6</property>

View File

@@ -57,30 +57,25 @@ static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(GuideEditor, guide_editor, GTK_TYPE_WIDGET); G_DEFINE_TYPE(GuideEditor, guide_editor, GTK_TYPE_WIDGET);
static GtkConstraintStrength static void
get_strength (unsigned int id) guide_strength_combo (GtkWidget *combo)
{ {
switch (id) gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
{ gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK; gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM; gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
default: g_assert_not_reached ();
}
} }
static unsigned int static GtkConstraintStrength
get_strength_id (GtkConstraintStrength strength) get_strength (const char *id)
{ {
switch (strength) GtkConstraintStrength strength;
{ GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0; GEnumValue *value = g_enum_get_value_by_nick (class, id);
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1; strength = value->value;
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2; g_type_class_unref (class);
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
default: g_assert_not_reached (); return strength;
}
} }
static const char * static const char *
@@ -121,11 +116,11 @@ static void
create_guide (GtkButton *button, create_guide (GtkButton *button,
GuideEditor *editor) GuideEditor *editor)
{ {
const char *id;
int strength; int strength;
const char *name; const char *name;
int w, h; int w, h;
GtkConstraintGuide *guide; GtkConstraintGuide *guide;
unsigned int id;
if (editor->guide) if (editor->guide)
guide = g_object_ref (editor->guide); guide = g_object_ref (editor->guide);
@@ -147,7 +142,7 @@ create_guide (GtkButton *button,
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_height)); h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_height));
gtk_constraint_guide_set_max_size (guide, w, h); gtk_constraint_guide_set_max_size (guide, w, h);
id = gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength)); id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->strength));
strength = get_strength (id); strength = get_strength (id);
gtk_constraint_guide_set_strength (guide, strength); gtk_constraint_guide_set_strength (guide, strength);
@@ -194,9 +189,14 @@ guide_editor_constructed (GObject *object)
{ {
GuideEditor *editor = GUIDE_EDITOR (object); GuideEditor *editor = GUIDE_EDITOR (object);
guide_strength_combo (editor->strength);
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL); g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL); g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL); g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL); g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
if (editor->guide) if (editor->guide)
@@ -222,7 +222,8 @@ guide_editor_constructed (GObject *object)
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), h); gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), h);
strength = gtk_constraint_guide_get_strength (editor->guide); strength = gtk_constraint_guide_get_strength (editor->guide);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength)); nick = get_strength_nick (strength);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply"); gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
} }
@@ -242,7 +243,7 @@ guide_editor_constructed (GObject *object)
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), G_MAXINT); gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), G_MAXINT);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), G_MAXINT); gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), G_MAXINT);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_MEDIUM)); gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), "medium");
gtk_button_set_label (GTK_BUTTON (editor->button), "Create"); gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
} }
@@ -293,10 +294,9 @@ guide_editor_dispose (GObject *object)
{ {
GuideEditor *self = (GuideEditor *)object; GuideEditor *self = (GuideEditor *)object;
g_clear_pointer (&self->grid, gtk_widget_unparent);
g_clear_object (&self->guide); g_clear_object (&self->guide);
gtk_widget_dispose_template (GTK_WIDGET (self), GUIDE_EDITOR_TYPE);
G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object); G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object);
} }

View File

@@ -167,17 +167,7 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkDropDown" id="strength"> <object class="GtkComboBoxText" id="strength">
<property name="model">
<object class="GtkStringList">
<items>
<item>Weak</item>
<item>Medium</item>
<item>Strong</item>
<item>Required</item>
</items>
</object>
</property>
<layout> <layout>
<property name="column">1</property> <property name="column">1</property>
<property name="row">4</property> <property name="row">4</property>

View File

@@ -9,7 +9,7 @@ constraint_editor_sources = [
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources', constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml', 'constraint-editor.gresource.xml',
source_dir: meson.current_source_dir(), source_dir: '.',
) )
executable('gtk4-constraint-editor', executable('gtk4-constraint-editor',
@@ -17,7 +17,7 @@ executable('gtk4-constraint-editor',
c_args: common_cflags, c_args: common_cflags,
dependencies: libgtk_dep, dependencies: libgtk_dep,
include_directories: confinc, include_directories: confinc,
win_subsystem: 'windows', gui_app: true,
link_args: extra_demo_ldflags, link_args: extra_demo_ldflags,
install: false, install: false,
) )

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -33,12 +33,22 @@ static void create_window (GApplication *app, const char *contents);
static void static void
show_action_dialog (GSimpleAction *action) show_action_dialog (GSimpleAction *action)
{ {
GtkAlertDialog *dialog; const char *name;
GtkWidget *dialog;
dialog = gtk_alert_dialog_new ("You activated action: \"%s\"", name = g_action_get_name (G_ACTION (action));
g_action_get_name (G_ACTION (action)));
gtk_alert_dialog_show (dialog, NULL); dialog = gtk_message_dialog_new (NULL,
g_object_unref (dialog); GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
"You activated action: \"%s\"",
name);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (dialog);
} }
static void static void
@@ -57,7 +67,7 @@ show_action_infobar (GSimpleAction *action,
text = g_strdup_printf ("You activated radio action: \"%s\".\n" text = g_strdup_printf ("You activated radio action: \"%s\".\n"
"Current value: %s", name, value); "Current value: %s", name, value);
gtk_label_set_text (GTK_LABEL (window->message), text); gtk_label_set_text (GTK_LABEL (window->message), text);
gtk_widget_set_visible (window->infobar, TRUE); gtk_widget_show (window->infobar);
g_free (text); g_free (text);
} }
@@ -80,38 +90,43 @@ activate_new (GSimpleAction *action,
} }
static void static void
open_response_cb (GObject *source, open_response_cb (GtkNativeDialog *dialog,
GAsyncResult *result, int response_id,
gpointer user_data) gpointer user_data)
{ {
GtkFileDialog *dialog = GTK_FILE_DIALOG (source); GtkFileChooserNative *native = user_data;
GApplication *app = G_APPLICATION (user_data); GApplication *app = g_object_get_data (G_OBJECT (native), "app");
GtkWidget *message_dialog;
GFile *file; GFile *file;
char *contents;
GError *error = NULL; GError *error = NULL;
file = gtk_file_dialog_open_finish (dialog, result, &error); if (response_id == GTK_RESPONSE_ACCEPT)
if (file)
{ {
char *contents; file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (native));
if (g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) if (g_file_load_contents (file, NULL, &contents, NULL, NULL, &error))
{ {
create_window (app, contents); create_window (app, contents);
g_free (contents); g_free (contents);
} }
else
{
message_dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Error loading file: \"%s\"",
error->message);
g_signal_connect (message_dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (message_dialog);
g_error_free (error);
}
} }
if (error) gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (native));
{ g_object_unref (native);
GtkAlertDialog *alert;
alert = gtk_alert_dialog_new ("Error loading file: \"%s\"", error->message);
gtk_alert_dialog_show (alert, NULL);
g_object_unref (alert);
g_error_free (error);
}
g_object_unref (app);
} }
@@ -121,11 +136,21 @@ activate_open (GSimpleAction *action,
gpointer user_data) gpointer user_data)
{ {
GApplication *app = user_data; GApplication *app = user_data;
GtkFileDialog *dialog; GtkFileChooserNative *native;
dialog = gtk_file_dialog_new (); native = gtk_file_chooser_native_new ("Open File",
gtk_file_dialog_open (dialog, NULL, NULL, open_response_cb, g_object_ref (app)); NULL,
g_object_unref (dialog); GTK_FILE_CHOOSER_ACTION_OPEN,
"_Open",
"_Cancel");
g_object_set_data_full (G_OBJECT (native), "app", g_object_ref (app), g_object_unref);
g_signal_connect (native,
"response",
G_CALLBACK (open_response_cb),
native);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (native));
} }
static void static void
@@ -214,41 +239,6 @@ activate_quit (GSimpleAction *action,
} }
} }
static void
delete_messages (gpointer data)
{
g_list_free_full ((GList *)data, g_free);
}
static void
pop_message (GtkWidget *status)
{
GList *messages = (GList *) g_object_steal_data (G_OBJECT (status), "messages");
if (messages)
{
char *message = messages->data;
messages = g_list_remove (messages, message);
g_object_set_data_full (G_OBJECT (status), "messages",
messages, delete_messages);
gtk_label_set_label (GTK_LABEL (status), message);
}
}
static void
push_message (GtkWidget *status,
const char *message)
{
GList *messages = (GList *) g_object_steal_data (G_OBJECT (status), "messages");
gtk_label_set_label (GTK_LABEL (status), message);
messages = g_list_prepend (messages, g_strdup (message));
g_object_set_data_full (G_OBJECT (status), "messages",
messages, delete_messages);
}
static void static void
update_statusbar (GtkTextBuffer *buffer, update_statusbar (GtkTextBuffer *buffer,
DemoApplicationWindow *window) DemoApplicationWindow *window)
@@ -259,7 +249,7 @@ update_statusbar (GtkTextBuffer *buffer,
GtkTextIter iter; GtkTextIter iter;
/* clear any previous message, underflow is allowed */ /* clear any previous message, underflow is allowed */
pop_message (window->status); gtk_statusbar_pop (GTK_STATUSBAR (window->status), 0);
count = gtk_text_buffer_get_char_count (buffer); count = gtk_text_buffer_get_char_count (buffer);
@@ -273,7 +263,7 @@ update_statusbar (GtkTextBuffer *buffer,
msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document", msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document",
row, col, count); row, col, count);
push_message (window->status, msg); gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, msg);
g_free (msg); g_free (msg);
} }
@@ -330,7 +320,7 @@ static GActionEntry win_entries[] = {
static void static void
clicked_cb (GtkWidget *widget, DemoApplicationWindow *window) clicked_cb (GtkWidget *widget, DemoApplicationWindow *window)
{ {
gtk_widget_set_visible (window->infobar, FALSE); gtk_widget_hide (window->infobar);
} }
static void static void
@@ -514,8 +504,6 @@ demo_application_window_dispose (GObject *object)
demo_application_window_store_state (window); demo_application_window_store_state (window);
gtk_widget_dispose_template (GTK_WIDGET (window), demo_application_window_get_type ());
G_OBJECT_CLASS (demo_application_window_parent_class)->dispose (object); G_OBJECT_CLASS (demo_application_window_parent_class)->dispose (object);
} }

View File

@@ -76,13 +76,8 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkLabel" id="status"> <object class="GtkStatusbar" id="status">
<property name="hexpand">1</property> <property name="hexpand">1</property>
<property name="xalign">0</property>
<property name="margin-start">2</property>
<property name="margin-end">2</property>
<property name="margin-top">2</property>
<property name="margin-bottom">2</property>
<layout> <layout>
<property name="column">0</property> <property name="column">0</property>
<property name="row">3</property> <property name="row">3</property>

View File

@@ -7,8 +7,6 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static GtkWidget *progress_bar = NULL; static GtkWidget *progress_bar = NULL;
static gboolean static gboolean
@@ -100,9 +98,6 @@ create_page1 (GtkWidget *assistant)
gtk_box_append (GTK_BOX (box), label); gtk_box_append (GTK_BOX (box), label);
entry = gtk_entry_new (); entry = gtk_entry_new ();
gtk_accessible_update_relation (GTK_ACCESSIBLE (entry),
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
-1);
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
gtk_widget_set_valign (entry, GTK_ALIGN_CENTER); gtk_widget_set_valign (entry, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (box), entry); gtk_box_append (GTK_BOX (box), entry);
@@ -142,6 +137,7 @@ create_page3 (GtkWidget *assistant)
label = gtk_label_new ("This is a confirmation page, press 'Apply' to apply changes"); label = gtk_label_new ("This is a confirmation page, press 'Apply' to apply changes");
gtk_widget_show (label);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), label); gtk_assistant_append_page (GTK_ASSISTANT (assistant), label);
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), label, GTK_ASSISTANT_PAGE_CONFIRM); gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), label, GTK_ASSISTANT_PAGE_CONFIRM);
gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label, TRUE); gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label, TRUE);
@@ -158,14 +154,11 @@ create_page4 (GtkWidget *assistant)
gtk_widget_set_margin_start (progress_bar, 40); gtk_widget_set_margin_start (progress_bar, 40);
gtk_widget_set_margin_end (progress_bar, 40); gtk_widget_set_margin_end (progress_bar, 40);
gtk_widget_show (progress_bar);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), progress_bar); gtk_assistant_append_page (GTK_ASSISTANT (assistant), progress_bar);
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), progress_bar, GTK_ASSISTANT_PAGE_PROGRESS); gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), progress_bar, GTK_ASSISTANT_PAGE_PROGRESS);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), progress_bar, "Applying changes"); gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), progress_bar, "Applying changes");
gtk_accessible_update_property (GTK_ACCESSIBLE (progress_bar),
GTK_ACCESSIBLE_PROPERTY_LABEL, "Applying changes",
-1);
/* This prevents the assistant window from being /* This prevents the assistant window from being
* closed while we're "busy" applying changes. * closed while we're "busy" applying changes.
*/ */
@@ -203,7 +196,7 @@ do_assistant (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (assistant)) if (!gtk_widget_get_visible (assistant))
gtk_widget_set_visible (assistant, TRUE); gtk_widget_show (assistant);
else else
gtk_window_destroy (GTK_WINDOW (assistant)); gtk_window_destroy (GTK_WINDOW (assistant));

View File

@@ -116,8 +116,7 @@ effective_align (GtkAlign align,
return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END; return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
case GTK_ALIGN_FILL: case GTK_ALIGN_FILL:
case GTK_ALIGN_CENTER: case GTK_ALIGN_CENTER:
case GTK_ALIGN_BASELINE_FILL: case GTK_ALIGN_BASELINE:
case GTK_ALIGN_BASELINE_CENTER:
default: default:
return align; return align;
} }
@@ -259,8 +258,7 @@ blur_overlay_get_child_position (BlurOverlay *overlay,
case GTK_ALIGN_END: case GTK_ALIGN_END:
alloc->x += width - alloc->width; alloc->x += width - alloc->width;
break; break;
case GTK_ALIGN_BASELINE_FILL: case GTK_ALIGN_BASELINE:
case GTK_ALIGN_BASELINE_CENTER:
default: default:
g_assert_not_reached (); g_assert_not_reached ();
break; break;
@@ -283,8 +281,7 @@ blur_overlay_get_child_position (BlurOverlay *overlay,
case GTK_ALIGN_END: case GTK_ALIGN_END:
alloc->y += height - alloc->height; alloc->y += height - alloc->height;
break; break;
case GTK_ALIGN_BASELINE_FILL: case GTK_ALIGN_BASELINE:
case GTK_ALIGN_BASELINE_CENTER:
default: default:
g_assert_not_reached (); g_assert_not_reached ();
break; break;
@@ -300,13 +297,12 @@ blur_overlay_snapshot (GtkWidget *widget,
GtkWidget *main_widget; GtkWidget *main_widget;
GskRenderNode *main_widget_node = NULL; GskRenderNode *main_widget_node = NULL;
GtkWidget *child; GtkWidget *child;
int width, height; GtkAllocation main_alloc;
cairo_region_t *clip = NULL; cairo_region_t *clip = NULL;
int i; int i;
main_widget = BLUR_OVERLAY (widget)->main_widget; main_widget = BLUR_OVERLAY (widget)->main_widget;
width = gtk_widget_get_width (widget); gtk_widget_get_allocation (widget, &main_alloc);
height = gtk_widget_get_height (widget);
for (child = gtk_widget_get_first_child (widget); for (child = gtk_widget_get_first_child (widget);
child != NULL; child != NULL;
@@ -319,7 +315,7 @@ blur_overlay_snapshot (GtkWidget *widget,
if (blur > 0) if (blur > 0)
{ {
cairo_rectangle_int_t rect; GtkAllocation alloc;
graphene_rect_t bounds; graphene_rect_t bounds;
if (main_widget_node == NULL) if (main_widget_node == NULL)
@@ -331,8 +327,8 @@ blur_overlay_snapshot (GtkWidget *widget,
main_widget_node = gtk_snapshot_free_to_node (child_snapshot); main_widget_node = gtk_snapshot_free_to_node (child_snapshot);
} }
if (!gtk_widget_compute_bounds (child, gtk_widget_get_parent (child), &bounds)) gtk_widget_get_allocation (child, &alloc);
graphene_rect_init (&bounds, 0, 0, 0, 0); graphene_rect_init (&bounds, alloc.x, alloc.y, alloc.width, alloc.height);
gtk_snapshot_push_blur (snapshot, blur); gtk_snapshot_push_blur (snapshot, blur);
gtk_snapshot_push_clip (snapshot, &bounds); gtk_snapshot_push_clip (snapshot, &bounds);
gtk_snapshot_append_node (snapshot, main_widget_node); gtk_snapshot_append_node (snapshot, main_widget_node);
@@ -341,17 +337,13 @@ blur_overlay_snapshot (GtkWidget *widget,
if (clip == NULL) if (clip == NULL)
{ {
cairo_rectangle_int_t rect;
rect.x = rect.y = 0; rect.x = rect.y = 0;
rect.width = width; rect.width = main_alloc.width;
rect.height = height; rect.height = main_alloc.height;
clip = cairo_region_create_rectangle (&rect); clip = cairo_region_create_rectangle (&rect);
} }
cairo_region_subtract_rectangle (clip, (cairo_rectangle_int_t *)&alloc);
rect.x = floor (bounds.origin.x);
rect.y = floor (bounds.origin.y);
rect.width = ceil (bounds.origin.x + bounds.size.width - rect.x);
rect.height = ceil (bounds.origin.y + bounds.size.height - rect.y);
cairo_region_subtract_rectangle (clip, &rect);
} }
} }

View File

@@ -18,7 +18,8 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #ifndef __BLUR_OVERLAY_H__
#define __BLUR_OVERLAY_H__
#include <gtk/gtk.h> #include <gtk/gtk.h>
@@ -50,12 +51,18 @@ struct _BlurOverlayClass
GtkAllocation *allocation); GtkAllocation *allocation);
}; };
GDK_AVAILABLE_IN_ALL
GType blur_overlay_get_type (void) G_GNUC_CONST; GType blur_overlay_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkWidget *blur_overlay_new (void); GtkWidget *blur_overlay_new (void);
GDK_AVAILABLE_IN_ALL
void blur_overlay_add_overlay (BlurOverlay *overlay, void blur_overlay_add_overlay (BlurOverlay *overlay,
GtkWidget *widget, GtkWidget *widget,
double blur); double blur);
GDK_AVAILABLE_IN_ALL
void blur_overlay_set_child (BlurOverlay *overlay, void blur_overlay_set_child (BlurOverlay *overlay,
GtkWidget *widget); GtkWidget *widget);
G_END_DECLS G_END_DECLS
#endif /* __BLUR_OVERLAY_H__ */

View File

@@ -1,5 +1,5 @@
/* Builder /* Builder
* #Keywords: GMenu, GtkPopoverMenuBar, GtkBuilder, GtkShortcutController, toolbar * #Keywords: GMenu, GtkPopoverMenuBar, GtkBuilder, GtkStatusBar, GtkShortcutController, toolbar
* *
* Demonstrates a traditional interface, loaded from a XML description, * Demonstrates a traditional interface, loaded from a XML description,
* and shows how to connect actions to the menu items and toolbar buttons. * and shows how to connect actions to the menu items and toolbar buttons.
@@ -37,30 +37,22 @@ remove_timeout (gpointer data)
g_source_remove (id); g_source_remove (id);
} }
static int static gboolean
pop_message (gpointer data) pop_status (gpointer data)
{ {
GtkWidget *status = data; gtk_statusbar_pop (GTK_STATUSBAR (data), 0);
g_object_set_data (G_OBJECT (data), "timeout", NULL);
gtk_label_set_label (GTK_LABEL (status), "");
g_object_set_data (G_OBJECT (status), "timeout", GUINT_TO_POINTER (0));
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static void static void
status_message (GtkWidget *status, status_message (GtkStatusbar *status,
const char *text) const char *text)
{ {
guint id; guint id;
id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (status), "timeout")); gtk_statusbar_push (GTK_STATUSBAR (status), 0, text);
if (id) id = g_timeout_add (5000, pop_status, status);
g_source_remove (id);
gtk_label_set_text (GTK_LABEL (status), text);
id = g_timeout_add (5000, pop_message, status);
g_object_set_data_full (G_OBJECT (status), "timeout", GUINT_TO_POINTER (id), remove_timeout); g_object_set_data_full (G_OBJECT (status), "timeout", GUINT_TO_POINTER (id), remove_timeout);
} }
@@ -73,7 +65,7 @@ help_activate (GSimpleAction *action,
GtkWidget *status; GtkWidget *status;
status = GTK_WIDGET (g_object_get_data (G_OBJECT (user_data), "status")); status = GTK_WIDGET (g_object_get_data (G_OBJECT (user_data), "status"));
status_message (status, "Help not available"); status_message (GTK_STATUSBAR (status), "Help not available");
} }
static void static void
@@ -86,7 +78,7 @@ not_implemented (GSimpleAction *action,
text = g_strdup_printf ("Action “%s” not implemented", g_action_get_name (G_ACTION (action))); text = g_strdup_printf ("Action “%s” not implemented", g_action_get_name (G_ACTION (action)));
status = GTK_WIDGET (g_object_get_data (G_OBJECT (user_data), "status")); status = GTK_WIDGET (g_object_get_data (G_OBJECT (user_data), "status"));
status_message (status, text); status_message (GTK_STATUSBAR (status), text);
g_free (text); g_free (text);
} }
@@ -176,7 +168,7 @@ do_builder (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,11 +1,12 @@
/* Clipboard /* Clipboard
* #Keywords: drag-and-drop, dnd
* *
* GdkClipboard is used for clipboard handling. This demo shows how to * GdkClipboard is used for clipboard handling. This demo shows how to
* copy and paste text, images, colors or files to and from the clipboard. * copy and paste text to and from the clipboard.
* *
* You can also use Drag-And-Drop to copy the data from the source to the * It also shows how to transfer images via the clipboard or via
* target. * drag-and-drop, and how to make clipboard contents persist after
* the application exits. Clipboard persistence requires a clipboard
* manager to run.
*/ */
#include <glib/gi18n.h> #include <glib/gi18n.h>
@@ -13,103 +14,22 @@
#include <string.h> #include <string.h>
#include "demoimage.h" #include "demoimage.h"
static GtkWidget *window = NULL;
static void static void
copy_button_clicked (GtkStack *source_stack, copy_button_clicked (GtkWidget *button,
gpointer user_data) gpointer user_data)
{ {
GtkWidget *entry;
GdkClipboard *clipboard; GdkClipboard *clipboard;
const char *visible_child_name;
GtkWidget *visible_child;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (source_stack)); entry = GTK_WIDGET (user_data);
visible_child = gtk_stack_get_visible_child (source_stack); /* Get the clipboard object */
visible_child_name = gtk_stack_get_visible_child_name (source_stack); clipboard = gtk_widget_get_clipboard (entry);
if (strcmp (visible_child_name, "Text") == 0) /* Set clipboard text */
{ gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (entry)));
gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (visible_child)));
}
else if (strcmp (visible_child_name, "Image") == 0)
{
GtkWidget *child;
for (child = gtk_widget_get_first_child (visible_child); child; child = gtk_widget_get_next_sibling (child))
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (child)))
{
GtkWidget *image = gtk_widget_get_first_child (child);
GdkPaintable *paintable = gtk_image_get_paintable (GTK_IMAGE (image));
if (GDK_IS_TEXTURE (paintable))
gdk_clipboard_set (clipboard, GDK_TYPE_TEXTURE, paintable);
else
gdk_clipboard_set (clipboard, GDK_TYPE_PAINTABLE, paintable);
break;
}
}
}
else if (strcmp (visible_child_name, "Color") == 0)
{
const GdkRGBA *color;
color = gtk_color_dialog_button_get_rgba (GTK_COLOR_DIALOG_BUTTON (visible_child));
gdk_clipboard_set (clipboard, GDK_TYPE_RGBA, color);
}
else if (strcmp (visible_child_name, "File") == 0)
{
gdk_clipboard_set (clipboard, G_TYPE_FILE, g_object_get_data (G_OBJECT (visible_child), "file"), NULL);
}
else
{
g_print ("TODO");
}
}
static void
present_value (GtkStack *dest_stack,
const GValue *value)
{
GtkWidget *child;
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
GFile *file;
gtk_stack_set_visible_child_name (dest_stack, "File");
child = gtk_stack_get_visible_child (dest_stack);
file = g_value_get_object (value);
g_object_set (child, "label", g_file_peek_path (file), NULL);
}
else if (G_VALUE_HOLDS (value, GDK_TYPE_RGBA))
{
GdkRGBA *color;
gtk_stack_set_visible_child_name (dest_stack, "Color");
child = gtk_widget_get_first_child (gtk_stack_get_visible_child (dest_stack));
color = g_value_get_boxed (value);
g_object_set (child, "rgba", color, NULL);
}
else if (G_VALUE_HOLDS (value, GDK_TYPE_TEXTURE) ||
G_VALUE_HOLDS (value, GDK_TYPE_PAINTABLE))
{
GdkPaintable *paintable;
gtk_stack_set_visible_child_name (dest_stack, "Image");
child = gtk_stack_get_visible_child (dest_stack);
paintable = g_value_get_object (value);
g_object_set (child, "paintable", paintable, NULL);
}
else if (G_VALUE_HOLDS (value, G_TYPE_STRING))
{
gtk_stack_set_visible_child_name (dest_stack, "Text");
child = gtk_stack_get_visible_child (dest_stack);
gtk_label_set_label (GTK_LABEL (child), g_value_get_string (value));
}
} }
static void static void
@@ -117,295 +37,153 @@ paste_received (GObject *source_object,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GtkStack *dest_stack = user_data;
GdkClipboard *clipboard; GdkClipboard *clipboard;
const GValue *value; GtkWidget *entry;
char *text;
GError *error = NULL; GError *error = NULL;
clipboard = GDK_CLIPBOARD (source_object); clipboard = GDK_CLIPBOARD (source_object);
entry = GTK_WIDGET (user_data);
value = gdk_clipboard_read_value_finish (clipboard, result, &error); /* Get the resulting text of the read operation */
if (value) text = gdk_clipboard_read_text_finish (clipboard, result, &error);
if (text)
{ {
present_value (dest_stack, value); /* Set the entry text */
gtk_editable_set_text (GTK_EDITABLE (entry), text);
g_free (text);
} }
else else
{ {
g_print ("%s\n", error->message); GtkWidget *dialog;
/* Show an error about why pasting failed.
* Usually you probably want to ignore such failures,
* but for demonstration purposes, we show the error.
*/
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Could not paste text: %s",
error->message);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (dialog);
g_error_free (error); g_error_free (error);
} }
} }
static void static void
paste_button_clicked (GtkStack *dest_stack, paste_button_clicked (GtkWidget *button,
gpointer user_data) gpointer user_data)
{ {
GtkWidget *entry;
GdkClipboard *clipboard; GdkClipboard *clipboard;
GdkContentFormats *formats;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (dest_stack)); entry = GTK_WIDGET (user_data);
formats = gdk_clipboard_get_formats (clipboard);
if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_TEXTURE)) /* Get the clipboard object */
gdk_clipboard_read_value_async (clipboard, GDK_TYPE_TEXTURE, 0, NULL, paste_received, dest_stack); clipboard = gtk_widget_get_clipboard (entry);
else if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_PAINTABLE))
gdk_clipboard_read_value_async (clipboard, GDK_TYPE_PAINTABLE, 0, NULL, paste_received, dest_stack);
else if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_RGBA))
gdk_clipboard_read_value_async (clipboard, GDK_TYPE_RGBA, 0, NULL, paste_received, dest_stack);
else if (gdk_content_formats_contain_gtype (formats, G_TYPE_FILE))
gdk_clipboard_read_value_async (clipboard, G_TYPE_FILE, 0, NULL, paste_received, dest_stack);
else if (gdk_content_formats_contain_gtype (formats, G_TYPE_STRING))
gdk_clipboard_read_value_async (clipboard, G_TYPE_STRING, 0, NULL, paste_received, dest_stack);
}
static void /* Request the contents of the clipboard, contents_received will be
update_copy_button_sensitivity (GtkWidget *source_stack) called when we do get the contents.
{ */
GtkButton *copy_button; gdk_clipboard_read_text_async (clipboard, NULL, paste_received, entry);
const char *visible_child_name;
GtkWidget *visible_child;
gboolean sensitive;
copy_button = GTK_BUTTON (g_object_get_data (G_OBJECT (source_stack), "copy-button"));
visible_child = gtk_stack_get_visible_child (GTK_STACK (source_stack));
visible_child_name = gtk_stack_get_visible_child_name (GTK_STACK (source_stack));
if (strcmp (visible_child_name, "Text") == 0)
{
sensitive = strlen (gtk_editable_get_text (GTK_EDITABLE (visible_child))) > 0;
}
else if (strcmp (visible_child_name, "Color") == 0 ||
strcmp (visible_child_name, "Image") == 0)
{
sensitive = TRUE;
}
else if (strcmp (visible_child_name, "File") == 0)
{
sensitive = g_object_get_data (G_OBJECT (visible_child), "file") != NULL;
}
else
{
sensitive = FALSE;
}
gtk_widget_set_sensitive (GTK_WIDGET (copy_button), sensitive);
}
static void
source_changed_cb (GtkButton *copy_button,
GParamSpec *pspec,
GtkWidget *source_stack)
{
update_copy_button_sensitivity (source_stack);
}
static void
text_changed_cb (GtkButton *copy_button,
GParamSpec *pspec,
GtkWidget *entry)
{
update_copy_button_sensitivity (gtk_widget_get_ancestor (entry, GTK_TYPE_STACK));
}
static void
file_button_set_file (GtkButton *button,
GFile *file)
{
gtk_label_set_label (GTK_LABEL (gtk_button_get_child (button)), g_file_peek_path (file));
g_object_set_data_full (G_OBJECT (button), "file", g_object_ref (file), g_object_unref);
}
static void
file_chooser_response (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
GtkButton *button = GTK_BUTTON (user_data);
GFile *file;
file = gtk_file_dialog_open_finish (dialog, result, NULL);
if (file)
{
file_button_set_file (button, file);
g_object_unref (file);
update_copy_button_sensitivity (gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_STACK));
}
}
static void
open_file_cb (GtkWidget *button)
{
GtkFileDialog *dialog;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_open (dialog,
GTK_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW)),
NULL,
file_chooser_response, button);
g_object_unref (dialog);
}
static void
folder_chooser_response (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
GtkButton *button = GTK_BUTTON (user_data);
GFile *file;
file = gtk_file_dialog_select_folder_finish (dialog, result, NULL);
if (file)
{
file_button_set_file (button, file);
g_object_unref (file);
update_copy_button_sensitivity (gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_STACK));
}
}
static void
open_folder_cb (GtkWidget *button)
{
GtkFileDialog *dialog;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_select_folder (dialog,
GTK_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW)),
NULL,
folder_chooser_response, button);
g_object_unref (dialog);
}
static void
update_paste_button_sensitivity (GdkClipboard *clipboard,
GtkWidget *paste_button)
{
GdkContentFormats *formats;
gboolean sensitive = FALSE;
formats = gdk_clipboard_get_formats (clipboard);
if (gdk_content_formats_contain_gtype (formats, G_TYPE_FILE) ||
gdk_content_formats_contain_gtype (formats, GDK_TYPE_RGBA) ||
gdk_content_formats_contain_gtype (formats, GDK_TYPE_TEXTURE) ||
gdk_content_formats_contain_gtype (formats, GDK_TYPE_PAINTABLE) ||
gdk_content_formats_contain_gtype (formats, G_TYPE_STRING))
sensitive = TRUE;
gtk_widget_set_sensitive (paste_button, sensitive);
}
static void
unset_clipboard_handler (gpointer data)
{
GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
g_signal_handlers_disconnect_by_func (clipboard, update_paste_button_sensitivity, data);
}
static gboolean
on_drop (GtkStack *dest_stack,
const GValue *value,
double x,
double y,
gpointer data)
{
present_value (dest_stack, value);
return TRUE;
}
static GdkContentProvider *
drag_prepare (GtkDragSource *drag_source,
double x,
double y,
gpointer data)
{
GtkWidget *button;
GValue value = G_VALUE_INIT;
button = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag_source));
if (GTK_IS_TOGGLE_BUTTON (button))
{
GtkWidget *image = gtk_widget_get_first_child (button);
GdkPaintable *paintable = gtk_image_get_paintable (GTK_IMAGE (image));
if (GDK_IS_TEXTURE (paintable))
{
g_value_init (&value, GDK_TYPE_TEXTURE);
g_value_set_object (&value, paintable);
}
else
{
g_value_init (&value, GDK_TYPE_PAINTABLE);
g_value_set_object (&value, paintable);
}
}
else
{
GFile *file = g_object_get_data (G_OBJECT (button), "file");
if (file)
{
g_value_init (&value, G_TYPE_FILE);
g_value_set_object (&value, file);
}
else
return NULL;
}
return gdk_content_provider_new_for_value (&value);
} }
GtkWidget * GtkWidget *
do_clipboard (GtkWidget *do_widget) do_clipboard (GtkWidget *do_widget)
{ {
static GtkWidget *window = NULL;
if (!window) if (!window)
{ {
GtkBuilderScope *scope; GtkWidget *vbox, *hbox;
GtkBuilder *builder; GtkWidget *label;
GtkWidget *button; GtkWidget *entry, *button;
GtkWidget *image;
scope = gtk_builder_cscope_new (); window = gtk_window_new ();
gtk_builder_cscope_add_callback (scope, copy_button_clicked); gtk_window_set_display (GTK_WINDOW (window),
gtk_builder_cscope_add_callback (scope, paste_button_clicked); gtk_widget_get_display (do_widget));
gtk_builder_cscope_add_callback (scope, source_changed_cb); gtk_window_set_title (GTK_WINDOW (window), "Clipboard");
gtk_builder_cscope_add_callback (scope, text_changed_cb);
gtk_builder_cscope_add_callback (scope, open_file_cb);
gtk_builder_cscope_add_callback (scope, open_folder_cb);
gtk_builder_cscope_add_callback (scope, on_drop);
gtk_builder_cscope_add_callback (scope, drag_prepare);
builder = gtk_builder_new ();
gtk_builder_set_scope (builder, scope);
gtk_builder_add_from_resource (builder, "/clipboard/clipboard.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
button = GTK_WIDGET (gtk_builder_get_object (builder, "copy_button")); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set_data (gtk_builder_get_object (builder, "source_stack"), "copy-button", button); gtk_widget_set_margin_start (vbox, 8);
gtk_widget_set_margin_end (vbox, 8);
gtk_widget_set_margin_top (vbox, 8);
gtk_widget_set_margin_bottom (vbox, 8);
button = GTK_WIDGET (gtk_builder_get_object (builder, "paste_button")); gtk_window_set_child (GTK_WINDOW (window), vbox);
g_signal_connect (gtk_widget_get_clipboard (button), "changed",
G_CALLBACK (update_paste_button_sensitivity), button);
g_object_set_data_full (G_OBJECT (button), "clipboard-handler", button, unset_clipboard_handler);
g_object_unref (builder); label = gtk_label_new ("\"Copy\" will copy the text\nin the entry to the clipboard");
g_object_unref (scope);
gtk_box_append (GTK_BOX (vbox), label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_widget_set_margin_start (hbox, 8);
gtk_widget_set_margin_end (hbox, 8);
gtk_widget_set_margin_top (hbox, 8);
gtk_widget_set_margin_bottom (hbox, 8);
gtk_box_append (GTK_BOX (vbox), hbox);
/* Create the first entry */
entry = gtk_entry_new ();
gtk_box_append (GTK_BOX (hbox), entry);
/* Create the button */
button = gtk_button_new_with_mnemonic (_("_Copy"));
gtk_box_append (GTK_BOX (hbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (copy_button_clicked), entry);
label = gtk_label_new ("\"Paste\" will paste the text from the clipboard to the entry");
gtk_box_append (GTK_BOX (vbox), label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_widget_set_margin_start (hbox, 8);
gtk_widget_set_margin_end (hbox, 8);
gtk_widget_set_margin_top (hbox, 8);
gtk_widget_set_margin_bottom (hbox, 8);
gtk_box_append (GTK_BOX (vbox), hbox);
/* Create the second entry */
entry = gtk_entry_new ();
gtk_box_append (GTK_BOX (hbox), entry);
/* Create the button */
button = gtk_button_new_with_mnemonic (_("_Paste"));
gtk_box_append (GTK_BOX (hbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (paste_button_clicked), entry);
label = gtk_label_new ("Images can be transferred via the clipboard, too");
gtk_box_append (GTK_BOX (vbox), label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_widget_set_margin_start (hbox, 8);
gtk_widget_set_margin_end (hbox, 8);
gtk_widget_set_margin_top (hbox, 8);
gtk_widget_set_margin_bottom (hbox, 8);
gtk_box_append (GTK_BOX (vbox), hbox);
/* Create the first image */
image = demo_image_new ("dialog-warning");
gtk_box_append (GTK_BOX (hbox), image);
/* Create the second image */
image = demo_image_new ("process-stop");
gtk_box_append (GTK_BOX (hbox), image);
/* Create the third image */
image = demo_image_new ("weather-clear");
gtk_box_append (GTK_BOX (hbox), image);
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -1,362 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="resizable">1</property>
<property name="title">Clipboard</property>
<accessibility>
<relation name="described-by">label</relation>
</accessibility>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label">
<property name="label">“Copy” will copy the selected data the clipboard, “Paste” will show the current clipboard contents. You can also drag the data to the bottom.</property>
<property name="wrap">1</property>
<property name="max-width-chars">40</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">12</property>
<child>
<object class="GtkDropDown" id="source_chooser">
<accessibility>
<property name="label">Source Type</property>
</accessibility>
<property name="valign">center</property>
<property name="model">
<object class="GtkStringList">
<items>
<item>Text</item>
<item>Color</item>
<item>Image</item>
<item>File</item>
<item>Folder</item>
</items>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStack" id="source_stack">
<signal name="notify::visible-child" handler="source_changed_cb" object="copy_button"/>
<property name="vexpand">1</property>
<binding name="visible-child-name">
<lookup name="string" type="GtkStringObject">
<lookup name="selected-item">
source_chooser
</lookup>
</lookup>
</binding>
<child>
<object class="GtkStackPage">
<property name="name">Text</property>
<property name="child">
<object class="GtkEntry" id="source_text">
<accessibility>
<property name="label">Text Drag Source</property>
</accessibility>
<property name="valign">center</property>
<signal name="notify::text" handler="text_changed_cb" object="copy_button"/>
<property name="text">Copy this!</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">Color</property>
<property name="child">
<object class="GtkColorDialogButton" id="source_color">
<accessibility>
<property name="label">Color Drag Source</property>
</accessibility>
<property name="dialog">
<object class="GtkColorDialog">
</object>
</property>
<property name="valign">center</property>
<property name="rgba">purple</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">Image</property>
<property name="child">
<object class="GtkBox">
<property name="valign">center</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkToggleButton" id="image_rose">
<accessibility>
<property name="label">Photo Drag Source</property>
</accessibility>
<property name="active">1</property>
<child>
</child>
<child>
<object class="GtkImage">
<accessibility>
<property name="label">Portland Rose Photo</property>
</accessibility>
<style>
<class name="large-icons"/>
</style>
<property name="paintable">resource:///transparent/portland-rose.jpg</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToggleButton" id="image_floppy">
<accessibility>
<property name="label">Icon Drag Source</property>
</accessibility>
<property name="group">image_rose</property>
<child>
<object class="GtkDragSource">
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<child>
<object class="GtkImage">
<accessibility>
<property name="label">Floppy Buddy Icon</property>
</accessibility>
<style>
<class name="large-icons"/>
</style>
<property name="paintable">resource:///images/floppybuddy.gif</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToggleButton" id="image_logo">
<accessibility>
<property name="label">SVG Drag Source</property>
</accessibility>
<property name="group">image_floppy</property>
<child>
<object class="GtkDragSource">
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<child>
<object class="GtkImage">
<accessibility>
<property name="label">gtk-demo logo</property>
</accessibility>
<style>
<class name="large-icons"/>
</style>
<property name="paintable">resource:///images/org.gtk.Demo4.svg</property>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">File</property>
<property name="child">
<object class="GtkButton" id="source_file">
<accessibility>
<property name="label">File Drag Source</property>
</accessibility>
<child>
<object class="GtkDragSource">
<property name="propagation-phase">capture</property>
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<property name="valign">center</property>
<property name="child">
<object class="GtkLabel">
<property name="label">—</property>
<property name="xalign">0</property>
<property name="ellipsize">start</property>
</object>
</property>
<signal name="clicked" handler="open_file_cb"/>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">Folder</property>
<property name="child">
<object class="GtkButton" id="source_folder">
<accessibility>
<property name="label">Folder Drag Source</property>
</accessibility>
<child>
<object class="GtkDragSource">
<property name="propagation-phase">capture</property>
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<property name="valign">center</property>
<property name="child">
<object class="GtkLabel">
<property name="label">—</property>
<property name="xalign">0</property>
<property name="ellipsize">start</property>
</object>
</property>
<signal name="clicked" handler="open_folder_cb"/>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="copy_button">
<property name="valign">center</property>
<property name="label" translatable="yes">_Copy</property>
<signal name="clicked" handler="copy_button_clicked" object="source_stack"/>
<property name="use-underline">1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSeparator">
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">12</property>
<child>
<object class="GtkDropTarget">
<property name="actions">copy</property>
<property name="formats">GdkTexture GdkPaintable GFile GdkRGBA gchararray</property>
<signal name="drop" handler="on_drop" object="dest_stack"/>
</object>
</child>
<child>
<object class="GtkButton" id="paste_button">
<property name="label" translatable="yes">_Paste</property>
<signal name="clicked" handler="paste_button_clicked" object="dest_stack"/>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkLabel" id="paste_label">
<property name="xalign">0</property>
<binding name="label">
<lookup name="visible-child-name" type="GtkStack">
dest_stack
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkStack" id="dest_stack">
<property name="halign">end</property>
<property name="valign">center</property>
<child>
<object class="GtkStackPage">
<property name="name"></property>
<property name="child">
<object class="GtkLabel">
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">Text</property>
<property name="child">
<object class="GtkLabel">
<accessibility>
<relation name="labelled-by">paste_label</relation>
</accessibility>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="xalign">0</property>
<property name="ellipsize">end</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">Image</property>
<property name="child">
<object class="GtkImage">
<accessibility>
<relation name="labelled-by">paste_label</relation>
</accessibility>
<property name="halign">end</property>
<property name="valign">center</property>
<style>
<class name="large-icons"/>
</style>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">Color</property>
<property name="child">
<object class="GtkBox">
<property name="halign">end</property>
<property name="valign">center</property>
<child>
<object class="GtkColorSwatch">
<accessibility>
<relation name="labelled-by">paste_label</relation>
</accessibility>
<property name="accessible-role">img</property>
<property name="can-focus">0</property>
<property name="selectable">0</property>
<property name="has-menu">0</property>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">File</property>
<property name="child">
<object class="GtkLabel">
<accessibility>
<relation name="labelled-by">paste_label</relation>
</accessibility>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<property name="ellipsize">start</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -11,8 +11,6 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
enum enum
{ {
ICON_NAME_COL, ICON_NAME_COL,
@@ -449,7 +447,7 @@ do_combobox (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -277,7 +277,7 @@ do_constraints (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -66,7 +66,7 @@ do_constraints_builder (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -229,7 +229,7 @@ do_constraints_interactive (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -152,7 +152,7 @@ do_constraints_vfl (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1019 B

After

Width:  |  Height:  |  Size: 985 B

View File

@@ -1,16 +1,20 @@
/* Theming/CSS Accordion /* Theming/CSS Accordion
* *
* A simple accordion demo written using CSS transitions and multiple backgrounds * A simple accordion demo written using CSS transitions and multiple backgrounds
*
*/ */
#include <gtk/gtk.h> #include <gtk/gtk.h>
static void static void
destroy_provider (GtkWidget *window, apply_css (GtkWidget *widget, GtkStyleProvider *provider)
GtkStyleProvider *provider)
{ {
gtk_style_context_remove_provider_for_display (gtk_widget_get_display (window), provider); GtkWidget *child;
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
} }
GtkWidget * GtkWidget *
@@ -20,8 +24,8 @@ do_css_accordion (GtkWidget *do_widget)
if (!window) if (!window)
{ {
GtkWidget *container, *styled_box, *child; GtkWidget *container, *child;
GtkCssProvider *provider; GtkStyleProvider *provider;
window = gtk_window_new (); window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "CSS Accordion"); gtk_window_set_title (GTK_WINDOW (window), "CSS Accordion");
@@ -29,13 +33,10 @@ do_css_accordion (GtkWidget *do_widget)
gtk_window_set_default_size (GTK_WINDOW (window), 600, 300); gtk_window_set_default_size (GTK_WINDOW (window), 600, 300);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
styled_box = gtk_frame_new (NULL);
gtk_window_set_child (GTK_WINDOW (window), styled_box);
gtk_widget_add_css_class (styled_box, "accordion");
container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_halign (container, GTK_ALIGN_CENTER); gtk_widget_set_halign (container, GTK_ALIGN_CENTER);
gtk_widget_set_valign (container, GTK_ALIGN_CENTER); gtk_widget_set_valign (container, GTK_ALIGN_CENTER);
gtk_frame_set_child (GTK_FRAME (styled_box), container); gtk_window_set_child (GTK_WINDOW (window), container);
child = gtk_button_new_with_label ("This"); child = gtk_button_new_with_label ("This");
gtk_box_append (GTK_BOX (container), child); gtk_box_append (GTK_BOX (container), child);
@@ -55,20 +56,14 @@ do_css_accordion (GtkWidget *do_widget)
child = gtk_button_new_with_label (":-)"); child = gtk_button_new_with_label (":-)");
gtk_box_append (GTK_BOX (container), child); gtk_box_append (GTK_BOX (container), child);
provider = gtk_css_provider_new (); provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
gtk_css_provider_load_from_resource (provider, "/css_accordion/css_accordion.css"); gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (provider), "/css_accordion/css_accordion.css");
gtk_style_context_add_provider_for_display (gtk_widget_get_display (window), apply_css (window, provider);
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_signal_connect (window, "destroy",
G_CALLBACK (destroy_provider), provider);
g_object_unref (provider);
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -1,13 +1,13 @@
.accordion, .accordion * { @import url("resource://css_accordion/reset.css");
all: unset;
* {
transition-property: color, background-color, border-color, background-image, padding, border-width; transition-property: color, background-color, border-color, background-image, padding, border-width;
transition-duration: 1s; transition-duration: 1s;
font: 20px Cantarell; font: 20px Cantarell;
} }
.accordion { window {
background: linear-gradient(153deg, #151515, #151515 5px, transparent 5px) 0 0, background: linear-gradient(153deg, #151515, #151515 5px, transparent 5px) 0 0,
linear-gradient(333deg, #151515, #151515 5px, transparent 5px) 10px 5px, linear-gradient(333deg, #151515, #151515 5px, transparent 5px) 10px 5px,
linear-gradient(153deg, #222, #222 5px, transparent 5px) 0 5px, linear-gradient(153deg, #222, #222 5px, transparent 5px) 0 5px,
@@ -18,7 +18,7 @@
background-size: 20px 20px; background-size: 20px 20px;
} }
.accordion button { button {
color: black; color: black;
background-color: #bbb; background-color: #bbb;
border-style: solid; border-style: solid;
@@ -28,25 +28,25 @@
padding: 12px 4px; padding: 12px 4px;
} }
.accordion button:first-child { button:first-child {
border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px;
} }
.accordion button:last-child { button:last-child {
border-radius: 0 5px 5px 0; border-radius: 0 5px 5px 0;
border-width: 2px; border-width: 2px;
} }
.accordion button:hover { button:hover {
padding: 12px 48px; padding: 12px 48px;
background-color: #4870bc; background-color: #4870bc;
} }
.accordion button *:hover { button *:hover {
color: white; color: white;
} }
.accordion button:hover:active, button:hover:active,
.accordion button:active { button:active {
background-color: #993401; background-color: #993401;
} }

View File

@@ -47,23 +47,20 @@ css_text_changed (GtkTextBuffer *buffer,
gtk_text_buffer_remove_all_tags (buffer, &start, &end); gtk_text_buffer_remove_all_tags (buffer, &start, &end);
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
gtk_css_provider_load_from_string (provider, text); gtk_css_provider_load_from_data (provider, text, -1);
g_free (text); g_free (text);
} }
static void
clear_provider (gpointer data)
{
GtkStyleProvider *provider = data;
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
}
static void static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider) apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{ {
gtk_style_context_add_provider_for_display (gdk_display_get_default (), provider, G_MAXUINT); GtkWidget *child;
g_object_set_data_full (G_OBJECT (widget), "provider", provider, clear_provider);
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
} }
GtkWidget * GtkWidget *
@@ -82,7 +79,6 @@ do_css_basics (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "CSS Basics"); gtk_window_set_title (GTK_WINDOW (window), "CSS Basics");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget)); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300); gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
gtk_widget_add_css_class (window, "demo");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
text = gtk_text_buffer_new (NULL); text = gtk_text_buffer_new (NULL);
@@ -117,7 +113,7 @@ do_css_basics (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -4,24 +4,23 @@
* anymore. :) * anymore. :)
*/ */
/* This resets all properties to their defaults values /* This CSS resets all properties to their defaults values
* and overrides all user settings and the theme in use * and overrides all user settings and the theme in use */
*/ @import url("resource://css_basics/reset.css");
@import url("resource://css_shadows/reset.css");
/* Set a very futuristic style by default */ /* Set a very futuristic style by default */
.demo * { * {
color: green; color: green;
font-family: Monospace; font-family: Monospace;
border: 1px solid; border: 1px solid;
} }
window.demo { window {
background-color: white; background-color: white;
} }
/* Make sure selections are visible */ /* Make sure selections are visible */
.demo selection { selection {
background-color: darkGreen; background-color: darkGreen;
color: black; color: black;
} }

View File

@@ -50,7 +50,7 @@ update_css_for_blend_mode (GtkCssProvider *provider,
blend_mode, blend_mode,
blend_mode); blend_mode);
gtk_css_provider_load_from_string (provider, css); gtk_css_provider_load_from_data (provider, css, -1);
g_bytes_unref (bytes); g_bytes_unref (bytes);
g_free (css); g_free (css);
@@ -139,7 +139,7 @@ do_css_blendmodes (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -48,23 +48,33 @@ css_text_changed (GtkTextBuffer *buffer,
gtk_text_buffer_remove_all_tags (buffer, &start, &end); gtk_text_buffer_remove_all_tags (buffer, &start, &end);
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
gtk_css_provider_load_from_string (provider, text); gtk_css_provider_load_from_data (provider, text, -1);
g_free (text); g_free (text);
} }
static void static void
clear_provider (gpointer data) drawing_area_draw (GtkDrawingArea *da,
cairo_t *cr,
int width,
int height,
gpointer data)
{ {
GtkStyleProvider *provider = data; GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (da));
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider); gtk_render_background (context, cr, 0, 0, width, height);
gtk_render_frame (context, cr, 0, 0, width, height);
} }
static void static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider) apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{ {
gtk_style_context_add_provider_for_display (gdk_display_get_default (), provider, G_MAXUINT); GtkWidget *child;
g_object_set_data_full (G_OBJECT (widget), "provider", provider, clear_provider);
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
} }
GtkWidget * GtkWidget *
@@ -83,17 +93,16 @@ do_css_multiplebgs (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "Multiple Backgrounds"); gtk_window_set_title (GTK_WINDOW (window), "Multiple Backgrounds");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget)); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300); gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
gtk_widget_add_css_class (window, "demo");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
overlay = gtk_overlay_new (); overlay = gtk_overlay_new ();
gtk_window_set_child (GTK_WINDOW (window), overlay); gtk_window_set_child (GTK_WINDOW (window), overlay);
child = gtk_drawing_area_new (); child = gtk_drawing_area_new ();
/* Don't set a draw_func, since we are only interested in CSS drawing,
* which happens automatically.
*/
gtk_widget_set_name (child, "canvas"); gtk_widget_set_name (child, "canvas");
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (child),
drawing_area_draw,
NULL, NULL);
gtk_overlay_set_child (GTK_OVERLAY (overlay), child); gtk_overlay_set_child (GTK_OVERLAY (overlay), child);
child = gtk_button_new (); child = gtk_button_new ();
@@ -144,7 +153,7 @@ do_css_multiplebgs (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -49,23 +49,20 @@ css_text_changed (GtkTextBuffer *buffer,
gtk_text_buffer_remove_all_tags (buffer, &start, &end); gtk_text_buffer_remove_all_tags (buffer, &start, &end);
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
gtk_css_provider_load_from_string (provider, text); gtk_css_provider_load_from_data (provider, text, -1);
g_free (text); g_free (text);
} }
static void
clear_provider (gpointer data)
{
GtkStyleProvider *provider = data;
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
}
static void static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider) apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{ {
gtk_style_context_add_provider_for_display (gdk_display_get_default (), provider, G_MAXUINT); GtkWidget *child;
g_object_set_data_full (G_OBJECT (widget), "provider", provider, clear_provider);
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
} }
GtkWidget * GtkWidget *
@@ -84,7 +81,6 @@ do_css_pixbufs (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "Animated Backgrounds"); gtk_window_set_title (GTK_WINDOW (window), "Animated Backgrounds");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget)); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300); gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
gtk_widget_add_css_class (window, "demo");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL); paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
@@ -126,7 +122,7 @@ do_css_pixbufs (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -50,7 +50,7 @@
100% { background-size: 12px, 96px, 12px, 96px, 12px, 96px, 12px, 96px, auto; } 100% { background-size: 12px, 96px, 12px, 96px, 12px, 96px, 12px, 96px, auto; }
} }
window.demo { window {
background-image: url("resource://css_pixbufs/images/apple-red.png"), background-image: url("resource://css_pixbufs/images/apple-red.png"),
url("resource://css_pixbufs/images/gnome-applets.png"), url("resource://css_pixbufs/images/gnome-applets.png"),
url("resource://css_pixbufs/images/gnome-calendar.png"), url("resource://css_pixbufs/images/gnome-calendar.png"),
@@ -66,11 +66,11 @@ window.demo {
} }
/* Make the text editor has a nice style */ /* Make the text editor has a nice style */
window.demo .view, scrollbar, separator { .view, scrollbar, separator {
color: black; color: black;
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
} }
window.demo .view:selected { .view:selected {
background-color: rgba(127,127,255,0.5); background-color: rgba(127,127,255,0.5);
} }

View File

@@ -46,23 +46,20 @@ css_text_changed (GtkTextBuffer *buffer,
gtk_text_buffer_remove_all_tags (buffer, &start, &end); gtk_text_buffer_remove_all_tags (buffer, &start, &end);
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
gtk_css_provider_load_from_string (provider, text); gtk_css_provider_load_from_data (provider, text, -1);
g_free (text); g_free (text);
} }
static void
clear_provider (gpointer data)
{
GtkStyleProvider *provider = data;
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
}
static void static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider) apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{ {
gtk_style_context_add_provider_for_display (gdk_display_get_default (), provider, G_MAXUINT); GtkWidget *child;
g_object_set_data_full (G_OBJECT (widget), "provider", provider, clear_provider);
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
} }
static GtkWidget * static GtkWidget *
@@ -102,7 +99,6 @@ do_css_shadows (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "Shadows"); gtk_window_set_title (GTK_WINDOW (window), "Shadows");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget)); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300); gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
gtk_widget_add_css_class (window, "demo");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL); paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
@@ -144,7 +140,7 @@ do_css_shadows (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window)); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -5,13 +5,12 @@
*/ */
/* This CSS resets all properties to their defaults values /* This CSS resets all properties to their defaults values
* and overrides all user settings and the theme in use * and overrides all user settings and the theme in use */
*/
@import url("resource://css_shadows/reset.css"); @import url("resource://css_shadows/reset.css");
@import url("resource://css_shadows/cssview.css"); @import url("resource://css_shadows/cssview.css");
/* Get a nice background for the window */ /* Get a nice background for the window */
window.demo.background { .background {
background-color: #4870bc; background-color: #4870bc;
background-image: linear-gradient(to left, transparent, rgba(255,255,255,.07) 50%, transparent 50%), background-image: linear-gradient(to left, transparent, rgba(255,255,255,.07) 50%, transparent 50%),
linear-gradient(to left, transparent, rgba(255,255,255,.13) 50%, transparent 50%), linear-gradient(to left, transparent, rgba(255,255,255,.13) 50%, transparent 50%),
@@ -20,7 +19,7 @@ window.demo.background {
background-size: 29px, 59px, 73px, 109px; background-size: 29px, 59px, 73px, 109px;
} }
window.demo button { button {
color: black; color: black;
padding: 10px; padding: 10px;
border-radius: 5px; border-radius: 5px;
@@ -28,15 +27,18 @@ window.demo button {
border: 1px transparent solid; border: 1px transparent solid;
} }
window.demo button:hover { button:hover {
text-shadow: 3px 3px 5px alpha(black, 0.75); text-shadow: 3px 3px 5px alpha(black, 0.75);
-gtk-icon-shadow: 3px 3px 5px alpha(black, 0.75); -gtk-icon-shadow: 3px 3px 5px alpha(black, 0.75);
box-shadow: 3px 3px 5px alpha(black, 0.5) inset; box-shadow: 3px 3px 5px alpha(black, 0.5) inset;
border: solid 1px alpha(black, 0.75); border: solid 1px alpha(black, 0.75);
} }
window.demo button:active { button:active {
padding: 11px 9px 9px 11px; padding: 11px 9px 9px 11px;
text-shadow: 1px 1px 2.5px alpha(black, 0.6); text-shadow: 1px 1px 2.5px alpha(black, 0.6);
-gtk-icon-shadow: 1px 1px 2.5px alpha(black, 0.6); -gtk-icon-shadow: 1px 1px 2.5px alpha(black, 0.6);
} }

View File

@@ -1,21 +1,21 @@
/* Make the text editor has a nice style */ /* Make the text editor has a nice style */
window.demo .view { .view {
color: #2e3436; color: #2e3436;
font-family: Monospace; font-family: Monospace;
background-color: alpha(white, 0.30); background-color: alpha(white, 0.30);
} }
window.demo .view:selected { .view:selected {
color: white; color: white;
background-color: #4a90d9; background-color: #4a90d9;
} }
window.demo scrollbar trough, scrollbar trough,
.scrollbars-junction { .scrollbars-junction {
background-color: alpha(white, 0.80); background-color: alpha(white, 0.80);
} }
window.demo scrollbar slider { scrollbar slider {
border-width: 3px; border-width: 3px;
border-style: solid; border-style: solid;
border-radius: 10px; border-radius: 10px;
@@ -24,11 +24,11 @@ window.demo scrollbar slider {
background-color: #999; background-color: #999;
} }
window.demo scrollbar slider:hover { scrollbar slider:hover {
background-color: #555; background-color: #555;
} }
window.demo paned separator { paned separator {
background-color: alpha(white, 0.80); background-color: alpha(white, 0.80);
background-image: linear-gradient(transparent, transparent 1px, #999 1px, #999 4px, transparent 4px); background-image: linear-gradient(transparent, transparent 1px, #999 1px, #999 4px, transparent 4px);
background-size: 40px auto; background-size: 40px auto;
@@ -36,6 +36,6 @@ window.demo paned separator {
background-position: center; background-position: center;
} }
window.demo paned separator:hover { paned separator:hover {
background-image: linear-gradient(transparent, transparent 1px, #555 1px, #555 4px, transparent 4px); background-image: linear-gradient(transparent, transparent 1px, #555 1px, #555 4px, transparent 4px);
} }

View File

@@ -15,73 +15,28 @@ on_destroy (gpointer data)
window = NULL; window = NULL;
} }
static GdkTexture *
cursor_callback (GdkCursor *cursor,
int cursor_size,
double scale,
int *width,
int *height,
int *hotspot_x,
int *hotspot_y,
gpointer data)
{
GdkPixbuf *pixbuf;
GdkTexture *texture;
GError *error = NULL;
int scaled_size;
scaled_size = ceil (cursor_size * scale);
pixbuf = gdk_pixbuf_new_from_resource_at_scale ("/cursors/images/gtk-logo.svg",
scaled_size, scaled_size,
TRUE,
&error);
if (!pixbuf)
{
g_print ("%s\n", error->message);
g_error_free (error);
return NULL;
}
texture = gdk_texture_new_for_pixbuf (pixbuf);
g_object_unref (pixbuf);
*width = cursor_size;
*height = cursor_size;
*hotspot_x = 18 * cursor_size / 32.0;
*hotspot_y = 2 * cursor_size / 32.0;
return texture;
}
GtkWidget * GtkWidget *
do_cursors (GtkWidget *do_widget) do_cursors (GtkWidget *do_widget)
{ {
if (!window) if (!window)
{ {
GtkBuilder *builder; GtkBuilder *builder;
GtkWidget *logo_callback;
GdkCursor *cursor;
builder = gtk_builder_new_from_resource ("/cursors/cursors.ui"); builder = gtk_builder_new_from_resource ("/cursors/cursors.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_display (GTK_WINDOW (window), gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget)); gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy", g_signal_connect (window, "destroy",
G_CALLBACK (on_destroy), NULL); G_CALLBACK (on_destroy), NULL);
logo_callback = GTK_WIDGET (gtk_builder_get_object (builder, "logo_callback"));
cursor = gdk_cursor_new_from_callback (cursor_callback, NULL, NULL, NULL);
gtk_widget_set_cursor (logo_callback, cursor);
g_object_unref (cursor);
g_object_unref (builder); g_object_unref (builder);
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); {
gtk_window_destroy (GTK_WINDOW (window));
}
return window; return window;
} }

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -15,7 +15,6 @@
<file>demo.ui</file> <file>demo.ui</file>
</gresource> </gresource>
<gresource prefix="/clipboard"> <gresource prefix="/clipboard">
<file>clipboard.ui</file>
<file>demoimage.c</file> <file>demoimage.c</file>
<file>demoimage.h</file> <file>demoimage.h</file>
</gresource> </gresource>
@@ -24,6 +23,7 @@
</gresource> </gresource>
<gresource prefix="/css_accordion"> <gresource prefix="/css_accordion">
<file>css_accordion.css</file> <file>css_accordion.css</file>
<file>reset.css</file>
</gresource> </gresource>
<gresource prefix="/css_basics"> <gresource prefix="/css_basics">
<file>css_basics.css</file> <file>css_basics.css</file>
@@ -43,7 +43,7 @@
<file>cssview.css</file> <file>cssview.css</file>
<file>reset.css</file> <file>reset.css</file>
</gresource> </gresource>
<gresource prefix="/listview_selections"> <gresource prefix="/dropdown">
<file>suggestionentry.h</file> <file>suggestionentry.h</file>
<file>suggestionentry.c</file> <file>suggestionentry.c</file>
<file>suggestionentry.css</file> <file>suggestionentry.css</file>
@@ -116,7 +116,6 @@
<file>w_resize_cursor.png</file> <file>w_resize_cursor.png</file>
<file>zoom_in_cursor.png</file> <file>zoom_in_cursor.png</file>
<file>zoom_out_cursor.png</file> <file>zoom_out_cursor.png</file>
<file>gtk-logo.svg</file>
</gresource> </gresource>
<gresource prefix="/dnd"> <gresource prefix="/dnd">
<file>dnd.css</file> <file>dnd.css</file>
@@ -128,10 +127,6 @@
<file>fishbowl.ui</file> <file>fishbowl.ui</file>
<file>gtkfishbowl.c</file> <file>gtkfishbowl.c</file>
<file>gtkfishbowl.h</file> <file>gtkfishbowl.h</file>
<file>tiger.node</file>
</gresource>
<gresource prefix="/frames">
<file>frames.ui</file>
</gresource> </gresource>
<gresource prefix="/gears"> <gresource prefix="/gears">
<file>gtkgears.c</file> <file>gtkgears.c</file>
@@ -197,9 +192,6 @@
<gresource prefix="/listview_settings"> <gresource prefix="/listview_settings">
<file>listview_settings.ui</file> <file>listview_settings.ui</file>
</gresource> </gresource>
<gresource prefix="/listview_settings2">
<file>listview_settings2.ui</file>
</gresource>
<gresource prefix="/listview_ucd_data/"> <gresource prefix="/listview_ucd_data/">
<file>ucdnames.data</file> <file>ucdnames.data</file>
</gresource> </gresource>
@@ -220,12 +212,6 @@
<file>demo3widget.h</file> <file>demo3widget.h</file>
<file>demo3widget.ui</file> <file>demo3widget.ui</file>
</gresource> </gresource>
<gresource prefix="/mask">
<file>demo4widget.c</file>
<file>demo4widget.h</file>
<file>hsla.h</file>
<file>hsla.c</file>
</gresource>
<gresource prefix="/paintable_svg"> <gresource prefix="/paintable_svg">
<file>svgpaintable.h</file> <file>svgpaintable.h</file>
<file>svgpaintable.c</file> <file>svgpaintable.c</file>
@@ -279,6 +265,7 @@
<file>cursors.c</file> <file>cursors.c</file>
<file>dialog.c</file> <file>dialog.c</file>
<file>drawingarea.c</file> <file>drawingarea.c</file>
<file>dropdown.c</file>
<file>dnd.c</file> <file>dnd.c</file>
<file>editable_cells.c</file> <file>editable_cells.c</file>
<file>entry_completion.c</file> <file>entry_completion.c</file>
@@ -289,7 +276,6 @@
<file>fishbowl.c</file> <file>fishbowl.c</file>
<file>fixed.c</file> <file>fixed.c</file>
<file>flowbox.c</file> <file>flowbox.c</file>
<file>frames.c</file>
<file>font_features.c</file> <file>font_features.c</file>
<file>fontplane.c</file> <file>fontplane.c</file>
<file>fontrendering.c</file> <file>fontrendering.c</file>
@@ -302,7 +288,6 @@
<file>iconscroll.c</file> <file>iconscroll.c</file>
<file>iconview.c</file> <file>iconview.c</file>
<file>iconview_edit.c</file> <file>iconview_edit.c</file>
<file>image_scaling.c</file>
<file>images.c</file> <file>images.c</file>
<file>infobar.c</file> <file>infobar.c</file>
<file>layoutmanager.c</file> <file>layoutmanager.c</file>
@@ -315,16 +300,14 @@
<file>listview_clocks.c</file> <file>listview_clocks.c</file>
<file>listview_filebrowser.c</file> <file>listview_filebrowser.c</file>
<file>listview_minesweeper.c</file> <file>listview_minesweeper.c</file>
<file>listview_selections.c</file>
<file>listview_settings.c</file> <file>listview_settings.c</file>
<file>listview_settings2.c</file>
<file>listview_ucd.c</file> <file>listview_ucd.c</file>
<file>listview_weather.c</file> <file>listview_weather.c</file>
<file>listview_words.c</file> <file>listview_words.c</file>
<file>list_store.c</file> <file>list_store.c</file>
<file>main.c</file> <file>main.c</file>
<file>markup.c</file> <file>markup.c</file>
<file>mask.c</file> <file>menu.c</file>
<file>overlay.c</file> <file>overlay.c</file>
<file>overlay_decorative.c</file> <file>overlay_decorative.c</file>
<file>paint.c</file> <file>paint.c</file>
@@ -334,19 +317,15 @@
<file>paintable_emblem.c</file> <file>paintable_emblem.c</file>
<file>paintable_mediastream.c</file> <file>paintable_mediastream.c</file>
<file>paintable_svg.c</file> <file>paintable_svg.c</file>
<file>paintable_symbolic.c</file>
<file>panes.c</file> <file>panes.c</file>
<file>password_entry.c</file> <file>password_entry.c</file>
<file>path_fill.c</file> <file>path_fill.c</file>
<file>path_maze.c</file> <file>path_maze.c</file>
<file>path_spinner.c</file>
<file>path_walk.c</file>
<file>path_text.c</file> <file>path_text.c</file>
<file>peg_solitaire.c</file> <file>peg_solitaire.c</file>
<file>pickers.c</file> <file>pickers.c</file>
<file>printing.c</file> <file>printing.c</file>
<file>revealer.c</file> <file>revealer.c</file>
<file>read_more.c</file>
<file>rotated_text.c</file> <file>rotated_text.c</file>
<file>scale.c</file> <file>scale.c</file>
<file>search_entry.c</file> <file>search_entry.c</file>
@@ -393,7 +372,7 @@
<file>glarea-gles.vs.glsl</file> <file>glarea-gles.vs.glsl</file>
</gresource> </gresource>
<gresource prefix="/font_features"> <gresource prefix="/font_features">
<file>font_features.ui</file> <file>font-features.ui</file>
<file>fontplane.c</file> <file>fontplane.c</file>
</gresource> </gresource>
<gresource prefix="/spinbutton"> <gresource prefix="/spinbutton">
@@ -427,10 +406,6 @@
<gresource prefix="/fontrendering"> <gresource prefix="/fontrendering">
<file>fontrendering.ui</file> <file>fontrendering.ui</file>
</gresource> </gresource>
<gresource prefix="/path_walk">
<file>path_walk.ui</file>
<file compressed="true">path_world.txt</file>
</gresource>
<gresource prefix="/path_text"> <gresource prefix="/path_text">
<file>path_text.ui</file> <file>path_text.ui</file>
</gresource> </gresource>
@@ -452,8 +427,6 @@
<file>icons/16x16/emotes/face-laugh-symbolic.symbolic.png</file> <file>icons/16x16/emotes/face-laugh-symbolic.symbolic.png</file>
<file>icons/16x16/status/battery-caution-charging-symbolic.symbolic.png</file> <file>icons/16x16/status/battery-caution-charging-symbolic.symbolic.png</file>
<file>icons/16x16/categories/applications-other.png</file> <file>icons/16x16/categories/applications-other.png</file>
<file>icons/48x48/status/starred.png</file>
<file alias="icons/scalable/apps/org.gtk.Demo4.svg">data/scalable/apps/org.gtk.Demo4.svg</file>
</gresource> </gresource>
<gresource prefix="/org/gtk/Demo4/gtk"> <gresource prefix="/org/gtk/Demo4/gtk">
<file preprocess="xml-stripblanks">help-overlay.ui</file> <file preprocess="xml-stripblanks">help-overlay.ui</file>

View File

@@ -208,13 +208,7 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkLabel" id="statusbar1"> <object class="GtkStatusbar" id="statusbar1"/>
<property name="xalign">0</property>
<property name="margin-start">2</property>
<property name="margin-end">2</property>
<property name="margin-top">2</property>
<property name="margin-bottom">2</property>
</object>
</child> </child>
</object> </object>
</child> </child>

View File

@@ -3,20 +3,16 @@
enum enum
{ {
PROP_TEXTURE = 1, PROP_PAINTABLE = 1,
PROP_FILTER, PROP_SCALE
PROP_SCALE,
PROP_ANGLE,
}; };
struct _Demo3Widget struct _Demo3Widget
{ {
GtkWidget parent_instance; GtkWidget parent_instance;
GdkTexture *texture; GdkPaintable *paintable;
float scale; float scale;
float angle;
GskScalingFilter filter;
GtkWidget *menu; GtkWidget *menu;
}; };
@@ -28,88 +24,10 @@ struct _Demo3WidgetClass
G_DEFINE_TYPE (Demo3Widget, demo3_widget, GTK_TYPE_WIDGET) G_DEFINE_TYPE (Demo3Widget, demo3_widget, GTK_TYPE_WIDGET)
static gboolean
query_tooltip (GtkWidget *widget,
int x,
int y,
gboolean keyboard_mode,
GtkTooltip *tooltip,
gpointer data)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
GtkWidget *grid;
GtkWidget *label;
char *s, *s2;
const char *filter[] = { "Linear", "Nearest", "Trilinear" };
int precision, l;
grid = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
label = gtk_label_new ("Texture");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
s = g_strdup_printf ("%d\342\200\206\303\227\342\200\206%d",
gdk_texture_get_width (self->texture),
gdk_texture_get_height (self->texture));
label = gtk_label_new (s);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
label = gtk_label_new ("Rotation");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
s = g_strdup_printf ("%.1f", self->angle);
if (g_str_has_suffix (s, ".0"))
s[strlen (s) - 2] = '\0';
s2 = g_strconcat (s, "\302\260", NULL);
label = gtk_label_new (s2);
g_free (s2);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1);
label = gtk_label_new ("Scale");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
precision = 1;
s = NULL;
do {
g_free (s);
s = g_strdup_printf ("%.*f", precision, self->scale);
l = strlen (s) - 1;
while (s[l] == '0')
l--;
if (s[l] == '.')
s[l] = '\0';
precision++;
} while (strcmp (s, "0") == 0);
label = gtk_label_new (s);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 2, 1, 1);
label = gtk_label_new ("Filter");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
label = gtk_label_new (filter[self->filter]);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1);
gtk_tooltip_set_custom (tooltip, grid);
return TRUE;
}
static void static void
demo3_widget_init (Demo3Widget *self) demo3_widget_init (Demo3Widget *self)
{ {
self->scale = 1.f; self->scale = 1.f;
self->angle = 0.f;
self->filter = GSK_SCALING_FILTER_LINEAR;
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
} }
@@ -118,9 +36,8 @@ demo3_widget_dispose (GObject *object)
{ {
Demo3Widget *self = DEMO3_WIDGET (object); Demo3Widget *self = DEMO3_WIDGET (object);
g_clear_object (&self->texture); g_clear_object (&self->paintable);
g_clear_pointer (&self->menu, gtk_widget_unparent);
gtk_widget_dispose_template (GTK_WIDGET (self), DEMO3_TYPE_WIDGET);
G_OBJECT_CLASS (demo3_widget_parent_class)->dispose (object); G_OBJECT_CLASS (demo3_widget_parent_class)->dispose (object);
} }
@@ -131,35 +48,21 @@ demo3_widget_snapshot (GtkWidget *widget,
{ {
Demo3Widget *self = DEMO3_WIDGET (widget); Demo3Widget *self = DEMO3_WIDGET (widget);
int x, y, width, height; int x, y, width, height;
double w, h, w2, h2; double w, h;
width = gtk_widget_get_width (widget); width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget); height = gtk_widget_get_height (widget);
w2 = w = self->scale * gdk_texture_get_width (self->texture); w = self->scale * gdk_paintable_get_intrinsic_width (self->paintable);
h2 = h = self->scale * gdk_texture_get_height (self->texture); h = self->scale * gdk_paintable_get_intrinsic_height (self->paintable);
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) || x = MAX (0, (width - ceil (w)) / 2);
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON)) y = MAX (0, (height - ceil (h)) / 2);
{
double s = w2;
w2 = h2;
h2 = s;
}
x = (width - ceil (w2)) / 2;
y = (height - ceil (h2)) / 2;
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height)); gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_save (snapshot); gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y)); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (w2 / 2, h2 / 2)); gdk_paintable_snapshot (self->paintable, snapshot, w, h);
gtk_snapshot_rotate (snapshot, self->angle);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- w / 2, - h / 2));
gtk_snapshot_append_scaled_texture (snapshot,
self->texture,
self->filter,
&GRAPHENE_RECT_INIT (0, 0, w, h));
gtk_snapshot_restore (snapshot); gtk_snapshot_restore (snapshot);
gtk_snapshot_pop (snapshot); gtk_snapshot_pop (snapshot);
} }
@@ -174,26 +77,14 @@ demo3_widget_measure (GtkWidget *widget,
int *natural_baseline) int *natural_baseline)
{ {
Demo3Widget *self = DEMO3_WIDGET (widget); Demo3Widget *self = DEMO3_WIDGET (widget);
int width, height;
int size; int size;
width = gdk_texture_get_width (self->texture);
height = gdk_texture_get_height (self->texture);
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
{
int s = width;
width = height;
height = s;
}
if (orientation == GTK_ORIENTATION_HORIZONTAL) if (orientation == GTK_ORIENTATION_HORIZONTAL)
size = width; size = gdk_paintable_get_intrinsic_width (self->paintable);
else else
size = height; size = gdk_paintable_get_intrinsic_height (self->paintable);
*minimum = *natural = (int) ceil (self->scale * size); *minimum = *natural = self->scale * size;
} }
static void static void
@@ -211,8 +102,6 @@ demo3_widget_size_allocate (GtkWidget *widget,
gtk_popover_present (GTK_POPOVER (self->menu)); gtk_popover_present (GTK_POPOVER (self->menu));
} }
static void update_actions (Demo3Widget *self);
static void static void
demo3_widget_set_property (GObject *object, demo3_widget_set_property (GObject *object,
guint prop_id, guint prop_id,
@@ -223,32 +112,14 @@ demo3_widget_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_TEXTURE: case PROP_PAINTABLE:
g_clear_object (&self->texture); g_clear_object (&self->paintable);
self->texture = g_value_dup_object (value); self->paintable = g_value_dup_object (value);
self->scale = 1.f;
self->angle = 0.f;
self->filter = GSK_SCALING_FILTER_LINEAR;
update_actions (self);
gtk_widget_queue_resize (GTK_WIDGET (object)); gtk_widget_queue_resize (GTK_WIDGET (object));
g_object_notify (object, "scale");
g_object_notify (object, "angle");
g_object_notify (object, "filter");
break; break;
case PROP_SCALE: case PROP_SCALE:
self->scale = g_value_get_float (value); self->scale = g_value_get_float (value);
update_actions (self);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
case PROP_ANGLE:
self->angle = fmodf (g_value_get_float (value), 360.f);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
case PROP_FILTER:
self->filter = g_value_get_enum (value);
gtk_widget_queue_resize (GTK_WIDGET (object)); gtk_widget_queue_resize (GTK_WIDGET (object));
break; break;
@@ -268,22 +139,14 @@ demo3_widget_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_TEXTURE: case PROP_PAINTABLE:
g_value_set_object (value, self->texture); g_value_set_object (value, self->paintable);
break; break;
case PROP_SCALE: case PROP_SCALE:
g_value_set_float (value, self->scale); g_value_set_float (value, self->scale);
break; break;
case PROP_ANGLE:
g_value_set_float (value, self->angle);
break;
case PROP_FILTER:
g_value_set_enum (value, self->filter);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -305,14 +168,6 @@ pressed_cb (GtkGestureClick *gesture,
gtk_popover_popup (GTK_POPOVER (self->menu)); gtk_popover_popup (GTK_POPOVER (self->menu));
} }
static void
update_actions (Demo3Widget *self)
{
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.in", self->scale < 1024.);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.out", self->scale > 1./1024.);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.reset", self->scale != 1.);
}
static void static void
zoom_cb (GtkWidget *widget, zoom_cb (GtkWidget *widget,
const char *action_name, const char *action_name,
@@ -322,30 +177,19 @@ zoom_cb (GtkWidget *widget,
float scale; float scale;
if (g_str_equal (action_name, "zoom.in")) if (g_str_equal (action_name, "zoom.in"))
scale = MIN (1024., self->scale * M_SQRT2); scale = MIN (10, self->scale * M_SQRT2);
else if (g_str_equal (action_name, "zoom.out")) else if (g_str_equal (action_name, "zoom.out"))
scale = MAX (1./1024., self->scale / M_SQRT2); scale = MAX (0.01, self->scale / M_SQRT2);
else if (g_str_equal (action_name, "zoom.reset"))
scale = 1.0;
else else
g_assert_not_reached (); scale = 1.0;
gtk_widget_action_set_enabled (widget, "zoom.in", scale < 10);
gtk_widget_action_set_enabled (widget, "zoom.out", scale > 0.01);
gtk_widget_action_set_enabled (widget, "zoom.reset", scale != 1);
g_object_set (widget, "scale", scale, NULL); g_object_set (widget, "scale", scale, NULL);
} }
static void
rotate_cb (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int angle;
g_variant_get (parameter, "i", &angle);
g_object_set (widget, "angle", fmodf (self->angle + angle, 360.f), NULL);
}
static void static void
demo3_widget_class_init (Demo3WidgetClass *class) demo3_widget_class_init (Demo3WidgetClass *class)
{ {
@@ -360,55 +204,40 @@ demo3_widget_class_init (Demo3WidgetClass *class)
widget_class->measure = demo3_widget_measure; widget_class->measure = demo3_widget_measure;
widget_class->size_allocate = demo3_widget_size_allocate; widget_class->size_allocate = demo3_widget_size_allocate;
g_object_class_install_property (object_class, PROP_TEXTURE, g_object_class_install_property (object_class, PROP_PAINTABLE,
g_param_spec_object ("texture", NULL, NULL, g_param_spec_object ("paintable", "Paintable", "Paintable",
GDK_TYPE_TEXTURE, GDK_TYPE_PAINTABLE,
G_PARAM_READWRITE)); G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_SCALE, g_object_class_install_property (object_class, PROP_SCALE,
g_param_spec_float ("scale", NULL, NULL, g_param_spec_float ("scale", "Scale", "Scale",
1./1024., 1024., 1.0, 0.0, 10.0, 1.0,
G_PARAM_READWRITE)); G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_ANGLE,
g_param_spec_float ("angle", NULL, NULL,
0.0, 360.0, 0.0,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_FILTER,
g_param_spec_enum ("filter", NULL, NULL,
GSK_TYPE_SCALING_FILTER, GSK_SCALING_FILTER_LINEAR,
G_PARAM_READWRITE));
/* These are the actions that we are using in the menu */ /* These are the actions that we are using in the menu */
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb); gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb); gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb); gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "rotate", "i", rotate_cb);
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu); gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);
gtk_widget_class_bind_template_callback (widget_class, pressed_cb); gtk_widget_class_bind_template_callback (widget_class, pressed_cb);
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_IMG);
} }
GtkWidget * GtkWidget *
demo3_widget_new (const char *resource) demo3_widget_new (const char *resource)
{ {
Demo3Widget *self; Demo3Widget *self;
GdkTexture *texture; GdkPixbuf *pixbuf;
GdkPaintable *paintable;
texture = gdk_texture_new_from_resource (resource); pixbuf = gdk_pixbuf_new_from_resource (resource, NULL);
paintable = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
self = g_object_new (DEMO3_TYPE_WIDGET, self = g_object_new (DEMO3_TYPE_WIDGET, "paintable", paintable, NULL);
"texture", texture,
"has-tooltip", TRUE,
NULL);
g_signal_connect (self, "query-tooltip", G_CALLBACK (query_tooltip), NULL); g_object_unref (pixbuf);
g_object_unref (paintable);
g_object_unref (texture);
return GTK_WIDGET (self); return GTK_WIDGET (self);
} }

View File

@@ -12,21 +12,10 @@
<attribute name="label">11</attribute> <attribute name="label">11</attribute>
<attribute name="action">zoom.reset</attribute> <attribute name="action">zoom.reset</attribute>
</item> </item>
<item>
<attribute name="label">Rotate</attribute>
<attribute name="action">rotate</attribute>
<attribute name="target" type="i">90</attribute>
</item>
</menu> </menu>
<template class="Demo3Widget"> <template class="Demo3Widget">
<accessibility>
<property name="label">Demo image</property>
</accessibility>
<child> <child>
<object class="GtkPopoverMenu" id="menu"> <object class="GtkPopoverMenu" id="menu">
<accessibility>
<property name="label">Context menu</property>
</accessibility>
<property name="has-arrow">0</property> <property name="has-arrow">0</property>
<property name="menu-model">model</property> <property name="menu-model">model</property>
</object> </object>

View File

@@ -1,226 +0,0 @@
#include <math.h>
#include "demo4widget.h"
#include "hsla.h"
enum
{
PROP_0,
PROP_PROGRESS,
};
struct _Demo4Widget
{
GtkWidget parent_instance;
PangoLayout *layout;
GskColorStop stops[8];
gsize n_stops;
double progress;
guint tick;
};
struct _Demo4WidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (Demo4Widget, demo4_widget, GTK_TYPE_WIDGET)
static void
rotate_color (GdkRGBA *rgba)
{
GdkHSLA hsla;
_gdk_hsla_init_from_rgba (&hsla, rgba);
hsla.hue -= 1;
_gdk_rgba_init_from_hsla (rgba, &hsla);
}
static gboolean
rotate_colors (GtkWidget *widget,
GdkFrameClock *clock,
gpointer user_data)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
for (unsigned int i = 0; i < self->n_stops; i++)
rotate_color (&self->stops[i].color);
gtk_widget_queue_draw (widget);
return G_SOURCE_CONTINUE;
}
static void
demo4_widget_init (Demo4Widget *self)
{
PangoFontDescription *desc;
self->progress = 0.5;
self->n_stops = 8;
self->stops[0].offset = 0;
self->stops[0].color = (GdkRGBA) { 1, 0, 0, 1 };
for (unsigned int i = 1; i < self->n_stops; i++)
{
GdkHSLA hsla;
self->stops[i].offset = i / (double)(self->n_stops - 1);
_gdk_hsla_init_from_rgba (&hsla, &self->stops[i - 1].color);
hsla.hue += 360.0 / (double)(self->n_stops - 1);
_gdk_rgba_init_from_hsla (&self->stops[i].color, &hsla);
}
self->layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "123");
desc = pango_font_description_from_string ("Cantarell Bold 210");
pango_layout_set_font_description (self->layout, desc);
pango_font_description_free (desc);
self->tick = gtk_widget_add_tick_callback (GTK_WIDGET (self), rotate_colors, NULL, NULL);
}
static void
demo4_widget_dispose (GObject *object)
{
Demo4Widget *self = DEMO4_WIDGET (object);
g_clear_object (&self->layout);
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick);
G_OBJECT_CLASS (demo4_widget_parent_class)->dispose (object);
}
static void
demo4_widget_snapshot_content (GtkWidget *widget,
GtkSnapshot *snapshot,
GskMaskMode mode)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
int width, height, layout_width, layout_height;
double scale;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_push_mask (snapshot, mode);
pango_layout_get_pixel_size (self->layout, &layout_width, &layout_height);
scale = MIN ((double) width / layout_width, (double) height / layout_height);
gtk_snapshot_translate (snapshot,
&GRAPHENE_POINT_INIT ((width - scale * layout_width) / 2,
(height - scale * layout_height) / 2));
gtk_snapshot_scale (snapshot, scale, scale);
gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
gtk_snapshot_pop (snapshot);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, height),
self->stops,
self->n_stops);
gtk_snapshot_pop (snapshot);
}
static void
demo4_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
int width, height;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_INVERTED_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, 0),
(GskColorStop[2]) {
{ MAX (0.0, self->progress - 5.0 / width), { 1, 1, 1, 1 } },
{ MIN (1.0, self->progress + 5.0 / width), { 0, 0, 0, 1 } }
}, 2);
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_INVERTED_ALPHA);
gtk_snapshot_pop (snapshot);
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, 0),
(GskColorStop[2]) {
{ MAX (0.0, self->progress - 5.0 / width), { 1, 1, 1, 1 } },
{ MIN (1.0, self->progress + 5.0 / width), { 0, 0, 0, 1 } }
}, 2);
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_ALPHA);
gtk_snapshot_pop (snapshot);
}
static void
demo4_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
self->progress = g_value_get_double (value);
gtk_widget_queue_draw (GTK_WIDGET (object));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo4_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
g_value_set_double (value, self->progress);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo4_widget_class_init (Demo4WidgetClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo4_widget_dispose;
object_class->get_property = demo4_widget_get_property;
object_class->set_property = demo4_widget_set_property;
widget_class->snapshot = demo4_widget_snapshot;
g_object_class_install_property (object_class, PROP_PROGRESS,
g_param_spec_double ("progress", NULL, NULL,
0.0, 1.0, 0.5,
G_PARAM_READWRITE));
}
GtkWidget *
demo4_widget_new (void)
{
return g_object_new (DEMO4_TYPE_WIDGET, NULL);
}

View File

@@ -1,8 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO4_TYPE_WIDGET (demo4_widget_get_type ())
G_DECLARE_FINAL_TYPE (Demo4Widget, demo4_widget, DEMO4, WIDGET, GtkWidget)
GtkWidget * demo4_widget_new (void);

View File

@@ -100,11 +100,7 @@ prepare_drag (GtkDragSource *source,
DemoImage *demo = DEMO_IMAGE (widget); DemoImage *demo = DEMO_IMAGE (widget);
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image)); GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
/* Textures can be serialized, paintables can't, so special case the textures */ return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
if (GDK_IS_TEXTURE (paintable))
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
else
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
} }
static gboolean static gboolean
@@ -133,11 +129,7 @@ copy_image (GtkWidget *widget,
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image)); GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
GValue value = G_VALUE_INIT; GValue value = G_VALUE_INIT;
/* Textures can be serialized, paintables can't, so special case the textures */ g_value_init (&value, GDK_TYPE_PAINTABLE);
if (GDK_IS_TEXTURE (paintable))
g_value_init (&value, GDK_TYPE_TEXTURE);
else
g_value_init (&value, GDK_TYPE_PAINTABLE);
g_value_set_object (&value, paintable); g_value_set_object (&value, paintable);
gdk_clipboard_set_value (clipboard, &value); gdk_clipboard_set_value (clipboard, &value);
g_value_unset (&value); g_value_unset (&value);
@@ -146,46 +138,24 @@ copy_image (GtkWidget *widget,
g_object_unref (paintable); g_object_unref (paintable);
} }
static void
paste_image_cb (GObject *source,
GAsyncResult *result,
gpointer data)
{
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
DemoImage *demo = DEMO_IMAGE (data);
const GValue *value;
value = gdk_clipboard_read_value_finish (clipboard, result, NULL);
if (value == NULL)
{
gtk_widget_error_bell (GTK_WIDGET (demo));
g_object_unref (demo);
return;
}
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), g_value_get_object (value));
g_object_unref (demo);
}
static void static void
paste_image (GtkWidget *widget, paste_image (GtkWidget *widget,
const char *action_name, const char *action_name,
GVariant *parameter) GVariant *parameter)
{ {
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget); GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
GType type; DemoImage *demo = DEMO_IMAGE (widget);
GdkContentProvider *content = gdk_clipboard_get_content (clipboard);
GValue value = G_VALUE_INIT;
GdkPaintable *paintable;
if (gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GDK_TYPE_TEXTURE)) g_value_init (&value, GDK_TYPE_PAINTABLE);
type = GDK_TYPE_TEXTURE; if (!gdk_content_provider_get_value (content, &value, NULL))
else return;
type = GDK_TYPE_PAINTABLE;
gdk_clipboard_read_value_async (clipboard, paintable = GDK_PAINTABLE (g_value_get_object (&value));
type, gtk_image_set_from_paintable (GTK_IMAGE (demo->image), paintable);
G_PRIORITY_DEFAULT, g_value_unset (&value);
NULL,
paste_image_cb,
g_object_ref (widget));
} }
static void static void

View File

@@ -18,7 +18,8 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #ifndef __DEMO_TAGGED_ENTRY_H__
#define __DEMO_TAGGED_ENTRY_H__
#include <gtk/gtk.h> #include <gtk/gtk.h>
@@ -56,3 +57,5 @@ void demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *
gboolean has_close_button); gboolean has_close_button);
G_END_DECLS G_END_DECLS
#endif /* __DEMO_TAGGED_ENTRY_H__ */

View File

@@ -34,7 +34,7 @@ transition (GtkWidget *widget,
{ {
DemoWidget *self = DEMO_WIDGET (widget); DemoWidget *self = DEMO_WIDGET (widget);
DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget)); DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget));
gint64 now = gdk_frame_clock_get_frame_time (frame_clock); gint64 now = g_get_monotonic_time ();
gtk_widget_queue_allocate (widget); gtk_widget_queue_allocate (widget);
@@ -66,13 +66,11 @@ clicked (GtkGestureClick *gesture,
gpointer data) gpointer data)
{ {
DemoWidget *self = data; DemoWidget *self = data;
GdkFrameClock *frame_clock;
if (self->tick_id != 0) if (self->tick_id != 0)
return; return;
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (self)); self->start_time = g_get_monotonic_time ();
self->start_time = gdk_frame_clock_get_frame_time (frame_clock);
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL); self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
} }

View File

@@ -8,8 +8,6 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static GtkWidget *window = NULL; static GtkWidget *window = NULL;
static GtkWidget *entry1 = NULL; static GtkWidget *entry1 = NULL;
static GtkWidget *entry2 = NULL; static GtkWidget *entry2 = NULL;
@@ -29,7 +27,7 @@ message_dialog_clicked (GtkButton *button,
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
ngettext ("Has been shown once", "Has been shown %d times", i), i); ngettext ("Has been shown once", "Has been shown %d times", i), i);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL); g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_window_present (GTK_WINDOW (dialog)); gtk_widget_show (dialog);
i++; i++;
} }
@@ -116,7 +114,7 @@ interactive_dialog_clicked (GtkButton *button,
data, (GClosureNotify) g_free, data, (GClosureNotify) g_free,
0); 0);
gtk_window_present (GTK_WINDOW (dialog)); gtk_widget_show (dialog);
} }
GtkWidget * GtkWidget *
@@ -186,7 +184,7 @@ do_dialog (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -11,7 +11,6 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (CanvasItem, canvas_item, CANVAS, ITEM, GtkWidget) G_DECLARE_FINAL_TYPE (CanvasItem, canvas_item, CANVAS, ITEM, GtkWidget)
struct _CanvasItem { struct _CanvasItem {
@@ -25,9 +24,6 @@ struct _CanvasItem {
double delta; double delta;
GtkWidget *editor; GtkWidget *editor;
GtkStyleProvider *provider;
char *css_class;
}; };
struct _CanvasItemClass { struct _CanvasItemClass {
@@ -38,41 +34,32 @@ G_DEFINE_TYPE (CanvasItem, canvas_item, GTK_TYPE_WIDGET)
static int n_items = 0; static int n_items = 0;
static void
unstyle_item (CanvasItem *item)
{
if (item->provider)
{
gtk_style_context_remove_provider_for_display (gtk_widget_get_display (item->label), item->provider);
g_clear_object (&item->provider);
}
if (item->css_class)
{
gtk_widget_remove_css_class (item->label, item->css_class);
g_clear_pointer (&item->css_class, g_free);
}
}
static void static void
set_color (CanvasItem *item, set_color (CanvasItem *item,
GdkRGBA *color) GdkRGBA *color)
{ {
char *css; char *css;
char *str; char *str;
GtkStyleContext *context;
GtkCssProvider *provider; GtkCssProvider *provider;
const char *name; const char *old_class;
unstyle_item (item);
str = gdk_rgba_to_string (color); str = gdk_rgba_to_string (color);
name = gtk_widget_get_name (item->label); css = g_strdup_printf ("* { background: %s; }", str);
css = g_strdup_printf ("#%s { background: %s; }", name, str);
context = gtk_widget_get_style_context (item->label);
provider = g_object_get_data (G_OBJECT (context), "style-provider");
if (provider)
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
if (old_class)
gtk_widget_remove_css_class (item->label, old_class);
provider = gtk_css_provider_new (); provider = gtk_css_provider_new ();
gtk_css_provider_load_from_string (provider, css); gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider_for_display (gtk_widget_get_display (item->label), GTK_STYLE_PROVIDER (provider), 700); gtk_style_context_add_provider (gtk_widget_get_style_context (item->label), GTK_STYLE_PROVIDER (provider), 800);
item->provider = GTK_STYLE_PROVIDER (provider); g_object_set_data_full (G_OBJECT (context), "style-provider", provider, g_object_unref);
g_free (str); g_free (str);
g_free (css); g_free (css);
@@ -82,10 +69,21 @@ static void
set_css (CanvasItem *item, set_css (CanvasItem *item,
const char *class) const char *class)
{ {
unstyle_item (item); GtkStyleContext *context;
GtkCssProvider *provider;
const char *old_class;
context = gtk_widget_get_style_context (item->label);
provider = g_object_get_data (G_OBJECT (context), "style-provider");
if (provider)
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
if (old_class)
gtk_widget_remove_css_class (item->label, old_class);
g_object_set_data_full (G_OBJECT (item->label), "css-class", g_strdup (class), g_free);
gtk_widget_add_css_class (item->label, class); gtk_widget_add_css_class (item->label, class);
item->css_class = g_strdup (class);
} }
static gboolean static gboolean
@@ -109,21 +107,15 @@ static void
apply_transform (CanvasItem *item) apply_transform (CanvasItem *item)
{ {
GskTransform *transform; GskTransform *transform;
graphene_rect_t bounds;
double x, y; double x, y;
/* Add css padding and margin */ x = gtk_widget_get_allocated_width (item->label) / 2.0;
if (!gtk_widget_compute_bounds (item->label, item->label, &bounds)) y = gtk_widget_get_allocated_height (item->label) / 2.0;
return; item->r = sqrt (x*x + y*y);
x = bounds.size.width / 2.;
y = bounds.size.height / 2.;
item->r = sqrt (x * x + y * y);
transform = gsk_transform_translate (NULL, &(graphene_point_t) { item->r, item->r }); transform = gsk_transform_translate (NULL, &(graphene_point_t) { item->r, item->r });
transform = gsk_transform_rotate (transform, item->angle + item->delta); transform = gsk_transform_rotate (transform, item->angle + item->delta);
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (-x, -y)); transform = gsk_transform_translate (transform, &(graphene_point_t) { -x, -y });
gtk_fixed_set_child_transform (GTK_FIXED (item->fixed), item->label, transform); gtk_fixed_set_child_transform (GTK_FIXED (item->fixed), item->label, transform);
gsk_transform_unref (transform); gsk_transform_unref (transform);
@@ -162,39 +154,27 @@ click_done (GtkGesture *gesture)
gtk_widget_insert_after (item, canvas, last_child); gtk_widget_insert_after (item, canvas, last_child);
} }
/* GtkSettings treats `GTK_THEME=foo:dark` as theme name `foo`, variant `dark`,
* and our embedded CSS files let `foo-dark` work as an alias for `foo:dark`. */
static gboolean
has_dark_suffix (const char *theme)
{
return g_str_has_suffix (theme, ":dark") ||
g_str_has_suffix (theme, "-dark");
}
/* So we can make a good guess whether the current theme is dark by checking for
* either: it is suffixed `[:-]dark`, or Settings:…prefer-dark-theme is TRUE. */
static gboolean static gboolean
theme_is_dark (void) theme_is_dark (void)
{ {
const char *env_theme;
GtkSettings *settings; GtkSettings *settings;
char *theme; char *theme;
gboolean prefer_dark; gboolean prefer_dark;
gboolean dark; gboolean dark;
/* Like GtkSettings, 1st see if theme is overridden by environment variable */
env_theme = g_getenv ("GTK_THEME");
if (env_theme != NULL)
return has_dark_suffix (env_theme);
/* If not, test Settings:…theme-name in the same way OR :…prefer-dark-theme */
settings = gtk_settings_get_default (); settings = gtk_settings_get_default ();
g_object_get (settings, g_object_get (settings,
"gtk-theme-name", &theme, "gtk-theme-name", &theme,
"gtk-application-prefer-dark-theme", &prefer_dark, "gtk-application-prefer-dark-theme", &prefer_dark,
NULL); NULL);
dark = prefer_dark || has_dark_suffix (theme);
if ((strcmp (theme, "Adwaita") == 0 && prefer_dark) || strcmp (theme, "HighContrastInverse") == 0)
dark = TRUE;
else
dark = FALSE;
g_free (theme); g_free (theme);
return dark; return dark;
} }
@@ -342,7 +322,7 @@ canvas_item_start_editing (CanvasItem *item)
GtkWidget *canvas = gtk_widget_get_parent (GTK_WIDGET (item)); GtkWidget *canvas = gtk_widget_get_parent (GTK_WIDGET (item));
GtkWidget *entry; GtkWidget *entry;
GtkWidget *scale; GtkWidget *scale;
graphene_point_t p; double x, y;
if (item->editor) if (item->editor)
return; return;
@@ -368,17 +348,12 @@ canvas_item_start_editing (CanvasItem *item)
gtk_box_append (GTK_BOX (item->editor), scale); gtk_box_append (GTK_BOX (item->editor), scale);
if (!gtk_widget_compute_point (GTK_WIDGET (item), canvas, &GRAPHENE_POINT_INIT (0, 0), &p)) gtk_widget_translate_coordinates (GTK_WIDGET (item), canvas, 0, 0, &x, &y);
graphene_point_init (&p, 0, 0); gtk_fixed_put (GTK_FIXED (canvas), item->editor, x, y + 2 * item->r);
gtk_fixed_put (GTK_FIXED (canvas), item->editor, p.x, p.y + 2 * item->r);
gtk_widget_grab_focus (entry); gtk_widget_grab_focus (entry);
} }
typedef struct {
double x, y;
} Hotspot;
static GdkContentProvider * static GdkContentProvider *
prepare (GtkDragSource *source, prepare (GtkDragSource *source,
double x, double x,
@@ -386,8 +361,6 @@ prepare (GtkDragSource *source,
{ {
GtkWidget *canvas; GtkWidget *canvas;
GtkWidget *item; GtkWidget *item;
Hotspot *hotspot;
graphene_point_t p;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source)); canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = gtk_widget_pick (canvas, x, y, GTK_PICK_DEFAULT); item = gtk_widget_pick (canvas, x, y, GTK_PICK_DEFAULT);
@@ -398,13 +371,6 @@ prepare (GtkDragSource *source,
g_object_set_data (G_OBJECT (canvas), "dragged-item", item); g_object_set_data (G_OBJECT (canvas), "dragged-item", item);
hotspot = g_new (Hotspot, 1);
if (!gtk_widget_compute_point (canvas, item, &GRAPHENE_POINT_INIT (x, y), &p))
graphene_point_init (&p, x, y);
hotspot->x = p.x;
hotspot->y = p.y;
g_object_set_data_full (G_OBJECT (canvas), "hotspot", hotspot, g_free);
return gdk_content_provider_new_typed (GTK_TYPE_WIDGET, item); return gdk_content_provider_new_typed (GTK_TYPE_WIDGET, item);
} }
@@ -415,14 +381,12 @@ drag_begin (GtkDragSource *source,
GtkWidget *canvas; GtkWidget *canvas;
CanvasItem *item; CanvasItem *item;
GdkPaintable *paintable; GdkPaintable *paintable;
Hotspot *hotspot;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source)); canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = CANVAS_ITEM (g_object_get_data (G_OBJECT (canvas), "dragged-item")); item = CANVAS_ITEM (g_object_get_data (G_OBJECT (canvas), "dragged-item"));
hotspot = (Hotspot *) g_object_get_data (G_OBJECT (canvas), "hotspot");
paintable = canvas_item_get_drag_icon (item); paintable = canvas_item_get_drag_icon (item);
gtk_drag_source_set_icon (source, paintable, hotspot->x, hotspot->y); gtk_drag_source_set_icon (source, paintable, item->r, item->r);
g_object_unref (paintable); g_object_unref (paintable);
gtk_widget_set_opacity (GTK_WIDGET (item), 0.3); gtk_widget_set_opacity (GTK_WIDGET (item), 0.3);
@@ -758,9 +722,8 @@ do_dnd (GtkWidget *do_widget)
int i; int i;
int x, y; int x, y;
GtkCssProvider *provider; GtkCssProvider *provider;
GString *css;
button = gtk_color_dialog_button_new (gtk_color_dialog_new ()); button = gtk_color_button_new ();
g_object_unref (g_object_ref_sink (button)); g_object_unref (g_object_ref_sink (button));
provider = gtk_css_provider_new (); provider = gtk_css_provider_new ();
@@ -770,18 +733,6 @@ do_dnd (GtkWidget *do_widget)
800); 800);
g_object_unref (provider); g_object_unref (provider);
css = g_string_new ("");
for (i = 0; colors[i]; i++)
g_string_append_printf (css, ".canvasitem.%s { background: %s; }\n", colors[i], colors[i]);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_string (provider, css->str);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
g_string_free (css, TRUE);
window = gtk_window_new (); window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget)); gtk_widget_get_display (do_widget));
@@ -834,7 +785,7 @@ do_dnd (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -334,17 +334,11 @@ do_drawingarea (GtkWidget *do_widget)
gtk_widget_set_vexpand (frame, TRUE); gtk_widget_set_vexpand (frame, TRUE);
gtk_box_append (GTK_BOX (vbox), frame); gtk_box_append (GTK_BOX (vbox), frame);
da = g_object_new (GTK_TYPE_DRAWING_AREA, da = gtk_drawing_area_new ();
"accessible-role", GTK_ACCESSIBLE_ROLE_IMG,
NULL);
gtk_frame_set_child (GTK_FRAME (frame), da);
gtk_accessible_update_relation (GTK_ACCESSIBLE (da),
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
-1);
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100); gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100); gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), groups_draw, NULL, NULL); gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), groups_draw, NULL, NULL);
gtk_frame_set_child (GTK_FRAME (frame), da);
/* /*
* Create the scribble area * Create the scribble area
@@ -358,23 +352,17 @@ do_drawingarea (GtkWidget *do_widget)
gtk_widget_set_vexpand (frame, TRUE); gtk_widget_set_vexpand (frame, TRUE);
gtk_box_append (GTK_BOX (vbox), frame); gtk_box_append (GTK_BOX (vbox), frame);
da = g_object_new (GTK_TYPE_DRAWING_AREA, da = gtk_drawing_area_new ();
"accessible-role", GTK_ACCESSIBLE_ROLE_IMG,
NULL);
gtk_frame_set_child (GTK_FRAME (frame), da);
gtk_accessible_update_relation (GTK_ACCESSIBLE (da),
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
-1);
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100); gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100); gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), scribble_draw, NULL, NULL); gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), scribble_draw, NULL, NULL);
gtk_frame_set_child (GTK_FRAME (frame), da);
g_signal_connect (da, "resize", g_signal_connect (da, "resize",
G_CALLBACK (scribble_resize), NULL); G_CALLBACK (scribble_resize), NULL);
drag = gtk_gesture_drag_new (); drag = gtk_gesture_drag_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), 0); gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
gtk_widget_add_controller (da, GTK_EVENT_CONTROLLER (drag)); gtk_widget_add_controller (da, GTK_EVENT_CONTROLLER (drag));
g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), da); g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), da);
@@ -384,7 +372,7 @@ do_drawingarea (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window)); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

571
demos/gtk-demo/dropdown.c Normal file
View File

@@ -0,0 +1,571 @@
/* Lists/Selections
*
* The GtkDropDown widget is a modern alternative to GtkComboBox.
* It uses list models instead of tree models, and the content is
* displayed using widgets instead of cell renderers.
*
* This example also shows a custom widget that can replace
* GtkEntryCompletion or GtkComboBoxText. It is not currently
* part of GTK.
*/
#include <gtk/gtk.h>
#include "suggestionentry.h"
#define STRING_TYPE_HOLDER (string_holder_get_type ())
G_DECLARE_FINAL_TYPE (StringHolder, string_holder, STRING, HOLDER, GObject)
struct _StringHolder {
GObject parent_instance;
char *title;
char *icon;
char *description;
};
G_DEFINE_TYPE (StringHolder, string_holder, G_TYPE_OBJECT);
static void
string_holder_init (StringHolder *holder)
{
}
static void
string_holder_finalize (GObject *object)
{
StringHolder *holder = STRING_HOLDER (object);
g_free (holder->title);
g_free (holder->icon);
g_free (holder->description);
G_OBJECT_CLASS (string_holder_parent_class)->finalize (object);
}
static void
string_holder_class_init (StringHolderClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = string_holder_finalize;
}
static StringHolder *
string_holder_new (const char *title, const char *icon, const char *description)
{
StringHolder *holder = g_object_new (STRING_TYPE_HOLDER, NULL);
holder->title = g_strdup (title);
holder->icon = g_strdup (icon);
holder->description = g_strdup (description);
return holder;
}
static void
strings_setup_item_single_line (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *box, *image, *title;
GtkWidget *checkmark;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
image = gtk_image_new ();
title = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
checkmark = gtk_image_new_from_icon_name ("object-select-symbolic");
gtk_box_append (GTK_BOX (box), image);
gtk_box_append (GTK_BOX (box), title);
gtk_box_append (GTK_BOX (box), checkmark);
g_object_set_data (G_OBJECT (item), "title", title);
g_object_set_data (G_OBJECT (item), "image", image);
g_object_set_data (G_OBJECT (item), "checkmark", checkmark);
gtk_list_item_set_child (item, box);
}
static void
strings_setup_item_full (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *box, *box2, *image, *title, *description;
GtkWidget *checkmark;
image = gtk_image_new ();
title = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
description = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (description), 0.0);
gtk_widget_add_css_class (description, "dim-label");
checkmark = gtk_image_new_from_icon_name ("object-select-symbolic");
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_box_append (GTK_BOX (box), image);
gtk_box_append (GTK_BOX (box), box2);
gtk_box_append (GTK_BOX (box2), title);
gtk_box_append (GTK_BOX (box2), description);
gtk_box_append (GTK_BOX (box), checkmark);
g_object_set_data (G_OBJECT (item), "title", title);
g_object_set_data (G_OBJECT (item), "image", image);
g_object_set_data (G_OBJECT (item), "description", description);
g_object_set_data (G_OBJECT (item), "checkmark", checkmark);
gtk_list_item_set_child (item, box);
}
static void
selected_item_changed (GtkDropDown *dropdown,
GParamSpec *pspec,
GtkListItem *item)
{
GtkWidget *checkmark;
checkmark = g_object_get_data (G_OBJECT (item), "checkmark");
if (gtk_drop_down_get_selected_item (dropdown) == gtk_list_item_get_item (item))
gtk_widget_set_opacity (checkmark, 1.0);
else
gtk_widget_set_opacity (checkmark, 0.0);
}
static void
strings_bind_item (GtkSignalListItemFactory *factory,
GtkListItem *item,
gpointer data)
{
GtkDropDown *dropdown = data;
GtkWidget *image, *title, *description;
GtkWidget *checkmark;
StringHolder *holder;
GtkWidget *popup;
holder = gtk_list_item_get_item (item);
title = g_object_get_data (G_OBJECT (item), "title");
image = g_object_get_data (G_OBJECT (item), "image");
description = g_object_get_data (G_OBJECT (item), "description");
checkmark = g_object_get_data (G_OBJECT (item), "checkmark");
gtk_label_set_label (GTK_LABEL (title), holder->title);
if (image)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), holder->icon);
gtk_widget_set_visible (image, holder->icon != NULL);
}
if (description)
{
gtk_label_set_label (GTK_LABEL (description), holder->description);
gtk_widget_set_visible (description , holder->description != NULL);
}
popup = gtk_widget_get_ancestor (title, GTK_TYPE_POPOVER);
if (popup && gtk_widget_is_ancestor (popup, GTK_WIDGET (dropdown)))
{
gtk_widget_show (checkmark);
g_signal_connect (dropdown, "notify::selected-item",
G_CALLBACK (selected_item_changed), item);
selected_item_changed (dropdown, NULL, item);
}
else
{
gtk_widget_hide (checkmark);
}
}
static void
strings_unbind_item (GtkSignalListItemFactory *factory,
GtkListItem *list_item,
gpointer data)
{
GtkDropDown *dropdown = data;
g_signal_handlers_disconnect_by_func (dropdown, selected_item_changed, list_item);
}
static GtkListItemFactory *
strings_factory_new (gpointer data, gboolean full)
{
GtkListItemFactory *factory;
factory = gtk_signal_list_item_factory_new ();
if (full)
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_full), data);
else
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_single_line), data);
g_signal_connect (factory, "bind", G_CALLBACK (strings_bind_item), data);
g_signal_connect (factory, "unbind", G_CALLBACK (strings_unbind_item), data);
return factory;
}
static GListModel *
strings_model_new (const char *const *titles,
const char *const *icons,
const char *const *descriptions)
{
GListStore *store;
int i;
store = g_list_store_new (STRING_TYPE_HOLDER);
for (i = 0; titles[i]; i++)
{
StringHolder *holder = string_holder_new (titles[i],
icons ? icons[i] : NULL,
descriptions ? descriptions[i] : NULL);
g_list_store_append (store, holder);
g_object_unref (holder);
}
return G_LIST_MODEL (store);
}
static GtkWidget *
drop_down_new_from_strings (const char *const *titles,
const char *const *icons,
const char *const *descriptions)
{
GtkWidget *widget;
GListModel *model;
GtkListItemFactory *factory;
GtkListItemFactory *list_factory;
g_return_val_if_fail (titles != NULL, NULL);
g_return_val_if_fail (icons == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)titles), NULL);
g_return_val_if_fail (descriptions == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)descriptions), NULL);
model = strings_model_new (titles, icons, descriptions);
widget = g_object_new (GTK_TYPE_DROP_DOWN,
"model", model,
NULL);
g_object_unref (model);
factory = strings_factory_new (widget, FALSE);
if (icons != NULL || descriptions != NULL)
list_factory = strings_factory_new (widget, TRUE);
else
list_factory = NULL;
g_object_set (widget,
"factory", factory,
"list-factory", list_factory,
NULL);
g_object_unref (factory);
if (list_factory)
g_object_unref (list_factory);
return widget;
}
static char *
get_family_name (gpointer item)
{
return g_strdup (pango_font_family_get_name (PANGO_FONT_FAMILY (item)));
}
static char *
get_title (gpointer item)
{
return g_strdup (STRING_HOLDER (item)->title);
}
static char *
get_file_name (gpointer item)
{
return g_strdup (g_file_info_get_display_name (G_FILE_INFO (item)));
}
static void
setup_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *box;
GtkWidget *icon;
GtkWidget *label;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
icon = gtk_image_new ();
label = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_box_append (GTK_BOX (box), icon);
gtk_box_append (GTK_BOX (box), label);
gtk_list_item_set_child (item, box);
}
static void
bind_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
MatchObject *match = MATCH_OBJECT (gtk_list_item_get_item (item));
GFileInfo *info = G_FILE_INFO (match_object_get_item (match));
GtkWidget *box = gtk_list_item_get_child (item);
GtkWidget *icon = gtk_widget_get_first_child (box);
GtkWidget *label = gtk_widget_get_last_child (box);
gtk_image_set_from_gicon (GTK_IMAGE (icon), g_file_info_get_icon (info));
gtk_label_set_label (GTK_LABEL (label), g_file_info_get_display_name (info));
}
static void
setup_highlight_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *label;
label = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_list_item_set_child (item, label);
}
static void
bind_highlight_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
MatchObject *obj;
GtkWidget *label;
PangoAttrList *attrs;
PangoAttribute *attr;
const char *str;
obj = MATCH_OBJECT (gtk_list_item_get_item (item));
label = gtk_list_item_get_child (item);
str = match_object_get_string (obj);
gtk_label_set_label (GTK_LABEL (label), str);
attrs = pango_attr_list_new ();
attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
attr->start_index = match_object_get_match_start (obj);
attr->end_index = match_object_get_match_end (obj);
pango_attr_list_insert (attrs, attr);
gtk_label_set_attributes (GTK_LABEL (label), attrs);
pango_attr_list_unref (attrs);
}
static void
match_func (MatchObject *obj,
const char *search,
gpointer user_data)
{
char *tmp1, *tmp2;
char *p;
tmp1 = g_utf8_normalize (match_object_get_string (obj), -1, G_NORMALIZE_ALL);
tmp2 = g_utf8_normalize (search, -1, G_NORMALIZE_ALL);
if ((p = strstr (tmp1, tmp2)) != NULL)
match_object_set_match (obj,
p - tmp1,
(p - tmp1) + g_utf8_strlen (search, -1),
1);
else
match_object_set_match (obj, 0, 0, 0);
g_free (tmp1);
g_free (tmp2);
}
GtkWidget *
do_dropdown (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *button, *box, *spin, *check, *hbox, *label, *entry;
GListModel *model;
GtkExpression *expression;
GtkListItemFactory *factory;
const char * const times[] = { "1 minute", "2 minutes", "5 minutes", "20 minutes", NULL };
const char * const many_times[] = {
"1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
"25 minutes", "30 minutes", "35 minutes", "40 minutes", "45 minutes", "50 minutes",
"55 minutes", "1 hour", "2 hours", "3 hours", "5 hours", "6 hours", "7 hours",
"8 hours", "9 hours", "10 hours", "11 hours", "12 hours", NULL
};
const char * const device_titles[] = { "Digital Output", "Headphones", "Digital Output", "Analog Output", NULL };
const char * const device_icons[] = { "audio-card-symbolic", "audio-headphones-symbolic", "audio-card-symbolic", "audio-card-symbolic", NULL };
const char * const device_descriptions[] = {
"Built-in Audio", "Built-in audio", "Thinkpad Tunderbolt 3 Dock USB Audio", "Thinkpad Tunderbolt 3 Dock USB Audio", NULL
};
char *cwd;
GFile *file;
GListModel *dir;
GtkStringList *strings;
if (!window)
{
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Selections");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
gtk_widget_set_margin_start (hbox, 20);
gtk_widget_set_margin_end (hbox, 20);
gtk_widget_set_margin_top (hbox, 20);
gtk_widget_set_margin_bottom (hbox, 20);
gtk_window_set_child (GTK_WINDOW (window), hbox);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_box_append (GTK_BOX (hbox), box);
label = gtk_label_new ("Dropdowns");
gtk_widget_add_css_class (label, "title-4");
gtk_box_append (GTK_BOX (box), label);
/* A basic dropdown */
button = drop_down_new_from_strings (times, NULL, NULL);
gtk_box_append (GTK_BOX (box), button);
/* A dropdown using an expression to obtain strings */
button = drop_down_new_from_strings (many_times, NULL, NULL);
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_title,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
gtk_expression_unref (expression);
gtk_box_append (GTK_BOX (box), button);
button = gtk_drop_down_new (NULL, NULL);
model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
gtk_drop_down_set_selected (GTK_DROP_DOWN (button), 0);
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_family_name,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
gtk_expression_unref (expression);
gtk_box_append (GTK_BOX (box), button);
spin = gtk_spin_button_new_with_range (-1, g_list_model_get_n_items (G_LIST_MODEL (model)), 1);
gtk_widget_set_halign (spin, GTK_ALIGN_START);
gtk_widget_set_margin_start (spin, 20);
g_object_bind_property (button, "selected", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), spin);
check = gtk_check_button_new_with_label ("Enable search");
gtk_widget_set_margin_start (check, 20);
g_object_bind_property (button, "enable-search", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), check);
g_object_unref (model);
/* A dropdown with a separate list factory */
button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
gtk_box_append (GTK_BOX (box), button);
gtk_box_append (GTK_BOX (hbox), gtk_separator_new (GTK_ORIENTATION_VERTICAL));
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_box_append (GTK_BOX (hbox), box);
label = gtk_label_new ("Suggestions");
gtk_widget_add_css_class (label, "title-4");
gtk_box_append (GTK_BOX (box), label);
/* A basic suggestion entry */
entry = suggestion_entry_new ();
g_object_set (entry, "placeholder-text", "Words with T or G…", NULL);
strings = gtk_string_list_new ((const char *[]){
"GNOME",
"gnominious",
"Gnomonic projection",
"total",
"totally",
"toto",
"tottery",
"totterer",
"Totten trust",
"totipotent",
"totipotency",
"totemism",
"totem pole",
"Totara",
"totalizer",
"totalizator",
"totalitarianism",
"total parenteral nutrition",
"total hysterectomy",
"total eclipse",
"Totipresence",
"Totipalmi",
"Tomboy",
"zombie",
NULL});
suggestion_entry_set_model (SUGGESTION_ENTRY (entry), G_LIST_MODEL (strings));
g_object_unref (strings);
gtk_box_append (GTK_BOX (box), entry);
/* A suggestion entry using a custom model, and no filtering */
entry = suggestion_entry_new ();
cwd = g_get_current_dir ();
file = g_file_new_for_path (cwd);
dir = G_LIST_MODEL (gtk_directory_list_new ("standard::display-name,standard::content-type,standard::icon,standard::size", file));
suggestion_entry_set_model (SUGGESTION_ENTRY (entry), dir);
g_object_unref (dir);
g_object_unref (file);
g_free (cwd);
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_file_name,
NULL, NULL);
suggestion_entry_set_expression (SUGGESTION_ENTRY (entry), expression);
gtk_expression_unref (expression);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
suggestion_entry_set_factory (SUGGESTION_ENTRY (entry), factory);
g_object_unref (factory);
suggestion_entry_set_use_filter (SUGGESTION_ENTRY (entry), FALSE);
suggestion_entry_set_show_arrow (SUGGESTION_ENTRY (entry), TRUE);
gtk_box_append (GTK_BOX (box), entry);
/* A suggestion entry with match highlighting */
entry = suggestion_entry_new ();
g_object_set (entry, "placeholder-text", "Destination", NULL);
strings = gtk_string_list_new ((const char *[]){
"app-mockups",
"settings-mockups",
"os-mockups",
"software-mockups",
"mocktails",
NULL});
suggestion_entry_set_model (SUGGESTION_ENTRY (entry), G_LIST_MODEL (strings));
g_object_unref (strings);
gtk_box_append (GTK_BOX (box), entry);
suggestion_entry_set_match_func (SUGGESTION_ENTRY (entry), match_func, NULL, NULL);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_highlight_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_highlight_item), NULL);
suggestion_entry_set_factory (SUGGESTION_ENTRY (entry), factory);
g_object_unref (factory);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -14,8 +14,6 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
typedef struct typedef struct
{ {
int number; int number;
@@ -409,7 +407,7 @@ do_editable_cells (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -8,8 +8,6 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
/* Creates a tree model containing the completions */ /* Creates a tree model containing the completions */
static GtkTreeModel * static GtkTreeModel *
create_completion_model (void) create_completion_model (void)
@@ -95,13 +93,6 @@ do_entry_completion (GtkWidget *do_widget)
entry = gtk_entry_new (); entry = gtk_entry_new ();
gtk_box_append (GTK_BOX (vbox), entry); gtk_box_append (GTK_BOX (vbox), entry);
gtk_accessible_update_relation (GTK_ACCESSIBLE (entry),
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
-1);
gtk_accessible_update_property (GTK_ACCESSIBLE (entry),
GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE, GTK_ACCESSIBLE_AUTOCOMPLETE_LIST,
-1);
/* Create the completion object */ /* Create the completion object */
completion = gtk_entry_completion_new (); completion = gtk_entry_completion_new ();
@@ -122,7 +113,7 @@ do_entry_completion (GtkWidget *do_widget)
} }
if (!gtk_widget_get_visible (window)) if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE); gtk_widget_show (window);
else else
gtk_window_destroy (GTK_WINDOW (window)); gtk_window_destroy (GTK_WINDOW (window));

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