Compare commits

..

175 Commits

Author SHA1 Message Date
Matthias Clasen d1675bfbc8 Add an animated text example 2022-04-06 23:59:47 -04:00
Matthias Clasen 6d606b19be Add a font rendering test 2022-04-06 23:59:47 -04:00
Matthias Clasen 07019887be glyphy: Implement synthetic italic
Use the font matrix found in the FcPattern to transform
the quads we use to render the glyphs. This makes
Cantarell Italic come out just like it does with freetype.
2022-04-06 23:59:47 -04:00
Matthias Clasen 0d52772f68 glyphy: Update for api changes in glyphy
With this, synthetic bold fonts work as well
as the do with freetype.
2022-04-06 23:59:47 -04:00
Matthias Clasen 269918b0f6 glyphy: Implement synthetic bold
When the font appears to be synthetic bold (as
indicated by th embolden property in FcPattern),
use glyphys boldness uniform to render the font
bolder.
2022-04-06 23:59:47 -04:00
Matthias Clasen 1bedfe3dcd glyphy: remove glyphy debug code
We don't have a knob to turn this on, and it is
not really useful outside of glyphy itself, so
remove it.
2022-04-06 23:59:47 -04:00
Matthias Clasen 1854f4d21a glyphy: Use gsk_path_simplify
This ensures that we hand contours to the glyphy
shader that it can actually handle.
2022-04-06 23:59:47 -04:00
Matthias Clasen 09d0f4289e glyphy: Pencil in outline rendering 2022-04-06 23:59:47 -04:00
Christian Hergert a227b4f69d gsk/gl: fix output color of glyphy fragment shader
This copied more or less what the coloring vertex shader was doing in
that we premultiply alpha. That changes how we apply alpha in the fragment
shader to match.

This fixes a white halo around the fonts.
2022-04-06 23:59:47 -04:00
Matthias Clasen e881918fea glyphy: Make glyphy cache size-independent
Use a hb font at nominal size when generating sdf
contours, and use a cache key that is independent
of the size.
2022-04-06 23:59:47 -04:00
Matthias Clasen 06adb709a1 glyphy: Shrink GskGlGlyphyValue a bit
Store the extent as floats, and drop the unused is_empty
and advance fields. With that, we fit into one cacheline.
2022-04-06 23:59:47 -04:00
Christian Hergert 1a8db5f112 gsk/gl: start on basic glyphy renderjob integration
This doesn't work correctly yet, as there are lots of bumps along the way
to still smooth out.
2022-04-06 23:59:47 -04:00
Christian Hergert 526f460d6b gsk/gl: add texture library for Glyphy
This adds a new texture library that can upload SDF data from libglyphy
into regions of a texture atlas so that it can be accessed by Glyphy
shaders in the appropriate place and format.

Some of the placement positioning may seem odd in that it needs to follow
a certain format to be decoded from the Glyphy shaders.
2022-04-06 23:59:47 -04:00
Christian Hergert 80b6a89a32 gsk/gl: dispatch text_node to legacy vs glyphy
If the text node has color glyphs, then we need to dispatch to the legacy
form of rendering which uses FreeType/Cairo/etc to upload glyphs to a
rendered glyph cache.

Otherwise, we can dispatch to a new function which will eventually use
Glyphy to shape to SDF content and upload to an alternate texture atlas.
2022-04-06 23:59:47 -04:00
Christian Hergert 0c192288cd build: add dependency on glyphy 2022-04-06 23:59:47 -04:00
Christian Hergert d34035c22c gsk/gl: use consistent library naming 2022-04-06 23:59:47 -04:00
Christian Hergert 1f7588087a gsk/gl: make texture libraries more autonomous
This moves a lot of the texture atlas control out of the driver and into
the various texture libraries through their base GskGLTextureLibrary class.

Additionally, this gives more control to libraries on allocating which can
be necessary for some tooling such as future Glyphy integration.

As part of this, the 1x1 pixel initialization is moved to the Glyph library
which is the only place where it is actually needed.

The compact vfunc now is responsible for compaction and it allows for us
to iterate the atlas hashtable a single time instead of twice as we were
doing previously.

The init_atlas vfunc is used to do per-library initialization such as
adding a 1x1 pixel in the Glyph cache used for coloring lines.

The allocate vfunc purely allocates but does no upload. This can be useful
for situations where a library wants to reuse the allocator from the
base class but does not want to actually insert a key/value entry. The
glyph library uses this for it's 1x1 pixel.

In the future, we will also likely want to decouple the rectangle packing
implementation from the atlas structure, or at least move it into a union
so that we do not allocate unused memory for alternate allocators.
2022-04-06 23:59:47 -04:00
Christian Hergert bef8d09040 gsk/gl: pin atlases to single texture library
This removes the sharing of atlases across various texture libraries. Doing
so is necessary so that atlases can have different semantics for how they
allocate within the texture as well as potentially allowing for different
formats of texture data.

For example, in the future we might store non-pixel data in the textures
such as Glyphy or even keep glyphs with color content separate from glyphs
which do not and can use alpha channel only.
2022-04-06 23:59:47 -04:00
Christian Hergert 6f1f1a7c89 gsk/gl: add more control over shader generation
This allows the gskglprograms.defs a bit more control over how a shader
will get generated and if it needs to combine sources. Currently, none of
the built-in shaders do that, but upcoming shaders which come from external
libraries will need the ability to inject additional sources in-between
layers.
2022-04-06 23:59:47 -04:00
Christian Hergert 4f5a2d7490 gsk/gl: rename glyphs to glyphs_library
This naming style is less likely to collide with shader naming and makes
it clear where it is consumed what it is.
2022-04-06 23:59:47 -04:00
Christian Hergert 8a8e165560 gsk/gl: allow configuring atlas size 2022-04-06 23:59:47 -04:00
Christian Hergert 0ec623da09 gsk/gl: check for format as well
This could potentially happen if a uniform had never been set.
2022-04-06 23:59:47 -04:00
Christian Hergert 3b147ad630 gsk/gl: only clear glyph cache durign reclaimation
We don't need to clear the front cache on every frame as we can clear it
specifically when we do reclaimation to avoid unnecessary memset() calls.
2022-04-06 23:59:47 -04:00
Christian Hergert 615cf2a782 gsk/gl: ignore max_entry_size when zero
If the max_entry_size is zero, then assume we can add anything to the
atlas. This allows for situations where we might be uploading an arc list
to the atlas instead of pixel data for GPU font rendering.
2022-04-06 23:59:47 -04:00
Christian Hergert f9725cc536 gsk/gl: make max-frame-age configurable
This is nice for some texture libraries that we might want to keep around
for longer than say 60 frames such as a glyph cache.
2022-04-06 23:59:47 -04:00
Matthias Clasen 468863a8b9 gtk-demo: Don't hardcode a title font
We want a large font size, but we don't have to
hardcode Sans.
2022-04-06 23:59:47 -04:00
Matthias Clasen 95a3d3c26f Add a demo for path ops 2022-04-06 23:59:17 -04:00
Matthias Clasen df1bca3027 Add some tests for pathops 2022-04-06 23:59:17 -04:00
Matthias Clasen acf81a0377 path: Implement path ops
Implement boolean operations on paths.
2022-04-06 23:59:17 -04:00
Matthias Clasen bf8fca391a path: Add gsk_path_transform
This is an obvious operation to want for paths.
2022-04-06 23:57:28 -04:00
Matthias Clasen aa722dcfac path: Add gsk_path_is_convex
Add a function to compute whether a path is convex.
2022-04-06 23:52:03 -04:00
Matthias Clasen f5ccf63550 path: Add gsk_path_get_flags
The flags contain some useful information.
2022-04-06 23:52:03 -04:00
Matthias Clasen 61f9b1d9e0 path: Add gsk_path_reverse
This is a natural operation, and useful for debugging things.
2022-04-06 23:52:03 -04:00
Matthias Clasen aa8ba37a0f curve: Cosmetics 2022-04-06 23:47:35 -04:00
Matthias Clasen 86c1493b4b contour: Fix winding for circle contour
Test included.
2022-04-06 23:47:35 -04:00
Matthias Clasen f58513e4dd path: Fix gsk_path_measure_in_fill
This was getting some simple polygon cases wrong :(

The problem here is a misunderstanding in line_get_crossing.
It was returning 'on edge' when a point of the polygon is
on the ray, which is not what 'on edge' is about.

Add some test cases involving horizontal edges that coincide
with the test point.
2022-04-06 23:47:35 -04:00
Matthias Clasen c816eee4d1 curve: Add more line-curve intersection tests 2022-04-06 23:47:35 -04:00
Matthias Clasen 436fe18084 curve: Add another intersection test 2022-04-06 23:47:35 -04:00
Matthias Clasen 3ba2659860 curve: Specify tolerance for intersections
We had 0.1 hardcoded in a bunch of places.
2022-04-06 23:47:35 -04:00
Matthias Clasen ffc5fdb9de Add a debug key for paths
Not used yet.
2022-04-06 23:47:35 -04:00
Matthias Clasen e88cf34642 curve: Add gsk_curve_print for debugging 2022-04-06 23:47:35 -04:00
Matthias Clasen 5eb79b3b01 curve: Move some curve apis to gskcurve.c
Some of this will be reused elsewhere, so move
it out of gskpathstroke.c.
2022-04-06 23:47:35 -04:00
Matthias Clasen cf793f94ac curve: Use GskBoundingBox 2022-04-06 23:47:35 -04:00
Matthias Clasen ba405bfbf1 Add a bounding box type
graphene_rect_t does not quite work for this purpose.
2022-04-06 23:47:35 -04:00
Matthias Clasen 4b6223e07d curve: Handle self-intersection 2022-04-06 23:47:35 -04:00
Matthias Clasen 8637ea8fb8 curve: Small improvement 2022-04-06 23:47:35 -04:00
Matthias Clasen ab8a32bc76 curve: Refine line-line intersection
For collinear line segments, return up to 2 intersections
for the endpoints of the intersection (which is also a
line segment in this case).

Tests included.
2022-04-06 23:47:35 -04:00
Matthias Clasen 6aa38e6b39 curve: Fix line-curve intersections 2022-04-06 23:47:35 -04:00
Matthias Clasen 46bef9b667 curve test: Fix the split test
We were misinterpreting the return value of
gsk_path_measure_get_closest_point.
2022-04-06 23:47:35 -04:00
Matthias Clasen 86862d56bd curve: Skip a failing test
We don't have a good error bound for approximating
conics. Until that changes, skip this test.
2022-04-06 23:47:35 -04:00
Matthias Clasen 1e5c025a1e curve: Add another intersection test 2022-04-06 23:47:35 -04:00
Matthias Clasen 60f87f2a7d path: Fix a typo 2022-04-06 23:47:35 -04:00
Matthias Clasen 001903aeef contour: Add some docs 2022-04-06 23:47:35 -04:00
Matthias Clasen 3b04f5a963 Allow showing points in curve2 test
This is useful for debugging intersections.
2022-04-06 23:47:35 -04:00
Matthias Clasen de29a01682 gsk: Use stroke bounds in the stroke node
We can use gsk_path_get_stroke_bounds to get a
better estimate for the bounds of the stroke node.
2022-04-06 23:47:35 -04:00
Matthias Clasen bd3b88b276 gtk-demo: Use gsk_path_builder_add_layout
We have an api now to hide the cairo use.
2022-04-06 23:47:35 -04:00
Matthias Clasen e7a9030fb5 gsk: Add gsk_path_builder_add_layout
This api makes it easy to turn text into a path that
can be further manipulated. The implementation currently
goes via cairo.
2022-04-06 23:47:35 -04:00
Matthias Clasen 98aca9e2cd curve2: Show osculating circles 2022-04-06 23:47:35 -04:00
Matthias Clasen 6e8b23d485 Add gsk_path_measure_get_curvature 2022-04-06 23:47:35 -04:00
Matthias Clasen 05678d44ca 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.
2022-04-06 23:47:35 -04:00
Matthias Clasen 7b4bc08254 stroke: Make gsk_stroke_to_cairo public
It comes in handy, and does no harm.
2022-04-06 23:47:35 -04:00
Matthias Clasen 3b81a9e529 gtk-demo: Add a curve editor demo 2022-04-06 23:47:35 -04:00
Matthias Clasen 6a0901c40e Implement offsetting
Implement offsetting of paths by reusing the
infrastructure of the stroker.
2022-04-06 23:47:33 -04:00
Matthias Clasen a7b3a0c472 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.
2022-04-06 23:47:08 -04:00
Matthias Clasen 645eddf838 stroker: Implement arcs
Implement arced joins as specified in SVG2.
2022-04-06 23:47:08 -04:00
Matthias Clasen ada1cc7dc5 Add GSK_LINE_JOIN_ARCS
Implementation will follow.
2022-04-06 23:47:08 -04:00
Matthias Clasen 042a3a1344 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.
2022-04-06 23:47:08 -04:00
Matthias Clasen 2542d913bc 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.
2022-04-06 23:47:08 -04:00
Matthias Clasen fc619b9783 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 would 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.
2022-04-06 23:47:06 -04:00
Matthias Clasen 3c56f326fc Special-case circles for strokes
The outline of a circle is just two circles.
2021-12-04 22:58:23 -05:00
Matthias Clasen 4c81600fc9 Special-case rects for strokes
In many cases, the outline of a rectangle is just
two rectangles.
2021-12-04 22:58:23 -05:00
Matthias Clasen 68661b7291 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.
2021-12-04 22:58:23 -05:00
Matthias Clasen b6a2a8b0fc Add gsk_curve_get_curvature
This will be used in the stroker.
2021-12-04 22:58:23 -05:00
Matthias Clasen d08802a2c3 Add gsk_curve_get_normal
Its easy but thats no reason not to have this api.
2021-12-04 22:58:23 -05:00
Matthias Clasen 759bf152d3 Add a test for gsk_curve_offset
The stroker relies on offsetting.
This only tests a few very simple cases.
2021-12-04 22:58:23 -05:00
Matthias Clasen 021bca4629 Add a test for gsk_curve_reverse
The stroker relies on this working.
2021-12-04 22:58:23 -05:00
Matthias Clasen f91995db06 Add a test for tangents of degenerate curves
The stroker relies on these to work.
2021-12-04 22:58:23 -05:00
Matthias Clasen ad145e201b 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.
2021-12-04 22:58:23 -05:00
Matthias Clasen 0bef169b32 Add gsk_curve_reverse
This will be used in stroking.
2021-12-04 22:58:23 -05:00
Matthias Clasen 5f40db5043 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.
2021-12-04 22:58:23 -05:00
Matthias Clasen afd398112b Add conic decomposition tests
We don't have good error bounds here, unfortunately.
2021-12-04 22:58:23 -05:00
Matthias Clasen 98591b383b path: support conic->curve in foreach 2021-12-04 22:58:23 -05:00
Matthias Clasen 319e75c73f 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.
2021-12-04 22:58:23 -05:00
Matthias Clasen c80d5f89d8 Add a performance test for curve eval
All curve types are equally fast here.
2021-12-04 22:58:23 -05:00
Matthias Clasen 8dd4f022c1 Add a performance test for curve intersection
This shows how much more expensive curve
intersections are.
2021-12-04 22:58:23 -05:00
Matthias Clasen ee42889790 Add curve split tests 2021-12-04 22:58:23 -05:00
Matthias Clasen bd0f92fa8b Add another intersection testcase
This tests horizontal line/conic intersection,
which failed before the fix in the previous commit.
2021-12-04 22:58:23 -05:00
Matthias Clasen c438527e49 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.
2021-12-04 22:58:23 -05:00
Matthias Clasen dad4e1da22 Add curve intersection tests
These tests check that gsk_curve_intersect finds
the intersections we want.
2021-12-04 22:58:23 -05:00
Matthias Clasen 52394b1520 Add gsk_curve_intersect
Add a way to find the intersections of two curves.
This will be used in stroking.
2021-12-04 22:58:23 -05:00
Matthias Clasen 3efd6c9a12 Add gsk_curve_get_bounds
Add getters for bounding boxes of curves.
2021-12-04 22:58:23 -05:00
Matthias Clasen 6d04869c85 Only test conic weights between 1/20 and 20
The rest just give us no end of numeric trouble.
2021-12-04 22:58:23 -05:00
Matthias Clasen 5781a8c66a xxx: Link ottie tests against libottie 2021-12-04 22:58:23 -05:00
Matthias Clasen 65813c3f19 xxx: Link ottie tools against libottie 2021-12-04 22:58:23 -05:00
Benjamin Otte 33d5acf1db Ottie: Add ottie-editor 2021-12-04 22:58:23 -05:00
Benjamin Otte d0d62ee0d6 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.
2021-12-04 22:58:23 -05:00
Benjamin Otte e359e0b146 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
2021-12-04 22:58:23 -05:00
Benjamin Otte 4a633e4476 Ottie: Add 2021-12-04 22:58:23 -05:00
Benjamin Otte 78c2fca48e path: Add gsk_path_builder_add_ellipse() 2021-12-04 22:58:23 -05:00
Benjamin Otte 9b93dcbbd8 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.
2021-12-04 22:58:23 -05:00
Benjamin Otte 5acdc8358e path: Add gsk_path_measure_is_closed () 2021-12-04 22:58:23 -05:00
Benjamin Otte 9ecd508b86 path: Add gsk_path_measure_restrict_to_contour() 2021-12-04 22:58:23 -05:00
Matthias Clasen 452eb951d7 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.
2021-12-04 22:58:23 -05:00
Benjamin Otte a6e665c6f3 gtk-demo: Use dashes in path-fill demo 2021-12-04 22:58:23 -05:00
Matthias Clasen 19f2eddf46 Add gsk_path_get_stroke_bounds
A relatively cheap way to get bounds for the area
that would be affected by stroking a path.
2021-12-04 22:58:23 -05:00
Benjamin Otte a79d427a4b testsuite: Add tests for the dasher 2021-12-04 22:58:23 -05:00
Benjamin Otte f9d794d315 path: Add a foreach function that dashes a path 2021-12-04 22:58:23 -05:00
Benjamin Otte 75b96fa7cf 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.
2021-12-04 22:58:23 -05:00
Benjamin Otte a5763a3de1 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.
2021-12-04 22:58:23 -05:00
Matthias Clasen 6c9206d46a testsuite Add curve tangent tests 2021-12-04 22:58:23 -05:00
Benjamin Otte 918b07967c testsuite: Add a test for the conic that got us segment() 2021-12-04 22:58:23 -05:00
Benjamin Otte 2f3aae002d path: Add gsk_curve_segment()
Using split() twice with scaled t values does not work with conics.
2021-12-04 22:58:23 -05:00
Benjamin Otte a1f9a45f17 testsuite: Add a test for gsk_curve_decompose() 2021-12-04 22:58:23 -05:00
Benjamin Otte 57cf7e6fc2 testuite: Add tests for gsk_curve_get_tangent() 2021-12-04 22:58:23 -05:00
Matthias Clasen 5c817aef62 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.
2021-12-04 22:58:23 -05:00
Benjamin Otte b7c83ce45c 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.
2021-12-04 22:58:23 -05:00
Matthias Clasen 8b13ea22be 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.
2021-12-04 22:58:23 -05:00
Benjamin Otte a21b3c7337 testsuite: Add conics to the random paths 2021-12-04 22:58:23 -05:00
Benjamin Otte eb04db32e0 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.
2021-12-04 22:58:23 -05:00
Benjamin Otte faf0c8d1f9 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.
2021-12-04 22:43:32 -05:00
Benjamin Otte 2f91089b71 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.
2021-12-04 22:43:32 -05:00
Benjamin Otte b0a1b4f672 WIP: pathbuilder: Add gsk_path_builder_add_rounded_rect()
It works, but does not use a custom contour yet.
2021-12-04 22:43:32 -05:00
Benjamin Otte 599baee1c4 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.
2021-12-04 22:43:32 -05:00
Benjamin Otte 51d645168f path: Rename to gtk_path_builder_add_segment()
It's about bulding paths, not about measuring them.
2021-12-04 22:43:32 -05:00
Benjamin Otte 5991f4b6c9 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.
2021-12-04 22:43:32 -05:00
Benjamin Otte a41b9ebec7 path: Make all private contour APIs take a GskContour
... instead of a path, index tuple.
2021-12-04 22:43:32 -05:00
Matthias Clasen 50098ba75b Add a nodeparser tests for fill and stroke nodes 2021-12-04 22:43:32 -05:00
Benjamin Otte c804a3863e stroke: Add support for dashes
... and hook it up in the node parser and for Cairo rendering.
2021-12-04 22:43:32 -05:00
Matthias Clasen a94a8857cc gsk: Implement parsing fill and stroke nodes
Make serialization and deserialization work for stroke and
fill nodes.
2021-12-04 22:43:31 -05:00
Benjamin Otte 4b5ee6e45d 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.
2021-12-04 22:43:31 -05:00
Benjamin Otte e30ef1989d testsuite: Add an in_fill() test 2021-12-04 22:43:31 -05:00
Matthias Clasen 288e8a46cf 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.
2021-12-04 22:43:31 -05:00
Benjamin Otte db8d6e3d99 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.
2021-12-04 22:43:31 -05:00
Matthias Clasen 9d313b3264 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.
2021-12-04 22:43:31 -05:00
Matthias Clasen a28311883f 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.
2021-12-04 22:43:31 -05:00
Benjamin Otte aa695ae1c2 testsuite: Add librsvg path tests 2021-12-04 22:43:31 -05:00
Matthias Clasen 42b017d073 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.
2021-12-04 22:43:31 -05:00
Matthias Clasen 0414c15537 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.
2021-12-04 22:43:31 -05:00
Matthias Clasen 98435e15dd 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.
2021-12-04 22:43:31 -05:00
Benjamin Otte 7f63e426cc testsuite: Add relative path functions
They're making the paths slightly weirder, but they test public API, so
woohoo!
2021-12-04 22:43:31 -05:00
Benjamin Otte 9e450370e8 pathbuilder: Add relative path commands
And gsk_path_builder_get_current_point().

They will be needed by the string parser.
2021-12-04 22:43:31 -05:00
Benjamin Otte 5fe35cb0fd path: Add GSK_CIRCLE_POINT_INIT() to initialize points on the circle
This is just splitting out a commonly done operation into a macro.
2021-12-04 22:43:31 -05:00
Benjamin Otte 70f097ebd7 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.
2021-12-04 22:43:31 -05:00
Benjamin Otte 1f1641fdfc gtk-demo: Show closest point in text-on-path demo 2021-12-04 22:43:31 -05:00
Benjamin Otte dce77dc2a5 path: Split GskPathBuilder into its own file
... and add missing API docs.
2021-12-04 22:42:38 -05:00
Benjamin Otte 1500250116 testsuite: Add a test using get_point() and get_closest_point() 2021-12-04 22:42:38 -05:00
Benjamin Otte 8a5c2e771a testsuite: Add a test for get_point() 2021-12-04 22:42:38 -05:00
Benjamin Otte 419f4f87a4 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.
2021-12-04 22:42:38 -05:00
Benjamin Otte 0f848aace9 gtk-demo: Add cute maze demo 2021-12-04 22:42:38 -05:00
Benjamin Otte c1111d9c4d testsuite: Add tests for gsk_path_measure_get_closest_point() 2021-12-04 22:42:14 -05:00
Benjamin Otte 614e043c94 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.
2021-12-04 22:42:14 -05:00
Benjamin Otte ee8ad62bb5 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.
2021-12-04 22:42:14 -05:00
Benjamin Otte ec6d102dc5 testsuite: Add tests for gsk_path_measure_add_segment() 2021-12-04 22:42:14 -05:00
Benjamin Otte c82cfa8b0c gtk-demo: Add a text-on-path demo 2021-12-04 22:42:14 -05:00
Benjamin Otte ab41ef43d8 gtk-demo: Add a path-fill demo 2021-12-04 22:42:14 -05:00
Benjamin Otte aa913100ba path: Add gsk_path_measure_get_point()
Allows querying the coordinates and direction of any specific point on a
path.
2021-12-04 22:40:12 -05:00
Matthias Clasen 0e256a6935 path: Add gsk_path_add_circle()
Adds a circle contour, too.
2021-12-04 22:40:12 -05:00
Benjamin Otte 2559885415 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.
2021-12-04 22:40:12 -05:00
Benjamin Otte d9a79c0a2f path: Implement gsk_path_to_cairo() using foreach() 2021-12-04 22:40:12 -05:00
Benjamin Otte 268efbd5a6 path: Add gsk_path_foreach() 2021-12-04 22:40:12 -05:00
Benjamin Otte a14770a47d path: Collect flags
We don't need them yet, but maybe later.
2021-12-04 22:40:12 -05:00
Benjamin Otte d42f45bc5a testsuite: Add path tests 2021-12-04 22:40:12 -05:00
Benjamin Otte 87b108209e pathmeasure: Add gsk_path_measure_add_segment()
This allows chunking paths, weeee.
2021-12-04 22:40:12 -05:00
Benjamin Otte 5ac2abc6d9 path: Add gsk_path_builder_add_path() 2021-12-04 22:40:12 -05:00
Benjamin Otte 9c721bff1b gsk: Add GskPathMeasure
An object to do measuring operations on paths - determining their
length, cutting off subpaths, things like that.
2021-12-04 22:40:12 -05:00
Benjamin Otte 78cae537a9 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.
2021-12-04 22:40:12 -05:00
Benjamin Otte 69cdeb6037 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?
2021-12-04 22:40:12 -05:00
Benjamin Otte 8d1f354d01 snapshot: Add gtk_snapshot_push_stroke() 2021-12-04 22:40:12 -05:00
Benjamin Otte c8928bf064 gsk: Add GskStrokeNode 2021-12-04 22:40:12 -05:00
Benjamin Otte 2b029af78f gsk: Add GskStroke
It's unused in this commit. This just prepares the new object.
2021-12-04 22:40:12 -05:00
Benjamin Otte 592bab384f demos: Add a simple demo filling a path 2021-12-04 22:40:12 -05:00
Benjamin Otte ffebe0c340 snapshot: Add gtk_snapshot_push_fill() 2021-12-04 22:40:12 -05:00
Benjamin Otte 16ca8f75fd gsk: Add GskFillNode
Take a rendernode as source and a GskPath and fill the region in the
path just like cairo_fill() would.
2021-12-04 22:40:12 -05:00
Benjamin Otte 955762c5e8 gsk: Add GskPath 2021-12-04 22:40:12 -05:00
Matthias Clasen c49205c1e6 gtk-demo: Small fixup to the cursors demo 2021-12-04 22:40:12 -05:00
534 changed files with 87878 additions and 43775 deletions
+3 -8
View File
@@ -25,7 +25,7 @@ variables:
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v36"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v35"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
.only-default:
@@ -88,7 +88,7 @@ fedora-x86_64:
- meson compile -C _build
- meson install -C _build
- 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
- meson compile -C _build_hello
- .gitlab-ci/run-tests.sh _build x11
- .gitlab-ci/run-tests.sh _build wayland
- .gitlab-ci/run-tests.sh _build waylandgles
@@ -156,11 +156,6 @@ msys2-mingw64:
variables:
MSYSTEM: "MINGW64"
CHERE_INVOKING: "yes"
artifacts:
when: always
expose_as: 'Windows_DLL_MSYS2_64_bit_toolchain'
paths:
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
macos:
extends: .only-default
@@ -172,7 +167,7 @@ macos:
needs: []
before_script:
- bash .gitlab-ci/show-info-osx.sh
- pip3 install --user meson==0.59
- pip3 install --user meson==0.56
- pip3 install --user ninja
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
- export MESON_FORCE_BACKTRACE=1
-2
View File
@@ -95,8 +95,6 @@ RUN dnf -y install \
weston-libs \
which \
xorg-x11-server-Xvfb \
&& dnf install -y 'dnf-command(builddep)' \
&& dnf builddep -y wayland \
&& dnf clean all
# Enable sudo for wheel users
+1 -1
View File
@@ -5,7 +5,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
@echo on
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson==0.59 || goto :error
pip3 install --upgrade --user meson==0.56.2 || goto :error
meson -Dmedia-gstreamer=disabled _build || goto :error
ninja -C _build || goto :error
+1 -4
View File
@@ -31,8 +31,7 @@ pacman --noconfirm -S --needed \
mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad \
mingw-w64-$MSYS2_ARCH-shared-mime-info \
mingw-w64-$MSYS2_ARCH-python-gobject
mingw-w64-$MSYS2_ARCH-shared-mime-info
mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"
@@ -73,5 +72,3 @@ unset CCACHE_DISABLE
ninja -C _build
ccache --show-stats
tar zcf _build/gtkdll.tar.gz _build/gtk/libgtk*.dll
+2 -188
View File
@@ -1,194 +1,8 @@
Overview of Changes in 4.6.1, 11-02-2022
========================================
* GtkFontChooser:
- Stop using PangoFc api
- Fix a crash
- Use new HarfBuzz api
* GtkMenuButton:
- Update accessible description
* GtkTextView:
- Fix intra-widget dnd
* Printing:
- Fix an fd leak
* Input:
- Make sure input methods get focus-in events
- Always flush events to avoid scroll event pileup
- Support hold events
- Update keysyms from libxkbcommon
* Theme:
- Improve text selection legibility
* Introspection:
- Add missing nullable annotations everywhere
* Build:
- Make stack noexec again
- Avoid symbol leaks
- Drop unneeded script data
* Windows:
- Stop using WM_SYNCPAINT
- Relax check for GL 3.x legacy contexts
- Use native apis for language names
- Rewrite the keymap code
- Use the GL renderer by default
* Wayland:
- Fix support for the new high-contrast setting
- Avoid redundant scale changes
- Fix DND hotspot handling
- Don't always restore the saved size when floating
* MacOS:
- Various performance improvements
* Translation updates:
Brazilian Portuguese
Catalan
Chinese (China)
Galician
Hebrew
Japanese
Lithuanian
Persian
Polish
Portuguese
Russian
Slovenian
Spanish
Ukrainian
Overview of Changes in 4.6.0, 30-12-2021
========================================
* GtkProgressBar:
- Fix handling of "inverted"
* GtkLabel:
- Add a "natural wrap mode" property to influence how
natural width is determined
* GtkTextView
- Scroll insertion on-screen after undo / redo
* gsk:
- Abort region diffing when changes are too complex
* gdk:
- Avoid compressing discrete scroll events
- Fix problems with hiding windows
- Improve GL and GLES version checks
* Wayland:
- Support new high-contrast setting
* Inspector:
- Add DND inspection support
* build:
- Avoid deprecated meson apis
* Translation updates
Galician
Portuguese
Ukrainian
Overview of Changes in 4.5.1, 16-12-2021
========================================
* GtkWidget sizing has been rewritten to implement
width-for-height more properly. This had some fallout,
and some widgets may still not react kindly to the
new way of doing things.
See https://blog.gtk.org/2021/12/03/sizable-news/
for details, and please file issues if you notice fallout.
Overview of Changes
===================
* Rename git `master` branch to `main`
* Css:
- Fully support font-variant-caps
- Fix a crash with gradients
* Make various widgets activatable:
- GtkComboBox
- GtkDropDown
* GtkPopover:
- Make focus indicators not disappear
* GtkTextView:
- Don't leave embedded children stranded when scrolling
- Don't insert Emoji into non-editable textviews
- Fix Emoji chooser positioning
- Fix problems with pasting text
- Improve scroll-to-mark behavior
- Support right-aligned, centered and decimal tabs
- Make child anchor replacement character settable
- Provide more context to input methods
* GtkDragIcon:
- Provide default icons for paintables and files
* GtkBuilder:
- Speed up template precompilation
* Actions:
- Reduce allocations during signal emissions
- Avoid duplication and unnecessary recursion
* Inspector:
- Show the selected im-module in the General tab
- Add a clipboard viewer
- Make the recorder record events too
- Add a graph visualizing gtk_widget_measure()
* Gsk:
- Fix hexbox rendering
- Fix transformed linear gradient rendering
* Printing:
- Fix dialog-less printing
* Windows:
- Use the common EGL setup code
- Respect GDK_DEBUG=gl-egl
- Fix AeroSnap indicator and positioning
* X11:
- Improve behavior of windows drags on headerbar controls
- Trap errors for RANDR changes
- Fix problems with drag icons
* Wayland:
- Ensure we prefer the Wayland im-module over others
* Translation updates
Basque
Catalan
Croatian
Friulian
Galician
Hebrew
Icelandic
Italian
Latvian
Lithuanian
Occitan
Persian
Portuguese
Spanish
Swedish
Ukrainian
Overview of Changes in 4.5.0
============================
+1 -2
View File
@@ -43,8 +43,7 @@
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git"
}
]
},
+1 -2
View File
@@ -43,8 +43,7 @@
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git"
}
]
},
@@ -43,8 +43,7 @@
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git"
}
]
},
+4 -4
View File
@@ -13,7 +13,7 @@ if 'DESTDIR' not in os.environ:
gtk_moduledir = os.path.join(gtk_libdir, 'gtk-' + gtk_api_version, gtk_abi_version)
gtk_printmodule_dir = os.path.join(gtk_moduledir, 'printbackends')
gtk_mediamodule_dir = os.path.join(gtk_moduledir, 'media')
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
print('Compiling GSettings schemas...')
glib_compile_schemas = subprocess.check_output(['pkg-config',
@@ -40,6 +40,6 @@ if 'DESTDIR' not in os.environ:
gio_querymodules = 'gio-querymodules'
subprocess.call([gio_querymodules, gtk_printmodule_dir])
print('Updating module cache for media backends...')
os.makedirs(gtk_mediamodule_dir, exist_ok=True)
subprocess.call([gio_querymodules, gtk_mediamodule_dir])
print('Updating module cache for input methods...')
os.makedirs(gtk_immodule_dir, exist_ok=True)
subprocess.call([gio_querymodules, gtk_immodule_dir])
+1 -1
View File
@@ -17,7 +17,7 @@ executable('gtk4-constraint-editor',
c_args: common_cflags,
dependencies: libgtk_dep,
include_directories: confinc,
win_subsystem: 'windows',
gui_app: true,
link_args: extra_demo_ldflags,
install: false,
)
+127 -316
View File
@@ -1,10 +1,12 @@
/* Clipboard
*
* 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
* target.
* It also shows how to transfer images via the clipboard or via
* 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>
@@ -12,103 +14,22 @@
#include <string.h>
#include "demoimage.h"
static GtkWidget *window = NULL;
static void
copy_button_clicked (GtkStack *source_stack,
gpointer user_data)
copy_button_clicked (GtkWidget *button,
gpointer user_data)
{
GtkWidget *entry;
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);
visible_child_name = gtk_stack_get_visible_child_name (source_stack);
/* Get the clipboard object */
clipboard = gtk_widget_get_clipboard (entry);
if (strcmp (visible_child_name, "Text") == 0)
{
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)
{
GdkRGBA color;
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (visible_child), &color);
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));
}
/* Set clipboard text */
gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (entry)));
}
static void
@@ -116,259 +37,149 @@ paste_received (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
GtkStack *dest_stack = user_data;
GdkClipboard *clipboard;
const GValue *value;
GtkWidget *entry;
char *text;
GError *error = NULL;
clipboard = GDK_CLIPBOARD (source_object);
entry = GTK_WIDGET (user_data);
value = gdk_clipboard_read_value_finish (clipboard, result, &error);
if (value)
/* Get the resulting text of the read operation */
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
{
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);
}
}
static void
paste_button_clicked (GtkStack *dest_stack,
gpointer user_data)
paste_button_clicked (GtkWidget *button,
gpointer user_data)
{
GtkWidget *entry;
GdkClipboard *clipboard;
GdkContentFormats *formats;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (dest_stack));
formats = gdk_clipboard_get_formats (clipboard);
entry = GTK_WIDGET (user_data);
if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_TEXTURE))
gdk_clipboard_read_value_async (clipboard, GDK_TYPE_TEXTURE, 0, NULL, paste_received, dest_stack);
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);
}
/* Get the clipboard object */
clipboard = gtk_widget_get_clipboard (entry);
static void
update_copy_button_sensitivity (GtkWidget *source_stack)
{
GtkButton *copy_button;
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 (GtkNativeDialog *dialog,
int response,
GtkButton *button)
{
gtk_native_dialog_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
file_button_set_file (button, file);
g_object_unref (file);
update_copy_button_sensitivity (gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_STACK));
}
gtk_native_dialog_destroy (dialog);
}
static void
open_file_cb (GtkWidget *button)
{
GtkFileChooserNative *chooser;
chooser = gtk_file_chooser_native_new ("Choose a file",
GTK_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW)),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Open",
"_Cancel");
g_signal_connect (chooser, "response", G_CALLBACK (file_chooser_response), button);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (chooser));
}
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);
/* Request the contents of the clipboard, contents_received will be
called when we do get the contents.
*/
gdk_clipboard_read_text_async (clipboard, NULL, paste_received, entry);
}
GtkWidget *
do_clipboard (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkBuilderScope *scope;
GtkBuilder *builder;
GtkWidget *button;
GtkWidget *vbox, *hbox;
GtkWidget *label;
GtkWidget *entry, *button;
GtkWidget *image;
scope = gtk_builder_cscope_new ();
gtk_builder_cscope_add_callback_symbols (GTK_BUILDER_CSCOPE (scope),
"copy_button_clicked", G_CALLBACK (copy_button_clicked),
"paste_button_clicked", G_CALLBACK (paste_button_clicked),
"source_changed_cb", G_CALLBACK (source_changed_cb),
"text_changed_cb", G_CALLBACK (text_changed_cb),
"open_file_cb", G_CALLBACK (open_file_cb),
"on_drop", G_CALLBACK (on_drop),
"drag_prepare", G_CALLBACK (drag_prepare),
NULL);
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"));
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Clipboard");
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"));
g_object_set_data (gtk_builder_get_object (builder, "source_stack"), "copy-button", button);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
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"));
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);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_unref (builder);
g_object_unref (scope);
label = gtk_label_new ("\"Copy\" will copy the text\nin the entry to the clipboard");
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))
-288
View File
@@ -1,288 +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>
<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">
<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">
<property name="valign">center</property>
<property name="model">
<object class="GtkStringList">
<items>
<item>Text</item>
<item>Color</item>
<item>Image</item>
<item>File</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">
<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="GtkColorButton" id="source_color">
<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">
<property name="active">1</property>
<child>
<object class="GtkDragSource">
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<child>
<object class="GtkImage">
<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">
<property name="group">image_rose</property>
<child>
<object class="GtkDragSource">
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<child>
<object class="GtkImage">
<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">
<property name="group">image_floppy</property>
<child>
<object class="GtkDragSource">
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<child>
<object class="GtkImage">
<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">
<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>
</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">
<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">
<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">
<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">
<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">
<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>
+2 -3
View File
@@ -24,6 +24,7 @@ do_cursors (GtkWidget *do_widget)
builder = gtk_builder_new_from_resource ("/cursors/cursors.ui");
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_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
@@ -34,9 +35,7 @@ do_cursors (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
{
gtk_window_destroy (GTK_WINDOW (window));
}
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
File diff suppressed because it is too large Load Diff
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CURVE_TYPE_EDITOR (curve_editor_get_type ())
G_DECLARE_FINAL_TYPE (CurveEditor, curve_editor, CURVE, EDITOR, GtkWidget)
GtkWidget * curve_editor_new (void);
void curve_editor_set_edit (CurveEditor *self,
gboolean edit);
void curve_editor_set_path (CurveEditor *self,
GskPath *path);
GskPath * curve_editor_get_path (CurveEditor *self);
void curve_editor_set_stroke (CurveEditor *self,
GskStroke *stroke);
const GskStroke * curve_editor_get_stroke (CurveEditor *self);
void curve_editor_set_color (CurveEditor *self,
GdkRGBA *color);
const GdkRGBA * curve_editor_get_color (CurveEditor *self);
gboolean curve_editor_get_show_outline (CurveEditor *self);
void curve_editor_set_show_outline (CurveEditor *self,
gboolean show_outline);
G_END_DECLS
+272
View File
@@ -0,0 +1,272 @@
/* Path/Curve Editor
*
* This demo shows an elaborate curve editor that you would expect to find
* in a vector graphics editor. It is built on top of GTK's path APIs.
*/
#include <gtk/gtk.h>
#include "curve-editor.h"
static GskPath *
make_circle_path (void)
{
float w = 310;
float h = 310;
float cx = w / 2;
float cy = h / 2;
float pad = 20;
float r = (w - 2 * pad) / 2;
float k = 0.55228;
float kr = k * r;
GskPathBuilder *builder;
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, cx, pad);
gsk_path_builder_curve_to (builder, cx + kr, pad,
w - pad, cy - kr,
w - pad, cy);
gsk_path_builder_curve_to (builder, w - pad, cy + kr,
cx + kr, h - pad,
cx, h - pad);
gsk_path_builder_curve_to (builder, cx - kr, h - pad,
pad, cy + kr,
pad, cy);
gsk_path_builder_curve_to (builder, pad, cy - kr,
cx - kr, pad,
cx, pad);
gsk_path_builder_close (builder);
return gsk_path_builder_free_to_path (builder);
}
static void
edit_changed (GtkToggleButton *button,
GParamSpec *pspec,
CurveEditor *editor)
{
curve_editor_set_edit (editor, gtk_toggle_button_get_active (button));
}
static void
reset (GtkButton *button,
CurveEditor *editor)
{
GskPath *path;
path = make_circle_path ();
curve_editor_set_path (editor, path);
gsk_path_unref (path);
}
static void
line_width_changed (GtkSpinButton *spin,
CurveEditor *editor)
{
GskStroke *stroke;
stroke = gsk_stroke_copy (curve_editor_get_stroke (editor));
gsk_stroke_set_line_width (stroke, gtk_spin_button_get_value (spin));
curve_editor_set_stroke (editor, stroke);
gsk_stroke_free (stroke);
}
static void
cap_changed (GtkDropDown *combo,
GParamSpec *pspec,
CurveEditor *editor)
{
GskStroke *stroke;
stroke = gsk_stroke_copy (curve_editor_get_stroke (editor));
gsk_stroke_set_line_cap (stroke, (GskLineCap)gtk_drop_down_get_selected (combo));
curve_editor_set_stroke (editor, stroke);
gsk_stroke_free (stroke);
}
static void
join_changed (GtkDropDown *combo,
GParamSpec *pspec,
CurveEditor *editor)
{
GskStroke *stroke;
stroke = gsk_stroke_copy (curve_editor_get_stroke (editor));
gsk_stroke_set_line_join (stroke, (GskLineJoin)gtk_drop_down_get_selected (combo));
curve_editor_set_stroke (editor, stroke);
gsk_stroke_free (stroke);
}
static void
color_changed (GtkColorChooser *chooser,
GParamSpec *pspec,
CurveEditor *editor)
{
GdkRGBA color;
gtk_color_chooser_get_rgba (chooser, &color);
curve_editor_set_color (editor, &color);
}
static void
stroke_toggled (GtkCheckButton *button,
CurveEditor *editor)
{
curve_editor_set_show_outline (editor, gtk_check_button_get_active (button));
gtk_widget_queue_draw (GTK_WIDGET (editor));
}
static void
limit_changed (GtkSpinButton *spin,
CurveEditor *editor)
{
GskStroke *stroke;
stroke = gsk_stroke_copy (curve_editor_get_stroke (editor));
gsk_stroke_set_miter_limit (stroke, gtk_spin_button_get_value (spin));
curve_editor_set_stroke (editor, stroke);
gsk_stroke_free (stroke);
}
static void
dashes_changed (GtkEntry *entry,
GParamSpec *spec,
CurveEditor *editor)
{
const char *text;
char **split;
GArray *dash;
GskStroke *stroke;
text = gtk_editable_get_text (GTK_EDITABLE (entry));
split = g_strsplit (text, " ", 0);
dash = g_array_new (FALSE, FALSE, sizeof (float));
for (int i = 0; split[i] != NULL; i++)
{
double d;
char *endp = 0;
d = g_strtod (split[i], &endp);
if (*endp == '\0')
g_array_append_vals (dash, (float[1]) { d }, 1);
}
g_strfreev (split);
stroke = gsk_stroke_copy (curve_editor_get_stroke (editor));
gsk_stroke_set_dash (stroke, (const float *)dash->data, dash->len);
curve_editor_set_stroke (editor, stroke);
gsk_stroke_free (stroke);
g_array_free (dash, TRUE);
}
GtkWidget *
do_curve (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *demo;
GtkWidget *edit_toggle;
GtkWidget *reset_button;
GtkWidget *titlebar;
GtkWidget *stroke_toggle;
GtkWidget *line_width_spin;
GtkWidget *stroke_button;
GtkWidget *popover;
GtkWidget *grid;
GtkWidget *cap_combo;
GtkWidget *join_combo;
GtkWidget *color_button;
GtkWidget *limit_spin;
GtkWidget *dash_entry;
if (!window)
{
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Curve Editor");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_default_size (GTK_WINDOW (window), 310, 350);
edit_toggle = gtk_toggle_button_new ();
gtk_button_set_icon_name (GTK_BUTTON (edit_toggle), "document-edit-symbolic");
reset_button = gtk_button_new_from_icon_name ("edit-undo-symbolic");
stroke_button = gtk_menu_button_new ();
gtk_menu_button_set_icon_name (GTK_MENU_BUTTON (stroke_button), "open-menu-symbolic");
popover = gtk_popover_new ();
gtk_menu_button_set_popover (GTK_MENU_BUTTON (stroke_button), popover);
grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
gtk_popover_set_child (GTK_POPOVER (popover), grid);
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Color:"), 0, 0, 1, 1);
color_button = gtk_color_button_new_with_rgba (&(GdkRGBA){ 0., 0., 0., 1.});
gtk_grid_attach (GTK_GRID (grid), color_button, 1, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line width:"), 0, 1, 1, 1);
line_width_spin = gtk_spin_button_new_with_range (1, 20, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (line_width_spin), 1);
gtk_grid_attach (GTK_GRID (grid), line_width_spin, 1, 1, 1, 1);
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line cap:"), 0, 2, 1, 1);
cap_combo = gtk_drop_down_new_from_strings ((const char *[]){"Butt", "Round", "Square", NULL});
gtk_grid_attach (GTK_GRID (grid), cap_combo, 1, 2, 1, 1);
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line join:"), 0, 3, 1, 1);
join_combo = gtk_drop_down_new_from_strings ((const char *[]){"Miter", "Miter-clip", "Round", "Bevel", "Arcs", NULL});
gtk_grid_attach (GTK_GRID (grid), join_combo, 1, 3, 1, 1);
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Miter limit:"), 0, 4, 1, 1);
limit_spin = gtk_spin_button_new_with_range (0, 10, 1);
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (limit_spin), 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (limit_spin), 4);
gtk_grid_attach (GTK_GRID (grid), limit_spin, 1, 4, 1, 1);
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Dashes:"), 0, 5, 1, 1);
dash_entry = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), dash_entry, 1, 5, 1, 1);
stroke_toggle = gtk_check_button_new_with_label ("Show outline");
gtk_grid_attach (GTK_GRID (grid), stroke_toggle, 1, 6, 1, 1);
titlebar = gtk_header_bar_new ();
gtk_header_bar_pack_start (GTK_HEADER_BAR (titlebar), edit_toggle);
gtk_header_bar_pack_start (GTK_HEADER_BAR (titlebar), reset_button);
gtk_header_bar_pack_start (GTK_HEADER_BAR (titlebar), stroke_button);
gtk_window_set_titlebar (GTK_WINDOW (window), titlebar);
demo = curve_editor_new ();
g_signal_connect (stroke_toggle, "toggled", G_CALLBACK (stroke_toggled), demo);
g_signal_connect (edit_toggle, "notify::active", G_CALLBACK (edit_changed), demo);
g_signal_connect (reset_button, "clicked", G_CALLBACK (reset), demo);
g_signal_connect (cap_combo, "notify::selected", G_CALLBACK (cap_changed), demo);
g_signal_connect (join_combo, "notify::selected", G_CALLBACK (join_changed), demo);
g_signal_connect (color_button, "notify::rgba", G_CALLBACK (color_changed), demo);
g_signal_connect (line_width_spin, "value-changed", G_CALLBACK (line_width_changed), demo);
g_signal_connect (limit_spin, "value-changed", G_CALLBACK (limit_changed), demo);
g_signal_connect (dash_entry, "notify::text", G_CALLBACK (dashes_changed), demo);
reset (NULL, CURVE_EDITOR (demo));
gtk_spin_button_set_value (GTK_SPIN_BUTTON (line_width_spin), 6);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_button), &(GdkRGBA) { 1, 0, 0, 1 });
gtk_drop_down_set_selected (GTK_DROP_DOWN (cap_combo), GSK_LINE_CAP_ROUND);
gtk_editable_set_text (GTK_EDITABLE (dash_entry), "0 8");
gtk_window_set_child (GTK_WINDOW (window), demo);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+12 -1
View File
@@ -15,7 +15,6 @@
<file>demo.ui</file>
</gresource>
<gresource prefix="/clipboard">
<file>clipboard.ui</file>
<file>demoimage.c</file>
<file>demoimage.h</file>
</gresource>
@@ -250,6 +249,10 @@
<gresource prefix="/video-player">
<file>bbb.png</file>
</gresource>
<gresource prefix="/curve">
<file>curve-editor.c</file>
<file>curve-editor.h</file>
</gresource>
<gresource prefix="/sources">
<file>application_demo.c</file>
<file>assistant.c</file>
@@ -267,6 +270,7 @@
<file>css_pixbufs.c</file>
<file>css_shadows.c</file>
<file>cursors.c</file>
<file>curve.c</file>
<file>dialog.c</file>
<file>drawingarea.c</file>
<file>dropdown.c</file>
@@ -287,6 +291,7 @@
<file>gears.c</file>
<file>gestures.c</file>
<file>glarea.c</file>
<file>glyphs.c</file>
<file>gltransition.c</file>
<file>headerbar.c</file>
<file>hypertext.c</file>
@@ -325,6 +330,9 @@
<file>paintable_symbolic.c</file>
<file>panes.c</file>
<file>password_entry.c</file>
<file>path_fill.c</file>
<file>path_maze.c</file>
<file>path_text.c</file>
<file>peg_solitaire.c</file>
<file>pickers.c</file>
<file>printing.c</file>
@@ -409,6 +417,9 @@
<gresource prefix="/fontrendering">
<file>fontrendering.ui</file>
</gresource>
<gresource prefix="/path_text">
<file>path_text.ui</file>
</gresource>
<gresource prefix="/org/gtk/Demo4">
<file>icons/16x16/actions/application-exit.png</file>
<file>icons/16x16/actions/document-new.png</file>
+1
View File
@@ -12,6 +12,7 @@
*/
#include <gtk/gtk.h>
#include <pango/pangofc-font.h>
#include <hb.h>
#include <hb-ot.h>
#include <glib/gi18n.h>
File diff suppressed because it is too large Load Diff
-72
View File
@@ -18,81 +18,15 @@
#include "language-names.h"
#ifdef G_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#ifndef ISO_CODES_PREFIX
#define ISO_CODES_PREFIX "/usr"
#endif
#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
#endif
static GHashTable *language_map;
#ifdef G_OS_WIN32
/* if we are using native Windows use native Windows API for language names */
static BOOL CALLBACK
get_win32_all_locales_scripts (LPWSTR locale_w, DWORD flags, LPARAM param)
{
wchar_t *langname_w = NULL;
wchar_t locale_abbrev_w[9];
gchar *langname, *locale_abbrev, *locale, *p;
gint i;
const LCTYPE iso639_lctypes[] = { LOCALE_SISO639LANGNAME, LOCALE_SISO639LANGNAME2 };
GHashTable *ht_scripts_langs = (GHashTable *) param;
PangoLanguage *lang;
gint langname_size, locale_abbrev_size;
langname_size = GetLocaleInfoEx (locale_w, LOCALE_SLOCALIZEDDISPLAYNAME, langname_w, 0);
if (langname_size == 0)
return FALSE;
langname_w = g_new0 (wchar_t, langname_size);
if (langname_size == 0)
return FALSE;
GetLocaleInfoEx (locale_w, LOCALE_SLOCALIZEDDISPLAYNAME, langname_w, langname_size);
langname = g_utf16_to_utf8 (langname_w, -1, NULL, NULL, NULL);
locale = g_utf16_to_utf8 (locale_w, -1, NULL, NULL, NULL);
p = strchr (locale, '-');
lang = pango_language_from_string (locale);
if (g_hash_table_lookup (ht_scripts_langs, lang) == NULL)
g_hash_table_insert (ht_scripts_langs, lang, langname);
/*
* Track 3+-letter ISO639-2/3 language codes as well (these have a max length of 9 including terminating NUL)
* ISO639-2: iso639_lctypes[0] = LOCALE_SISO639LANGNAME
* ISO639-3: iso639_lctypes[1] = LOCALE_SISO639LANGNAME2
*/
for (i = 0; i < 2; i++)
{
locale_abbrev_size = GetLocaleInfoEx (locale_w, iso639_lctypes[i], locale_abbrev_w, 0);
if (locale_abbrev_size > 0)
{
GetLocaleInfoEx (locale_w, iso639_lctypes[i], locale_abbrev_w, locale_abbrev_size);
locale_abbrev = g_utf16_to_utf8 (locale_abbrev_w, -1, NULL, NULL, NULL);
lang = pango_language_from_string (locale_abbrev);
if (g_hash_table_lookup (ht_scripts_langs, lang) == NULL)
g_hash_table_insert (ht_scripts_langs, lang, langname);
g_free (locale_abbrev);
}
}
g_free (locale);
g_free (langname_w);
return TRUE;
}
#else /* non-Windows */
static char *
get_first_item_in_semicolon_list (const char *list)
{
@@ -276,7 +210,6 @@ languages_variant_init (const char *variant)
g_free (filename);
g_free (buf);
}
#endif
static void
languages_init (void)
@@ -285,13 +218,8 @@ languages_init (void)
return;
language_map = g_hash_table_new_full (NULL, NULL, NULL, g_free);
#ifdef G_OS_WIN32
g_return_if_fail (EnumSystemLocalesEx (&get_win32_all_locales_scripts, LOCALE_ALL, (LPARAM) language_map, NULL));
#else
languages_variant_init ("iso_639");
languages_variant_init ("iso_639_3");
#endif
}
const char *
+1 -1
View File
@@ -512,7 +512,7 @@ load_file (const char *demoname,
info_buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (info_buffer, "title",
"font", "Sans 18",
"size", 18 * 1024,
"pixels-below-lines", 10,
NULL);
+1 -1
View File
@@ -21,7 +21,7 @@
<item>
<attribute name="label" translatable="yes">Save _As...</attribute>
<attribute name="action">app.save-as</attribute>
<attribute name="accel">&lt;Control&gt;&lt;Shift&gt;s</attribute>
<attribute name="accel">&lt;Control&gt;s</attribute>
</item>
</section>
<section>
+14 -8
View File
@@ -17,6 +17,7 @@ demos = files([
'css_pixbufs.c',
'css_shadows.c',
'cursors.c',
'curve.c',
'dialog.c',
'drawingarea.c',
'dnd.c',
@@ -34,6 +35,7 @@ demos = files([
'gestures.c',
'glarea.c',
'gltransition.c',
'glyphs.c',
'headerbar.c',
'hypertext.c',
'iconscroll.c',
@@ -70,6 +72,9 @@ demos = files([
'paintable_symbolic.c',
'panes.c',
'password_entry.c',
'path_fill.c',
'path_maze.c',
'path_text.c',
'peg_solitaire.c',
'pickers.c',
'printing.c',
@@ -98,7 +103,6 @@ demos = files([
'transparent.c',
'tree_store.c',
'video_player.c',
'font_features.c',
])
gtkdemo_deps = [ libgtk_dep, ]
@@ -129,9 +133,15 @@ extra_demo_sources = files([
'script-names.c',
'unicode-names.c',
'suggestionentry.c',
'language-names.c',
'curve-editor.c',
])
if harfbuzz_dep.found() and pangoft_dep.found()
demos += files(['font_features.c'])
extra_demo_sources += files(['language-names.c'])
gtkdemo_deps += [ harfbuzz_dep, epoxy_dep ]
endif
if os_unix
demos += files('pagesetup.c')
endif
@@ -170,7 +180,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
depfile : 'gtkdemo.gresource.d',
command : [glib_compile_resources,
'--generate',
'--internal',
'--target=@OUTPUT@',
'--dependency-file=@DEPFILE@',
'--sourcedir=' + meson.current_source_dir(),
@@ -184,7 +193,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
depfile : 'gtkdemo_resources.c.d',
command : [glib_compile_resources,
'--generate-source',
'--internal',
'--target=@OUTPUT@',
'--dependency-file=@DEPFILE@',
'--sourcedir=' + meson.current_source_dir(),
@@ -198,7 +206,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
input : gtkdemo_gresource,
output : 'gtkdemo_resources.o',
command : [ld,
'-z', 'noexecstack',
'-r',
'-b','binary',
'@INPUT@',
@@ -209,7 +216,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
input : gtkdemo_resources_binary,
output : 'gtkdemo_resources2.o',
command : [objcopy,
'--strip-all',
'--add-symbol','_g_binary_gtkdemo_resource_data=.data:0',
'@INPUT@',
'@OUTPUT@'])
@@ -242,7 +248,7 @@ executable('gtk4-demo',
c_args: gtkdemo_args + demo_cflags,
dependencies: gtkdemo_deps,
include_directories: confinc,
win_subsystem: 'windows',
gui_app: true,
link_args: extra_demo_ldflags,
install: true,
)
@@ -252,7 +258,7 @@ executable('gtk4-demo-application',
c_args: gtkdemo_args + common_cflags,
dependencies: gtkdemo_deps,
include_directories: confinc,
win_subsystem: 'windows',
gui_app: true,
link_args: extra_demo_ldflags,
install: true,
)
+348
View File
@@ -0,0 +1,348 @@
/* Path/Text Fill
*
* This demo shows how to use PangoCairo to draw text with more than
* just a single color.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "paintable.h"
#include "gsk/gskpathdashprivate.h"
#define GTK_TYPE_PATH_PAINTABLE (gtk_path_paintable_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathPaintable, gtk_path_paintable, GTK, PATH_PAINTABLE, GObject)
struct _GtkPathPaintable
{
GObject parent_instance;
int width;
int height;
GskPath *path;
GdkPaintable *background;
};
struct _GtkPathPaintableClass
{
GObjectClass parent_class;
};
static int
gtk_path_paintable_get_intrinsic_width (GdkPaintable *paintable)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
if (self->background)
return MAX (gdk_paintable_get_intrinsic_width (self->background), self->width);
else
return self->width;
}
static int
gtk_path_paintable_get_intrinsic_height (GdkPaintable *paintable)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
if (self->background)
return MAX (gdk_paintable_get_intrinsic_height (self->background), self->height);
else
return self->height;
}
static void
gtk_path_paintable_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
#if 0
gtk_snapshot_push_fill (snapshot, self->path, GSK_FILL_RULE_WINDING);
#else
GskStroke *stroke = gsk_stroke_new (2.0);
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
gsk_stroke_free (stroke);
#endif
if (self->background)
{
gdk_paintable_snapshot (self->background, snapshot, width, height);
}
else
{
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, height),
(GskColorStop[8]) {
{ 0.0, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.2, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.3, { 1.0, 1.0, 0.0, 1.0 } },
{ 0.4, { 0.0, 1.0, 0.0, 1.0 } },
{ 0.6, { 0.0, 1.0, 1.0, 1.0 } },
{ 0.7, { 0.0, 0.0, 1.0, 1.0 } },
{ 0.8, { 1.0, 0.0, 1.0, 1.0 } },
{ 1.0, { 1.0, 0.0, 1.0, 1.0 } }
},
8);
}
gtk_snapshot_pop (snapshot);
}
static GdkPaintableFlags
gtk_path_paintable_get_flags (GdkPaintable *paintable)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
if (self->background)
return gdk_paintable_get_flags (self->background);
else
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
}
static void
gtk_path_paintable_paintable_init (GdkPaintableInterface *iface)
{
iface->get_intrinsic_width = gtk_path_paintable_get_intrinsic_width;
iface->get_intrinsic_height = gtk_path_paintable_get_intrinsic_height;
iface->snapshot = gtk_path_paintable_snapshot;
iface->get_flags = gtk_path_paintable_get_flags;
}
/* When defining the GType, we need to implement the GdkPaintable interface */
G_DEFINE_TYPE_WITH_CODE (GtkPathPaintable, gtk_path_paintable, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_path_paintable_paintable_init))
/* Here's the boilerplate for the GObject declaration.
* We don't need to do anything special here, because we keep no
* data of our own.
*/
static void
gtk_path_paintable_class_init (GtkPathPaintableClass *klass)
{
}
static void
gtk_path_paintable_init (GtkPathPaintable *self)
{
}
/* And finally, we add a simple constructor.
* It is declared in the header so that the other examples
* can use it.
*/
GdkPaintable *
gtk_path_paintable_new (GskPath *path,
GdkPaintable *background,
int width,
int height)
{
GtkPathPaintable *self;
self = g_object_new (GTK_TYPE_PATH_PAINTABLE, NULL);
self->path = path;
self->background = background;
if (self->background)
{
g_signal_connect_swapped (self->background, "invalidate-contents", G_CALLBACK (gdk_paintable_invalidate_contents), self);
g_signal_connect_swapped (self->background, "invalidate-size", G_CALLBACK (gdk_paintable_invalidate_size), self);
}
self->width = width;
self->height = height;
return GDK_PAINTABLE (self);
}
void
gtk_path_paintable_set_path (GtkPathPaintable *self,
GskPath *path)
{
g_clear_pointer (&self->path, gsk_path_unref);
self->path = gsk_path_ref (path);
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
}
static GskPath *
create_hexagon (GtkWidget *widget)
{
GskPathBuilder *builder;
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, 120, 0);
gsk_path_builder_line_to (builder, 360, 0);
gsk_path_builder_line_to (builder, 480, 208);
gsk_path_builder_line_to (builder, 360, 416);
gsk_path_builder_line_to (builder, 120, 416);
gsk_path_builder_line_to (builder, 0, 208);
gsk_path_builder_close (builder);
return gsk_path_builder_free_to_path (builder);
}
static GskPath *
create_path_from_text (GtkWidget *widget)
{
PangoLayout *layout;
PangoFontDescription *desc;
GskPathBuilder *builder;
layout = gtk_widget_create_pango_layout (widget, "Pango power!\nPango power!\nPango power!");
desc = pango_font_description_from_string ("sans bold 36");
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
builder = gsk_path_builder_new ();
gsk_path_builder_add_layout (builder, layout);
return gsk_path_builder_free_to_path (builder);
}
static gboolean
build_path (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data)
{
GskPathBuilder *builder = user_data;
switch (op)
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
gsk_path_builder_close (builder);
break;
case GSK_PATH_LINE:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
break;
case GSK_PATH_CURVE:
gsk_path_builder_curve_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
break;
case GSK_PATH_CONIC:
gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, weight);
break;
default:
g_assert_not_reached ();
break;
}
return TRUE;
}
static gboolean
update_path (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer measure)
{
float progress = gdk_frame_clock_get_frame_time (frame_clock) % (60 * G_USEC_PER_SEC) / (float) (30 * G_USEC_PER_SEC);
GskPathBuilder *builder;
GskPath *path;
graphene_point_t pos;
graphene_vec2_t tangent;
GskStroke *stroke;
builder = gsk_path_builder_new ();
gsk_path_builder_add_segment (builder,
measure,
#if 1
0.0, gsk_path_measure_get_length (measure));
#else
progress > 1 ? (progress - 1) * gsk_path_measure_get_length (measure) : 0.0,
(progress < 1 ? progress : 1.0) * gsk_path_measure_get_length (measure));
#endif
path = gsk_path_builder_free_to_path (builder);
stroke = gsk_stroke_new (1);
gsk_stroke_set_dash (stroke, (float[2]) { 10, 5 }, 2);
gsk_stroke_set_dash_offset (stroke, - (gdk_frame_clock_get_frame_time (frame_clock) % G_USEC_PER_SEC) * 15. / G_USEC_PER_SEC);
builder = gsk_path_builder_new ();
gsk_path_dash (path, stroke, 0.2, build_path, builder);
gsk_path_unref (path);
gsk_path_measure_get_point (measure,
(progress > 1 ? (progress - 1) : progress) * gsk_path_measure_get_length (measure),
&pos,
&tangent);
gsk_path_builder_move_to (builder, pos.x + 5 * graphene_vec2_get_x (&tangent), pos.y + 5 * graphene_vec2_get_y (&tangent));
gsk_path_builder_line_to (builder, pos.x + 3 * graphene_vec2_get_y (&tangent), pos.y + 3 * graphene_vec2_get_x (&tangent));
gsk_path_builder_line_to (builder, pos.x - 3 * graphene_vec2_get_y (&tangent), pos.y - 3 * graphene_vec2_get_x (&tangent));
gsk_path_builder_close (builder);
path = gsk_path_builder_free_to_path (builder);
gtk_path_paintable_set_path (GTK_PATH_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget))),
path);
gsk_path_unref (path);
return G_SOURCE_CONTINUE;
}
GtkWidget *
do_path_fill (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *picture;
GdkPaintable *paintable;
GtkMediaStream *stream;
GskPath *path;
graphene_rect_t bounds;
GskPathMeasure *measure;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Path Fill");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
#if 0
stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
#else
stream = gtk_nuclear_media_stream_new ();
#endif
gtk_media_stream_play (stream);
gtk_media_stream_set_loop (stream, TRUE);
path = create_hexagon (window);
path = create_path_from_text (window);
gsk_path_get_bounds (path, &bounds);
paintable = gtk_path_paintable_new (path,
GDK_PAINTABLE (stream),
bounds.origin.x + bounds.size.width,
bounds.origin.y + bounds.size.height);
picture = gtk_picture_new_for_paintable (paintable);
measure = gsk_path_measure_new (path);
gtk_widget_add_tick_callback (picture, update_path, measure, (GDestroyNotify) gsk_path_measure_unref);
gtk_picture_set_keep_aspect_ratio (GTK_PICTURE (picture), FALSE);
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
g_object_unref (paintable);
gtk_window_set_child (GTK_WINDOW (window), picture);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+339
View File
@@ -0,0 +1,339 @@
/* Path/Maze
* #Keywords: game, mouse
*
* This demo shows how to use a GskPath to create a maze and use
* gsk_path_measure_get_closest_point() to check the mouse stays
* on the path.
*
* It also shows off the performance of GskPath (or not) as this
* is a rather complex path.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "paintable.h"
#define MAZE_GRID_SIZE 20
#define MAZE_STROKE_SIZE_ACTIVE (MAZE_GRID_SIZE - 4)
#define MAZE_STROKE_SIZE_INACTIVE (MAZE_GRID_SIZE - 12)
#define MAZE_WIDTH 31
#define MAZE_HEIGHT 21
#define GTK_TYPE_MAZE (gtk_maze_get_type ())
G_DECLARE_FINAL_TYPE (GtkMaze, gtk_maze, GTK, MAZE, GtkWidget)
struct _GtkMaze
{
GtkWidget parent_instance;
int width;
int height;
GskPath *path;
GskPathMeasure *measure;
GdkPaintable *background;
gboolean active;
};
struct _GtkMazeClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (GtkMaze, gtk_maze, GTK_TYPE_WIDGET)
static void
gtk_maze_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkMaze *self = GTK_MAZE (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = self->width;
else
*minimum = *natural = self->height;
}
static void
gtk_maze_snapshot (GtkWidget *widget,
GdkSnapshot *snapshot)
{
GtkMaze *self = GTK_MAZE (widget);
double width = gtk_widget_get_width (widget);
double height = gtk_widget_get_height (widget);
GskStroke *stroke;
stroke = gsk_stroke_new (MAZE_STROKE_SIZE_INACTIVE);
if (self->active)
gsk_stroke_set_line_width (stroke, MAZE_STROKE_SIZE_ACTIVE);
gsk_stroke_set_line_join (stroke, GSK_LINE_JOIN_ROUND);
gsk_stroke_set_line_cap (stroke, GSK_LINE_CAP_ROUND);
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
gsk_stroke_free (stroke);
if (self->background)
{
gdk_paintable_snapshot (self->background, snapshot, width, height);
}
else
{
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, height),
(GskColorStop[8]) {
{ 0.0, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.2, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.3, { 1.0, 1.0, 0.0, 1.0 } },
{ 0.4, { 0.0, 1.0, 0.0, 1.0 } },
{ 0.6, { 0.0, 1.0, 1.0, 1.0 } },
{ 0.7, { 0.0, 0.0, 1.0, 1.0 } },
{ 0.8, { 1.0, 0.0, 1.0, 1.0 } },
{ 1.0, { 1.0, 0.0, 1.0, 1.0 } }
},
8);
}
gtk_snapshot_pop (snapshot);
}
static void
gtk_maze_dispose (GObject *object)
{
GtkMaze *self = GTK_MAZE (object);
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
if (self->background)
{
g_signal_handlers_disconnect_matched (self->background, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
g_clear_object (&self->background);
}
G_OBJECT_CLASS (gtk_maze_parent_class)->dispose (object);
}
static void
gtk_maze_class_init (GtkMazeClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_maze_dispose;
widget_class->measure = gtk_maze_measure;
widget_class->snapshot = gtk_maze_snapshot;
}
static void
pointer_motion (GtkEventControllerMotion *controller,
double x,
double y,
GtkMaze *self)
{
if (!self->active)
return;
if (gsk_path_measure_get_closest_point (self->measure, &GRAPHENE_POINT_INIT (x, y), NULL) <= MAZE_STROKE_SIZE_ACTIVE / 2.0f)
return;
self->active = FALSE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_leave (GtkEventControllerMotion *controller,
GtkMaze *self)
{
if (!self->active)
{
self->active = TRUE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
}
static void
gtk_maze_init (GtkMaze *self)
{
GtkEventController *controller;
controller = GTK_EVENT_CONTROLLER (gtk_event_controller_motion_new ());
g_signal_connect (controller, "motion", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->active = TRUE;
}
static void
gtk_maze_set_path (GtkMaze *self,
GskPath *path)
{
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
self->path = gsk_path_ref (path);
self->measure = gsk_path_measure_new (path);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
GtkWidget *
gtk_maze_new (GskPath *path,
GdkPaintable *background,
int width,
int height)
{
GtkMaze *self;
self = g_object_new (GTK_TYPE_MAZE, NULL);
gtk_maze_set_path (self, path);
gsk_path_unref (path);
self->background = background;
if (self->background)
{
g_signal_connect_swapped (self->background, "invalidate-contents", G_CALLBACK (gtk_widget_queue_draw), self);
g_signal_connect_swapped (self->background, "invalidate-size", G_CALLBACK (gtk_widget_queue_resize), self);
}
self->width = width;
self->height = height;
return GTK_WIDGET (self);
}
static void
add_point_to_maze (GtkBitset *maze,
GskPathBuilder *builder,
guint x,
guint y)
{
gboolean set[4] = { };
guint dir;
gtk_bitset_add (maze, y * MAZE_WIDTH + x);
while (TRUE)
{
set[0] = set[0] || x == 0 || gtk_bitset_contains (maze, y * MAZE_WIDTH + x - 1);
set[1] = set[1] || y == 0 || gtk_bitset_contains (maze, (y - 1) * MAZE_WIDTH + x);
set[2] = set[2] || x + 1 == MAZE_WIDTH || gtk_bitset_contains (maze, y * MAZE_WIDTH + x + 1);
set[3] = set[3] || y + 1 == MAZE_HEIGHT || gtk_bitset_contains (maze, (y + 1) * MAZE_WIDTH + x);
if (set[0] && set[1] && set[2] && set[3])
return;
do
{
dir = g_random_int_range (0, 4);
}
while (set[dir]);
switch (dir)
{
case 0:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x - 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x - 1, y);
break;
case 1:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y - 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x, y - 1);
break;
case 2:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 1.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x + 1, y);
break;
case 3:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 1.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x, y + 1);
break;
default:
g_assert_not_reached ();
break;
}
}
}
static GskPath *
create_path_for_maze (GtkWidget *widget)
{
GskPathBuilder *builder;
GtkBitset *maze;
builder = gsk_path_builder_new ();
maze = gtk_bitset_new_empty ();
/* make sure the outer lines are unreachable:
* Set the full range, then remove the center again. */
gtk_bitset_add_range (maze, 0, MAZE_WIDTH * MAZE_HEIGHT);
gtk_bitset_remove_rectangle (maze, MAZE_WIDTH + 1, MAZE_WIDTH - 2, MAZE_HEIGHT - 2, MAZE_WIDTH);
/* Fill the maze */
add_point_to_maze (maze, builder, MAZE_WIDTH / 2, MAZE_HEIGHT / 2);
/* Add start and stop lines */
gsk_path_builder_move_to (builder, 1.5 * MAZE_GRID_SIZE, -0.5 * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, 1.5 * MAZE_GRID_SIZE, 1.5 * MAZE_GRID_SIZE);
gsk_path_builder_move_to (builder, (MAZE_WIDTH - 1.5) * MAZE_GRID_SIZE, (MAZE_HEIGHT - 1.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (MAZE_WIDTH - 1.5) * MAZE_GRID_SIZE, (MAZE_HEIGHT + 0.5) * MAZE_GRID_SIZE);
gtk_bitset_unref (maze);
return gsk_path_builder_free_to_path (builder);
}
GtkWidget *
do_path_maze (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *maze;
GtkMediaStream *stream;
GskPath *path;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Follow the maze with the mouse");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
#if 0
stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
#else
stream = gtk_nuclear_media_stream_new ();
#endif
gtk_media_stream_play (stream);
gtk_media_stream_set_loop (stream, TRUE);
path = create_path_for_maze (window);
maze = gtk_maze_new (path,
GDK_PAINTABLE (stream),
MAZE_WIDTH * MAZE_GRID_SIZE,
MAZE_HEIGHT * MAZE_GRID_SIZE);
gtk_window_set_child (GTK_WINDOW (window), maze);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+594
View File
@@ -0,0 +1,594 @@
/* Path/Curved Text
*
* This demo shows how to use GskPath to animate a path along another path.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define GTK_TYPE_PATH_WIDGET (gtk_path_widget_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathWidget, gtk_path_widget, GTK, PATH_WIDGET, GtkWidget)
#define POINT_SIZE 8
enum {
PROP_0,
PROP_TEXT,
PROP_EDITABLE,
N_PROPS
};
struct _GtkPathWidget
{
GtkWidget parent_instance;
char *text;
gboolean editable;
graphene_point_t points[4];
guint active_point;
float line_closest;
GskPath *line_path;
GskPathMeasure *line_measure;
GskPath *text_path;
GdkPaintable *background;
};
struct _GtkPathWidgetClass
{
GtkWidgetClass parent_class;
};
static GParamSpec *properties[N_PROPS] = { NULL, };
G_DEFINE_TYPE (GtkPathWidget, gtk_path_widget, GTK_TYPE_WIDGET)
static GskPath *
create_path_from_text (GtkWidget *widget,
const char *text)
{
cairo_surface_t *surface;
cairo_t *cr;
cairo_path_t *path;
PangoLayout *layout;
PangoFontDescription *desc;
GskPath *result;
surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
cr = cairo_create (surface);
layout = gtk_widget_create_pango_layout (widget, text);
desc = pango_font_description_from_string ("sans bold 36");
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
cairo_move_to (cr, 0, - pango_layout_get_baseline (layout) / (double) PANGO_SCALE);
pango_cairo_layout_path (cr, layout);
path = cairo_copy_path_flat (cr);
result = gsk_path_new_from_cairo (path);
cairo_path_destroy (path);
g_object_unref (layout);
cairo_destroy (cr);
cairo_surface_destroy (surface);
return result;
}
typedef struct
{
GskPathMeasure *measure;
GskPathBuilder *builder;
double scale;
} GtkPathTransform;
static void
gtk_path_transform_point (GskPathMeasure *measure,
const graphene_point_t *pt,
float scale,
graphene_point_t *res)
{
graphene_vec2_t tangent;
gsk_path_measure_get_point (measure, pt->x * scale, res, &tangent);
res->x -= pt->y * scale * graphene_vec2_get_y (&tangent);
res->y += pt->y * scale * graphene_vec2_get_x (&tangent);
}
static gboolean
gtk_path_transform_op (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
GtkPathTransform *transform = data;
switch (op)
{
case GSK_PATH_MOVE:
{
graphene_point_t res;
gtk_path_transform_point (transform->measure, &pts[0], transform->scale, &res);
gsk_path_builder_move_to (transform->builder, res.x, res.y);
}
break;
case GSK_PATH_LINE:
{
graphene_point_t res;
gtk_path_transform_point (transform->measure, &pts[1], transform->scale, &res);
gsk_path_builder_line_to (transform->builder, res.x, res.y);
}
break;
case GSK_PATH_CURVE:
{
graphene_point_t res[3];
gtk_path_transform_point (transform->measure, &pts[1], transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, &pts[2], transform->scale, &res[1]);
gtk_path_transform_point (transform->measure, &pts[3], transform->scale, &res[2]);
gsk_path_builder_curve_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, res[2].x, res[2].y);
}
break;
case GSK_PATH_CONIC:
{
graphene_point_t res[2];
gtk_path_transform_point (transform->measure, &pts[1], transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, &pts[2], transform->scale, &res[1]);
gsk_path_builder_conic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, weight);
}
break;
case GSK_PATH_CLOSE:
gsk_path_builder_close (transform->builder);
break;
default:
g_assert_not_reached();
return FALSE;
}
return TRUE;
}
static GskPath *
gtk_path_transform (GskPathMeasure *measure,
GskPath *path)
{
GtkPathTransform transform = { measure, gsk_path_builder_new () };
graphene_rect_t bounds;
gsk_path_get_bounds (path, &bounds);
if (bounds.origin.x + bounds.size.width > 0)
transform.scale = gsk_path_measure_get_length (measure) / (bounds.origin.x + bounds.size.width);
else
transform.scale = 1.0f;
gsk_path_foreach (path, GSK_PATH_FOREACH_ALLOW_CURVE, gtk_path_transform_op, &transform);
return gsk_path_builder_free_to_path (transform.builder);
}
static void
gtk_path_widget_clear_text_path (GtkPathWidget *self)
{
g_clear_pointer (&self->text_path, gsk_path_unref);
}
static void
gtk_path_widget_clear_paths (GtkPathWidget *self)
{
gtk_path_widget_clear_text_path (self);
g_clear_pointer (&self->line_path, gsk_path_unref);
g_clear_pointer (&self->line_measure, gsk_path_measure_unref);
}
static void
gtk_path_widget_create_text_path (GtkPathWidget *self)
{
GskPath *path;
gtk_path_widget_clear_text_path (self);
if (self->line_measure == NULL)
return;
path = create_path_from_text (GTK_WIDGET (self), self->text);
self->text_path = gtk_path_transform (self->line_measure, path);
gsk_path_unref (path);
}
static void
gtk_path_widget_create_paths (GtkPathWidget *self)
{
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
GskPathBuilder *builder;
gtk_path_widget_clear_paths (self);
if (width <= 0 || height <= 0)
return;
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder,
self->points[0].x * width, self->points[0].y * height);
gsk_path_builder_curve_to (builder,
self->points[1].x * width, self->points[1].y * height,
self->points[2].x * width, self->points[2].y * height,
self->points[3].x * width, self->points[3].y * height);
self->line_path = gsk_path_builder_free_to_path (builder);
self->line_measure = gsk_path_measure_new (self->line_path);
gtk_path_widget_create_text_path (self);
}
static void
gtk_path_widget_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkPathWidget *self = GTK_PATH_WIDGET (widget);
GTK_WIDGET_CLASS (gtk_path_widget_parent_class)->size_allocate (widget, width, height, baseline);
gtk_path_widget_create_paths (self);
}
static void
gtk_path_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkPathWidget *self = GTK_PATH_WIDGET (widget);
double width = gtk_widget_get_width (widget);
double height = gtk_widget_get_height (widget);
GskPath *path;
GskStroke *stroke;
gsize i;
/* frosted glass the background */
gtk_snapshot_push_blur (snapshot, 100);
gdk_paintable_snapshot (self->background, snapshot, width, height);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 1, 1, 0.5 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
/* draw the text */
if (self->text_path)
{
gtk_snapshot_push_fill (snapshot, self->text_path, GSK_FILL_RULE_WINDING);
gdk_paintable_snapshot (self->background, snapshot, width, height);
/* ... with an emboss effect */
stroke = gsk_stroke_new (2.0);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT(1, 1));
gtk_snapshot_push_stroke (snapshot, self->text_path, stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 0.2 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gsk_stroke_free (stroke);
gtk_snapshot_pop (snapshot);
gtk_snapshot_pop (snapshot);
}
if (self->editable && self->line_path)
{
/* draw the control line */
stroke = gsk_stroke_new (1.0);
gtk_snapshot_push_stroke (snapshot, self->line_path, stroke);
gsk_stroke_free (stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
}
if (self->line_closest >= 0)
{
GskPathBuilder *builder;
graphene_point_t closest;
builder = gsk_path_builder_new ();
gsk_path_measure_get_point (self->line_measure, self->line_closest, &closest, NULL);
gsk_path_builder_add_circle (builder, &closest, POINT_SIZE);
path = gsk_path_builder_free_to_path (builder);
gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
gsk_path_unref (path);
}
if (self->editable && self->line_path)
{
GskPathBuilder *builder;
/* draw the points */
builder = gsk_path_builder_new ();
for (i = 0; i < 4; i++)
{
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (self->points[i].x * width, self->points[i].y * height), POINT_SIZE);
}
path = gsk_path_builder_free_to_path (builder);
gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 1, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
stroke = gsk_stroke_new (1.0);
gtk_snapshot_push_stroke (snapshot, path, stroke);
gsk_stroke_free (stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
gsk_path_unref (path);
}
}
static void
gtk_path_widget_set_text (GtkPathWidget *self,
const char *text)
{
if (g_strcmp0 (self->text, text) == 0)
return;
g_free (self->text);
self->text = g_strdup (text);
gtk_path_widget_create_paths (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT]);
}
static void
gtk_path_widget_set_editable (GtkPathWidget *self,
gboolean editable)
{
if (self->editable == editable)
return;
self->editable = editable;
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EDITABLE]);
}
static void
gtk_path_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
switch (prop_id)
{
case PROP_TEXT:
gtk_path_widget_set_text (self, g_value_get_string (value));
break;
case PROP_EDITABLE:
gtk_path_widget_set_editable (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
switch (prop_id)
{
case PROP_TEXT:
g_value_set_string (value, self->text);
break;
case PROP_EDITABLE:
g_value_set_boolean (value, self->editable);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_widget_dispose (GObject *object)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
gtk_path_widget_clear_paths (self);
G_OBJECT_CLASS (gtk_path_widget_parent_class)->dispose (object);
}
static void
gtk_path_widget_class_init (GtkPathWidgetClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_path_widget_dispose;
object_class->set_property = gtk_path_widget_set_property;
object_class->get_property = gtk_path_widget_get_property;
widget_class->size_allocate = gtk_path_widget_allocate;
widget_class->snapshot = gtk_path_widget_snapshot;
properties[PROP_TEXT] =
g_param_spec_string ("text",
"text",
"Text transformed along a path",
NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_EDITABLE] =
g_param_spec_boolean ("editable",
"editable",
"If the path can be edited by the user",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
drag_begin (GtkGestureDrag *gesture,
double x,
double y,
GtkPathWidget *self)
{
graphene_point_t mouse = GRAPHENE_POINT_INIT (x, y);
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
gsize i;
for (i = 0; i < 4; i++)
{
if (graphene_point_distance (&GRAPHENE_POINT_INIT (self->points[i].x * width, self->points[i].y * height), &mouse, NULL, NULL) <= POINT_SIZE)
{
self->active_point = i;
break;
}
}
if (i == 4)
{
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
return;
}
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
drag_update (GtkGestureDrag *drag,
double offset_x,
double offset_y,
GtkPathWidget *self)
{
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
double start_x, start_y;
gtk_gesture_drag_get_start_point (drag, &start_x, &start_y);
self->points[self->active_point] = GRAPHENE_POINT_INIT ((start_x + offset_x) / width,
(start_y + offset_y) / height);
self->points[self->active_point].x = CLAMP (self->points[self->active_point].x, 0, 1);
self->points[self->active_point].y = CLAMP (self->points[self->active_point].y, 0, 1);
gtk_path_widget_create_paths (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_motion (GtkEventControllerMotion *controller,
double x,
double y,
GtkPathWidget *self)
{
gsk_path_measure_get_closest_point_full (self->line_measure,
&GRAPHENE_POINT_INIT (x, y),
INFINITY,
NULL, NULL,
&self->line_closest,
NULL);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_leave (GtkEventControllerMotion *controller,
GtkPathWidget *self)
{
self->line_closest = -1;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
gtk_path_widget_init (GtkPathWidget *self)
{
GtkEventController *controller;
controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_update), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
controller = GTK_EVENT_CONTROLLER (gtk_event_controller_motion_new ());
g_signal_connect (controller, "enter", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "motion", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->line_closest = -1;
self->points[0] = GRAPHENE_POINT_INIT (0.1, 0.9);
self->points[1] = GRAPHENE_POINT_INIT (0.3, 0.1);
self->points[2] = GRAPHENE_POINT_INIT (0.7, 0.1);
self->points[3] = GRAPHENE_POINT_INIT (0.9, 0.9);
self->background = GDK_PAINTABLE (gdk_texture_new_from_resource ("/sliding_puzzle/portland-rose.jpg"));
gtk_path_widget_set_text (self, "It's almost working");
}
GtkWidget *
gtk_path_widget_new (void)
{
GtkPathWidget *self;
self = g_object_new (GTK_TYPE_PATH_WIDGET, NULL);
return GTK_WIDGET (self);
}
GtkWidget *
do_path_text (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkBuilder *builder;
g_type_ensure (GTK_TYPE_PATH_WIDGET);
builder = gtk_builder_new_from_resource ("/path_text/path_text.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">Text along a Path</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<child type="end">
<object class="GtkToggleButton" id="edit-toggle">
<property name="icon-name">document-edit-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkRevealer">
<property name="reveal-child" bind-source="edit-toggle" bind-property="active" bind-flags="sync-create"></property>
<child>
<object class="GtkEntry" id="text">
<property name="text">Through the looking glass</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPathWidget" id="view">
<property name="editable" bind-source="edit-toggle" bind-property="active" bind-flags="sync-create"></property>
<property name="text" bind-source="text" bind-property="text" bind-flags="sync-create"></property>
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</child>
</object>
</interface>
+1 -1
View File
@@ -16,7 +16,7 @@ executable('gtk4-icon-browser',
c_args: common_cflags,
dependencies: [ libgtk_dep, demo_conf_h ],
include_directories: confinc,
win_subsystem: 'windows',
gui_app: true,
link_args: extra_demo_ldflags,
install: true,
)
+1 -1
View File
@@ -3,7 +3,7 @@ demo_profile = get_option('profile')
demo_conf_h = declare_dependency(
sources: custom_target('demo-header',
command: [gen_demo_header, meson.project_source_root(), demo_profile],
command: [gen_demo_header, meson.source_root(), demo_profile],
capture: true,
output: 'demo_conf.h',
build_by_default: true,
+1 -1
View File
@@ -17,7 +17,7 @@ executable('gtk4-node-editor',
c_args: [
'-DNODE_EDITOR_SOURCE_DIR="@0@/../../testsuite/gsk/compare/"'.format(meson.current_source_dir())
] + common_cflags,
win_subsystem: 'windows',
gui_app: true,
link_args: extra_demo_ldflags,
install: false,
)
+1 -1
View File
@@ -3,7 +3,7 @@ executable('gtk4-print-editor',
c_args: common_cflags,
dependencies: [ libgtk_dep, demo_conf_h ],
include_directories: confinc,
win_subsystem: 'windows',
gui_app: true,
link_args: extra_demo_ldflags,
install: true,
)
+1 -5
View File
@@ -18,7 +18,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
depfile: 'widgetfactory.gresource.d',
command : [glib_compile_resources,
'--generate',
'--internal',
'--target=@OUTPUT@',
'--dependency-file=@DEPFILE@',
'--sourcedir=' + meson.current_source_dir(),
@@ -32,7 +31,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
depfile: 'widgetfactory_resources.c.d',
command : [glib_compile_resources,
'--generate-source',
'--internal',
'--target=@OUTPUT@',
'--dependency-file=@DEPFILE@',
'--sourcedir=' + meson.current_source_dir(),
@@ -46,7 +44,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
input : widgetfactory_gresource,
output : 'widgetfactory_resources.o',
command : [ld,
'-z', 'noexecstack',
'-r',
'-b','binary',
'@INPUT@',
@@ -57,7 +54,6 @@ if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_ad
input : widgetfactory_resources_binary,
output : 'widgetfactory_resources2.o',
command : [objcopy,
'--strip-all',
'--add-symbol','_g_binary_widgetfactory_resource_data=.data:0',
'@INPUT@',
'@OUTPUT@'])
@@ -78,7 +74,7 @@ executable('gtk4-widget-factory',
c_args: common_cflags,
dependencies: [ libgtk_dep, demo_conf_h ],
include_directories: confinc,
win_subsystem: 'windows',
gui_app: true,
link_args: extra_demo_ldflags,
install: true,
)
-6
View File
@@ -1927,12 +1927,6 @@ microphone-sensitivity-medium-symbolic</property>
<property name="tooltip-text" translatable="1">Insert something</property>
</object>
</child>
<child>
<object class="GtkColorButton">
<property name="rgba">#9141AC</property>
<property name="tooltip-text" translatable="1">Select a color</property>
</object>
</child>
</object>
</child>
<child>
+1 -1
View File
@@ -20,7 +20,7 @@ name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/master/"
[extra]
content_images = [
+1 -1
View File
@@ -20,7 +20,7 @@ name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/master/"
[extra]
content_images = [
+1 -1
View File
@@ -43,7 +43,7 @@ show_index_summary = true
show_class_hierarchy = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/master/"
[extra]
content_files = [
+1 -1
View File
@@ -38,7 +38,7 @@ show_index_summary = true
show_class_hierarchy = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/master/"
[extra]
content_images = [
+12 -12
View File
@@ -170,7 +170,7 @@ activate (GtkApplication *app,
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
gtk_window_set_child (GTK_WINDOW (window), box);
button = gtk_button_new_with_label ("Hello World");
@@ -752,7 +752,7 @@ templates, resources, application menus, settings, [class@Gtk.HeaderBar], [class
The full, buildable sources for these examples can be found in the
`examples` directory of the GTK source distribution, or
[online](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples) in the GTK
[online](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples) in the GTK
source code repository. You can build each example separately by using make
with the `Makefile.example` file. For more information, see the `README`
included in the examples directory.
@@ -972,7 +972,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application2/exampleappwin.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application2/exampleappwin.c))
You may have noticed that we used the `_from_resource()` variant of the function
that sets a template. Now we need to use
@@ -1043,7 +1043,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application3/exampleappwin.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application3/exampleappwin.c))
Now we revisit the `example_app_window_open()` function that is called for each
commandline argument, and construct a GtkTextView that we then add as a page
@@ -1087,7 +1087,7 @@ example_app_window_open (ExampleAppWindow *win,
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application3/exampleappwin.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application3/exampleappwin.c))
Lastly, we add a [class@Gtk.StackSwitcher] to the titlebar area in the UI file, and we
tell it to display information about our stack.
@@ -1188,7 +1188,7 @@ example_app_class_init (ExampleAppClass *class)
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application4/exampleapp.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application4/exampleapp.c))
Our preferences menu item does not do anything yet, but the Quit menu item
is fully functional. Note that it can also be activated by the usual Ctrl-Q
@@ -1258,7 +1258,7 @@ example_app_window_init (ExampleAppWindow *win)
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application5/exampleappwin.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application5/exampleappwin.c))
The code to connect the font setting is a little more involved, since there
is no simple object property that it corresponds to, so we are not going to
@@ -1429,7 +1429,7 @@ preferences_activated (GSimpleAction *action,
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application6/exampleapp.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application6/exampleapp.c))
After all this work, our application can now show a preference dialog
like this:
@@ -1549,7 +1549,7 @@ example_app_window_init (ExampleAppWindow *win)
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application7/exampleappwin.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application7/exampleappwin.c))
With the search bar, our application now looks like this:
@@ -1682,7 +1682,7 @@ example_app_window_init (ExampleAppWindow *win)
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application8/exampleappwin.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application8/exampleappwin.c))
What our application looks like now:
@@ -1760,10 +1760,10 @@ example_app_window_init (ExampleAppWindow *win)
...
```
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application9/exampleappwin.c))
([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application9/exampleappwin.c))
We also need a function that counts the lines of the currently active tab,
and updates the `lines` label. See the [full source](https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application9/exampleappwin.c)
and updates the `lines` label. See the [full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application9/exampleappwin.c)
if you are interested in the details.
This brings our example application to this appearance:
+1 -1
View File
@@ -43,7 +43,7 @@ show_index_summary = true
show_class_hierarchy = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/master/"
[extra]
# The same order will be used when generating the index
+1 -1
View File
@@ -42,7 +42,7 @@ univocally identifies events that are related to the same
interaction.
When GTK creates a `GdkSurface`, it connects to the ::event
signal on it, which receives all of these input events. Surfaces
signal on it, which receives all of these input events. Surfaces have
have signals and properties, e.g. to deal with window management
related events.
+1 -10
View File
@@ -1276,15 +1276,6 @@ is provided in the form of a `GtkIconPaintable` (this can be checked with
[method@Gtk.IconPaintable.is_symbolic]), you have to call
[method@Gtk.IconPaintable.get_icon_name] and set the icon name on a `GtkImage`.
### Adapt to GtkImage changes
`GtkPicture`'s behaviour was "split out" of `GtkImage` as the latter was covering
too many use cases; if you're loading an icon, [class@Gtk.Image] in GTK3 and GTK4 are
perfectly equivalent. If you are loading a more complex image asset, like a picture
or a thumbnail, then [class@Gtk.Picture] is the appropriate widget.
One noteworthy distinction is that while `GtkImage` has its size computed by
GTK, `GtkPicture` lets you decide about the size.
### Update to GtkFileChooser API changes
`GtkFileChooser` moved to a GFile-based API. If you need to convert a path
@@ -1382,5 +1373,5 @@ a new family of widgets for this purpose that uses list models instead
of tree models, and widgets instead of cell renderers.
To learn more about the new list widgets, you can read the [List Widget
Overview](https://docs.gtk.org/gtk4/section-list-widget.html).
Overview](#ListWidget).
+1 -1
View File
@@ -26,7 +26,7 @@ GTK with your code applied, and run the test suite, on multiple platforms
and architectures, and verify that nothing breaks. They also allow us to
do proper code reviews, so we can iterate over the changes.
You should follow the [contribution guide](https://gitlab.gnome.org/GNOME/gtk/blob/main/CONTRIBUTING.md)
You should follow the [contribution guide](https://gitlab.gnome.org/GNOME/gtk/blob/master/CONTRIBUTING.md)
for GTK, available on GitLab.
If you want to discuss your approach before or after working on it,
+4 -1
View File
@@ -286,7 +286,7 @@ requires that GTK is compiled with support for that backend.
The following backends can be selected, provided they are
included in the GDK libraries you are using:
`macos`
`quartz`
: Selects the native Quartz backend
`win32`
@@ -336,6 +336,9 @@ using and the GDK backend supports them:
`gl`
: Selects the "gl" OpenGL renderer
`ngl`
: Selects the "ngl" OpenGL renderer
`vulkan`
: Selects the Vulkan renderer
+3 -5
View File
@@ -31,7 +31,8 @@
* `GdkAppLaunchContext` handles launching an application in a graphical context.
*
* It is an implementation of `GAppLaunchContext` that provides startup
* notification and allows to launch applications on a specific workspace.
* notification and allows to launch applications on a specific screen
* or workspace.
*
* ## Launching an application
*
@@ -40,6 +41,7 @@
*
* context = gdk_display_get_app_launch_context (display);
*
* gdk_app_launch_context_set_display (display);
* gdk_app_launch_context_set_timestamp (gdk_event_get_time (event));
*
* if (!g_app_info_launch_default_for_uri ("http://www.gtk.org", context, &error))
@@ -194,10 +196,6 @@ gdk_app_launch_context_get_display (GdkAppLaunchContext *context)
* This only works when running under a window manager that
* supports multiple workspaces, as described in the
* [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec).
* Specifically this sets the `_NET_WM_DESKTOP` property described
* in that spec.
*
* This only works when using the X11 backend.
*
* When the workspace is not specified or @desktop is set to -1,
* it is up to the window manager to pick one, typically it will
+21 -2
View File
@@ -49,7 +49,7 @@
typedef struct _Deserializer Deserializer;
struct _Deserializer
struct _Deserializer
{
const char * mime_type; /* interned */
GType type;
@@ -264,7 +264,7 @@ gdk_content_deserializer_get_priority (GdkContentDeserializer *deserializer)
*
* This is the `GCancellable` that was passed to [func@Gdk.content_deserialize_async].
*
* Returns: (transfer none) (nullable): the cancellable for the current operation
* Returns: (transfer none): the cancellable for the current operation
*/
GCancellable *
gdk_content_deserializer_get_cancellable (GdkContentDeserializer *deserializer)
@@ -934,6 +934,25 @@ init (void)
formats = gdk_pixbuf_get_formats ();
/* Make sure png comes first */
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
char *name;
name = gdk_pixbuf_format_get_name (fmt);
if (g_str_equal (name, "png"))
{
formats = g_slist_delete_link (formats, f);
formats = g_slist_prepend (formats, fmt);
g_free (name);
break;
}
g_free (name);
}
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
+12 -26
View File
@@ -718,33 +718,19 @@ gdk_content_formats_builder_to_formats (GdkContentFormatsBuilder *builder)
g_return_val_if_fail (builder != NULL, NULL);
if (builder->n_gtypes > 0)
{
gtypes = g_new (GType, builder->n_gtypes + 1);
i = builder->n_gtypes;
gtypes[i--] = G_TYPE_INVALID;
/* add backwards because most important type is last in the list */
for (l = builder->gtypes; l; l = l->next)
gtypes[i--] = GPOINTER_TO_SIZE (l->data);
}
else
{
gtypes = NULL;
}
gtypes = g_new (GType, builder->n_gtypes + 1);
i = builder->n_gtypes;
gtypes[i--] = G_TYPE_INVALID;
/* add backwards because most important type is last in the list */
for (l = builder->gtypes; l; l = l->next)
gtypes[i--] = GPOINTER_TO_SIZE (l->data);
if (builder->n_mime_types > 0)
{
mime_types = g_new (const char *, builder->n_mime_types + 1);
i = builder->n_mime_types;
mime_types[i--] = NULL;
/* add backwards because most important type is last in the list */
for (l = builder->mime_types; l; l = l->next)
mime_types[i--] = l->data;
}
else
{
mime_types = NULL;
}
mime_types = g_new (const char *, builder->n_mime_types + 1);
i = builder->n_mime_types;
mime_types[i--] = NULL;
/* add backwards because most important type is last in the list */
for (l = builder->mime_types; l; l = l->next)
mime_types[i--] = l->data;
result = gdk_content_formats_new_take (gtypes, builder->n_gtypes,
mime_types, builder->n_mime_types);
+1 -1
View File
@@ -342,7 +342,7 @@ gdk_content_provider_write_mime_type_finish (GdkContentProvider *provider,
/**
* gdk_content_provider_get_value:
* @provider: a `GdkContentProvider`
* @value: (out caller-allocates): the `GValue` to fill
* @value: the `GValue` to fill
* @error: a `GError` location to store the error occurring
*
* Gets the contents of @provider stored in @value.
+26 -7
View File
@@ -54,7 +54,7 @@
typedef struct _Serializer Serializer;
struct _Serializer
struct _Serializer
{
const char * mime_type; /* interned */
GType type;
@@ -270,7 +270,7 @@ gdk_content_serializer_get_priority (GdkContentSerializer *serializer)
*
* This is the `GCancellable` that was passed to [func@content_serialize_async].
*
* Returns: (transfer none) (nullable): the cancellable for the current operation
* Returns: (transfer none): the cancellable for the current operation
*/
GCancellable *
gdk_content_serializer_get_cancellable (GdkContentSerializer *serializer)
@@ -446,7 +446,7 @@ lookup_serializer (const char *mime_type,
serializer->type == type)
return serializer;
}
return NULL;
}
@@ -630,7 +630,7 @@ pixbuf_serializer (GdkContentSerializer *serializer)
const GValue *value;
GdkPixbuf *pixbuf;
const char *name;
name = gdk_content_serializer_get_user_data (serializer);
value = gdk_content_serializer_get_value (serializer);
@@ -651,7 +651,7 @@ pixbuf_serializer (GdkContentSerializer *serializer)
gdk_pixbuf_save_to_stream_async (pixbuf,
gdk_content_serializer_get_output_stream (serializer),
name,
gdk_content_serializer_get_cancellable (serializer),
gdk_content_serializer_get_cancellable (serializer),
pixbuf_serializer_finish,
serializer,
g_str_equal (name, "png") ? "compression" : NULL, "2",
@@ -823,7 +823,7 @@ file_uri_serializer (GdkContentSerializer *serializer)
else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
{
GSList *l;
for (l = g_value_get_boxed (value); l; l = l->next)
{
uri = g_file_get_uri (l->data);
@@ -867,7 +867,7 @@ file_text_serializer (GdkContentSerializer *serializer)
{
GString *str;
GSList *l;
str = g_string_new (NULL);
for (l = g_value_get_boxed (value); l; l = l->next)
@@ -966,6 +966,25 @@ init (void)
formats = gdk_pixbuf_get_formats ();
/* Make sure png comes first */
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
char *name;
name = gdk_pixbuf_format_get_name (fmt);
if (g_str_equal (name, "png"))
{
formats = g_slist_delete_link (formats, f);
formats = g_slist_prepend (formats, fmt);
g_free (name);
break;
}
g_free (name);
}
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
+2 -1
View File
@@ -47,7 +47,8 @@
* Cursors by themselves are not very interesting: they must be bound to a
* window for users to see them. This is done with [method@Gdk.Surface.set_cursor]
* or [method@Gdk.Surface.set_device_cursor]. Applications will typically
* use higher-level GTK functions such as [method@Gtk.Widget.set_cursor] instead.
* use higher-level GTK functions such as [method@Gtk.Widget.set_cursor]`
* instead.
*
* Cursors are not bound to a given [class@Gdk.Display], so they can be shared.
* However, the appearance of cursors may vary when used on different
+1 -1
View File
@@ -1238,7 +1238,7 @@ gdk_device_get_num_touches (GdkDevice *device)
*
* Retrieves the current tool for @device.
*
* Returns: (transfer none) (nullable): the `GdkDeviceTool`
* Returns: (transfer none): the `GdkDeviceTool`
*/
GdkDeviceTool *
gdk_device_get_device_tool (GdkDevice *device)
-2
View File
@@ -1727,8 +1727,6 @@ gdk_display_init_egl (GdkDisplay *self,
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_no_config_context");
self->have_egl_pixel_format_float =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
self->have_egl_win32_libangle =
epoxy_has_egl_extension (priv->egl_display, "EGL_ANGLE_d3d_share_handle_client_buffer");
if (self->have_egl_no_config_context)
priv->egl_config_high_depth = gdk_display_create_egl_config (self,
-1
View File
@@ -110,7 +110,6 @@ struct _GdkDisplay
guint have_egl_swap_buffers_with_damage : 1;
guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
guint have_egl_win32_libangle : 1;
};
struct _GdkDisplayClass
+81 -162
View File
@@ -19,7 +19,7 @@
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
@@ -522,9 +522,7 @@ _gdk_event_queue_find_first (GdkDisplay *display)
if (pending_motion)
return pending_motion;
if ((event->event_type == GDK_MOTION_NOTIFY ||
(event->event_type == GDK_SCROLL && gdk_scroll_event_get_direction (event) == GDK_SCROLL_SMOOTH)) &&
(event->flags & GDK_EVENT_FLUSHED) == 0)
if (event->event_type == GDK_MOTION_NOTIFY && (event->flags & GDK_EVENT_FLUSHED) == 0)
pending_motion = tmp_list;
else
return tmp_list;
@@ -598,9 +596,6 @@ _gdk_event_unqueue (GdkDisplay *display)
/*
* If the last N events in the event queue are smooth scroll events
* for the same surface and device, combine them into one.
*
* We give the remaining event a history with N items, and deltas
* that are the sum over the history entries.
*/
void
gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
@@ -610,6 +605,7 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
GdkDevice *device = NULL;
GdkEvent *last_event = NULL;
GList *scrolls = NULL;
double delta_x, delta_y;
GArray *history = NULL;
GdkTimeCoord hist;
@@ -644,42 +640,35 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
l = l->prev;
}
delta_x = delta_y = 0;
while (scrolls && scrolls->next != NULL)
{
GdkEvent *event = scrolls->data;
GList *next = scrolls->next;
double dx, dy;
gboolean inherited = FALSE;
if (!history && ((GdkScrollEvent *)event)->history)
{
history = ((GdkScrollEvent *)event)->history;
((GdkScrollEvent *)event)->history = NULL;
inherited = TRUE;
}
if (!history)
history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
if (!inherited)
{
gdk_scroll_event_get_deltas (event, &dx, &dy);
gdk_scroll_event_get_deltas (event, &dx, &dy);
delta_x += dx;
delta_y += dy;
memset (&hist, 0, sizeof (GdkTimeCoord));
hist.time = gdk_event_get_time (event);
hist.flags = GDK_AXIS_FLAG_DELTA_X | GDK_AXIS_FLAG_DELTA_Y;
hist.axes[GDK_AXIS_DELTA_X] = dx;
hist.axes[GDK_AXIS_DELTA_Y] = dy;
memset (&hist, 0, sizeof (GdkTimeCoord));
hist.time = gdk_event_get_time (event);
hist.flags = GDK_AXIS_FLAG_DELTA_X | GDK_AXIS_FLAG_DELTA_Y;
hist.axes[GDK_AXIS_DELTA_X] = dx;
hist.axes[GDK_AXIS_DELTA_Y] = dy;
g_array_append_val (history, hist);
}
g_array_append_val (history, hist);
gdk_event_unref (event);
g_queue_delete_link (&display->queued_events, scrolls);
scrolls = next;
}
if (scrolls && history)
if (scrolls)
{
GdkEvent *old_event, *event;
double dx, dy;
@@ -687,29 +676,13 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
old_event = scrolls->data;
gdk_scroll_event_get_deltas (old_event, &dx, &dy);
memset (&hist, 0, sizeof (GdkTimeCoord));
hist.time = gdk_event_get_time (old_event);
hist.flags = GDK_AXIS_FLAG_DELTA_X | GDK_AXIS_FLAG_DELTA_Y;
hist.axes[GDK_AXIS_DELTA_X] = dx;
hist.axes[GDK_AXIS_DELTA_Y] = dy;
g_array_append_val (history, hist);
dx = dy = 0;
for (int i = 0; i < history->len; i++)
{
GdkTimeCoord *val = &g_array_index (history, GdkTimeCoord, i);
dx += val->axes[GDK_AXIS_DELTA_X];
dy += val->axes[GDK_AXIS_DELTA_Y];
}
event = gdk_scroll_event_new (surface,
device,
gdk_event_get_device_tool (old_event),
gdk_event_get_time (old_event),
gdk_event_get_modifier_state (old_event),
dx,
dy,
delta_x + dx,
delta_y + dy,
gdk_scroll_event_is_stop (old_event));
((GdkScrollEvent *)event)->history = history;
@@ -719,6 +692,14 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
gdk_event_unref (old_event);
}
if (g_queue_get_length (&display->queued_events) == 1 &&
g_queue_peek_head_link (&display->queued_events) == scrolls)
{
GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
if (clock) /* might be NULL if surface was destroyed */
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
}
}
static void
@@ -733,41 +714,24 @@ gdk_motion_event_push_history (GdkEvent *event,
g_assert (GDK_IS_EVENT_TYPE (event, GDK_MOTION_NOTIFY));
g_assert (GDK_IS_EVENT_TYPE (history_event, GDK_MOTION_NOTIFY));
if (G_UNLIKELY (!self->history))
self->history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
if (((GdkMotionEvent *)history_event)->history)
{
GArray *history = ((GdkMotionEvent *)history_event)->history;
g_array_append_vals (self->history, history->data, history->len);
}
if (!self->tool)
return;
tool = gdk_event_get_device_tool (history_event);
memset (&hist, 0, sizeof (GdkTimeCoord));
hist.time = gdk_event_get_time (history_event);
if (tool)
{
hist.flags = gdk_device_tool_get_axes (tool);
for (i = GDK_AXIS_X; i < GDK_AXIS_LAST; i++)
gdk_event_get_axis (history_event, i, &hist.axes[i]);
}
else
{
hist.flags = GDK_AXIS_FLAG_X | GDK_AXIS_FLAG_Y;
gdk_event_get_position (history_event, &hist.axes[GDK_AXIS_X], &hist.axes[GDK_AXIS_Y]);
}
hist.flags = gdk_device_tool_get_axes (tool);
for (i = GDK_AXIS_X; i < GDK_AXIS_LAST; i++)
gdk_event_get_axis (history_event, i, &hist.axes[i]);
if (G_UNLIKELY (!self->history))
self->history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
g_array_append_val (self->history, hist);
}
/* If the last N events in the event queue are motion notify
* events for the same surface, drop all but the last.
*
* If a button is held down or the device has a tool, then
* we give the remaining events a history containing the N-1
* dropped events.
*/
void
_gdk_event_queue_handle_motion_compression (GdkDisplay *display)
{
@@ -777,6 +741,9 @@ _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
GdkDevice *pending_motion_device = NULL;
GdkEvent *last_motion = NULL;
/* If the last N events in the event queue are motion notify
* events for the same surface, drop all but the last */
tmp_list = g_queue_peek_tail_link (&display->queued_events);
while (tmp_list)
@@ -813,17 +780,26 @@ _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
if (last_motion != NULL)
{
if ((gdk_event_get_modifier_state (last_motion) &
(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)) ||
gdk_event_get_device_tool (last_motion) != NULL)
gdk_motion_event_push_history (last_motion, pending_motions->data);
GdkModifierType state = gdk_event_get_modifier_state (last_motion);
if (state &
(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
GDK_BUTTON4_MASK | GDK_BUTTON5_MASK))
gdk_motion_event_push_history (last_motion, pending_motions->data);
}
gdk_event_unref (pending_motions->data);
g_queue_delete_link (&display->queued_events, pending_motions);
pending_motions = next;
}
if (g_queue_get_length (&display->queued_events) == 1 &&
g_queue_peek_head_link (&display->queued_events) == pending_motions)
{
GdkFrameClock *clock = gdk_surface_get_frame_clock (pending_motion_surface);
if (clock) /* might be NULL if surface was destroyed */
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
}
}
void
@@ -927,9 +903,6 @@ gdk_event_get_pointer_emulated (GdkEvent *event)
* Extract the axis value for a particular axis use from
* an event structure.
*
* To find out which axes are used, use [method@Gdk.DeviceTool.get_axes]
* on the device tool returned by [method@Gdk.Event.get_device_tool].
*
* Returns: %TRUE if the specified axis was found, otherwise %FALSE
*/
gboolean
@@ -1156,9 +1129,6 @@ G_DEFINE_BOXED_TYPE (GdkEventSequence, gdk_event_sequence,
*
* Extracts all axis values from an event.
*
* To find out which axes are used, use [method@Gdk.DeviceTool.get_axes]
* on the device tool returned by [method@Gdk.Event.get_device_tool].
*
* Returns: %TRUE on success, otherwise %FALSE
*/
gboolean
@@ -1209,7 +1179,7 @@ gdk_event_get_event_type (GdkEvent *event)
*
* Extracts the surface associated with an event.
*
* Returns: (transfer none) (nullable): The `GdkSurface` associated with the event
* Returns: (transfer none): The `GdkSurface` associated with the event
*/
GdkSurface *
gdk_event_get_surface (GdkEvent *event)
@@ -2461,14 +2431,6 @@ gdk_touchpad_event_get_state (GdkEvent *event)
return self->state;
}
static GdkEventSequence *
gdk_touchpad_event_get_sequence (GdkEvent *event)
{
GdkTouchpadEvent *self = (GdkTouchpadEvent *) event;
return self->sequence;
}
static gboolean
gdk_touchpad_event_get_position (GdkEvent *event,
double *x,
@@ -2488,7 +2450,7 @@ static const GdkEventTypeInfo gdk_touchpad_event_info = {
NULL,
gdk_touchpad_event_get_state,
gdk_touchpad_event_get_position,
gdk_touchpad_event_get_sequence,
NULL,
NULL,
NULL,
};
@@ -2496,32 +2458,22 @@ static const GdkEventTypeInfo gdk_touchpad_event_info = {
GDK_DEFINE_EVENT_TYPE (GdkTouchpadEvent, gdk_touchpad_event,
&gdk_touchpad_event_info,
GDK_EVENT_TYPE_SLOT (GDK_TOUCHPAD_SWIPE)
GDK_EVENT_TYPE_SLOT (GDK_TOUCHPAD_PINCH)
GDK_EVENT_TYPE_SLOT (GDK_TOUCHPAD_HOLD))
GDK_EVENT_TYPE_SLOT (GDK_TOUCHPAD_PINCH))
GdkEvent *
gdk_touchpad_event_new_swipe (GdkSurface *surface,
GdkEventSequence *sequence,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkTouchpadGesturePhase phase,
double x,
double y,
int n_fingers,
double dx,
double dy)
gdk_touchpad_event_new_swipe (GdkSurface *surface,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkTouchpadGesturePhase phase,
double x,
double y,
int n_fingers,
double dx,
double dy)
{
GdkTouchpadEvent *self;
GdkTouchpadEvent *self = gdk_event_alloc (GDK_TOUCHPAD_SWIPE, surface, device, time);
g_return_val_if_fail (phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN ||
phase == GDK_TOUCHPAD_GESTURE_PHASE_END ||
phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE ||
phase == GDK_TOUCHPAD_GESTURE_PHASE_CANCEL, NULL);
self = gdk_event_alloc (GDK_TOUCHPAD_SWIPE, surface, device, time);
self->sequence = sequence;
self->state = state;
self->phase = phase;
self->x = x;
@@ -2534,30 +2486,21 @@ gdk_touchpad_event_new_swipe (GdkSurface *surface,
}
GdkEvent *
gdk_touchpad_event_new_pinch (GdkSurface *surface,
GdkEventSequence *sequence,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkTouchpadGesturePhase phase,
double x,
double y,
int n_fingers,
double dx,
double dy,
double scale,
double angle_delta)
gdk_touchpad_event_new_pinch (GdkSurface *surface,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkTouchpadGesturePhase phase,
double x,
double y,
int n_fingers,
double dx,
double dy,
double scale,
double angle_delta)
{
GdkTouchpadEvent *self;
GdkTouchpadEvent *self = gdk_event_alloc (GDK_TOUCHPAD_PINCH, surface, device, time);
g_return_val_if_fail (phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN ||
phase == GDK_TOUCHPAD_GESTURE_PHASE_END ||
phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE ||
phase == GDK_TOUCHPAD_GESTURE_PHASE_CANCEL, NULL);
self = gdk_event_alloc (GDK_TOUCHPAD_PINCH, surface, device, time);
self->sequence = sequence;
self->state = state;
self->phase = phase;
self->x = x;
@@ -2571,27 +2514,6 @@ gdk_touchpad_event_new_pinch (GdkSurface *surface,
return (GdkEvent *) self;
}
GdkEvent *
gdk_touchpad_event_new_hold (GdkSurface *surface,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkTouchpadGesturePhase phase,
double x,
double y,
int n_fingers)
{
GdkTouchpadEvent *self = gdk_event_alloc (GDK_TOUCHPAD_HOLD, surface, device, time);
self->state = state;
self->phase = phase;
self->x = x;
self->y = y;
self->n_fingers = n_fingers;
return (GdkEvent *) self;
}
/**
* gdk_touchpad_event_get_gesture_phase:
* @event: (type GdkTouchpadEvent): a touchpad event
@@ -2607,8 +2529,7 @@ gdk_touchpad_event_get_gesture_phase (GdkEvent *event)
g_return_val_if_fail (GDK_IS_EVENT (event), 0);
g_return_val_if_fail (GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_PINCH) ||
GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_SWIPE) ||
GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_HOLD), 0);
GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_SWIPE), 0);
return self->phase;
}
@@ -2628,8 +2549,7 @@ gdk_touchpad_event_get_n_fingers (GdkEvent *event)
g_return_val_if_fail (GDK_IS_EVENT (event), 0);
g_return_val_if_fail (GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_PINCH) ||
GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_SWIPE) ||
GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_HOLD), 0);
GDK_IS_EVENT_TYPE (event, GDK_TOUCHPAD_SWIPE), 0);
return self->n_fingers;
}
@@ -2987,8 +2907,7 @@ gdk_motion_event_new (GdkSurface *surface,
* to the application because they occurred in the same frame as @event.
*
* Note that only motion and scroll events record history, and motion
* events do it only if one of the mouse buttons is down, or the device
* has a tool.
* events do it only if one of the mouse buttons is down.
*
* Returns: (transfer container) (array length=out_n_coords) (nullable): an
* array of time and coordinates
-3
View File
@@ -169,8 +169,6 @@ typedef struct _GdkTouchpadEvent GdkTouchpadEvent;
* @GDK_PAD_RING: A tablet pad axis event from a "ring".
* @GDK_PAD_STRIP: A tablet pad axis event from a "strip".
* @GDK_PAD_GROUP_MODE: A tablet pad group mode change.
* @GDK_TOUCHPAD_HOLD: A touchpad hold gesture event, the current state
* is determined by its phase field. Since: 4.6
* @GDK_EVENT_LAST: marks the end of the GdkEventType enumeration.
*
* Specifies the type of the event.
@@ -205,7 +203,6 @@ typedef enum
GDK_PAD_RING,
GDK_PAD_STRIP,
GDK_PAD_GROUP_MODE,
GDK_TOUCHPAD_HOLD,
GDK_EVENT_LAST /* helper variable for decls */
} GdkEventType;
+11 -23
View File
@@ -209,7 +209,7 @@ struct _GdkTouchEvent
* @pointer_emulated: whether the scroll event was the result of
* a pointer emulation
* @tool: a `GdkDeviceTool`
* @history: (element-type GdkTimeCoord): array of times and deltas
* @history: (element-type GdkScrollHistory): array of times and deltas
* for other scroll events that were compressed before delivering the
* current event
*
@@ -233,7 +233,7 @@ struct _GdkScrollEvent
gboolean pointer_emulated;
gboolean is_stop;
GdkDeviceTool *tool;
GArray *history; /* <GdkTimeCoord> */
GArray *history; /* <GdkScrollHistory> */
};
/*
@@ -402,7 +402,6 @@ struct _GdkTouchpadEvent
{
GdkEvent parent_instance;
GdkEventSequence *sequence;
GdkModifierType state;
gint8 phase;
gint8 n_fingers;
@@ -507,20 +506,18 @@ GdkEvent * gdk_touch_event_new (GdkEventType type,
double *axes,
gboolean emulating);
GdkEvent * gdk_touchpad_event_new_swipe (GdkSurface *surface,
GdkEventSequence *sequence,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkEvent * gdk_touchpad_event_new_swipe (GdkSurface *surface,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkTouchpadGesturePhase phase,
double x,
double y,
int n_fingers,
double dx,
double dy);
double x,
double y,
int n_fingers,
double dx,
double dy);
GdkEvent * gdk_touchpad_event_new_pinch (GdkSurface *surface,
GdkEventSequence *sequence,
GdkDevice *device,
guint32 time,
GdkModifierType state,
@@ -533,15 +530,6 @@ GdkEvent * gdk_touchpad_event_new_pinch (GdkSurface *surface,
double scale,
double angle_delta);
GdkEvent * gdk_touchpad_event_new_hold (GdkSurface *surface,
GdkDevice *device,
guint32 time,
GdkModifierType state,
GdkTouchpadGesturePhase phase,
double x,
double y,
int n_fingers);
GdkEvent * gdk_pad_event_new_ring (GdkSurface *surface,
GdkDevice *device,
guint32 time,
+18 -86
View File
@@ -151,12 +151,6 @@ unmask_context (MaskedContext *mask)
return GDK_GL_CONTEXT (GSIZE_TO_POINTER (GPOINTER_TO_SIZE (mask) & ~(gsize) 1));
}
static inline gboolean
mask_is_surfaceless (MaskedContext *mask)
{
return GPOINTER_TO_SIZE (mask) & (gsize) 1;
}
static void
unref_unmasked (gpointer data)
{
@@ -185,7 +179,8 @@ gdk_gl_context_dispose (GObject *gobject)
if (priv->egl_context != NULL)
{
GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkDisplay *display = gdk_surface_get_display (surface);
EGLDisplay *egl_display = gdk_display_get_egl_display (display);
if (eglGetCurrentContext () == priv->egl_context)
@@ -278,15 +273,7 @@ gdk_gl_context_real_realize (GdkGLContext *context,
int i = 0;
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
if (share != NULL)
{
gdk_gl_context_get_required_version (share, &major, &minor);
gdk_gl_context_set_allowed_apis (context,
gdk_gl_context_get_allowed_apis (share));
}
else
gdk_gl_context_get_required_version (context, &major, &minor);
gdk_gl_context_get_required_version (context, &major, &minor);
debug_bit = gdk_gl_context_get_debug_enabled (context);
forward_bit = gdk_gl_context_get_forward_compatible (context);
legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ||
@@ -587,8 +574,8 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
glViewport (0, 0, ww, wh);
#ifdef HAVE_EGL
if (priv->egl_context && gdk_gl_context_check_version (context, 0, 0, 3, 0))
glDrawBuffers (1, (GLenum[1]) { gdk_gl_context_get_use_es (context) ? GL_BACK : GL_BACK_LEFT });
if (priv->egl_context)
glDrawBuffers (1, (GLenum[1]) { GL_BACK_LEFT });
#endif
}
@@ -1010,33 +997,16 @@ gdk_gl_context_set_required_version (GdkGLContext *context,
}
gboolean
gdk_gl_context_check_version (GdkGLContext *self,
int required_gl_major,
int required_gl_minor,
int required_gles_major,
int required_gles_minor)
gdk_gl_context_check_version (GdkGLContext *context,
int required_major,
int required_minor)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
g_return_val_if_fail (required_gl_minor < 10, FALSE);
g_return_val_if_fail (required_gles_minor < 10, FALSE);
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), FALSE);
g_return_val_if_fail (required_minor < 10, FALSE);
if (!gdk_gl_context_is_realized (self))
return FALSE;
switch (priv->api)
{
case GDK_GL_API_GL:
return priv->gl_version >= required_gl_major * 10 + required_gl_minor;
case GDK_GL_API_GLES:
return priv->gl_version >= required_gles_major * 10 + required_gles_minor;
default:
g_return_val_if_reached (FALSE);
}
return priv->gl_version >= required_major * 10 + required_minor;
}
/**
@@ -1056,29 +1026,26 @@ gdk_gl_context_get_required_version (GdkGLContext *context,
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
gboolean force_gles = FALSE;
#ifdef G_ENABLE_DEBUG
GdkDisplay *display;
#endif
int default_major, default_minor;
int maj, min;
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
#ifdef G_ENABLE_DEBUG
display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
force_gles = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES);
#endif
/* libANGLE on Windows at least requires GLES 3.0+ */
if (display->have_egl_win32_libangle)
force_gles = TRUE;
/* Default fallback values for uninitialised contexts; we
* enforce a context version number of 3.2 for desktop GL,
* and 2.0 for GLES
*/
if (gdk_gl_context_get_use_es (context) || force_gles)
{
default_major = display->have_egl_win32_libangle ? 3 : 2;
default_major = 2;
default_minor = 0;
}
else
@@ -1356,7 +1323,6 @@ gl_debug_message_callback (GLenum source,
const char *message_source;
const char *message_type;
const char *message_severity;
GLogLevelFlags log_level;
if (severity == GL_DEBUG_SEVERITY_NOTIFICATION)
return;
@@ -1418,31 +1384,22 @@ gl_debug_message_callback (GLenum source,
{
case GL_DEBUG_SEVERITY_HIGH:
message_severity = "High";
log_level = G_LOG_LEVEL_CRITICAL;
break;
case GL_DEBUG_SEVERITY_MEDIUM:
message_severity = "Medium";
log_level = G_LOG_LEVEL_WARNING;
break;
case GL_DEBUG_SEVERITY_LOW:
message_severity = "Low";
log_level = G_LOG_LEVEL_MESSAGE;
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
message_severity = "Notification";
log_level = G_LOG_LEVEL_INFO;
break;
default:
message_severity = "Unknown";
log_level = G_LOG_LEVEL_MESSAGE;
}
/* There's no higher level function taking a log level argument... */
g_log_structured_standard (G_LOG_DOMAIN, log_level,
__FILE__, G_STRINGIFY (__LINE__),
G_STRFUNC,
"OPENGL:\n Source: %s\n Type: %s\n Severity: %s\n Message: %s",
message_source, message_type, message_severity, message);
g_warning ("OPENGL:\n Source: %s\n Type: %s\n Severity: %s\n Message: %s",
message_source, message_type, message_severity, message);
}
/**
@@ -1698,31 +1655,6 @@ gdk_gl_context_clear_current (void)
}
}
/*<private>
* gdk_gl_context_clear_current_if_surface:
* @surface: surface to clear for
*
* Does a gdk_gl_context_clear_current() if the current context is attached
* to @surface, leaves the current context alone otherwise.
**/
void
gdk_gl_context_clear_current_if_surface (GdkSurface *surface)
{
MaskedContext *current;
current = g_private_get (&thread_current_context);
if (current != NULL && !mask_is_surfaceless (current))
{
GdkGLContext *context = unmask_context (current);
if (gdk_gl_context_get_surface (context) != surface)
return;
if (GDK_GL_CONTEXT_GET_CLASS (context)->clear_current (context))
g_private_replace (&thread_current_context, NULL);
}
}
/**
* gdk_gl_context_get_current:
*
+2 -6
View File
@@ -99,8 +99,6 @@ gboolean gdk_gl_backend_can_be_used (GdkGLBackend
GError **error);
void gdk_gl_backend_use (GdkGLBackend backend_type);
void gdk_gl_context_clear_current_if_surface (GdkSurface *surface);
GdkGLContext * gdk_gl_context_new (GdkDisplay *display,
GdkSurface *surface);
@@ -111,10 +109,8 @@ void gdk_gl_context_set_is_legacy (GdkGLContext
gboolean is_legacy);
gboolean gdk_gl_context_check_version (GdkGLContext *context,
int required_gl_major,
int required_gl_minor,
int required_gles_major,
int required_gles_minor);
int required_major,
int required_minor);
gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context);
void gdk_gl_context_push_debug_group (GdkGLContext *context,
+7 -20
View File
@@ -21,7 +21,6 @@
#include "gdkgltextureprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkglcontextprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdktextureprivate.h"
@@ -175,19 +174,10 @@ gdk_gl_texture_do_download (gpointer texture_,
glGenFramebuffers (1, &fbo);
glBindFramebuffer (GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->id, 0);
if (gdk_gl_context_check_version (self->context, 4, 3, 3, 1))
{
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_read_format);
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_read_type);
if (!gdk_gl_texture_find_format (gdk_gl_context_get_use_es (self->context), gl_read_format, gl_read_type, &actual_format))
actual_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED; /* pray */
}
else
{
gl_read_format = GL_RGBA;
gl_read_type = GL_UNSIGNED_BYTE;
actual_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
}
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_read_format);
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_read_type);
if (!gdk_gl_texture_find_format (gdk_gl_context_get_use_es (self->context), gl_read_format, gl_read_type, &actual_format))
actual_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED; /* pray */
if (download->format == actual_format &&
(download->stride == expected_stride))
@@ -315,11 +305,9 @@ gdk_gl_texture_determine_format (GdkGLTexture *self)
GLint active_texture;
GLint internal_format;
/* Abort if somebody else is GL-ing here... */
if (self->context != gdk_gl_context_get_current () ||
/* ... or glGetTexLevelParameter() isn't supported */
!gdk_gl_context_check_version (self->context, 0, 0, 3, 1))
if (self->context != gdk_gl_context_get_current ())
{
/* Somebody else is GL-ing here, abort! */
texture->format = GDK_MEMORY_DEFAULT;
return;
}
@@ -392,8 +380,7 @@ gdk_gl_texture_determine_format (GdkGLTexture *self)
* which will happen when the GdkTexture object is finalized, or due to
* an explicit call of [method@Gdk.GLTexture.release].
*
* Return value: (transfer full) (type GdkGLTexture): A newly-created
* `GdkTexture`
* Return value: (transfer full): A newly-created `GdkTexture`
*/
GdkTexture *
gdk_gl_texture_new (GdkGLContext *context,
+8 -8
View File
@@ -1,16 +1,16 @@
#!/usr/bin/env perl
# Updates https://gitlab.gnome.org/GNOME/gtk/tree/main/gdk/gdkkeysyms.h from upstream (X.org 7.x),
# Updates https://gitlab.gnome.org/GNOME/gtk/tree/master/gdk/gdkkeysyms.h from upstream (X.org 7.x),
# from https://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h
#
#
# Author : Simos Xenitellis <simos at gnome dot org>.
# Author : Bastien Nocera <hadess@hadess.net>
# Version : 1.2
#
# Input : https://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h
# Input : https://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h
# Output : https://gitlab.gnome.org/GNOME/gtk/tree/main/gdk/gdkkeysyms.h
#
# Output : https://gitlab.gnome.org/GNOME/gtk/tree/master/gdk/gdkkeysyms.h
#
# Notes : It downloads keysymdef.h from the Internet, if not found locally,
# Notes : and creates an updated gdkkeysyms.h
# Notes : This version updates the source of gdkkeysyms.h from CVS to the GIT server.
@@ -24,7 +24,7 @@ if ( ! -f "keysymdef.h" )
{
print "Trying to download keysymdef.h from\n";
print "http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h\n";
die "Unable to download keysymdef.h from http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h\n"
die "Unable to download keysymdef.h from http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h\n"
unless system("wget -c -O keysymdef.h \"http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h\"") == 0;
print " done.\n\n";
}
@@ -39,7 +39,7 @@ if ( ! -f "XF86keysym.h" )
{
print "Trying to download XF86keysym.h from\n";
print "http://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h\n";
die "Unable to download keysymdef.h from http://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h\n"
die "Unable to download keysymdef.h from http://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h\n"
unless system("wget -c -O XF86keysym.h \"http://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h\"") == 0;
print " done.\n\n";
}
@@ -82,7 +82,7 @@ print OUT_GDKKEYSYMS $LICENSE_HEADER;
print OUT_GDKKEYSYMS<<EOF;
/*
* File auto-generated from script https://gitlab.gnome.org/GNOME/gtk/tree/main/gdk/gdkkeysyms-update.pl
* File auto-generated from script https://gitlab.gnome.org/GNOME/gtk/tree/master/gdk/gdkkeysyms-update.pl
* using the input file
* http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h
* and
@@ -111,7 +111,7 @@ while (<IN_KEYSYMDEF>)
$_ = $keysymelements[1];
die "Internal error, was expecting \"XC_*\", found: $_\n" if ( ! /^XK_/ );
$_ = $keysymelements[2];
die "Internal error, was expecting \"0x*\", found: $_\n" if ( ! /^0x/ );
+1 -1
View File
@@ -18,7 +18,7 @@
/*
* File auto-generated from script https://gitlab.gnome.org/GNOME/gtk/tree/main/gdk/gdkkeysyms-update.pl
* File auto-generated from script https://gitlab.gnome.org/GNOME/gtk/tree/master/gdk/gdkkeysyms-update.pl
* using the input file
* http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h
* and
+43 -58
View File
@@ -369,7 +369,7 @@ static const struct {
{ 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
{ 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
{ 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
{ 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
{ 0x07a5, 0x03aa }, /* Greek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
{ 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
{ 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
{ 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
@@ -436,22 +436,22 @@ static const struct {
{ 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */
{ 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */
{ 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */
{ 0x08a1, 0x23b7 }, /* leftradical ??? */
{ 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
{ 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */
/* 0x08a1 leftradical ? ??? */
/* 0x08a2 topleftradical ? ??? */
/* 0x08a3 horizconnector ? ??? */
{ 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */
{ 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */
{ 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
{ 0x08a7, 0x23a1 }, /* topleftsqbracket ??? */
{ 0x08a8, 0x23a3 }, /* botleftsqbracket ??? */
{ 0x08a9, 0x23a4 }, /* toprightsqbracket ??? */
{ 0x08aa, 0x23a6 }, /* botrightsqbracket ??? */
{ 0x08ab, 0x239b }, /* topleftparens ??? */
{ 0x08ac, 0x239d }, /* botleftparens ??? */
{ 0x08ad, 0x239e }, /* toprightparens ??? */
{ 0x08ae, 0x23a0 }, /* botrightparens ??? */
{ 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ??? */
{ 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ??? */
/* 0x08a7 topleftsqbracket ? ??? */
/* 0x08a8 botleftsqbracket ? ??? */
/* 0x08a9 toprightsqbracket ? ??? */
/* 0x08aa botrightsqbracket ? ??? */
/* 0x08ab topleftparens ? ??? */
/* 0x08ac botleftparens ? ??? */
/* 0x08ad toprightparens ? ??? */
/* 0x08ae botrightparens ? ??? */
/* 0x08af leftmiddlecurlybrace ? ??? */
/* 0x08b0 rightmiddlecurlybrace ? ??? */
/* 0x08b1 topleftsummation ? ??? */
/* 0x08b2 botleftsummation ? ??? */
/* 0x08b3 topvertsummationconnector ? ??? */
@@ -467,8 +467,8 @@ static const struct {
{ 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */
{ 0x08c2, 0x221e }, /* infinity ∞ INFINITY */
{ 0x08c5, 0x2207 }, /* nabla ∇ NABLA */
{ 0x08c8, 0x223c }, /* approximate TILDE OPERATOR */
{ 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */
{ 0x08c8, 0x2245 }, /* approximate ≅ APPROXIMATELY EQUAL TO */
/* 0x08c9 similarequal ? ??? */
{ 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
{ 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */
{ 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */
@@ -485,7 +485,7 @@ static const struct {
{ 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */
{ 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */
{ 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */
/* 0x09df blank ? ??? */
{ 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */
{ 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */
{ 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */
{ 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
@@ -499,11 +499,11 @@ static const struct {
{ 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
{ 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
{ 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
{ 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */
{ 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */
/* 0x09ef horizlinescan1 ? ??? */
/* 0x09f0 horizlinescan3 ? ??? */
{ 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
{ 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */
{ 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */
/* 0x09f2 horizlinescan7 ? ??? */
/* 0x09f3 horizlinescan9 ? ??? */
{ 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
{ 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
{ 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
@@ -519,9 +519,9 @@ static const struct {
{ 0x0aa8, 0x200a }, /* hairspace HAIR SPACE */
{ 0x0aa9, 0x2014 }, /* emdash — EM DASH */
{ 0x0aaa, 0x2013 }, /* endash EN DASH */
{ 0x0aac, 0x2423 }, /* signifblank ␣ OPEN BOX */
/* 0x0aac signifblank ? ??? */
{ 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */
{ 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */
/* 0x0aaf doubbaselinedot ? ??? */
{ 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */
{ 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */
{ 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */
@@ -532,9 +532,9 @@ static const struct {
{ 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
{ 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */
{ 0x0abb, 0x2012 }, /* figdash FIGURE DASH */
{ 0x0abc, 0x27e8 }, /* leftanglebracket ⟨ MATHEMATICAL LEFT ANGLE BRACKET */
{ 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
{ 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */
{ 0x0abe, 0x27e9 }, /* rightanglebracket ⟩ MATHEMATICAL RIGHT ANGLE BRACKET */
{ 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
/* 0x0abf marker ? ??? */
{ 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
{ 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
@@ -546,13 +546,12 @@ static const struct {
{ 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
{ 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
{ 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */
{ 0x0acf, 0x25af }, /* emopenrectangle WHITE VERTICAL RECTANGLE */
{ 0x0acf, 0x25a1 }, /* emopenrectangle WHITE SQUARE */
{ 0x0ad0, 0x2018 }, /* leftsinglequotemark LEFT SINGLE QUOTATION MARK */
{ 0x0ad1, 0x2019 }, /* rightsinglequotemark RIGHT SINGLE QUOTATION MARK */
{ 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
{ 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
{ 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */
{ 0x0ad5, 0x2030 }, /* permille ‰ PER MILLE SIGN */
{ 0x0ad6, 0x2032 }, /* minutes PRIME */
{ 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */
{ 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */
@@ -561,7 +560,7 @@ static const struct {
{ 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
{ 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
{ 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */
{ 0x0adf, 0x25ae }, /* emfilledrect BLACK VERTICAL RECTANGLE */
{ 0x0adf, 0x25a0 }, /* emfilledrect BLACK SQUARE */
{ 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */
{ 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */
{ 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */
@@ -806,16 +805,15 @@ static const struct {
{ 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
{ 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
{ 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
{ 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */
/* 0x0ef3 Hangul_KkogjiDalrinIeung ? ??? */
{ 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
{ 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
{ 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
{ 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
{ 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
{ 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */
/* 0x0ef9 Hangul_J_KkogjiDalrinIeung ? ??? */
{ 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
{ 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */
{ 0x13a4, 0x20ac }, /* Euro € EURO SIGN */
{ 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */
{ 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */
{ 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
@@ -837,13 +835,18 @@ static const struct {
/* Following items added to GTK, not in the xterm table */
/* A few ASCII control characters */
#ifndef GDK_WINDOWING_WIN32
{ 0xFF08 /* Backspace */, '\b' },
{ 0xFF09 /* Tab */, '\t' },
#endif
{ 0xFF0A /* Linefeed */, '\n' },
{ 0xFF0B /* Vert. Tab */, '\v' },
#ifndef GDK_WINDOWING_WIN32
{ 0xFF0D /* Return */, '\r' },
{ 0xFF1B /* Escape */, '\033' },
#endif
/* Numeric keypad */
@@ -868,7 +871,9 @@ static const struct {
/* End numeric keypad */
#ifndef GDK_WINDOWING_WIN32
{ 0xFFFF /* Delete */, '\177' }
#endif
};
/**
@@ -1079,7 +1084,7 @@ static const struct {
{ 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */
{ 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
{ 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
{ 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
{ 0x07a5, 0x03aa }, /* Greek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
{ 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
{ 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
{ 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
@@ -1394,7 +1399,6 @@ static const struct {
{ 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
{ 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
{ 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
{ 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */
{ 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
{ 0x0aa2, 0x2002 }, /* enspace EN SPACE */
{ 0x0aa1, 0x2003 }, /* emspace EM SPACE */
@@ -1418,9 +1422,7 @@ static const struct {
{ 0x0af1, 0x2020 }, /* dagger † DAGGER */
{ 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */
{ 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */
{ 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */
{ 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */
{ 0x0ad5, 0x2030 }, /* permille ‰ PER MILLE SIGN */
{ 0x0ad6, 0x2032 }, /* minutes PRIME */
{ 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */
{ 0x0afc, 0x2038 }, /* caret ‸ CARET */
@@ -1478,8 +1480,7 @@ static const struct {
{ 0x0bd6, 0x222a }, /* downshoe UNION */
{ 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */
{ 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */
{ 0x08c8, 0x223c }, /* approximate TILDE OPERATOR */
{ 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */
{ 0x08c8, 0x2245 }, /* approximate ≅ APPROXIMATELY EQUAL TO */
{ 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */
{ 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */
{ 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */
@@ -1497,28 +1498,15 @@ static const struct {
{ 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */
{ 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */
{ 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */
{ 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
{ 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
{ 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */
{ 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ ??? */
{ 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ ??? */
{ 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ ??? */
{ 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ ??? */
{ 0x08ab, 0x239b }, /* topleftparens ⎛ ??? */
{ 0x08ac, 0x239d }, /* botleftparens ⎝ ??? */
{ 0x08ad, 0x239e }, /* toprightparens ⎞ ??? */
{ 0x08ae, 0x23a0 }, /* botrightparens ⎠ ??? */
{ 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */
{ 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */
{ 0x08a1, 0x23b7 }, /* leftradical ⎷ ??? */
{ 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */
{ 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */
{ 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */
{ 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */
{ 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
{ 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */
{ 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */
{ 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */
{ 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */
{ 0x0aac, 0x2423 }, /* signifblank ␣ OPEN BOX */
{ 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */
{ 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */
{ 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
{ 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
@@ -1534,11 +1522,11 @@ static const struct {
{ 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
{ 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */
{ 0x0adf, 0x25a0 }, /* emfilledrect ■ BLACK SQUARE */
{ 0x0acf, 0x25a1 }, /* emopenrectangle □ WHITE SQUARE */
{ 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */
{ 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */
{ 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */
{ 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */
{ 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */
{ 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
{ 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */
{ 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
@@ -1568,8 +1556,6 @@ static const struct {
{ 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */
{ 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */
{ 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */
{ 0x0abc, 0x27e8 }, /* leftanglebracket ⟨ MATHEMATICAL LEFT ANGLE BRACKET */
{ 0x0abe, 0x27e9 }, /* rightanglebracket ⟩ MATHEMATICAL RIGHT ANGLE BRACKET */
{ 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */
{ 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */
{ 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */
@@ -1688,7 +1674,6 @@ static const struct {
{ 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
{ 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
{ 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
{ 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */
{ 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
{ 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
{ 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
-1
View File
@@ -2,4 +2,3 @@ BOOLEAN:BOXED
BOOLEAN:OBJECT
BOOLEAN:POINTER
VOID:POINTER,POINTER,BOOLEAN,BOOLEAN
VOID:INT,INT
+2 -2
View File
@@ -133,10 +133,10 @@ gdk_memory_sanitize (GBytes *bytes,
*
* Creates a new texture for a blob of image data.
*
* The `GBytes` must contain @stride × @height pixels
* The `GBytes` must contain @stride x @height pixels
* in the given format.
*
* Returns: (type GdkMemoryTexture): A newly-created `GdkTexture`
* Returns: A newly-created `GdkTexture`
*/
GdkTexture *
gdk_memory_texture_new (int width,
+17 -17
View File
@@ -1,5 +1,5 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2000 Red Hat, Inc.
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -52,25 +52,25 @@ layout_iter_get_line_clip_region (PangoLayoutIter *iter,
i = 0;
while (i < n_ranges)
{
{
int *pixel_ranges = NULL;
int n_pixel_ranges = 0;
int j;
/* Note that get_x_ranges returns layout coordinates
*/
if (index_ranges[i*2+1] >= pango_layout_line_get_start_index (line) &&
index_ranges[i*2] < pango_layout_line_get_start_index (line) + pango_layout_line_get_length (line))
if (index_ranges[i*2+1] >= line->start_index &&
index_ranges[i*2] < line->start_index + line->length)
pango_layout_line_get_x_ranges (line,
index_ranges[i*2],
index_ranges[i*2+1],
&pixel_ranges, &n_pixel_ranges);
for (j = 0; j < n_pixel_ranges; j++)
{
GdkRectangle rect;
int x_off, y_off;
x_off = PANGO_PIXELS (pixel_ranges[2*j] - logical_rect.x);
y_off = PANGO_PIXELS (baseline - logical_rect.y);
@@ -124,14 +124,14 @@ gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
{
cairo_region_t *clip_region;
PangoLayoutIter *iter;
g_return_val_if_fail (line != NULL, NULL);
g_return_val_if_fail (index_ranges != NULL, NULL);
iter = pango_layout_get_iter (line->layout);
while (pango_layout_iter_get_line_readonly (iter) != line)
pango_layout_iter_next_line (iter);
clip_region = layout_iter_get_line_clip_region(iter, x_origin, y_origin, index_ranges, n_ranges);
pango_layout_iter_free (iter);
@@ -167,26 +167,26 @@ gdk_pango_layout_get_clip_region (PangoLayout *layout,
const int *index_ranges,
int n_ranges)
{
PangoLayoutIter *iter;
PangoLayoutIter *iter;
cairo_region_t *clip_region;
g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
g_return_val_if_fail (index_ranges != NULL, NULL);
clip_region = cairo_region_create ();
iter = pango_layout_get_iter (layout);
do
{
PangoRectangle logical_rect;
cairo_region_t *line_region;
int baseline;
pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
baseline = pango_layout_iter_get_baseline (iter);
baseline = pango_layout_iter_get_baseline (iter);
line_region = layout_iter_get_line_clip_region(iter,
line_region = layout_iter_get_line_clip_region(iter,
x_origin + PANGO_PIXELS (logical_rect.x),
y_origin + PANGO_PIXELS (baseline),
index_ranges,
+1 -1
View File
@@ -187,7 +187,7 @@ gdk_popup_get_rect_anchor (GdkPopup *popup)
*
* Returns the parent surface of a popup.
*
* Returns: (transfer none) (nullable): the parent surface
* Returns: (transfer none): the parent surface
*/
GdkSurface *
gdk_popup_get_parent (GdkPopup *popup)
+1 -1
View File
@@ -33,7 +33,7 @@
((_GDK_RGBA_SELECT_COLOR(str, 0, 0) << 4) | _GDK_RGBA_SELECT_COLOR(str, 0, 1)) / 255., \
((_GDK_RGBA_SELECT_COLOR(str, 1, 2) << 4) | _GDK_RGBA_SELECT_COLOR(str, 1, 3)) / 255., \
((_GDK_RGBA_SELECT_COLOR(str, 2, 4) << 4) | _GDK_RGBA_SELECT_COLOR(str, 2, 5)) / 255., \
((sizeof(str) % 4 == 1) ? ((_GDK_RGBA_SELECT_COLOR(str, 3, 6) << 4) | _GDK_RGBA_SELECT_COLOR(str, 3, 7)) : 0xFF) / 255. })
((sizeof(str) % 4 == 1) ? ((_GDK_RGBA_SELECT_COLOR(str, 3, 6) << 4) | _GDK_RGBA_SELECT_COLOR(str, 3, 7)) : 0xFF) / 255 })
gboolean gdk_rgba_parser_parse (GtkCssParser *parser,
+2 -15
View File
@@ -605,14 +605,11 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
0,
NULL,
NULL,
_gdk_marshal_VOID__INT_INT,
NULL,
G_TYPE_NONE,
2,
G_TYPE_INT,
G_TYPE_INT);
g_signal_set_va_marshaller (signals[LAYOUT],
G_OBJECT_CLASS_TYPE (object_class),
_gdk_marshal_VOID__INT_INTv);
/**
* GdkSurface::render:
@@ -1095,7 +1092,6 @@ gdk_surface_set_egl_native_window (GdkSurface *self,
if (priv->egl_surface != NULL)
{
gdk_gl_context_clear_current_if_surface (self);
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
priv->egl_surface = NULL;
}
@@ -1124,7 +1120,6 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
priv->egl_surface != NULL &&
gdk_display_get_egl_config_high_depth (display) != gdk_display_get_egl_config (display))
{
gdk_gl_context_clear_current_if_surface (self);
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
priv->egl_surface = NULL;
}
@@ -2244,7 +2239,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
GdkEvent *event,
gulong serial)
{
GdkSurface *event_surface = NULL;
GdkSurface *event_surface;
gboolean unlink_event = FALSE;
GdkDeviceGrabInfo *button_release_grab;
GdkPointerSurfaceInfo *pointer_info = NULL;
@@ -2336,14 +2331,6 @@ _gdk_windowing_got_event (GdkDisplay *display,
*/
_gdk_event_queue_handle_motion_compression (display);
gdk_event_queue_handle_scroll_compression (display);
if (event_surface)
{
GdkFrameClock *clock = gdk_surface_get_frame_clock (event_surface);
if (clock) /* might be NULL if surface was destroyed */
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
}
}
/**
+10 -10
View File
@@ -25,14 +25,14 @@
* multiple frames, and will be used for a long time.
*
* There are various ways to create `GdkTexture` objects from a
* [class@GdkPixbuf.Pixbuf], or a Cairo surface, or other pixel data.
* `GdkPixbuf`, or a Cairo surface, or other pixel data.
*
* The ownership of the pixel data is transferred to the `GdkTexture`
* instance; you can only make a copy of it, via [method@Gdk.Texture.download].
*
* `GdkTexture` is an immutable object: That means you cannot change
* anything about it other than increasing the reference count via
* [method@GObject.Object.ref], and consequently, it is a thread-safe object.
* g_object_ref().
*/
#include "config.h"
@@ -346,7 +346,7 @@ gdk_texture_init (GdkTexture *self)
*
* Creates a new texture object representing the surface.
*
* @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
* @surface must be an image surface with format CAIRO_FORMAT_ARGB32.
*
* Returns: a new `GdkTexture`
*/
@@ -384,7 +384,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
* Creates a new texture object representing the `GdkPixbuf`.
*
* This function is threadsafe, so that you can e.g. use GTask
* and [method@Gio.Task.run_in_thread] to avoid blocking the main thread
* and g_task_run_in_thread() to avoid blocking the main thread
* while loading a big image.
*
* Returns: a new `GdkTexture`
@@ -430,7 +430,7 @@ gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
* [ctor@Gdk.Texture.new_from_file] to load it.
*
* This function is threadsafe, so that you can e.g. use GTask
* and [method@Gio.Task.run_in_thread] to avoid blocking the main thread
* and g_task_run_in_thread() to avoid blocking the main thread
* while loading a big image.
*
* Return value: A newly-created `GdkTexture`
@@ -454,7 +454,7 @@ gdk_texture_new_from_resource (const char *resource_path)
texture = NULL;
if (texture == NULL)
g_error ("Resource path %s is not a valid image: %s", resource_path, error->message);
g_error ("Resource path %s s not a valid image: %s", resource_path, error->message);
return texture;
}
@@ -472,7 +472,7 @@ gdk_texture_new_from_resource (const char *resource_path)
* If %NULL is returned, then @error will be set.
*
* This function is threadsafe, so that you can e.g. use GTask
* and [method@Gio.Task.run_in_thread] to avoid blocking the main thread
* and g_task_run_in_thread() to avoid blocking the main thread
* while loading a big image.
*
* Return value: A newly-created `GdkTexture`
@@ -565,7 +565,7 @@ gdk_texture_new_from_bytes_pixbuf (GBytes *bytes,
* If %NULL is returned, then @error will be set.
*
* This function is threadsafe, so that you can e.g. use GTask
* and [method@Gio.Task.run_in_thread] to avoid blocking the main thread
* and g_task_run_in_thread() to avoid blocking the main thread
* while loading a big image.
*
* Return value: A newly-created `GdkTexture`
@@ -611,7 +611,7 @@ gdk_texture_new_from_bytes (GBytes *bytes,
* If %NULL is returned, then @error will be set.
*
* This function is threadsafe, so that you can e.g. use GTask
* and [method@Gio.Task.run_in_thread] to avoid blocking the main thread
* and g_task_run_in_thread() to avoid blocking the main thread
* while loading a big image.
*
* Return value: A newly-created `GdkTexture`
@@ -796,7 +796,7 @@ gdk_texture_get_render_data (GdkTexture *self,
*
* This is a utility function intended for debugging and testing.
* If you want more control over formats, proper error handling or
* want to store to a [iface@Gio.File] or other location, you might want to
* want to store to a `GFile` or other location, you might want to
* use [method@Gdk.Texture.save_to_png_bytes] or look into the
* gdk-pixbuf library.
*
+4
View File
@@ -89,6 +89,10 @@ GDK_AVAILABLE_IN_ALL
void gdk_texture_download (GdkTexture *texture,
guchar *data,
gsize stride);
GDK_AVAILABLE_IN_4_6
void gdk_texture_download_float (GdkTexture *texture,
float *data,
gsize stride);
GDK_AVAILABLE_IN_ALL
gboolean gdk_texture_save_to_png (GdkTexture *texture,
const char *filename);
-2
View File
@@ -15,8 +15,6 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "config.h"
#include "gdkjpegprivate.h"
+16
View File
@@ -222,7 +222,11 @@ gdk_load_png (GBytes *bytes,
case PNG_COLOR_TYPE_RGB_ALPHA:
if (depth == 8)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
format = GDK_MEMORY_R8G8B8A8;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
format = GDK_MEMORY_A8B8G8R8;
#endif
}
else
{
@@ -232,7 +236,11 @@ gdk_load_png (GBytes *bytes,
case PNG_COLOR_TYPE_RGB:
if (depth == 8)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
format = GDK_MEMORY_R8G8B8;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
format = GDK_MEMORY_B8G8R8;
#endif
}
else if (depth == 16)
{
@@ -317,14 +325,22 @@ gdk_save_png (GdkTexture *texture)
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
format = GDK_MEMORY_R8G8B8A8;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
format = GDK_MEMORY_A8B8G8R8;
#endif
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
depth = 8;
break;
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
format = GDK_MEMORY_R8G8B8;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
format = GDK_MEMORY_B8G8R8;
#endif
png_format = PNG_COLOR_TYPE_RGB;
depth = 8;
break;
+1 -8
View File
@@ -240,7 +240,7 @@ static const FormatData format_data[] = {
[GDK_MEMORY_A8R8G8B8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA },
[GDK_MEMORY_R8G8B8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA },
[GDK_MEMORY_A8B8G8R8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA },
[GDK_MEMORY_R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0 },
[GDK_MEMORY_R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0 },
[GDK_MEMORY_B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0 },
[GDK_MEMORY_R16G16B16] = { GDK_MEMORY_R16G16B16, 16, 3, SAMPLEFORMAT_UINT, 0 },
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA },
@@ -376,13 +376,6 @@ gdk_load_tiff (GBytes *input_bytes,
G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME;
tif = tiff_open_read (input_bytes);
if (!tif)
{
g_set_error_literal (error,
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
_("Could not load TIFF data"));
return NULL;
}
TIFFSetDirectory (tif, 0);
+109 -75
View File
@@ -23,6 +23,7 @@
#include <CoreGraphics/CoreGraphics.h>
#include <cairo-quartz.h>
#import "GdkMacosCairoSubview.h"
#import "GdkMacosCairoView.h"
@@ -32,9 +33,7 @@
-(void)dealloc
{
g_clear_pointer (&self->clip, g_array_unref);
g_clear_pointer (&self->damage, g_array_unref);
g_clear_pointer (&self->image, CGImageRelease);
g_clear_pointer (&self->clip, cairo_region_destroy);
[super dealloc];
}
@@ -56,67 +55,132 @@
-(void)drawRect:(NSRect)rect
{
CGContextRef cgContext;
GdkSurface *gdk_surface;
cairo_surface_t *dest;
const NSRect *rects = NULL;
NSView *root_view;
CGRect image_rect;
CGRect abs_bounds;
NSInteger n_rects = 0;
NSRect abs_bounds;
cairo_t *cr;
CGSize scale;
int abs_height;
int scale_factor;
if (self->image == NULL)
if (self->cairoSurface == NULL)
return;
cgContext = [[NSGraphicsContext currentContext] CGContext];
/* Acquire everything we need to do translations, drawing, etc */
gdk_surface = [self gdkSurface];
scale_factor = gdk_surface_get_scale_factor (gdk_surface);
root_view = [[self window] contentView];
cgContext = [[NSGraphicsContext currentContext] CGContext];
abs_bounds = [self convertRect:[self bounds] toView:root_view];
abs_height = CGImageGetHeight (self->image);
CGContextSaveGState (cgContext);
/* Clip while our context is still using matching coordinates
* to the self->clip region. This is usually just on the views
* for the shadow areas.
/* Translate scaling to remove HiDPI scaling from CGContext as
* cairo will be doing that for us already.
*/
CGContextAddRect (cgContext, [self bounds]);
if (self->clip != NULL)
{
for (guint i = 0; i < self->clip->len; i++)
CGContextAddRect (cgContext, g_array_index (self->clip, CGRect, i));
}
if (self->damage != NULL)
{
for (guint i = 0; i < self->damage->len; i++)
CGContextAddRect (cgContext, g_array_index (self->damage, CGRect, i));
}
CGContextClip (cgContext);
/* Scale/Translate so that the CGImageRef draws in proper format/placement */
scale = CGSizeMake (1.0, 1.0);
scale = CGContextConvertSizeToDeviceSpace (cgContext, scale);
CGContextScaleCTM (cgContext, 1.0 / scale.width, 1.0 / scale.height);
CGContextTranslateCTM (cgContext, -abs_bounds.origin.x, -abs_bounds.origin.y);
image_rect = CGRectMake (-abs_bounds.origin.x,
-abs_bounds.origin.y,
CGImageGetWidth (self->image),
CGImageGetHeight (self->image));
CGContextDrawImage (cgContext, image_rect, self->image);
/* Create the cairo surface to draw to the CGContext and translate
* coordinates so we can pretend we are in the same coordinate system
* as the GDK surface.
*/
dest = cairo_quartz_surface_create_for_cg_context (cgContext,
gdk_surface->width * scale_factor,
gdk_surface->height * scale_factor);
cairo_surface_set_device_scale (dest, scale_factor, scale_factor);
/* Create cairo context and translate things into the origin of
* the topmost contentView so that we just draw at 0,0 with a
* clip region to paint the surface.
*/
cr = cairo_create (dest);
cairo_translate (cr, -abs_bounds.origin.x, -abs_bounds.origin.y);
/* Apply the clip if provided one */
if (self->clip != NULL)
{
cairo_rectangle_int_t area;
n_rects = cairo_region_num_rectangles (self->clip);
for (guint i = 0; i < n_rects; i++)
{
cairo_region_get_rectangle (self->clip, i, &area);
cairo_rectangle (cr, area.x, area.y, area.width, area.height);
}
cairo_clip (cr);
}
/* Clip the cairo context based on the rectangles to be drawn
* within the bounding box :rect.
*/
[self getRectsBeingDrawn:&rects count:&n_rects];
for (NSInteger i = 0; i < n_rects; i++)
{
NSRect area = [self convertRect:rects[i] toView:root_view];
cairo_rectangle (cr,
area.origin.x, area.origin.y,
area.size.width, area.size.height);
}
cairo_clip (cr);
/* Now paint the surface (without blending) as we do not need
* any compositing here. The transparent regions (like shadows)
* are already on non-opaque layers.
*/
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface (cr, self->cairoSurface, 0, 0);
cairo_paint (cr);
/* Cleanup state, flush the surface to the backing layer, and
* restore GState for future use.
*/
cairo_destroy (cr);
cairo_surface_flush (dest);
cairo_surface_destroy (dest);
CGContextRestoreGState (cgContext);
}
-(void)setImage:(CGImageRef)theImage
withDamage:(cairo_region_t *)region
-(void)setCairoSurface:(cairo_surface_t *)surface
withDamage:(cairo_region_t *)region
{
if (theImage != image)
if (surface != self->cairoSurface)
{
g_clear_pointer (&image, CGImageRelease);
if (theImage)
image = CGImageRetain (theImage);
g_clear_pointer (&self->cairoSurface, cairo_surface_destroy);
if (surface != NULL)
self->cairoSurface = cairo_surface_reference (surface);
}
[self convertRegion:region toArray:&self->damage andDisplay:YES];
if (region != NULL)
{
NSView *root_view = [[self window] contentView];
NSRect abs_bounds = [self convertRect:[self bounds] toView:root_view];
guint n_rects = cairo_region_num_rectangles (region);
for (guint i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
NSRect nsrect;
cairo_region_get_rectangle (region, i, &rect);
nsrect = NSMakeRect (rect.x, rect.y, rect.width, rect.height);
if (NSIntersectsRect (abs_bounds, nsrect))
{
nsrect.origin.x -= abs_bounds.origin.x;
nsrect.origin.y -= abs_bounds.origin.y;
[self setNeedsDisplayInRect:nsrect];
}
}
}
for (id view in [self subviews])
[(GdkMacosCairoSubview *)view setImage:theImage withDamage:region];
[(GdkMacosCairoSubview *)view setCairoSurface:surface
withDamage:region];
}
-(void)setOpaque:(BOOL)opaque
@@ -124,44 +188,14 @@
self->_isOpaque = opaque;
}
-(void)convertRegion:(const cairo_region_t *)region
toArray:(GArray **)array
andDisplay:(BOOL)display
-(void)setClip:(cairo_region_t*)region
{
NSView *root_view;
CGRect abs_bounds;
guint n_rects;
if (*array == NULL)
*array = g_array_new (FALSE, FALSE, sizeof (CGRect));
else
g_array_set_size (*array, 0);
root_view = [[self window] contentView];
abs_bounds = [self convertRect:[self bounds] toView:root_view];
n_rects = cairo_region_num_rectangles (region);
for (guint i = 0; i < n_rects; i++)
if (region != self->clip)
{
cairo_rectangle_int_t rect;
CGRect nsrect;
cairo_region_get_rectangle (region, i, &rect);
nsrect = CGRectIntersection (abs_bounds, CGRectMake (rect.x, rect.y, rect.width, rect.height));
if (!CGRectIsNull (nsrect))
g_array_append_val (*array, nsrect);
if (display)
[self setNeedsDisplayInRect:CGRectMake (rect.x - abs_bounds.origin.x,
rect.y - abs_bounds.origin.y,
rect.width, rect.height)];
g_clear_pointer (&self->clip, cairo_region_destroy);
if (region != NULL)
self->clip = cairo_region_reference (region);
}
}
-(void)setClip:(cairo_region_t*)region
{
[self convertRegion:region toArray:&self->clip andDisplay:NO];
}
@end
+5 -7
View File
@@ -19,21 +19,19 @@
*/
#include <AppKit/AppKit.h>
#include <cairo.h>
#include <glib.h>
#define GDK_IS_MACOS_CAIRO_SUBVIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoSubview class]])
@interface GdkMacosCairoSubview : NSView
{
BOOL _isOpaque;
GArray *clip;
GArray *damage;
CGImageRef image;
BOOL _isOpaque;
cairo_surface_t *cairoSurface;
cairo_region_t *clip;
}
-(void)setOpaque:(BOOL)opaque;
-(void)setImage:(CGImageRef)theImage withDamage:(cairo_region_t *)region;
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
withDamage:(cairo_region_t *)region;
-(void)setClip:(cairo_region_t*)region;
@end
+3 -83
View File
@@ -28,7 +28,6 @@
#import "GdkMacosCairoView.h"
#import "GdkMacosCairoSubview.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacossurface-private.h"
@implementation GdkMacosCairoView
@@ -59,92 +58,12 @@
[child setNeedsDisplay:needsDisplay];
}
static void
release_surface_provider (void *info,
const void *data,
size_t size)
{
cairo_surface_destroy (info);
}
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
withDamage:(cairo_region_t *)cairoRegion
{
CGImageRef image = NULL;
if (cairoSurface != NULL)
{
const CGColorRenderingIntent intent = kCGRenderingIntentDefault;
CGDataProviderRef provider;
CGColorSpaceRef rgb;
cairo_format_t format;
CGBitmapInfo bitmap = kCGBitmapByteOrder32Host;
GdkMonitor *monitor;
guint8 *framebuffer;
size_t width;
size_t height;
int rowstride;
int bpp;
int bpc;
cairo_surface_flush (cairoSurface);
format = cairo_image_surface_get_format (cairoSurface);
framebuffer = cairo_image_surface_get_data (cairoSurface);
rowstride = cairo_image_surface_get_stride (cairoSurface);
width = cairo_image_surface_get_width (cairoSurface);
height = cairo_image_surface_get_height (cairoSurface);
monitor = _gdk_macos_surface_get_best_monitor ([self gdkSurface]);
rgb = _gdk_macos_monitor_copy_colorspace (GDK_MACOS_MONITOR (monitor));
/* If we have an WCG colorspace, just take the slow path or we risk
* really screwing things up.
*/
if (CGColorSpaceIsWideGamutRGB (rgb))
{
CGColorSpaceRelease (rgb);
rgb = CGColorSpaceCreateDeviceRGB ();
}
/* Assert that our image surface was created correctly with
* 16-byte aligned pointers and strides. This is needed to
* ensure that we're working with fast paths in CoreGraphics.
*/
g_assert (format == CAIRO_FORMAT_ARGB32 || format == CAIRO_FORMAT_RGB24);
g_assert (framebuffer != NULL);
g_assert (((intptr_t)framebuffer & (intptr_t)~0xF) == (intptr_t)framebuffer);
g_assert ((rowstride & ~0xF) == rowstride);
if (format == CAIRO_FORMAT_ARGB32)
{
bitmap |= kCGImageAlphaPremultipliedFirst;
bpp = 32;
bpc = 8;
}
else
{
bitmap |= kCGImageAlphaNoneSkipFirst;
bpp = 32;
bpc = 8;
}
provider = CGDataProviderCreateWithData (cairo_surface_reference (cairoSurface),
framebuffer,
rowstride * height,
release_surface_provider);
image = CGImageCreate (width, height, bpc, bpp, rowstride, rgb, bitmap, provider, NULL, FALSE, intent);
CGDataProviderRelease (provider);
CGColorSpaceRelease (rgb);
}
for (id view in [self subviews])
[(GdkMacosCairoSubview *)view setImage:image
withDamage:cairoRegion];
if (image != NULL)
CGImageRelease (image);
[(GdkMacosCairoSubview *)view setCairoSurface:cairoSurface
withDamage:cairoRegion];
}
-(void)removeOpaqueChildren
@@ -243,6 +162,7 @@ release_surface_provider (void *info,
*/
self->transparent = [[GdkMacosCairoSubview alloc] initWithFrame:frame];
[self addSubview:self->transparent];
}
return self;
+1 -8
View File
@@ -214,14 +214,7 @@ typedef NSString *CALayerContentsGravity;
* as we are leaving maximized state.
*/
if ((style_mask & NSWindowStyleMaskTitled) == 0 && [self isOpaque])
{
GdkSurface *surface = GDK_SURFACE ([self gdkSurface]);
[self setOpaque:NO];
/* Force updating of various styling, regions, etc */
_gdk_surface_update_size (surface);
}
[self setOpaque:NO];
}
-(void)windowDidMove:(NSNotification *)aNotification
-1
View File
@@ -27,7 +27,6 @@
#include "gdkdisplaylinksource.h"
#include "gdkmacoseventsource-private.h"
#include "gdk-private.h"
static gint64 host_to_frame_clock_time (gint64 val);
+26 -79
View File
@@ -34,7 +34,6 @@ struct _GdkMacosCairoContext
GdkCairoContext parent_instance;
cairo_surface_t *window_surface;
cairo_t *cr;
};
struct _GdkMacosCairoContextClass
@@ -47,66 +46,30 @@ G_DEFINE_TYPE (GdkMacosCairoContext, _gdk_macos_cairo_context, GDK_TYPE_CAIRO_CO
static cairo_surface_t *
create_cairo_surface_for_surface (GdkSurface *surface)
{
static const cairo_user_data_key_t buffer_key;
cairo_surface_t *cairo_surface;
guint8 *data;
cairo_format_t format;
size_t size;
size_t rowstride;
size_t width;
size_t height;
int scale;
int width;
int height;
g_assert (GDK_IS_MACOS_SURFACE (surface));
/* We use a cairo image surface here instead of a quartz surface because
* we get strange artifacts with the quartz surface such as empty
* cross-fades when hovering buttons. For performance, we want to be using
* GL rendering so there isn't much point here as correctness is better.
*
* Additionally, so we can take avantage of faster paths in Core
* Graphics, we want our data pointer to be 16-byte aligned and our rows
* to be 16-byte aligned or we risk errors below us. Normally, cairo
* image surface does not guarantee the later, which means we could end
* up doing some costly copies along the way to compositing.
*/
if ([GDK_MACOS_SURFACE (surface)->window isOpaque])
format = CAIRO_FORMAT_RGB24;
else
format = CAIRO_FORMAT_ARGB32;
scale = gdk_surface_get_scale_factor (surface);
width = scale * gdk_surface_get_width (surface);
height = scale * gdk_surface_get_height (surface);
rowstride = (cairo_format_stride_for_width (format, width) + 0xF) & ~0xF;
size = rowstride * height;
data = g_malloc0 (size);
cairo_surface = cairo_image_surface_create_for_data (data, format, width, height, rowstride);
cairo_surface_set_user_data (cairo_surface, &buffer_key, data, g_free);
cairo_surface_set_device_scale (cairo_surface, scale, scale);
/* We use a cairo image surface here instead of a quartz surface because we
* get strange artifacts with the quartz surface such as empty cross-fades
* when hovering buttons. For performance, we want to be using GL rendering
* so there isn't much point here as correctness is better.
*/
cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
if (cairo_surface != NULL)
cairo_surface_set_device_scale (cairo_surface, scale, scale);
return cairo_surface;
}
static cairo_t *
do_cairo_create (GdkMacosCairoContext *self)
{
GdkSurface *surface;
cairo_t *cr;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
cr = cairo_create (self->window_surface);
/* Draw upside down as quartz prefers */
cairo_translate (cr, 0, surface->height);
cairo_scale (cr, 1.0, -1.0);
return cr;
}
static cairo_t *
_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
{
@@ -114,10 +77,7 @@ _gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
if (self->cr != NULL)
return cairo_reference (self->cr);
return do_cairo_create (self);
return cairo_create (self->window_surface);
}
static void
@@ -135,18 +95,20 @@ _gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
if (self->window_surface == NULL)
self->window_surface = create_cairo_surface_for_surface (surface);
self->cr = do_cairo_create (self);
if (![nswindow isOpaque])
{
cairo_save (self->cr);
gdk_cairo_region (self->cr, region);
cairo_set_source_rgba (self->cr, 0, 0, 0, 0);
cairo_set_operator (self->cr, CAIRO_OPERATOR_SOURCE);
cairo_fill (self->cr);
cairo_restore (self->cr);
self->window_surface = create_cairo_surface_for_surface (surface);
}
else
{
if (![nswindow isOpaque])
{
cairo_t *cr = cairo_create (self->window_surface);
gdk_cairo_region (cr, region);
cairo_set_source_rgba (cr, 0, 0, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_fill (cr);
cairo_destroy (cr);
}
}
}
@@ -164,8 +126,6 @@ _gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
surface = gdk_draw_context_get_surface (draw_context);
nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
g_clear_pointer (&self->cr, cairo_destroy);
if (GDK_IS_MACOS_CAIRO_VIEW (nsview))
[(GdkMacosCairoView *)nsview setCairoSurface:self->window_surface
withDamage:painted];
@@ -181,25 +141,12 @@ _gdk_macos_cairo_context_surface_resized (GdkDrawContext *draw_context)
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
}
static void
_gdk_macos_cairo_context_dispose (GObject *object)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)object;
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
G_OBJECT_CLASS (_gdk_macos_cairo_context_parent_class)->dispose (object);
}
static void
_gdk_macos_cairo_context_class_init (GdkMacosCairoContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
object_class->dispose = _gdk_macos_cairo_context_dispose;
draw_context_class->begin_frame = _gdk_macos_cairo_context_begin_frame;
draw_context_class->end_frame = _gdk_macos_cairo_context_end_frame;
draw_context_class->surface_resized = _gdk_macos_cairo_context_surface_resized;
-1
View File
@@ -537,7 +537,6 @@ fill_pinch_event (GdkMacosDisplay *display,
seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
return gdk_touchpad_event_new_pinch (GDK_SURFACE (surface),
NULL, /* FIXME make up sequences */
gdk_seat_get_pointer (seat),
get_time_from_ns_event (nsevent),
get_keyboard_modifiers_from_ns_event (nsevent),
+5 -14
View File
@@ -301,14 +301,10 @@ gdk_macos_display_frame_cb (gpointer data)
iter = iter->next;
_gdk_macos_surface_publish_timings (surface,
source->presentation_time,
source->refresh_interval);
_gdk_macos_display_remove_frame_callback (self, surface);
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
gdk_surface_thaw_updates (GDK_SURFACE (surface));
_gdk_macos_surface_thaw (surface,
source->presentation_time,
source->refresh_interval);
}
return G_SOURCE_CONTINUE;
@@ -730,8 +726,7 @@ _gdk_macos_display_open (const char *display_name)
if (self != NULL)
return NULL;
display_name = display_name ? display_name : "";
GDK_NOTE (MISC, g_message ("opening display %s", display_name));
GDK_NOTE (MISC, g_message ("opening display %s", display_name ? display_name : ""));
/* Make the current process a foreground application, i.e. an app
* with a user interface, in case we're not running from a .app bundle
@@ -992,11 +987,7 @@ _gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
if (!queue_contains (&self->awaiting_frames, &surface->frame))
{
/* Processing frames is always head to tail, so push to the
* head so that we don't possibly re-enter this right after
* adding to the queue.
*/
g_queue_push_head_link (&self->awaiting_frames, &surface->frame);
g_queue_push_tail_link (&self->awaiting_frames, &surface->frame);
if (self->awaiting_frames.length == 1)
gdk_display_link_source_unpause ((GdkDisplayLinkSource *)self->frame_source);
+4 -5
View File
@@ -29,11 +29,10 @@
G_BEGIN_DECLS
GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay *display,
CGDirectDisplayID screen_id);
CGDirectDisplayID _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self);
gboolean _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self);
CGColorSpaceRef _gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self);
GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay *display,
CGDirectDisplayID screen_id);
CGDirectDisplayID _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self);
gboolean _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self);
G_END_DECLS
-8
View File
@@ -298,11 +298,3 @@ _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self)
return self->screen_id;
}
CGColorSpaceRef
_gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self)
{
g_return_val_if_fail (GDK_IS_MACOS_MONITOR (self), NULL);
return CGDisplayCopyColorSpace (self->screen_id);
}
-4
View File
@@ -204,10 +204,6 @@ static void
_gdk_macos_popup_surface_finalize (GObject *object)
{
GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)object;
GdkSurface *parent = GDK_SURFACE (self)->parent;
if (parent != NULL)
parent->children = g_list_remove (parent->children, self);
g_clear_object (&GDK_SURFACE (self)->parent);
g_clear_pointer (&self->layout, gdk_popup_layout_unref);
+1 -1
View File
@@ -104,7 +104,7 @@ void _gdk_macos_surface_resize (GdkMacosSurface
void _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self);
void _gdk_macos_surface_update_position (GdkMacosSurface *self);
void _gdk_macos_surface_show (GdkMacosSurface *self);
void _gdk_macos_surface_publish_timings (GdkMacosSurface *self,
void _gdk_macos_surface_thaw (GdkMacosSurface *self,
gint64 predicted_presentation_time,
gint64 refresh_interval);
CGContextRef _gdk_macos_surface_acquire_context (GdkMacosSurface *self,
+13 -24
View File
@@ -125,8 +125,6 @@ gdk_macos_surface_hide (GdkSurface *surface)
g_assert (GDK_IS_MACOS_SURFACE (self));
_gdk_macos_display_remove_frame_callback (GDK_MACOS_DISPLAY (surface->display), self);
was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
seat = gdk_display_get_default_seat (surface->display);
@@ -192,20 +190,15 @@ gdk_macos_surface_end_frame (GdkMacosSurface *self)
g_assert (GDK_IS_MACOS_SURFACE (self));
if (GDK_SURFACE_DESTROYED (self))
return;
display = gdk_surface_get_display (GDK_SURFACE (self));
frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
if ((timings = gdk_frame_clock_get_current_timings (frame_clock)))
self->pending_frame_counter = timings->frame_counter;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
{
_gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
gdk_surface_freeze_updates (GDK_SURFACE (self));
}
_gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
gdk_surface_freeze_updates (GDK_SURFACE (self));
}
static void
@@ -217,11 +210,10 @@ gdk_macos_surface_before_paint (GdkMacosSurface *self,
g_assert (GDK_IS_MACOS_SURFACE (self));
g_assert (GDK_IS_FRAME_CLOCK (frame_clock));
if (GDK_SURFACE_DESTROYED (self))
if (surface->update_freeze_count > 0)
return;
if (surface->update_freeze_count == 0)
gdk_macos_surface_begin_frame (self);
gdk_macos_surface_begin_frame (self);
}
static void
@@ -233,11 +225,10 @@ gdk_macos_surface_after_paint (GdkMacosSurface *self,
g_assert (GDK_IS_MACOS_SURFACE (self));
g_assert (GDK_IS_FRAME_CLOCK (frame_clock));
if (GDK_SURFACE_DESTROYED (self))
if (surface->update_freeze_count > 0)
return;
if (surface->update_freeze_count == 0)
gdk_macos_surface_end_frame (self);
gdk_macos_surface_end_frame (self);
}
static void
@@ -724,17 +715,18 @@ _gdk_macos_surface_update_position (GdkMacosSurface *self)
}
void
_gdk_macos_surface_publish_timings (GdkMacosSurface *self,
gint64 presentation_time,
gint64 refresh_interval)
_gdk_macos_surface_thaw (GdkMacosSurface *self,
gint64 presentation_time,
gint64 refresh_interval)
{
GdkFrameTimings *timings;
GdkFrameClock *frame_clock;
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
if (!(frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
return;
gdk_surface_thaw_updates (GDK_SURFACE (self));
frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
if (self->pending_frame_counter)
{
@@ -994,9 +986,6 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
g_object_unref (monitor);
}
_gdk_surface_update_size (GDK_SURFACE (self));
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
}
GdkMonitor *
+1 -1
View File
@@ -181,8 +181,8 @@ gdk_wayland_cairo_context_end_frame (GdkDrawContext *draw_context,
GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context);
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
gdk_wayland_surface_sync (surface);
gdk_wayland_surface_attach_image (surface, self->paint_surface, painted);
gdk_wayland_surface_sync (surface);
gdk_wayland_surface_request_frame (surface);
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "wayland", "surface commit");
+4 -105
View File
@@ -137,7 +137,6 @@ struct _GdkWaylandPointerData {
guint cursor_timeout_id;
guint cursor_image_index;
guint cursor_image_delay;
guint touchpad_event_sequence;
guint current_output_scale;
GSList *pointer_surface_outputs;
@@ -227,7 +226,6 @@ struct _GdkWaylandSeat
struct wl_touch *wl_touch;
struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe;
struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch;
struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold;
struct zwp_tablet_seat_v2 *wp_tablet_seat;
GdkDisplay *display;
@@ -1129,7 +1127,7 @@ data_offer_source_actions (void *data,
seat->pending_source_actions = gdk_wayland_actions_to_gdk_actions (source_actions);
return;
}
if (seat->drop == NULL)
return;
@@ -1154,7 +1152,7 @@ data_offer_action (void *data,
seat->pending_action = gdk_wayland_actions_to_gdk_actions (action);
return;
}
if (seat->drop == NULL)
return;
@@ -2166,7 +2164,7 @@ deliver_key_event (GdkWaylandSeat *seat,
key,
device_get_modifiers (seat->logical_pointer),
_gdk_wayland_keymap_key_is_modifier (keymap, key),
&translated,
&translated,
&no_lock);
_gdk_wayland_display_deliver_event (seat->display, event);
@@ -2669,11 +2667,7 @@ emit_gesture_swipe_event (GdkWaylandSeat *seat,
seat->pointer_info.time = _time;
if (phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)
seat->pointer_info.touchpad_event_sequence++;
event = gdk_touchpad_event_new_swipe (seat->pointer_info.focus,
GDK_SLOT_TO_EVENT_SEQUENCE (seat->pointer_info.touchpad_event_sequence),
seat->logical_pointer,
_time,
device_get_modifiers (seat->logical_pointer),
@@ -2769,11 +2763,7 @@ emit_gesture_pinch_event (GdkWaylandSeat *seat,
seat->pointer_info.time = _time;
if (phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)
seat->pointer_info.touchpad_event_sequence++;
event = gdk_touchpad_event_new_pinch (seat->pointer_info.focus,
GDK_SLOT_TO_EVENT_SEQUENCE (seat->pointer_info.touchpad_event_sequence),
seat->logical_pointer,
_time,
device_get_modifiers (seat->logical_pointer),
@@ -2857,81 +2847,6 @@ gesture_pinch_end (void *data,
0, 0, 1, 0);
}
static void
emit_gesture_hold_event (GdkWaylandSeat *seat,
GdkTouchpadGesturePhase phase,
guint32 _time,
guint32 n_fingers)
{
GdkEvent *event;
if (!seat->pointer_info.focus)
return;
seat->pointer_info.time = _time;
event = gdk_touchpad_event_new_hold (seat->pointer_info.focus,
seat->logical_pointer,
_time,
device_get_modifiers (seat->logical_pointer),
phase,
seat->pointer_info.surface_x,
seat->pointer_info.surface_y,
n_fingers);
if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS))
{
double x, y;
gdk_event_get_position (event, &x, &y);
g_message ("hold event %d, coords: %f %f, seat %p state %d",
gdk_event_get_event_type (event),
x, y, seat,
gdk_event_get_modifier_state (event));
}
_gdk_wayland_display_deliver_event (seat->display, event);
}
static void
gesture_hold_begin (void *data,
struct zwp_pointer_gesture_hold_v1 *hold,
uint32_t serial,
uint32_t time,
struct wl_surface *surface,
uint32_t fingers)
{
GdkWaylandSeat *seat = data;
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display);
_gdk_wayland_display_update_serial (display, serial);
emit_gesture_hold_event (seat,
GDK_TOUCHPAD_GESTURE_PHASE_BEGIN,
time, fingers);
seat->gesture_n_fingers = fingers;
}
static void
gesture_hold_end (void *data,
struct zwp_pointer_gesture_hold_v1 *hold,
uint32_t serial,
uint32_t time,
int32_t cancelled)
{
GdkWaylandSeat *seat = data;
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display);
GdkTouchpadGesturePhase phase;
_gdk_wayland_display_update_serial (display, serial);
phase = (cancelled) ?
GDK_TOUCHPAD_GESTURE_PHASE_CANCEL :
GDK_TOUCHPAD_GESTURE_PHASE_END;
emit_gesture_hold_event (seat, phase, time,
seat->gesture_n_fingers);
}
static void
_gdk_wayland_seat_remove_tool (GdkWaylandSeat *seat,
GdkWaylandTabletToolData *tool)
@@ -3141,11 +3056,6 @@ static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener
gesture_pinch_end
};
static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = {
gesture_hold_begin,
gesture_hold_end
};
static const struct zwp_tablet_v2_listener tablet_listener = {
tablet_handle_name,
tablet_handle_id,
@@ -3201,17 +3111,6 @@ seat_handle_capabilities (void *data,
seat);
zwp_pointer_gesture_pinch_v1_add_listener (seat->wp_pointer_gesture_pinch,
&gesture_pinch_listener, seat);
if (display_wayland->pointer_gestures_version >= ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION)
{
seat->wp_pointer_gesture_hold =
zwp_pointer_gestures_v1_get_hold_gesture (display_wayland->pointer_gestures,
seat->wl_pointer);
zwp_pointer_gesture_hold_v1_set_user_data (seat->wp_pointer_gesture_hold,
seat);
zwp_pointer_gesture_hold_v1_add_listener (seat->wp_pointer_gesture_hold,
&gesture_hold_listener, seat);
}
}
}
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer)
@@ -4189,7 +4088,7 @@ tablet_pad_strip_handle_frame (void *data,
event = gdk_pad_event_new_strip (seat->keyboard_focus,
pad->device,
time,
g_list_index (pad->mode_groups, group),
g_list_index (pad->mode_groups, group),
g_list_index (pad->strips, wp_tablet_pad_strip),
group->current_mode,
group->axis_tmp_info.value);
+1 -48
View File
@@ -366,8 +366,7 @@ gdk_registry_handle_global (void *data,
if (strcmp (interface, "wl_compositor") == 0)
{
display_wayland->compositor =
wl_registry_bind (display_wayland->wl_registry, id,
&wl_compositor_interface, MIN (version, 5));
wl_registry_bind (display_wayland->wl_registry, id, &wl_compositor_interface, MIN (version, 4));
display_wayland->compositor_version = MIN (version, 4);
}
else if (strcmp (interface, "wl_shm") == 0)
@@ -431,9 +430,6 @@ gdk_registry_handle_global (void *data,
}
else if (strcmp (interface, "zwp_pointer_gestures_v1") == 0)
{
display_wayland->pointer_gestures_version =
MIN (version, GDK_ZWP_POINTER_GESTURES_V1_VERSION);
display_wayland->pointer_gestures =
wl_registry_bind (display_wayland->wl_registry,
id, &zwp_pointer_gestures_v1_interface,
@@ -1666,7 +1662,6 @@ static TranslationEntry translations[] = {
{ FALSE, "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } },
{ FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } },
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } },
{ FALSE, "org.gnome.desktop.a11y.interface", "high-contrast", "high-contast", G_TYPE_NONE, { .b = FALSE } },
/* Note, this setting doesn't exist, the portal and gsd fake it */
{ FALSE, "org.gnome.fontconfig", "serial", "gtk-fontconfig-timestamp", G_TYPE_NONE, { .i = 0 } },
};
@@ -1716,13 +1711,6 @@ find_translation_entry_by_setting (const char *setting)
return NULL;
}
static void
high_contrast_changed (GdkDisplay *display)
{
gdk_display_setting_changed (display, "gtk-theme-name");
gdk_display_setting_changed (display, "gtk-icon-theme-name");
}
static void
settings_changed (GSettings *settings,
const char *key,
@@ -1736,8 +1724,6 @@ settings_changed (GSettings *settings,
{
if (entry->type != G_TYPE_NONE)
gdk_display_setting_changed (display, entry->setting);
else if (strcmp (key, "high-contrast") == 0)
high_contrast_changed (display);
else
update_xft_settings (display);
}
@@ -2104,36 +2090,6 @@ set_decoration_layout_from_entry (GdkDisplay *display,
}
}
static void
set_theme_from_entry (GdkDisplay *display,
TranslationEntry *entry,
GValue *value)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GSettings *settings = NULL;
GSettingsSchema *schema = NULL;
gboolean hc = FALSE;
if (display_wayland->settings_portal == NULL)
{
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings,
"org.gnome.desktop.a11y.interface");
}
if (settings)
g_object_get (settings, "settings-schema", &schema, NULL);
if (schema && g_settings_schema_has_key (schema, "high-contrast"))
hc = g_settings_get_boolean (settings, "high-contrast");
g_clear_pointer (&schema, g_settings_schema_unref);
if (hc)
g_value_set_static_string (value, "HighContrast");
else
set_value_from_entry (display, entry, value);
}
static gboolean
set_capability_setting (GdkDisplay *display,
GValue *value,
@@ -2165,9 +2121,6 @@ gdk_wayland_display_get_setting (GdkDisplay *display,
{
if (strcmp (name, "gtk-decoration-layout") == 0)
set_decoration_layout_from_entry (display, entry, value);
else if (strcmp (name, "gtk-theme-name") == 0 ||
strcmp (name, "gtk-icon-theme-name") == 0)
set_theme_from_entry (display, entry, value);
else
set_value_from_entry (display, entry, value);
return TRUE;
+1 -2
View File
@@ -52,7 +52,7 @@
G_BEGIN_DECLS
#define GDK_ZWP_POINTER_GESTURES_V1_VERSION 3
#define GDK_ZWP_POINTER_GESTURES_V1_VERSION 1
typedef struct _GdkWaylandSelection GdkWaylandSelection;
@@ -140,7 +140,6 @@ struct _GdkWaylandDisplay
int data_device_manager_version;
int gtk_shell_version;
int xdg_output_manager_version;
int pointer_gestures_version;
int xdg_activation_version;
uint32_t server_decoration_mode;
-1
View File
@@ -101,7 +101,6 @@ gdk_wayland_primary_claim_remote (GdkWaylandPrimary *cb,
{
GDK_DISPLAY_NOTE (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)), CLIPBOARD, g_message ("%p: Ignoring clipboard offer for self", cb));
gdk_content_formats_unref (formats);
g_clear_pointer (&offer, zwp_primary_selection_offer_v1_destroy);
return;
}
+25 -45
View File
@@ -118,6 +118,7 @@ struct _GdkWaylandSurface
unsigned int mapped : 1;
unsigned int awaiting_frame : 1;
unsigned int awaiting_frame_frozen : 1;
unsigned int is_drag_surface : 1;
int pending_buffer_offset_x;
int pending_buffer_offset_y;
@@ -779,22 +780,11 @@ gdk_wayland_surface_update_scale (GdkSurface *surface)
return;
}
if (!impl->display_server.outputs)
scale = 1;
for (l = impl->display_server.outputs; l != NULL; l = l->next)
{
scale = impl->scale;
}
else
{
scale = 1;
for (l = impl->display_server.outputs; l != NULL; l = l->next)
{
struct wl_output *output = l->data;
uint32_t output_scale;
output_scale = gdk_wayland_display_get_output_scale (display_wayland,
output);
scale = MAX (scale, output_scale);
}
guint32 output_scale = gdk_wayland_display_get_output_scale (display_wayland, l->data);
scale = MAX (scale, output_scale);
}
/* Notify app that scale changed */
@@ -935,33 +925,12 @@ gdk_wayland_surface_attach_image (GdkSurface *surface,
}
}
static void
gdk_wayland_surface_sync_offset (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
if (wl_surface_get_version (impl->display_server.wl_surface) <
WL_SURFACE_OFFSET_SINCE_VERSION)
return;
if (impl->pending_buffer_offset_x == 0 &&
impl->pending_buffer_offset_y == 0)
return;
wl_surface_offset (impl->display_server.wl_surface,
impl->pending_buffer_offset_x,
impl->pending_buffer_offset_y);
impl->pending_buffer_offset_x = 0;
impl->pending_buffer_offset_y = 0;
}
void
gdk_wayland_surface_sync (GdkSurface *surface)
{
gdk_wayland_surface_sync_shadow (surface);
gdk_wayland_surface_sync_opaque_region (surface);
gdk_wayland_surface_sync_input_region (surface);
gdk_wayland_surface_sync_offset (surface);
}
static gboolean
@@ -1498,7 +1467,6 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
int width, height;
gboolean is_resizing;
gboolean fixed_size;
gboolean was_fixed_size;
gboolean saved_size;
new_state = impl->pending.toplevel.state;
@@ -1513,11 +1481,6 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
GDK_TOPLEVEL_STATE_TILED) ||
is_resizing;
was_fixed_size =
surface->state & (GDK_TOPLEVEL_STATE_MAXIMIZED |
GDK_TOPLEVEL_STATE_FULLSCREEN |
GDK_TOPLEVEL_STATE_TILED);
width = impl->pending.toplevel.width;
height = impl->pending.toplevel.height;
@@ -1530,7 +1493,7 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
* the client should configure its size back to what it was before
* being maximize or fullscreen.
*/
if (saved_size && !fixed_size && was_fixed_size)
if (saved_size && !fixed_size)
{
width = impl->saved_width;
height = impl->saved_height;
@@ -2320,7 +2283,8 @@ gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel)
if (!wayland_toplevel->idle_inhibitor)
{
g_assert (wayland_toplevel->idle_inhibitor_refcount == 0);
g_assert (wayland_toplevel->idle_inhibitor &&
wayland_toplevel->idle_inhibitor_refcount > 0);
wayland_toplevel->idle_inhibitor =
zwp_idle_inhibit_manager_v1_create_inhibitor (display_wayland->idle_inhibit_manager,
@@ -2861,12 +2825,27 @@ find_grab_input_seat (GdkSurface *surface,
return NULL;
}
static gboolean
should_be_mapped (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
/* Don't map crazy temp that GTK uses for internal X11 shenanigans. */
if (GDK_IS_DRAG_SURFACE (surface) && surface->x < 0 && surface->y < 0)
return FALSE;
if (impl->is_drag_surface)
return FALSE;
return TRUE;
}
static void
gdk_wayland_surface_map_toplevel (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
if (!GDK_IS_WAYLAND_TOPLEVEL (surface))
if (!should_be_mapped (surface))
return;
if (impl->mapped)
@@ -4724,6 +4703,7 @@ create_dnd_surface (GdkDisplay *display)
GDK_SURFACE_TEMP,
NULL,
0, 0, 100, 100);
GDK_WAYLAND_SURFACE (surface)->is_drag_surface = TRUE;
return surface;
}
+1 -1
View File
@@ -71,7 +71,7 @@ foreach p: proto_sources
elif proto_stability == 'staging'
proto_version = p.get(2)
output_base = '@0@-@1@'.format(proto_name, proto_version)
input = files(join_paths(wlproto_dir, '@0@/@1@/@2@.xml'.format(proto_stability, proto_name, output_base)))
input = join_paths(wlproto_dir, '@0@/@1@/@2@.xml'.format(proto_stability, proto_name, output_base))
elif proto_stability == 'private'
output_base = proto_name
input = files('protocol/@0@.xml'.format(proto_name))
+406
View File
@@ -0,0 +1,406 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2001 Stefan Ondrejicka
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
#include <glib.h>
typedef struct {
char *name;
int id;
char *bitmap;
int hotx;
int hoty;
} font_info_t;
typedef struct {
char *name;
int id;
int width;
int height;
int hotx;
int hoty;
char *data;
} cursor_info_t;
static GSList *fonts = NULL;
static GSList *cursors = NULL;
static int dw,dh;
static gboolean debug = FALSE;
#define HEX(c) (((c) >= '0' && (c) <= '9') ? \
((c) - '0') : (toupper(c) - 'A' + 10))
static void print_font(fi)
font_info_t *fi;
{
int x,y;
for (y = 0; y < dh; y++)
{
for (x = 0; x < dw; x++)
{
printf(fi->bitmap[y*dw+x]? "X" : " ");
}
printf("\n");
}
}
static void print_cursor(ci)
cursor_info_t *ci;
{
int x,y;
for (y = 0; y < ci->height; y++)
{
printf("/* ");
for (x = 0; x < ci->width; x++)
{
if (ci->hotx == x && ci->hoty == y)
printf("o");
else
switch (ci->data[y*ci->width+x])
{
case 0:
printf(" ");
break;
case 1:
printf(".");
break;
case 2:
printf("X");
break;
}
}
printf(" */\n");
}
}
static int read_bdf_font(fname)
char *fname;
{
FILE *f;
char line[2048];
int rv = 0;
gboolean startchar = FALSE, startbitmap = FALSE;
char *charname,*p,*bitmap;
int dx = 0,dy = 0;
int w,h,x,y,py;
int id,tmp;
dw = 0;
dh = 0;
if (!(f = fopen(fname, "r")))
{
perror(fname);
return -1;
}
if (fgets(line, sizeof(line), f) && strncasecmp("STARTFONT ", line, 10))
{
printf("!BDF font file\n");
fclose(f);
return -1;
}
p = line;
while (fgets(line, sizeof(line), f))
{
if (!startchar)
{
if (!strncasecmp("STARTCHAR ", line, 10))
{
startchar = TRUE;
charname = g_strndup(p + 10,
strcspn(p+10, "\r\n"));
}
else if (!strncasecmp("FONTBOUNDINGBOX ", line, 16))
sscanf(p+16, "%d %d %d %d", &dw, &dh, &dx, &dy);
}
else
{
if (!strncasecmp("ENDCHAR", line, 7))
{
font_info_t *nfi;
if (debug)
printf(" %*s*/\n", dw, "");
startchar = FALSE;
startbitmap = FALSE;
nfi = g_malloc(sizeof(font_info_t));
memset(nfi, '\0', sizeof(font_info_t));
nfi->name = charname;
nfi->id = id;
nfi->bitmap = bitmap;
nfi->hotx = 0 - dx;
nfi->hoty = 0 - dy;
fonts = g_slist_append(fonts, nfi);
}
else if (startbitmap)
{
int px,cx;
guchar mask;
px = x - dx + py * dw;
for (cx = 0; cx < w; cx++)
{
mask = 1 << (3 - (cx % 4));
bitmap[px+cx] =
(mask & HEX(line[cx/4])) != 0;
if (debug)
printf(bitmap[px+cx] ? "X" : " ");
}
py++;
if (debug)
printf(" %*s*/\n/* %*s", dw-w, "", dw+dx, "");
}
else if (!strncasecmp("BBX ", line, 4))
{
sscanf(p+4, "%d %d %d %d", &w, &h, &x, &y);
if (debug)
printf("/* %s: */\n/* %*s", charname, dw+dx, "");
}
else if (!strncasecmp("ENCODING ", line, 9))
{
if (sscanf(p+9, "%d %d", &tmp, &id) != 2)
id = tmp;
}
else if (!strncasecmp("BITMAP", line, 6))
{
py = y - dy;
startbitmap = TRUE;
bitmap = g_malloc(dw*dh);
memset(bitmap, '\0', dw*dh);
}
}
}
if (strncasecmp("ENDFONT", line, 7))
rv = -1;
fclose(f);
return rv;
}
static int font_info_compare(fi, name)
font_info_t *fi;
char *name;
{
return strcmp(name, fi->name);
}
static cursor_info_t *gen_cursor(bmap, mask)
font_info_t *bmap;
font_info_t *mask;
{
cursor_info_t *ci;
int bx = dw,by = dh,ex = 0,ey = 0;
int i,j;
for (j = 0; j < dh; j++)
{
gboolean havep = FALSE;
for (i = 0; i < dw; i++)
{
if (bmap->bitmap[j*dw+i] || mask->bitmap[j*dw+i])
{
havep = TRUE;
bx = MIN(bx, i);
ex = MAX(i+1, ex);
}
}
if (havep)
{
by = MIN(by, j);
ey = MAX(ey, j+1);
}
}
ci = g_malloc(sizeof(cursor_info_t));
ci->name = g_strdup(bmap->name);
ci->id = bmap->id;
ci->width = ex - bx;
ci->height = ey - by;
ci->hotx = bmap->hotx - bx;
ci->hoty = ci->height - (bmap->hoty - by);
ci->data = g_malloc(ci->width * ci->height);
memset(ci->data, '\0', ci->width * ci->height);
for (j = 0; j < ci->height; j++)
{
for (i = 0; i < ci->width; i++)
{
int ofs = (by + j) * dw + bx + i;
ci->data[j*ci->width + i] = mask->bitmap[ofs] *
(1 + bmap->bitmap[ofs]);
}
}
return ci;
}
static void compose_cursors_from_fonts()
{
GSList *l;
for (l = g_slist_copy (fonts); l; l = g_slist_delete_link (l,l))
{
font_info_t *fi = l->data;
char *name;
GSList *ml;
name = g_strconcat(fi->name, "_mask", NULL);
if ((ml = g_slist_find_custom(fonts, name,
(GCompareFunc) font_info_compare)))
{
cursors = g_slist_append(cursors, gen_cursor(l->data, ml->data));
fonts = g_slist_remove(fonts, l->data);
fonts = g_slist_remove(fonts, ml->data);
}
g_free(name);
}
}
static char *dump_cursor(ci, id)
cursor_info_t *ci;
int id;
{
static char cdata[8192];
char *p;
int i;
int c;
gboolean flushed;
sprintf(cdata, " { \"%s\", %d, %d, %d, %d, %d, \n \"",
ci->name, ci->id, ci->width, ci->height, ci->hotx, ci->hoty);
p = cdata + strlen(cdata);
for (i = 0; i < ci->width * ci->height; i++)
{
flushed = FALSE;
if (!(i%4))
c = 0;
c = c << 2;
c += ci->data[i];
if ((i % 4) == 3)
{
flushed = TRUE;
sprintf(p, "\\%03o", c);
p += strlen(p);
}
if (i > 0 && !(i % 64))
{
strcpy(p ,"\"\n \"");
p += strlen(p);
}
}
if (!flushed)
{
sprintf(p, "\\%03o", c);
p += strlen(p);
}
strcpy(p, "\" }");
return cdata;
}
static int dump_cursors()
{
GSList *ptr;
FILE *f = stdout;
fprintf(f, "static const struct { const char *name; int type; guchar width; guchar height; guchar hotx; guchar hoty; guchar *data; } cursors[] = {\n");
for (ptr = cursors; ptr; ptr = ptr->next)
{
if (debug)
print_cursor(ptr->data);
fprintf(f, "%s, \n", dump_cursor(ptr->data));
}
fprintf(f, " { NULL, 0, 0, 0, 0, 0, NULL },\n};\n");
return 0;
}
int main(argc, argv)
int argc;
char **argv;
{
if (argc != 2)
{
printf("missing parameters !\n");
printf("Usage: %s [BDF cursor file]\n", argv[0]);
return -1;
}
if (g_getenv ("BDFCURSOR_DEBUG") != NULL)
debug = TRUE;
if (read_bdf_font(argv[1]) || !fonts)
{
printf("Error reading font\n");
return 1;
}
compose_cursors_from_fonts();
if (!cursors)
{
printf("failed to generate cursors from font!\n");
return 1;
}
dump_cursors();
if (fonts)
{
printf("some fonts remained unconverted!\n");
return 1;
}
return 0;
}
+3385
View File
File diff suppressed because it is too large Load Diff
+54 -80
View File
@@ -945,71 +945,38 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display)
}
}
gboolean
_gdk_win32_check_processor (GdkWin32ProcessorCheckType check_type)
static void
_gdk_win32_check_on_arm64 (GdkWin32Display *display)
{
static gsize checked = 0;
static gboolean is_arm64 = FALSE;
static gboolean is_wow64 = FALSE;
if (g_once_init_enter (&checked))
{
gboolean fallback_wow64_check = FALSE;
HMODULE kernel32 = LoadLibraryW (L"kernel32.dll");
if (kernel32 != NULL)
{
typedef BOOL (WINAPI *funcIsWow64Process2) (HANDLE, USHORT *, USHORT *);
funcIsWow64Process2 isWow64Process2 =
display->cpu_funcs.isWow64Process2 =
(funcIsWow64Process2) GetProcAddress (kernel32, "IsWow64Process2");
if (isWow64Process2 != NULL)
if (display->cpu_funcs.isWow64Process2 != NULL)
{
USHORT proc_cpu = 0;
USHORT native_cpu = 0;
isWow64Process2 (GetCurrentProcess (), &proc_cpu, &native_cpu);
display->cpu_funcs.isWow64Process2 (GetCurrentProcess (),
&proc_cpu,
&native_cpu);
if (native_cpu == IMAGE_FILE_MACHINE_ARM64)
is_arm64 = TRUE;
if (proc_cpu != IMAGE_FILE_MACHINE_UNKNOWN)
is_wow64 = TRUE;
}
else
{
fallback_wow64_check = TRUE;
display->running_on_arm64 = TRUE;
}
FreeLibrary (kernel32);
}
else
{
fallback_wow64_check = TRUE;
}
if (fallback_wow64_check)
IsWow64Process (GetCurrentProcess (), &is_wow64);
g_once_init_leave (&checked, 1);
}
switch (check_type)
{
case GDK_WIN32_ARM64:
return is_arm64;
break;
case GDK_WIN32_WOW64:
return is_wow64;
break;
default:
g_warning ("unknown CPU check type");
return FALSE;
break;
}
}
static void
@@ -1020,7 +987,7 @@ gdk_win32_display_init (GdkWin32Display *display_win32)
display_win32->monitors = G_LIST_MODEL (g_list_store_new (GDK_TYPE_MONITOR));
_gdk_win32_enable_hidpi (display_win32);
display_win32->running_on_arm64 = _gdk_win32_check_processor (GDK_WIN32_ARM64);
_gdk_win32_check_on_arm64 (display_win32);
/* if we have DPI awareness, set up fixed scale if set */
if (display_win32->dpi_aware_type != PROCESS_DPI_UNAWARE &&
@@ -1175,18 +1142,16 @@ gdk_win32_display_get_setting (GdkDisplay *display,
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#endif
static GdkGLContext *
gdk_win32_display_init_gl (GdkDisplay *display,
GError **error)
static gboolean
gdk_win32_display_init_gl_backend (GdkDisplay *display,
GError **error)
{
gboolean result = FALSE;
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
HDC init_gl_hdc = NULL;
if (display_win32->dummy_context_wgl.hdc == NULL)
display_win32->dummy_context_wgl.hdc = GetDC (display_win32->hwnd);
init_gl_hdc = display_win32->dummy_context_wgl.hdc;
/*
* No env vars set, do the regular GL initialization, first WGL and then EGL,
* as WGL is the more tried-and-tested configuration.
@@ -1194,50 +1159,59 @@ gdk_win32_display_init_gl (GdkDisplay *display,
#ifdef HAVE_EGL
/*
* Disable defaulting to EGL as EGL is used more as a compatibility layer
* Disable defaulting to EGL for now, since shaders need to be fixed for
* usage against libANGLE EGL. EGL is used more as a compatibility layer
* on Windows rather than being a native citizen on Windows
*/
if (GDK_DEBUG_CHECK (GL_EGL) || GDK_DEBUG_CHECK (GL_GLES))
{
if (gdk_display_init_egl (display,
EGL_PLATFORM_ANGLE_ANGLE,
init_gl_hdc,
FALSE,
error))
{
return g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_EGL,
"display", display,
NULL);
}
else
g_clear_error (error);
}
if (_gdk_debug_flags & GDK_DEBUG_GL_EGL)
result = gdk_display_init_egl (display,
EGL_PLATFORM_ANGLE_ANGLE,
display_win32->dummy_context_wgl.hdc,
FALSE,
error);
#endif
if (gdk_win32_display_init_wgl (display, error))
if (!result)
{
return g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_WGL,
"display", display,
NULL);
g_clear_error (error);
result = gdk_win32_display_init_wgl (display, error);
}
#ifdef HAVE_EGL
g_clear_error (error);
if (gdk_display_init_egl (display,
EGL_PLATFORM_ANGLE_ANGLE,
init_gl_hdc,
TRUE,
error))
if (!result)
{
return g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_EGL,
"display", display,
NULL);
g_clear_error (error);
result = gdk_display_init_egl (display,
EGL_PLATFORM_ANGLE_ANGLE,
display_win32->dummy_context_wgl.hdc,
TRUE,
error);
}
#endif
return NULL;
return result;
}
static GdkGLContext *
gdk_win32_display_init_gl (GdkDisplay *display,
GError **error)
{
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
GdkGLContext *gl_context = NULL;
if (!gdk_win32_display_init_gl_backend (display, error))
return NULL;
if (display_win32->wgl_pixel_format != 0)
gl_context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_WGL, "display", display, NULL);
#ifdef HAVE_EGL
else if (gdk_display_get_egl_display (display))
gl_context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_EGL, "display", display, NULL);
#endif
g_return_val_if_fail (gl_context != NULL, NULL);
return gl_context;
}
/**
+9
View File
@@ -105,6 +105,13 @@ typedef enum {
GDK_WIN32_TABLET_INPUT_API_WINPOINTER
} GdkWin32TabletInputAPI;
/* Detect running architecture */
typedef BOOL (WINAPI *funcIsWow64Process2) (HANDLE, USHORT *, USHORT *);
typedef struct _GdkWin32KernelCPUFuncs
{
funcIsWow64Process2 isWow64Process2;
} GdkWin32KernelCPUFuncs;
typedef struct
{
HDC hdc;
@@ -125,6 +132,7 @@ struct _GdkWin32Display
/* WGL/OpenGL Items */
GdkWin32GLDummyContextWGL dummy_context_wgl;
int wgl_pixel_format;
guint gl_version;
GListModel *monitors;
@@ -169,6 +177,7 @@ struct _GdkWin32Display
/* Running CPU items */
guint running_on_arm64 : 1;
GdkWin32KernelCPUFuncs cpu_funcs;
};
struct _GdkWin32DisplayClass
+314 -306
View File
@@ -19,7 +19,7 @@
*/
/*
* Modified by the GTK+ Team and others 1997-2020. See the AUTHORS
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
@@ -157,6 +157,7 @@ static HKL latin_locale = NULL;
static gboolean in_ime_composition = FALSE;
static UINT modal_timer;
static UINT sync_timer = 0;
static int debug_indent = 0;
@@ -644,9 +645,11 @@ build_key_event_state (BYTE *key_state)
{
GdkModifierType state;
GdkWin32Keymap *keymap;
keymap = GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display));
state = _gdk_win32_keymap_get_mod_mask (keymap);
state = 0;
if (key_state[VK_SHIFT] & 0x80)
state |= GDK_SHIFT_MASK;
if (key_state[VK_CAPITAL] & 0x01)
state |= GDK_LOCK_MASK;
@@ -662,6 +665,26 @@ build_key_event_state (BYTE *key_state)
if (key_state[VK_XBUTTON2] & 0x80)
state |= GDK_BUTTON5_MASK;
keymap = GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display));
if (_gdk_win32_keymap_has_altgr (keymap) &&
(key_state[VK_LCONTROL] & 0x80) &&
(key_state[VK_RMENU] & 0x80))
{
state |= GDK_MOD2_MASK;
if (key_state[VK_RCONTROL] & 0x80)
state |= GDK_CONTROL_MASK;
if (key_state[VK_LMENU] & 0x80)
state |= GDK_ALT_MASK;
}
else
{
if (key_state[VK_CONTROL] & 0x80)
state |= GDK_CONTROL_MASK;
if (key_state[VK_MENU] & 0x80)
state |= GDK_ALT_MASK;
}
return state;
}
@@ -1430,6 +1453,23 @@ _gdk_win32_end_modal_call (GdkWin32ModalOpKind kind)
}
}
static VOID CALLBACK
sync_timer_proc (HWND hwnd,
UINT msg,
UINT_PTR id,
DWORD time)
{
MSG message;
if (PeekMessageW (&message, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE))
{
return;
}
RedrawWindow (hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
KillTimer (hwnd, sync_timer);
}
static gboolean
handle_nchittest (HWND hwnd,
GdkSurface *window,
@@ -1740,12 +1780,16 @@ gdk_event_translate (MSG *msg,
POINT point;
MINMAXINFO *mmi;
HWND hwnd;
BYTE key_state[256];
HIMC himc;
WINDOWPOS *windowpos;
gboolean ignore_leave;
GdkEvent *event;
wchar_t wbuf[100];
int ccount;
GdkDisplay *display;
GdkSurface *window = NULL;
GdkWin32Surface *impl;
@@ -1763,12 +1807,20 @@ gdk_event_translate (MSG *msg,
int button;
char buf[256];
gboolean return_val = FALSE;
int i;
GdkModifierType state;
guint keyval;
guint16 keycode;
guint8 group;
gboolean is_modifier;
double delta_x, delta_y;
GdkScrollDirection direction;
GdkTranslatedKey translated;
display = gdk_display_get_default ();
win32_display = GDK_WIN32_DISPLAY (display);
@@ -1827,39 +1879,35 @@ gdk_event_translate (MSG *msg,
switch (msg->message)
{
case WM_INPUTLANGCHANGE:
{
GdkWin32Keymap *win32_keymap;
GdkTranslatedKey translated;
_gdk_input_locale = (HKL) msg->lParam;
_gdk_win32_keymap_set_active_layout (GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display)), _gdk_input_locale);
GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT),
LOCALE_IDEFAULTANSICODEPAGE,
buf, sizeof (buf));
_gdk_input_codepage = atoi (buf);
_gdk_keymap_serial++;
GDK_NOTE (EVENTS,
g_print (" cs:%lu hkl:%p%s cp:%d",
(gulong) msg->wParam,
(gpointer) msg->lParam, _gdk_input_locale_is_ime ? " (IME)" : "",
_gdk_input_codepage));
gdk_display_setting_changed (display, "gtk-im-module");
win32_keymap = GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display));
_gdk_input_locale = (HKL) msg->lParam;
_gdk_win32_keymap_set_active_layout (win32_keymap, _gdk_input_locale);
_gdk_keymap_serial++;
GDK_NOTE (EVENTS,
g_print (" cs:%lu hkl:%p%s",
(gulong) msg->wParam,
(gpointer) msg->lParam,
_gdk_input_locale_is_ime ? " (IME)" : ""));
gdk_display_setting_changed (display, "gtk-im-module");
/* Generate a dummy key event to "nudge" IMContext */
translated.keyval = GDK_KEY_VoidSymbol;
translated.consumed = 0;
translated.layout = 0;
translated.level = 0;
event = gdk_key_event_new (GDK_KEY_PRESS,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
0,
FALSE,
&translated,
&translated);
_gdk_win32_append_event (event);
}
/* Generate a dummy key event to "nudge" IMContext */
translated.keyval = GDK_KEY_VoidSymbol;
translated.consumed = 0;
translated.layout = 0;
translated.level = 0;
event = gdk_key_event_new (GDK_KEY_PRESS,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
0,
FALSE,
&translated,
&translated);
_gdk_win32_append_event (event);
break;
case WM_SYSKEYUP:
@@ -1896,203 +1944,177 @@ gdk_event_translate (MSG *msg,
decode_key_lparam (msg->lParam)));
keyup_or_down:
{
GdkWin32Keymap *win32_keymap;
GdkModifierType state;
guint keyval;
guint16 keycode;
guint8 group;
gboolean is_modifier;
GdkTranslatedKey translated;
GdkTranslatedKey no_lock;
BYTE key_state[256];
wchar_t wbuf[100];
int ccount = 0;
/* Ignore key messages intended for the IME */
if (msg->wParam == VK_PROCESSKEY || in_ime_composition)
break;
/* Ignore key messages intended for the IME */
if (msg->wParam == VK_PROCESSKEY ||
in_ime_composition)
break;
/* Ignore autorepeats on modifiers */
if (msg->message == WM_KEYDOWN &&
(msg->wParam == VK_MENU ||
msg->wParam == VK_CONTROL ||
msg->wParam == VK_SHIFT) &&
((HIWORD(msg->lParam) & KF_REPEAT) >= 1))
break;
/* Ignore autorepeats on modifiers */
if (msg->message == WM_KEYDOWN &&
(msg->wParam == VK_MENU ||
msg->wParam == VK_CONTROL ||
msg->wParam == VK_SHIFT) &&
((HIWORD(msg->lParam) & KF_REPEAT) >= 1))
break;
if (GDK_SURFACE_DESTROYED (window))
break;
if (GDK_SURFACE_DESTROYED (window))
break;
win32_keymap = GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (display));
impl = GDK_WIN32_SURFACE (window);
impl = GDK_WIN32_SURFACE (window);
API_CALL (GetKeyboardState, (key_state));
API_CALL (GetKeyboardState, (key_state));
ccount = 0;
ccount = 0;
if (msg->wParam == VK_PACKET)
{
ccount = ToUnicode (VK_PACKET, HIWORD (msg->lParam), key_state, wbuf, 1, 0);
if (ccount == 1)
{
if (wbuf[0] >= 0xD800 && wbuf[0] < 0xDC00)
{
if (msg->message == WM_KEYDOWN)
impl->leading_surrogate_keydown = wbuf[0];
else
impl->leading_surrogate_keyup = wbuf[0];
if (msg->wParam == VK_PACKET)
{
ccount = ToUnicode (VK_PACKET, HIWORD (msg->lParam), key_state, wbuf, 1, 0);
if (ccount == 1)
{
if (wbuf[0] >= 0xD800 && wbuf[0] < 0xDC00)
{
if (msg->message == WM_KEYDOWN)
impl->leading_surrogate_keydown = wbuf[0];
else
impl->leading_surrogate_keyup = wbuf[0];
/* don't emit an event */
return_val = TRUE;
break;
}
else
{
/* wait until an event is created */;
}
}
}
/* don't emit an event */
return_val = TRUE;
break;
}
else
{
/* wait until an event is created */;
}
}
}
keyval = GDK_KEY_VoidSymbol;
keycode = msg->wParam;
keyval = GDK_KEY_VoidSymbol;
keycode = msg->wParam;
if (HIWORD (msg->lParam) & KF_EXTENDED)
{
switch (msg->wParam)
{
case VK_CONTROL:
keycode = VK_RCONTROL;
break;
case VK_SHIFT: /* Actually, KF_EXTENDED is not set
* for the right shift key.
*/
keycode = VK_RSHIFT;
break;
case VK_MENU:
keycode = VK_RMENU;
break;
}
}
else if (msg->wParam == VK_SHIFT &&
LOBYTE (HIWORD (msg->lParam)) == _gdk_win32_keymap_get_rshift_scancode (win32_keymap))
keycode = VK_RSHIFT;
if (HIWORD (msg->lParam) & KF_EXTENDED)
{
switch (msg->wParam)
{
case VK_CONTROL:
keycode = VK_RCONTROL;
break;
case VK_SHIFT: /* Actually, KF_EXTENDED is not set
* for the right shift key.
*/
keycode = VK_RSHIFT;
break;
case VK_MENU:
keycode = VK_RMENU;
break;
}
}
else if (msg->wParam == VK_SHIFT &&
LOBYTE (HIWORD (msg->lParam)) == _gdk_win32_keymap_get_rshift_scancode (GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display))))
keycode = VK_RSHIFT;
is_modifier = (msg->wParam == VK_CONTROL ||
msg->wParam == VK_SHIFT ||
msg->wParam == VK_MENU);
is_modifier = (msg->wParam == VK_CONTROL ||
msg->wParam == VK_SHIFT ||
msg->wParam == VK_MENU);
/* g_print ("ctrl:%02x lctrl:%02x rctrl:%02x alt:%02x lalt:%02x ralt:%02x\n", key_state[VK_CONTROL], key_state[VK_LCONTROL], key_state[VK_RCONTROL], key_state[VK_MENU], key_state[VK_LMENU], key_state[VK_RMENU]); */
state = build_key_event_state (key_state);
group = get_active_group ();
state = build_key_event_state (key_state);
group = get_active_group ();
if (msg->wParam == VK_PACKET && ccount == 1)
{
if (wbuf[0] >= 0xD800 && wbuf[0] < 0xDC00)
{
g_assert_not_reached ();
}
else if (wbuf[0] >= 0xDC00 && wbuf[0] < 0xE000)
{
wchar_t leading;
if (msg->wParam == VK_PACKET && ccount == 1)
{
if (wbuf[0] >= 0xD800 && wbuf[0] < 0xDC00)
{
g_assert_not_reached ();
}
else if (wbuf[0] >= 0xDC00 && wbuf[0] < 0xE000)
{
wchar_t leading;
if (msg->message == WM_KEYDOWN)
leading = impl->leading_surrogate_keydown;
else
leading = impl->leading_surrogate_keyup;
if (msg->message == WM_KEYDOWN)
leading = impl->leading_surrogate_keydown;
else
leading = impl->leading_surrogate_keyup;
keyval = gdk_unicode_to_keyval ((leading - 0xD800) * 0x400 + wbuf[0] - 0xDC00 + 0x10000);
}
else
{
keyval = gdk_unicode_to_keyval (wbuf[0]);
}
keyval = gdk_unicode_to_keyval ((leading - 0xD800) * 0x400 + wbuf[0] - 0xDC00 + 0x10000);
}
else
{
keyval = gdk_unicode_to_keyval (wbuf[0]);
}
}
else
{
gdk_keymap_translate_keyboard_state (_gdk_win32_display_get_keymap (display),
keycode,
state,
group,
&keyval,
NULL, NULL, NULL);
}
translated.keyval = keyval;
translated.consumed = 0;
translated.layout = 0;
translated.level = 0;
if (msg->message == WM_KEYDOWN)
impl->leading_surrogate_keydown = 0;
else
impl->leading_surrogate_keyup = 0;
no_lock = translated;
}
else
{
int level = 0;
int effective_group = 0;
GdkModifierType consumed = 0;
/* Only one release key event is fired when both shift keys are pressed together
and then released. In order to send the missing event, press events for shift
keys are recorded and sent together when the release event occurs.
Other modifiers (e.g. ctrl, alt) don't have this problem. */
if (msg->message == WM_KEYDOWN && msg->wParam == VK_SHIFT)
{
int pressed_shift = msg->lParam & 0xffffff; /* mask shift modifier */
if (both_shift_pressed[0] == 0)
both_shift_pressed[0] = pressed_shift;
else if (both_shift_pressed[0] != pressed_shift)
both_shift_pressed[1] = pressed_shift;
}
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode, state, group,
&keyval, &effective_group, &level, &consumed);
translated.keyval = keyval;
translated.consumed = consumed;
translated.layout = effective_group;
translated.level = level;
if (msg->message == WM_KEYUP && msg->wParam == VK_SHIFT)
{
if (both_shift_pressed[0] != 0 && both_shift_pressed[1] != 0)
{
int tmp_retval;
MSG fake_release = *msg;
int pressed_shift = msg->lParam & 0xffffff;
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode,
state & ~GDK_LOCK_MASK, group, &keyval,
&effective_group, &level, &consumed);
no_lock.keyval = keyval;
no_lock.consumed = consumed;
no_lock.layout = effective_group;
no_lock.level = level;
}
if (both_shift_pressed[0] == pressed_shift)
fake_release.lParam = both_shift_pressed[1];
else
fake_release.lParam = both_shift_pressed[0];
if (msg->message == WM_KEYDOWN)
impl->leading_surrogate_keydown = 0;
else
impl->leading_surrogate_keyup = 0;
both_shift_pressed[0] = both_shift_pressed[1] = 0;
gdk_event_translate (&fake_release, &tmp_retval);
}
both_shift_pressed[0] = both_shift_pressed[1] = 0;
}
/* Only one release key event is fired when both shift keys are pressed together
and then released. In order to send the missing event, press events for shift
keys are recorded and sent together when the release event occurs.
Other modifiers (e.g. ctrl, alt) don't have this problem. */
if (msg->message == WM_KEYDOWN && msg->wParam == VK_SHIFT)
{
int pressed_shift = msg->lParam & 0xffffff; /* mask shift modifier */
if (both_shift_pressed[0] == 0)
both_shift_pressed[0] = pressed_shift;
else if (both_shift_pressed[0] != pressed_shift)
both_shift_pressed[1] = pressed_shift;
}
/* Reset ALT_MASK if it is the Alt key itself */
if (msg->wParam == VK_MENU)
state &= ~GDK_ALT_MASK;
if (msg->message == WM_KEYUP && msg->wParam == VK_SHIFT)
{
if (both_shift_pressed[0] != 0 && both_shift_pressed[1] != 0)
{
int tmp_retval;
MSG fake_release = *msg;
int pressed_shift = msg->lParam & 0xffffff;
/* FIXME do proper translation */
translated.keyval = keyval;
translated.consumed = 0;
translated.layout = group;
translated.level = 0;
event = gdk_key_event_new ((msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
? GDK_KEY_PRESS
: GDK_KEY_RELEASE,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
keycode,
state,
is_modifier,
&translated,
&translated);
if (both_shift_pressed[0] == pressed_shift)
fake_release.lParam = both_shift_pressed[1];
else
fake_release.lParam = both_shift_pressed[0];
_gdk_win32_append_event (event);
both_shift_pressed[0] = both_shift_pressed[1] = 0;
gdk_event_translate (&fake_release, &tmp_retval);
}
both_shift_pressed[0] = both_shift_pressed[1] = 0;
}
/* Reset ALT_MASK if it is the Alt key itself */
if (msg->wParam == VK_MENU)
state &= ~GDK_ALT_MASK;
event = gdk_key_event_new ((msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
? GDK_KEY_PRESS
: GDK_KEY_RELEASE,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
keycode,
state,
is_modifier,
&translated,
&no_lock);
_gdk_win32_append_event (event);
return_val = TRUE;
}
return_val = TRUE;
break;
case WM_SYSCHAR:
@@ -2113,82 +2135,73 @@ gdk_event_translate (MSG *msg,
break;
case WM_IME_COMPOSITION:
{
BYTE key_state[256];
wchar_t wbuf[100];
int ccount = 0;
/* On Win2k WM_IME_CHAR doesn't work correctly for non-Unicode
* applications. Thus, handle WM_IME_COMPOSITION with
* GCS_RESULTSTR instead, fetch the Unicode chars from the IME
* with ImmGetCompositionStringW().
*
* See for instance
* http://groups.google.com/groups?selm=natX5.57%24g77.19788%40nntp2.onemain.com
* and
* http://groups.google.com/groups?selm=u2XfrXw5BHA.1628%40tkmsftngp02
* for comments by other people that seems to have the same
* experience. WM_IME_CHAR just gives question marks, apparently
* because of going through some conversion to the current code
* page.
*
* WM_IME_CHAR might work on NT4 or Win9x with ActiveIMM, but
* use WM_IME_COMPOSITION there, too, to simplify the code.
*/
GDK_NOTE (EVENTS, g_print (" %#lx", (long) msg->lParam));
/* On Win2k WM_IME_CHAR doesn't work correctly for non-Unicode
* applications. Thus, handle WM_IME_COMPOSITION with
* GCS_RESULTSTR instead, fetch the Unicode chars from the IME
* with ImmGetCompositionStringW().
*
* See for instance
* http://groups.google.com/groups?selm=natX5.57%24g77.19788%40nntp2.onemain.com
* and
* http://groups.google.com/groups?selm=u2XfrXw5BHA.1628%40tkmsftngp02
* for comments by other people that seems to have the same
* experience. WM_IME_CHAR just gives question marks, apparently
* because of going through some conversion to the current code
* page.
*
* WM_IME_CHAR might work on NT4 or Win9x with ActiveIMM, but
* use WM_IME_COMPOSITION there, too, to simplify the code.
*/
GDK_NOTE (EVENTS, g_print (" %#lx", (long) msg->lParam));
if (!(msg->lParam & GCS_RESULTSTR))
break;
if (!(msg->lParam & GCS_RESULTSTR))
break;
if (GDK_SURFACE_DESTROYED (window))
break;
if (GDK_SURFACE_DESTROYED (window))
break;
himc = ImmGetContext (msg->hwnd);
ccount = ImmGetCompositionStringW (himc, GCS_RESULTSTR,
wbuf, sizeof (wbuf));
ImmReleaseContext (msg->hwnd, himc);
himc = ImmGetContext (msg->hwnd);
ccount = ImmGetCompositionStringW (himc, GCS_RESULTSTR,
wbuf, sizeof (wbuf));
ImmReleaseContext (msg->hwnd, himc);
ccount /= 2;
ccount /= 2;
API_CALL (GetKeyboardState, (key_state));
API_CALL (GetKeyboardState, (key_state));
for (i = 0; i < ccount; i++)
{
/* Build a key press event */
translated.keyval = gdk_unicode_to_keyval (wbuf[i]);
translated.consumed = 0;
translated.layout = get_active_group ();
translated.level = 0;
event = gdk_key_event_new (GDK_KEY_PRESS,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
build_key_event_state (key_state),
FALSE,
&translated,
&translated);
for (i = 0; i < ccount; i++)
{
GdkTranslatedKey translated;
_gdk_win32_append_event (event);
/* Build a key press event */
translated.keyval = gdk_unicode_to_keyval (wbuf[i]);
translated.consumed = 0;
translated.layout = get_active_group ();
translated.level = 0;
event = gdk_key_event_new (GDK_KEY_PRESS,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
build_key_event_state (key_state),
FALSE,
&translated,
&translated);
/* Build a key release event. */
event = gdk_key_event_new (GDK_KEY_RELEASE,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
build_key_event_state (key_state),
FALSE,
&translated,
&translated);
_gdk_win32_append_event (event);
/* Build a key release event. */
event = gdk_key_event_new (GDK_KEY_RELEASE,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
build_key_event_state (key_state),
FALSE,
&translated,
&translated);
_gdk_win32_append_event (event);
}
return_val = TRUE;
}
_gdk_win32_append_event (event);
}
return_val = TRUE;
break;
case WM_LBUTTONDOWN:
@@ -2841,6 +2854,12 @@ gdk_event_translate (MSG *msg,
*ret_valp = 1;
break;
case WM_SYNCPAINT:
sync_timer = SetTimer (GDK_SURFACE_HWND (window),
1,
200, sync_timer_proc);
break;
case WM_PAINT:
handle_wm_paint (msg, window);
break;
@@ -2985,22 +3004,17 @@ gdk_event_translate (MSG *msg,
break;
case WM_WINDOWPOSCHANGING:
#ifdef G_ENABLE_DEBUG
{
char buf[256];
GDK_NOTE (EVENTS, (windowpos = (WINDOWPOS *) msg->lParam,
g_print (" %s %s %dx%d@%+d%+d now below %p",
_gdk_win32_surface_pos_bits_to_string (windowpos->flags),
(windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
(windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
(windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
(windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
(sprintf (buf, "%p", windowpos->hwndInsertAfter),
buf))))),
windowpos->cx, windowpos->cy, windowpos->x, windowpos->y,
GetNextWindow (msg->hwnd, GW_HWNDPREV))));
}
#endif
GDK_NOTE (EVENTS, (windowpos = (WINDOWPOS *) msg->lParam,
g_print (" %s %s %dx%d@%+d%+d now below %p",
_gdk_win32_surface_pos_bits_to_string (windowpos->flags),
(windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
(windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
(windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
(windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
(sprintf (buf, "%p", windowpos->hwndInsertAfter),
buf))))),
windowpos->cx, windowpos->cy, windowpos->x, windowpos->y,
GetNextWindow (msg->hwnd, GW_HWNDPREV))));
if (GDK_SURFACE_IS_MAPPED (window))
{
@@ -3026,21 +3040,15 @@ gdk_event_translate (MSG *msg,
case WM_WINDOWPOSCHANGED:
windowpos = (WINDOWPOS *) msg->lParam;
#ifdef G_ENABLE_DEBUG
{
char buf[256];
GDK_NOTE (EVENTS, g_print (" %s %s %dx%d@%+d%+d",
_gdk_win32_surface_pos_bits_to_string (windowpos->flags),
(windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
(windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
(windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
(windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
(sprintf (buf, "%p", windowpos->hwndInsertAfter),
buf))))),
windowpos->cx, windowpos->cy, windowpos->x, windowpos->y));
}
#endif
GDK_NOTE (EVENTS, g_print (" %s %s %dx%d@%+d%+d",
_gdk_win32_surface_pos_bits_to_string (windowpos->flags),
(windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
(windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
(windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
(windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
(sprintf (buf, "%p", windowpos->hwndInsertAfter),
buf))))),
windowpos->cx, windowpos->cy, windowpos->x, windowpos->y));
/* Break grabs on unmap or minimize */
if (windowpos->flags & SWP_HIDEWINDOW ||
+35 -29
View File
@@ -258,6 +258,9 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
if (!gdk_gl_backend_can_be_used (GDK_GL_WGL, error))
return FALSE;
if (display_win32->wgl_pixel_format != 0)
return TRUE;
/* acquire and cache dummy Window (HWND & HDC) and
* dummy GL Context, it is used to query functions
* and used for other stuff as well
@@ -296,6 +299,8 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
}
}
display_win32->wgl_pixel_format = best_idx;
display_win32->hasWglARBCreateContext =
epoxy_has_wgl_extension (hdc, "WGL_ARB_create_context");
display_win32->hasWglEXTSwapControl =
@@ -427,13 +432,33 @@ create_wgl_context (HDC hdc,
goto gl_fail;
}
hglrc = create_wgl_context_with_attribs (hdc,
hglrc_base,
share,
flags,
major,
minor,
is_legacy);
/*
* We need a Core GL 4.1 context in order to use the GL support in
* the GStreamer media widget backend, but wglCreateContextAttribsARB()
* may only give us the GL context version that we ask for here, and
* nothing more. So, if we are asking for a pre-GL 4.1 context,
* try to ask for a 4.1 context explicitly first. If that is not supported,
* then we fall back to whatever version that we were asking for (or, even a
* legacy context if that fails), at a price of not able to have GL support
* for the media GStreamer backend.
*/
if (major < 4 || (major == 4 && minor < 1))
hglrc = create_wgl_context_with_attribs (hdc,
hglrc_base,
share,
flags,
4,
1,
is_legacy);
if (hglrc == NULL)
hglrc = create_wgl_context_with_attribs (hdc,
hglrc_base,
share,
flags,
major,
minor,
is_legacy);
/* return the legacy context we have if it could be setup properly, in case the 3.0+ context creation failed */
if (hglrc == NULL)
@@ -539,27 +564,10 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
if (!gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, error))
return 0;
gdk_gl_context_get_required_version (context, &major, &minor);
debug_bit = gdk_gl_context_get_debug_enabled (context);
compat_bit = gdk_gl_context_get_forward_compatible (context);
/*
* We may need a Core GL 4.1+ context in order to use the GL support in
* the GStreamer media widget backend (such as on Intel drivers), but
* wglCreateContextAttribsARB() may only give us the GL context version
* that we ask for here, and nothing more. So, improve things here by
* asking for the GL version that is reported to us via epoxy_gl_version(),
* rather than the default GL core 3.2 context. Save this up in our
* GdkGLContext so that subsequent contexts that are shared with this
* context are created likewise too.
*/
if (share != NULL)
gdk_gl_context_get_required_version (share, &major, &minor);
else
{
major = display_win32->gl_version / 10;
minor = display_win32->gl_version % 10;
}
if (surface != NULL)
hdc = GDK_WIN32_SURFACE (surface)->hdc;
else
@@ -626,7 +634,6 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
/* Ensure that any other context is created with a legacy bit set */
gdk_gl_context_set_is_legacy (context, legacy_bit);
gdk_gl_context_set_required_version (context, major, minor);
return GDK_GL_API_GL;
}
@@ -721,10 +728,9 @@ gdk_win32_display_get_wgl_version (GdkDisplay *display,
if (!GDK_IS_WIN32_DISPLAY (display))
return FALSE;
if (!gdk_gl_backend_can_be_used (GDK_GL_WGL, NULL))
return FALSE;
display_win32 = GDK_WIN32_DISPLAY (display);
if (display_win32->wgl_pixel_format == 0)
return FALSE;
if (major != NULL)
*major = display_win32->gl_version / 10;
+1
View File
@@ -38,6 +38,7 @@ int _gdk_input_ignore_core;
HKL _gdk_input_locale;
gboolean _gdk_input_locale_is_ime = FALSE;
UINT _gdk_input_codepage;
GdkWin32ModalOpKind _modal_operation_in_progress = GDK_WIN32_MODAL_OP_NONE;
HWND _modal_move_resize_window = NULL;
-26
View File
@@ -1,26 +0,0 @@
/*
* Copyright (c) 2021 Philip Zander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _WIN64
#define GDK_WIN32_COMPILE_FOR_WOW64 1
#include "gdkkeys-win32-impl.c"
#endif

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