Compare commits

..

270 Commits

Author SHA1 Message Date
Matthias Clasen 3ff7c86b65 Add css parser tests for filter() 2021-02-06 19:59:45 -05:00
Matthias Clasen 79a0f183ec css: Implement filter() for images
We have all the pieces, so this is suprisingly easy.
2021-02-06 19:59:45 -05:00
Matthias Clasen e8c8be8e37 Merge branch 'matthiasc/for-master' into 'master'
Implement drop-shadow css filter

See merge request GNOME/gtk!3163
2021-02-06 22:35:23 +00:00
Matthias Clasen bfc80c32ea Add tests for the css filter property
Test that we can parse filters and that we
don't accept invalid filters.
2021-02-06 16:16:44 -05:00
Matthias Clasen 5f48764ac8 cssfiltervalue: Reject invalid filters
The Filter Effects Spec doesn't allow negative values
for most of the filter parameters.
2021-02-06 16:16:44 -05:00
Matthias Clasen cc6fcbfc09 cssfiltervalue: Fix blur filter interpretation
According to https://www.w3.org/TR/filter-effects-1/,
the length passed to blur() is the standard deviation,
and according to https://www.w3.org/TR/css-backgrounds-3/#shadow-blur
the blur radius is twice the standard deviation.
2021-02-06 16:16:44 -05:00
Matthias Clasen ea7185bdb1 cssfiltervalue: Implement drop-shadows
We have all the pieces, so this is surprisingly easy.
2021-02-06 16:16:43 -05:00
Matthias Clasen 429dfcf483 cssshadowvalue: Add a 'filter mode'
Shadow values created by gtk_css_shadow_value_new_filter or
gtk_css_shadow_value_parse_filter interpret their radius value
as standard deviation. Add a flag for this mode, and use it
where necessary.
2021-02-06 16:10:34 -05:00
Matthias Clasen be3f352b59 cssshadowvalue: Add a parsing function
Add a variant of the parse function that parses
just a single (non-box) shadow, as required for
the drop-shadow filter.
2021-02-06 16:10:32 -05:00
Matthias Clasen 5b8896f1db cssshadowvalue: Add gtk_css_shadow_value_pop_snapshot
This is the counterpart ot gtk_css_shadow_value_push_snapshot.

To make this easy, move the determination whether we need a
shadow out of the push function and save it.
2021-02-06 16:09:21 -05:00
Matthias Clasen 4e27de7df9 cssshadowvalue: Drop the underscore
Rename _gtk_css_shadow_value_parse to drop the underscore.
It was the only underscore-prefixed function in this file.
2021-02-06 16:08:19 -05:00
Marek Černocký 2712f536c2 Updated Czech translation 2021-02-06 09:44:09 +01:00
Matthias Clasen a1f7073ff5 Add tests for the css filter property
Test that we can parse filters.
2021-02-05 21:37:47 -05:00
Matthias Clasen 9770872d12 css: Implement the drop-shadow filter
We have all the pieces, so this is surprisingly easy.
2021-02-05 21:37:14 -05:00
Matthias Clasen de24b4f91b cssshadowvalue: Add a parsing function
Add a variant of the parse function that parses
just a single (non-box) shadow, as required for
the drop-shadow filter.
2021-02-05 21:36:22 -05:00
Matthias Clasen 650fd9c291 Merge branch 'module-ext' into 'master'
meson: use correct module file extension on macOS

Closes #3645

See merge request GNOME/gtk!3162
2021-02-06 01:15:09 +00:00
David Lechner b509809f34 meson: use correct module file extension on macOS
GModule requires the .so file extension on macOS for historic reasons.
However Meson defaults to .dylib for modules, so we need to override
it to get the correct extension.

Fixes #3645.
2021-02-05 16:54:28 -06:00
Matthias Clasen 60ff231fac Merge branch 'matthiasc/for-master' into 'master'
iconbrowser: Make image dnd work again

Closes #3648

See merge request GNOME/gtk!3159
2021-02-05 12:48:10 +00:00
Emmanuele Bassi 958005317b Merge branch 'master' into 'master'
Improve the docs of GtkWidget and GtkGrid

See merge request GNOME/gtk!2946
2021-02-05 12:14:26 +00:00
Matthias Clasen 15c36aaa1e iconbrowser: Make image dnd work again
We need to drag a texture, not a paintable.

Fixes: #3648
2021-02-04 20:47:19 -05:00
Matthias Clasen 482b73c376 Merge branch 'matthiasc/for-master' into 'master'
docs: Rewrite the long description for GtkDialog

Closes #3646

See merge request GNOME/gtk!3156
2021-02-05 00:10:47 +00:00
Matthias Clasen 4a8bf6e13d Merge branch 'doc-typo' into 'master'
gtkshow: Fix doc typo

See merge request GNOME/gtk!3158
2021-02-05 00:07:18 +00:00
Maximiliano Sandoval R 3e2e6633b0 gtkshow: Fix doc typo 2021-02-04 21:02:22 +01:00
Matthias Clasen 4724f9907c docs: Rewrite the long description for GtkDialog
As was pointed out in #3646, some of the content here
was a bit outdated.

Fixes: #3646
2021-02-04 13:05:28 -05:00
Matthias Clasen 26e84a7b8c Merge branch 'matthiasc/for-master' into 'master'
More work on css transition tests

See merge request GNOME/gtk!3154
2021-02-04 13:28:59 +00:00
Matthias Clasen d5838f14f9 Drop the installed test for now
It fails in ci, and I have no idea why.
2021-02-04 07:26:10 -05:00
Matthias Clasen 5c532104e4 Merge branch 'pvs-fixes' into 'master'
Pvs fixes

See merge request GNOME/gtk!3155
2021-02-04 12:20:24 +00:00
Matthias Clasen 2f42e1fb89 treemodelfilter: Drop unreachable code
We never get here. The compiler says so.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:40:14 -05:00
Matthias Clasen b5200bd076 css: Drop a bit of unreachable code
We never get here. The compiler says so.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:39:34 -05:00
Matthias Clasen aa5bd38137 a11y: Avoid out-of-bounds access
Don't use the index before we've checked its good.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:34:05 -05:00
Matthias Clasen 0eba833595 gdk: Remove a redundant check
We already know desktop_notification_id is not NULL.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:29:51 -05:00
Matthias Clasen 1e0ea21297 messagedialog: Don't initialize twice
We don't need to set these fields more than once.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:25:36 -05:00
Matthias Clasen e91e75173d composetable: Remove a redundant check
We already know seq_index is not NULL here.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:22:52 -05:00
Matthias Clasen 927fdb9a83 x11: A case of argument order confusion
translate_keysym was expecting its arguments the
other way around.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:20:26 -05:00
Matthias Clasen 041f410838 textbtree: Avoid line vs char count confusion
The post_insert_fixup helper function was confused about
its argument order.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:17:55 -05:00
Matthias Clasen c71c8919fe listbase: Don't specify the same thing twice
We only need to set EXPLICIT_NOTIFY once.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:13:53 -05:00
Matthias Clasen 3f28399f7d css: Fix border value parsing
This function was not resetting computed as it meant
to because the last loop was never executed.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:12:51 -05:00
Matthias Clasen 3c15fa96bc vulkan: Fix image uploading by regions
This code did not make sense; it was incrementing
the wrong variable.

Pointed out in https://www.viva64.com/en/b/0793/
2021-02-04 00:12:44 -05:00
Matthias Clasen 0a0a059397 docs: Mention css drop-shadow filter
We don't support this filter, currently.
2021-02-03 22:10:13 -05:00
Matthias Clasen 18e83fe16d Add more css transition tests 2021-02-03 22:10:13 -05:00
Matthias Clasen 90d7ed5dd1 Rename test to transition
Thats what it is about, so name it clearly.

Add missing installed tests too.
2021-02-03 22:10:13 -05:00
Matthias Clasen 3c6e7569ff Add more css transition tests
Test font size transitions.
2021-02-03 22:10:13 -05:00
Matthias Clasen 4e2ec2d68d testsuite: Pass GDK_DEBUG=default-settings to css tests
Otherwise, settings might creep in and change css defaults.
2021-02-03 22:10:13 -05:00
Matthias Clasen 1af72eac21 cssvalue: Cosmetic change
Don't return FALSE from pointer-returning functions.
2021-02-03 22:10:13 -05:00
Matthias Clasen 640273a0e2 Improve the css value tests
The test code had some bugs. Fix those, and
print out useful information when tests fail.
2021-02-03 22:10:13 -05:00
Matthias Clasen a14a0c6315 css: Fix shadow value equal
This function was not doing the right thing.

Once we are doing the right thing and not compare
shadows as unequal, some reftests that inhibit
snapshots for a few frames now hang forever, since
we are no more redrawing unnecessarily. Fix that
with an explicit queue_draw.
2021-02-03 22:10:13 -05:00
Matthias Clasen 38481680e1 Merge branch 'wip/jimmac/colored-list-image-buttons' into 'master'
Adwaita: allow suggested and destructive action buttons in lists

Closes #3643

See merge request GNOME/gtk!3153
2021-02-04 01:38:47 +00:00
Matthias Clasen 12a540c284 Merge branch 'ebassi/for-master' into 'master'
Graphene is a dependency of Gsk, not Gdk

See merge request GNOME/gtk!3149
2021-02-04 01:38:09 +00:00
Jakub Steiner 289bf078bf Adwaita: allow suggested and destructive action buttons in lists
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3643
2021-02-03 23:15:30 +01:00
Matthias Clasen 58ab9ddc40 Merge branch 'x11-dnd-fix' into 'master'
x11: Handle X-specific targets in drops

Closes #3642

See merge request GNOME/gtk!3151
2021-02-03 20:11:33 +00:00
Matthias Clasen c78036fc51 x11: Handle X-specific targets in drops
This code is very similar to the handling for these
targets in the clipboard case.

Fixes: #3642
2021-02-03 14:17:04 -05:00
Matthias Clasen 120f2768e6 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!3150
2021-02-03 15:17:34 +00:00
Emmanuele Bassi 592b33cb48 Graphene is a dependency of Gsk, not Gdk
So let's put it in the right place when building the introspection data.
2021-02-03 14:05:27 +00:00
Matthias Clasen 7a9bc1f1d8 Link the data url tests statically
Thats the cleaner way to test internal apis.
2021-02-03 09:02:06 -05:00
Matthias Clasen 9cc6f3ee29 Add tests for css value transitions
Just a few cases for now, enough to test a recently
fixed regression with shadow transitions.
2021-02-03 08:56:57 -05:00
Chun-wei Fan 9efaa0b51d Merge branch 'uac.meson.master' into 'master'
gtk4-update-icon-cache: Avoid UAC on 32-bit Windows

Closes #3632

See merge request GNOME/gtk!3141
2021-02-03 02:16:58 +00:00
Chun-wei Fan f0967fa5e4 gtk4-update-icon-cache: Avoid UAC on 32-bit Windows
As the program executable name has 'update' in its filename,
gtk4-update-icon-cache.exe is considered to be an installer program on 32-bit
Windows [1], which will cause the program to fail to run unless it is running
with elevated privileges (i.e. UAC).

Avoid this situation by embedding a manifest file into the final executable
that tells Windows that this is not a program that requires elevation.

Fixes issue #3632.

[1]: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc709628(v=ws.10)?redirectedfrom=MSDN,
     under section "Installer Detection  Technology"
2021-02-03 02:16:58 +00:00
Matthias Clasen f8529983f9 Merge branch 'matthiasc/for-master' into 'master'
css: Allow transitioning different-size shadows

See merge request GNOME/gtk!3145
2021-02-03 00:43:44 +00:00
Matthias Clasen 919c08d4fd css: Allow transitioning different-size shadows
The code handles it just fine. The length check was
an erronous addition.
2021-02-02 15:27:42 -05:00
Matthias Clasen e9b06b6346 Merge branch 'im-context-work' into 'master'
Some im context work

Closes #1004, #186, and #3521

See merge request GNOME/gtk!3143
2021-02-02 17:29:14 +00:00
Matthias Clasen 949c783187 composetable: Parse hex escapes too
This was a small omission from the Compose file
syntax that doesn't cost us much to support.

Add a test for this syntax too.

Fixes: #1004
2021-02-02 12:05:19 -05:00
Matthias Clasen 814a4a781a Add tests for string values
Add a test that checks we parse values with
multiple characters correctly.
2021-02-02 11:55:00 -05:00
Matthias Clasen 676f875bf6 composetable: Support string values in the cache
Change the cache format to include the character
data that we need to hold string values in the table.
2021-02-02 11:55:00 -05:00
Matthias Clasen 140c5c5333 composetable: Don't use GSlice for big blobs
This just doesn't make sense. This will use malloc
anyway, so just call malloc directly.
2021-02-02 11:55:00 -05:00
Matthias Clasen cebf2b2009 composetable: Keep multi-char values
Keep string values in the table, and return them
from the check function. This commit temporarily
disables the table caching, since the cache format
does not handle string values yet.

Fixes: #186
2021-02-02 11:54:53 -05:00
Matthias Clasen 86b437a1b6 Merge branch 'wip/silence-bounds-warnings' into 'master'
gdk/toplevelsize: Remove warnings about exceeding bounds

Closes #3035

See merge request GNOME/gtk!3142
2021-02-02 16:38:20 +00:00
Matthias Clasen 773ae0cd0f composetable: Parse multi-char values
Rewrite the value parsing function to accept strings
that hold more than a single Unicode character.
2021-02-02 09:03:53 -05:00
Matthias Clasen 564793d5b5 composetable: Another step towards multi-char values
Change the parser data structures to hold a string, rather
than a gunichar. We still only put a single Unicode character
into it, currently.
2021-02-02 09:02:46 -05:00
Matthias Clasen 9142aa0f51 composetable: Prepare for multi character values
Make it possible for gtk_compose_table_check to return
a string instead of just a single Unicode character.
Currently, we only ever return strings holding a single
character, still.
2021-02-02 09:02:00 -05:00
Matthias Clasen af9a578d68 imcontext: Prepare for multi-char values
Reshuffle things so we can easily handle values
that are strings instead of just single Unicode
characters.
2021-02-01 23:43:59 -05:00
Matthias Clasen ecb072fdd0 composetable: Check algorithmic matching
Just some spot checks, enough to verify the
fix in the previous commit.
2021-02-01 21:59:21 -05:00
Matthias Clasen ef053ebb4a composetable: Fix algorithmic matching
The code wasn't paying attention to (lack of) nul-termination
in one place, causing it to not match when it should.
2021-02-01 21:51:51 -05:00
Matthias Clasen 8d18d93742 composetable: Add tests for compact table matching
Not very exhaustive, just some spot checks.
2021-02-01 21:10:44 -05:00
Matthias Clasen 10fcdd88e3 imcontext: Code cleanup
Get rid of auxiliary check_table function.
2021-02-01 20:41:45 -05:00
Matthias Clasen 5d9509c51b imcontext: Move code around
Move all the checking code to gtkcomposetable.c, and
add api that we can use in tests.
2021-02-01 20:27:38 -05:00
Matthias Clasen c9cac5fbc3 composetable: Add tests for matching
This tests the api we use to match key sequences
against compose tables.
2021-02-01 19:55:56 -05:00
Matthias Clasen aa9054a5f1 imcontext: Use gtk_compose_table_check
Use the just-introduced api.
2021-02-01 19:41:07 -05:00
Matthias Clasen 9ebf3fac73 composetable: Add api to check tables
This copies the check_table code from gtkimcontextsimple.c,
in order to have an api for tests.
2021-02-01 19:40:22 -05:00
Matthias Clasen 569294070b Add tests for GtkComposeTable
Add some tests for the code that parses Compose files.

This tests the fix in the previous commit.
2021-02-01 19:02:31 -05:00
Matthias Clasen be35c46ce9 composetable: Drop table debug code
This is better off in the tests that we are going to add.
2021-02-01 19:02:21 -05:00
Matthias Clasen dbbcb13721 composetable: Parser fixes
We were not handling octal escapes right.
2021-02-01 16:05:05 -05:00
Matthias Clasen edeaf9c040 imcontext: Drop GTK_MAX_COMPOSE_LEN
Drop GTK_MAX_COMPOSE_LEN from docs. It is no longer
used by GTK at all.  We leave the define in place
for now, to avoid breaking 3rd party code that might
use it.
2021-02-01 12:31:23 -05:00
Matthias Clasen 61f709811c composetable: Warn when ignoring things
We should at least give a hint that we've seen the line,
otherwise people will wonder why nothing happened.
2021-02-01 12:27:41 -05:00
Matthias Clasen f7c4375509 composetable: parse long sequences
Allow compose sequences of up to 20 code points.

Fixes: #3521
2021-02-01 12:27:35 -05:00
Matthias Clasen 52fb900ced composetable: Fix an off-by-one
Fix an off-by-one in the code parsing octal escapes
in compose files.
2021-02-01 12:10:05 -05:00
Matthias Clasen 031944ad30 imcontext: Stop using GTK_MAX_COMPOSE_LEN
Allocate the compose_buffer, and resize it when needed
to match the tables we use.
2021-02-01 12:10:05 -05:00
Matthias Clasen bf8b974f68 imcontext: Code cleanup
Use g_clear_pointer instead of opencoding it in
multiple places.
2021-02-01 12:10:05 -05:00
Jonas Ådahl 6ad2a049e7 gdk/toplevelsize: Remove warnings about exceeding bounds
Sometimes the size will exceed the minimum bounds. For example crazy
applications like the widget factory that contains the world, or when a
user interactively resizes a window to be larger than the monitor the
window is on is.

The former is questionable, but the latter is not, and from here we
can't really see the difference, so just stop complaining.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3035
2021-02-01 11:31:11 +01:00
Matthias Clasen 3d85d53e5d Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

Closes #2319

See merge request GNOME/gtk!3140
2021-02-01 06:20:40 +00:00
Matthias Clasen 094a346539 imcontext: Allow sequences of length GTK_MAX_COMPOSE_LEN
There was an off-by-one error, making us reject sequences
of this length. But the rest of the code handles them
just fine.

Fixes: #2319
2021-02-01 00:55:25 -05:00
Matthias Clasen 162814f969 imcontext: Improve an error message
This error message was misleading, as pointed out
by Ralf Jung.
2021-02-01 00:44:41 -05:00
Matthias Clasen e39b5c99f1 imcontext: Add a precondition check 2021-02-01 00:43:44 -05:00
Matthias Clasen 8883243aaa imcontext: Show preedit for compose sequences
Show the sequences as they are entered, using ⎄ for
the compose key, to match what IBus does nowadays.
Also handle backspace to allow corrections.
2021-02-01 00:37:43 -05:00
Matthias Clasen 89511eecf1 imcontext: Update our check for dead keys
A bunch of keysyms for dead keys have been added since this
code was last touched. Update the check to cover the full
range from dead_grave to dead_greek.
2021-01-31 23:56:24 -05:00
Matthias Clasen 2c304ca80d Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!3139
2021-02-01 01:48:47 +00:00
Matthias Clasen bf4102e664 Merge branch 'wip/exalm/consumes-motion' into 'master'
Drag fixes and cleanups

Closes #3513

See merge request GNOME/gtk!3001
2021-02-01 01:34:45 +00:00
Matthias Clasen b86153cee3 Remove a forgotten file
The example series only has 9 steps now. Remove remnants
of step 10.
2021-01-31 20:26:02 -05:00
Matthias Clasen 7985d277b3 nativedialog: Add more docs
Emphasize that native dialogs aren't widgets, and are not
kept alive by GTK.
2021-01-31 20:25:44 -05:00
Matthias Clasen 752da5c2a5 Merge branch 'tool-static' into 'master'
tools: Don't static and dynamic link on libgtk4

See merge request GNOME/gtk!3138
2021-02-01 00:44:08 +00:00
Matthias Clasen de4b8d547b Merge branch 'wip/exalm/activate' into 'master'
listitemwidget: Activate on release instead of press

Closes #3345

See merge request GNOME/gtk!3008
2021-02-01 00:32:05 +00:00
Xavier Claessens 1048ad1a01 tools: Don't static and dynamic link on libgtk4 2021-01-31 11:09:20 -05:00
Ungedummt 4d11158d97 GtkGrid: Add xml example for GtkBuildable to docs
Added an example and a short discription for the properties
2021-01-31 10:19:14 +01:00
Ungedummt 293b81cad2 Fix small typo in the docs of GtkWidget
In a XML example was MyGrid as a class defined; replaced with GtkGrid
2021-01-31 10:19:08 +01:00
Matthias Clasen 65c38111f9 4.1.0 2021-01-30 19:57:24 -05:00
Matthias Clasen ec8db379a6 tests: Disable the textview-margins reftest
It is too flaky to be useful.
2021-01-30 19:57:24 -05:00
Matthias Clasen 1484b4ae9f node editor: Add a dark mode toggle
This is useful to see light rendering clearly.
2021-01-30 19:57:24 -05:00
Rafael Fontenelle 4cecbf1654 Update Brazilian Portuguese translation
(cherry picked from commit 056c3e11a1)
2021-01-30 19:16:02 +00:00
Timm Bäder 234ba90e2b Merge branch 'mcclurgm-master-patch-63249' into 'master'
Document nullability of gtk_list_box_get_selected_row

See merge request GNOME/gtk!3137
2021-01-30 17:58:33 +00:00
Rafael Fontenelle bdd2244f75 Update Brazilian Portuguese translation
(cherry picked from commit f224c8fab9)
2021-01-30 16:00:45 +00:00
Michael McClurg cd7ec8ac92 Document nullability of gtk_list_box_get_selected_row 2021-01-30 15:23:41 +00:00
Piotr Drąg cc5edbbbb2 Update POTFILES.in 2021-01-30 14:21:32 +01:00
Matthias Clasen 94d9e34dd3 Merge branch 'fix-unfocus-on-unmap' into 'master'
Fix unsetting focus

Closes #3623

See merge request GNOME/gtk!3136
2021-01-30 03:25:19 +00:00
Matthias Clasen 3dbf5038fa Fix unsetting focus
Make _gtk_window_unset_focus_and_default queue the changes
for after the next draw. This achieves two things: first,
it avoids invalidating css at the wrong time (e.g. when
setting child-visible during size-allocation), and second,
it defers the focus change until after the widget is
hidden, so that moving the focus has the desired effect
of picking a different, visible widget.

Fixes: #3623
2021-01-29 21:41:16 -05:00
Matthias Clasen 456a2f3bcf Merge branch 'msvc.nounistd' into 'master'
testsuite/testutils.c: Fix build on Visual Studio

See merge request GNOME/gtk!3131
2021-01-29 20:16:13 +00:00
Matthias Clasen 8e1fa52d14 Merge branch 'gst-vaapi-fix' into 'master'
gtkgstsink: Sync texture before handing it to GDK

See merge request GNOME/gtk!3114
2021-01-29 19:06:03 +00:00
Matthias Clasen cbf2feb633 Merge branch 'ci-gstreamer-deps' into 'master'
Ci gstreamer deps

See merge request GNOME/gtk!3133
2021-01-29 19:05:47 +00:00
Matthias Clasen afe8ee501c Merge branch 'ebassi/for-master' into 'master'
Ebassi/for master

See merge request GNOME/gtk!3134
2021-01-29 18:47:31 +00:00
Jan Alexander Steffens (heftig) 4644dab081 gtkgstsink: Sync texture before handing it to GDK
We need to synchronize when moving the texture between contexts, or we
get glitches with VA-API decoding.
2021-01-29 18:58:17 +01:00
Matthias Clasen b37a69d76c ci: Add mesa-libGLES-devel
Try again, since libglvnd-devel is not the right choice.
2021-01-29 12:55:46 -05:00
Emmanuele Bassi 51bc6ce2e4 build: Disable subproject Cairo tests
There's really no point in running them.
2021-01-29 16:31:10 +00:00
Emmanuele Bassi 988ebc2248 docs: Annotate XML fragments as such
This way we can get syntax highlighting.
2021-01-29 16:31:10 +00:00
Emmanuele Bassi 9f31e95420 docs: Escape bare tags
Otherwise tools processing the description of GtkWidget will be *very*
confused.
2021-01-29 16:31:10 +00:00
Emmanuele Bassi 3a076e26f7 docs: Use the appropriate syntax for code block language 2021-01-29 16:31:09 +00:00
Emmanuele Bassi e3e85fc6f3 docs: Remove stray code block end marker 2021-01-29 16:31:09 +00:00
Jonas Ådahl ad3a35b4c5 Merge branch 'gtk-surface-release-4' into 'master'
wayland: Signal gtk-shell surface destruction to the server

See merge request GNOME/gtk!3129
2021-01-29 16:21:05 +00:00
Matthias Clasen 454caa3eec ci: Use v26 of the Fedora image
This includes libglvnd-devel and should fix using the
gstreamer gl support.
2021-01-29 11:14:54 -05:00
Matthias Clasen 0ffe67ffed ci: Add libglvnd-devel to images
gstreamers gl support included headers from this
package without depending on it. Work around this
packaging error by explicitly adding the needed
dependencies.
2021-01-29 11:07:11 -05:00
Matthias Clasen 8eb46bbfb2 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

Closes #3615

See merge request GNOME/gtk!3132
2021-01-29 15:15:43 +00:00
Chun-wei Fan d8e8b3c235 testsuite/testutils.c: Fix build on Visual Studio
Visual Studio does not come with unistd.h, but Windows do have write() and
close() in io.h, so include io.h instead of unistd.h on Windows.

For MinGW, unistd.h in turn includes io.h.
2021-01-29 17:59:10 +08:00
Timm Bäder 79f273348d gl renderer: Fix viewport computation when rendering offscreen
Fixes #3615
2021-01-29 10:37:48 +01:00
Timm Bäder fc99081658 showrendernode: Monitor input file 2021-01-29 09:45:25 +01:00
Timm Bäder aba14e6a43 node editor: Show some default node data
Show case the icon and the render node format this way.
2021-01-29 09:45:25 +01:00
Timm Bäder 8ebcef97ff shader builder: Improve error output 2021-01-29 09:45:25 +01:00
Timm Bäder 00956a3770 node editor: Make help textview monospace
Otherwise the nice markdown tables don't line up.
2021-01-29 08:07:39 +01:00
Alexander Mikhaylenko 11f3b7730c windowhandle: Use drag threshold instead of double click threshold
Now that we have gtk_drag_check_threshold_double(), be consistent with
other draggable widgets and make sure we don't take over a drag before a
child does.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3513
2021-01-29 12:01:34 +05:00
Alexander Mikhaylenko f63e6394ac dragsource: Use double coordinates for checking drag threshold
If multiple nested widgets have drag sources on them, both using bubble
phase, we need to reliably pick the inner one. Both of them will try to
start dragging, and we need to make sure there are no situations where the
outer widget starts drag earlier and cancels the inner one.

Currently, this can easily happen via integer rounding: start and current
coordinates passed into gtk_drag_check_threshold() are initially doubles
(other than in GtkNotebook and GtkIconView), and are casted to ints. Then
those rounded values are used to calculate deltas to compare to the drag
threshold, losing quite a lot of precision along the way, and often
resulting in the outer widget getting larger deltas.

To avoid it, just don't round it. Introduce a variant of the function that
operates on doubles: gtk_drag_check_threshold_double() and use it instead
of the original everywhere.
2021-01-29 12:01:34 +05:00
Alexander Mikhaylenko bbca4c38df entry: Fix drag threshold check
It was passing offsets as current oordinates.
2021-01-29 12:00:10 +05:00
Alexander Mikhaylenko 28f5d26719 windowhandle: Don't drag on capture phase
This was needed to work around widgets claiming event sequences on press,
by ignoring them and starting the drag anyway unless they have certain
event controllers on them.

The most visible offender was GtkButton, but since the last commit it
doesn't claim the sequence anymore and we can remove the hack.
2021-01-29 12:00:10 +05:00
Alexander Mikhaylenko bf2620f041 checkbutton: Claim sequence on release instead of press
Make it possible to drag windows from check buttons in future.
2021-01-29 12:00:10 +05:00
Alexander Mikhaylenko 870b82b541 button: Stop claiming event sequence on press
Currently GtkButton claims the sequence both on press and on release. Stop
claiming it on press and only do it on release, allowing drags to start
from it.

This will allow to remove a hack from GtkWindowHandle.
2021-01-29 12:00:10 +05:00
Matthias Clasen 1635d9fb78 Merge branch 'pango-glyph-positions' into 'master'
Tell pango not to round glyph positions

See merge request GNOME/gtk!2058
2021-01-29 01:41:56 +00:00
Matthias Clasen 20fb155e8c gsk: Fix render node serialization
When looking for ascii glyphs, we must match
the pango shape flags that GTK is using.
2021-01-28 18:19:42 -05:00
Matthias Clasen da59c77ae2 widget: Use subpixel positioning
Before turning off pangos rounding of glyph positions,
we must check if the cairo we are using is new enough
to have working subpixel positioning (the relevant
cairo commit is 52a7c79fd4ff96bb5fac175f0199819b0f8c18fc).
2021-01-28 18:17:22 -05:00
Matthias Clasen 0d0bdaa02e gsk: Fix a thinko
With subpixel positioning, we need to offset the
cached glyphs by their phase.
2021-01-28 18:16:16 -05:00
Sebastian Keller 04cf5044da wayland: Signal gtk-shell surface destruction to the server
This adds a "release" destructor for the gtk_surface1 interface which
signals to the server that a surface has been destroyed on the client
side, which the current "destroy" does not do.

Ideally the protocol would have specified a destroy request marked as
destructor to handle this automatically, however this is no longer
possible due to the destroy method being implicitly generated in the
absence of an explicit request in the protocol. Adding a destroy request
marked as destructor now would generate a new destroy method that
unconditionally would send the request to the server, which would break
clients running on servers not supporting that request.
2021-01-28 22:31:03 +01:00
Anders Jonsson b005cd0bbd Update Swedish translation
(cherry picked from commit 5a5bb9099e)
2021-01-28 20:39:25 +00:00
Matthias Clasen f5379d2047 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!3127
2021-01-28 19:12:18 +00:00
Matthias Clasen 98c247ec29 label: Drop some unused includes 2021-01-28 12:27:07 -05:00
Matthias Clasen 38e2f9138d Remove vestigial glade support
These files have not been kept up to date, and
glade doesn't work with GTK4 currently.
2021-01-28 12:27:07 -05:00
Matthias Clasen 3cc7d9b8c0 Move the gesture icons in the right place
Put these images into gtk/icons, where they belong.
2021-01-28 12:27:07 -05:00
Matthias Clasen 1ac9400712 Drop unused logo resource
The inspector no longer sets a window icon.
2021-01-28 12:27:07 -05:00
Matthias Clasen 10d5705b70 Reduce use of GtkStyleContext
Remove some unnecessary uses of GtkStyleContext where
we can directly go to the GtkCssStyle, and and drop
unnnecessary includes.
2021-01-28 12:27:07 -05:00
Matthias Clasen 2d0d579735 Unify border-spacing handling
Avoid using GtkStyleContext unnecessarily, just go
to the css node directly.
2021-01-28 12:27:07 -05:00
Matthias Clasen ac0f524722 build: Redo the tools build
Move the tools directory to be toplevel, and instead of
recompiling sources twice, link them with the our new
static libgtk.a.
2021-01-28 12:27:07 -05:00
Matthias Clasen 2cd0e5f60b Merge branch 'wip/fl/gl-renderer-fixes' into 'master'
gskglshaderbuilder: bind correct uv location

See merge request GNOME/gtk!3128
2021-01-28 17:15:43 +00:00
Fabio Lagalla d83502d054 gskglshaderbuilder: bind correct uv location 2021-01-28 17:08:46 +01:00
Matthias Clasen 9e539a7f59 Merge branch 'matthiasc/for-master' into 'master'
builder-tool: Translate GtkImage:pixbuf

See merge request GNOME/gtk!3126
2021-01-28 02:04:48 +00:00
Matthias Clasen c60247f51f Merge branch 'wip/fl/gl-gradients' into 'master'
OpenGL gradient rendering improvements and additions

See merge request GNOME/gtk!3105
2021-01-28 01:43:57 +00:00
Matthias Clasen 06321511ad builder-tool: Translate GtkImage:pixbuf
The pixbuf property doesn't exist anymore. It is
commonly set to a path in ui files, so translate it
to the file property.
2021-01-27 17:01:51 -05:00
Matthias Clasen 2e7923cad0 Merge branch 'matthiasc/for-master' into 'master'
docs: Add gtk_widget_grab_default to migration guide

See merge request GNOME/gtk!3125
2021-01-27 21:53:02 +00:00
Matthias Clasen 3c66c27caa docs: Add gtk_widget_grab_default to migration guide
Point out the replacement for this api.
2021-01-27 13:50:05 -05:00
Timm Bäder 7f4bd6917e Merge branch 'sophie-h-master-patch-47269' into 'master'
widget: get_name() is not nullable

See merge request GNOME/gtk!3124
2021-01-27 18:34:10 +00:00
Sophie Herold b89376da55 widget: get_name() is not nullable
Partial revert of !2905
2021-01-27 17:49:17 +00:00
Fabio Lagalla a1dd6521e8 gskglrenderer: Remove switch fallthrough comments 2021-01-27 12:52:11 +01:00
Fabio Lagalla 0088f840fe gskrendernode: Cache angle in conic gradients 2021-01-27 12:44:10 +01:00
Fabio Lagalla 1b698c896e gskglrenderer: Use gboolean instead of bool 2021-01-27 12:44:10 +01:00
Fabio Lagalla 04000f28e7 gskglrenderer: First class support of repeating-radial-gradient 2021-01-27 12:44:10 +01:00
Fabio Lagalla 976a05f6eb gskglrenderer: First class support of repeating-linear-gradient 2021-01-27 12:44:10 +01:00
Fabio Lagalla b15902bf44 gskglrenderer: Optimize conic-gradient shader 2021-01-27 12:44:10 +01:00
Fabio Lagalla 5ac7529771 gskglrenderer: Optimize radial-gradient shader 2021-01-27 12:44:10 +01:00
Fabio Lagalla bbf68c0d9d gskglrenderer: Optimize linear-gradient shader 2021-01-27 12:44:10 +01:00
Matthias Clasen eeb3dd3511 Merge branch 'fix-can-focus' into 'master'
widget: Fix can-focus

Closes #3610

See merge request GNOME/gtk!3123
2021-01-27 05:34:21 +00:00
Matthias Clasen 7b0ce11e46 Merge branch 'search-entry-capture' into 'master'
Search entry capture

Closes #3098

See merge request GNOME/gtk!3115
2021-01-27 05:14:30 +00:00
Matthias Clasen 8ef1d6a49c widget: Fix can-focus
Setting can-focus to FALSE on a widget is supposed
to prevent focus from entering the entire subtree.
So when we grab focus directly to a widget, we need
to check the can-focus flag not just of the widget
itself, but all its ancestors.

Fixes: #3610
2021-01-26 23:45:06 -05:00
Matthias Clasen 7db60f958d searchentry: Capture events in the bubble phase
This is an unfortunate naming clash, but it avoids
an event handling clash between the capture widget
and its children.

Fixes: #3098
2021-01-26 22:17:57 -05:00
Matthias Clasen 30043e072e Merge branch 'css-crossfade-color' into 'master'
Css crossfade color

See merge request GNOME/gtk!3122
2021-01-27 03:11:17 +00:00
Matthias Clasen 5ee7606779 css: Support colors in cross fades
The CSS Image Spec (Level 4) allows colors in
cross-fade expressions to specify solid-color images.

Support this.
2021-01-26 21:14:09 -05:00
Matthias Clasen 25409c5a5a css: Add a constructor for GtkCssImageFallback
Add a way to create a solid color image.
2021-01-26 21:10:11 -05:00
Matthias Clasen 51122dd287 docs: Cosmetics
Tweak the css docs slightly.
2021-01-26 20:33:16 -05:00
Matthias Clasen ec9159f983 Merge branch 'gst-vaapi-fix-pre' into 'master'
Minor fixes to gtkgstsink

See merge request GNOME/gtk!3120
2021-01-27 01:11:54 +00:00
Matthias Clasen f3d77d1c21 Merge branch 'css-text-decoration' into 'master'
css: Fix text-decoration-line support

Closes #3621

See merge request GNOME/gtk!3121
2021-01-27 00:42:40 +00:00
Matthias Clasen 1258fcaaf4 css: Fix text-decoration-line support
This property needs to be treated as flags, not as
enum, since it should be possible to specify more
than one value, e.g.

text-decoration-line: underline overline;

Tests included.

Fixes: #3621
2021-01-26 17:53:14 -05:00
Jan Alexander Steffens (heftig) 00fd60aaa8 gtkgstsink: Use video_frame_free also for the GL path
The video frame needs to stay mapped while the texture is in use.

Avoid using g_memdup because the structure is not supposed to be moved.
2021-01-26 20:30:47 +01:00
Jan Alexander Steffens (heftig) c7a7d0582a gtkgstsink: Report allocation size even if no pool requested
We can do that so we should.
2021-01-26 20:30:47 +01:00
Matthias Clasen b6e7acfb90 Merge branch 'matthiasc/for-master' into 'master'
docs: Update border-size docs

See merge request GNOME/gtk!3119
2021-01-26 16:25:24 +00:00
Matthias Clasen 40eae298d5 docs: Update border-size docs
GtkCenterLayout respected border-size as well.
2021-01-26 10:40:22 -05:00
Marek Černocký 09a9131a10 Updated Czech translation 2021-01-26 16:21:18 +01:00
Marek Černocký c93c9f5c2a Updated Czech translation 2021-01-26 16:12:36 +01:00
Matthias Clasen 7f08adc23e Merge branch 'ebassi/for-master' into 'master'
Fixes for gdk_surface_translate_coordinates()

See merge request GNOME/gtk!3118
2021-01-26 13:57:50 +00:00
Emmanuele Bassi f41012080f Validate arguments
We're just assuming everything is not NULL or with a valid type.
2021-01-26 12:56:32 +00:00
Emmanuele Bassi 786e9d351c Make the inout argument logic clearer
It's easy to misread a `+=`.
2021-01-26 12:54:53 +00:00
Emmanuele Bassi 3d2cf97fbf Fix annotations
The arguments are really (inout), not (out).
2021-01-26 12:54:00 +00:00
Matthias Clasen 1fe6fb6739 Merge branch 'circular-menubutton' into 'master'
Allow circular menubuttons

Closes #3423 and #3523

See merge request GNOME/gtk!3117
2021-01-26 12:47:38 +00:00
Emmanuele Bassi 6710eb5eb3 Merge branch 'ricotz/for-master' into 'master'
gdk: Add missing g-i annotations for gdk_surface_translate_coordinates

See merge request GNOME/gtk!3112
2021-01-26 12:28:55 +00:00
Matthias Clasen 80b1d55683 Merge branch 'css-overline' into 'master'
css: Support overline

See merge request GNOME/gtk!3116
2021-01-26 05:44:14 +00:00
Matthias Clasen 1cebc4316b Allow circular menubuttons
Fixes #3523
2021-01-26 00:20:23 -05:00
Matthias Clasen 20895d6f3f Merge branch 'adaptive-emojichooser' into 'master'
Adaptive emojichooser

Closes #3307

See merge request GNOME/gtk!2989
2021-01-26 05:07:46 +00:00
Matthias Clasen 65a4118d50 css: Support overline
We can support text-decoration-line: overline,
since pango supports it now.
2021-01-26 00:04:04 -05:00
Matthias Clasen 4857829aaa popover: Try to not exceed monitor bounds
When the natural size of the popover exceeds
the monitor width, clamp it to fit on screen.

This gives the Emoji chooser a chance to
work on phone screens.

Fixes: #3307
2021-01-25 23:33:04 -05:00
Matthias Clasen 2ea4574caf emojichooser: Allow the section buttons to wrap
Use a flowbox instead of a horizontal box for
the section buttons at the bottom, so they can
wrap and allow for narrow layout.

We also need to stop giving the scrolledwindow
a content height, so it can shrink to make room
for more rows of section buttons.
2021-01-25 23:32:15 -05:00
Matthias Clasen 102b74f9eb emojichooser: Make keynav work with != 7 columns
The number of 7 columns was hardcoded in a few places
related to keynav across sections. The flowbox does
not have an api for it, but we can find out anyway
how many columns there are.
2021-01-25 23:32:08 -05:00
Matthias Clasen 8a0d4dfa94 searchbar: Capture events in the bubble phase
This is an unfortunate naming clash, but it avoids
an event handling clash between the capture widget
and its children.

Fixes: #3098
2021-01-25 22:16:29 -05:00
Matthias Clasen b4e645862a searchbar: Fix documentation mishap
The css section was inserted between the example
and the sentence referring to it.
2021-01-25 22:15:56 -05:00
Matthias Clasen ea48506a32 Merge branch 'simplify-get-module-path' into 'master'
modules: Simplify _gtk_get_module_path

See merge request GNOME/gtk!3113
2021-01-26 02:53:38 +00:00
Jan Alexander Steffens (heftig) 23f0a29260 modules: Simplify _gtk_get_module_path
Remove the bizarre loops.
2021-01-25 22:47:16 +01:00
Rico Tzschichholz 9249717cf4 gdk: Add missing g-i annotations for gdk_surface_translate_coordinates 2021-01-25 20:18:33 +01:00
Matthias Clasen 4196dfc374 Merge branch 'wip/jimmac/larger-scrollbars-gtk4' into 'master'
Adwaita: make scrollbars larger

Closes #1886

See merge request GNOME/gtk!3109
2021-01-25 13:35:47 +00:00
Jakub Steiner 23af707b41 Adwaita: make scrollbars larger
When using scrollbars as active controls, rather than their primary role as indicators,
increase their size as click targets.

Fixes https://gitlab.gnome.org/GNOME/gtk/issues/1886
2021-01-25 14:15:22 +01:00
Matthias Clasen 421088c3a0 Merge branch 'transform-origin' into 'master'
Transform origin

See merge request GNOME/gtk!3108
2021-01-25 12:58:36 +00:00
Matthias Clasen 749f1a7c00 Add a reftest for transform-origin 2021-01-24 23:47:10 -05:00
Matthias Clasen 344f9fcf05 css: Implement transform-origin
Implement most of transform-origin. We only
handle the xy components currently, which lets
us reuse the position value implementation that
is used for background-position.
2021-01-24 22:49:08 -05:00
Matthias Clasen 4c971cd4da docs: Fix reference for css transform
Refer to the canonical location for the css
transform spec.
2021-01-24 22:48:00 -05:00
A S Alam 43d553dcfb Update Punjabi translation
(cherry picked from commit 64519d73bb)
2021-01-24 22:52:47 +00:00
A S Alam 66264f9a3d Update Punjabi translation
(cherry picked from commit 518331812e)
2021-01-24 22:42:39 +00:00
Efstathios Iosifidis 269f369541 Update Greek translation
(cherry picked from commit 281c17c400)
2021-01-24 10:17:36 +00:00
Matthias Clasen 1973019962 Merge branch 'static-lib-for-tests' into 'master'
Static lib for tests

See merge request GNOME/gtk!3107
2021-01-23 16:15:23 +00:00
Matthias Clasen fe515c4c1c testsuite: Link some tests statically
Link tests for private apis statically.
2021-01-23 10:34:57 -05:00
Matthias Clasen 14f0a0addb Create a static library
Rearrange our build to create a libgtk.a for the the contents of gtk/,
and build libgtk-4.so from our per-subdirectory static libraries.
This will let us link tests statically for testing internal apis.
2021-01-23 10:31:23 -05:00
Matthias Clasen 64a2d0221c Merge branch 'lsan-leaks-2' into 'master'
Lsan leaks 2

See merge request GNOME/gtk!3106
2021-01-22 20:08:54 +00:00
Matthias Clasen 0ef91c3ba8 Avoid a buffer overrun
We were putting the '\0' behind the end. Oops.
2021-01-22 13:56:04 -05:00
Matthias Clasen 2adcb7be71 Tweak lsan suppressions
We don't use atk-bridge anymore, and we don't want
to see gio leaks.
2021-01-22 13:32:41 -05:00
Matthias Clasen a332f2402a ci: Don't print lsan suppressions
Printing these out breaks TAP output, and we really
aren't interested in them.
2021-01-22 13:01:09 -05:00
Matthias Clasen 131a61c51b testsuite: Fix a leak
asan pointed out that the array tests leak.
2021-01-22 11:50:04 -05:00
Matthias Clasen 39d5dd89c5 Avoid a heap-use-after-free
_gtk_gesture_cancel_sequence frees the struct pointed to by data,
so don't write to it afterwards. Found by asan.
2021-01-22 11:39:04 -05:00
Danial Behzadi 341efe9a40 Update Persian translation 2021-01-22 14:57:52 +00:00
Matthias Clasen 5ed6f89b4a Merge branch 'lsan-leaks' into 'master'
Lsan leaks

See merge request GNOME/gtk!3104
2021-01-22 12:30:22 +00:00
Matthias Clasen 4d609149d2 Merge branch 'tests-without-diff' into 'master'
testsuite: Stop requiring diff

See merge request GNOME/gtk!3103
2021-01-22 05:16:08 +00:00
Matthias Clasen 0d790505aa Force malloc of g_slices in asan build
Otherwise leaks could be missed.
2021-01-22 00:13:13 -05:00
Matthias Clasen a486536925 Remove libc from leak suppression list
Every program starts in __libc_start_main, so this would suppress
everything. This doesn't happen in practice because asan by default
is unable to unwind the stack. Setting
ASAN_OPTIONS=fast_unwind_on_malloc=0,malloc_context_size=15 can unwind
the stack, and if malloc_context_size is large enough it will indeed
suppress everything.
2021-01-22 00:12:46 -05:00
Matthias Clasen e808fb424a testsuite: Stop requiring diff
Unify the many copies of diff_with_file in one source
file, and patch it to detect diff at runtime and fall
back to a simple strcmp if we don't have it. Make all
tests use this new testutils.c, and stop requiring
diff for building the tests.

This should let us allow to build on Windows with the
default value for -Dbuild-tests.
2021-01-21 23:57:24 -05:00
Matthias Clasen 6c54abeca7 wayland: Explicitly announce ssd for kwin
Without this, kwin correctly assumes that we are
using client-side decorations. This is a port
of 32ae97f1 from GTK 3.24.

Fixes: #3609
2021-01-21 22:45:47 -05:00
Daniel Șerbănescu d24b8a094c Update Romanian translation 2021-01-21 19:27:47 +00:00
Emmanuele Bassi c46391420f Merge branch 'ebassi/lazier-a11y' into 'master'
Lazier accessibility

See merge request GNOME/gtk!3102
2021-01-21 18:57:34 +00:00
Yuri Chornoivan 68df7527f7 Update Ukrainian translation 2021-01-21 18:23:25 +00:00
Matthias Clasen 5a3c3d8210 Merge branch 'inspector-controllers' into 'master'
Inspector controllers

See merge request GNOME/gtk!3101
2021-01-21 18:15:57 +00:00
Emmanuele Bassi 95ceb49770 a11y: Make GtkATContext realization lazier
We only realize the ATContext on the top level, which will create an
GtkAtSpiRoot object and the corresponding GtkAtSpiCache object. Whenever
an AT connects to the accessibility bus, and asks for the various
objects, all the ATContext will be realized on demand.
2021-01-21 16:40:57 +00:00
Emmanuele Bassi 0bde58ffd7 a11y: Avoid signal emission during cache population
If we're responding to a request to get all the cached items, there's no
need to emit signals when adding an ATContext to the cache.
2021-01-21 16:40:57 +00:00
Matthias Clasen ccd9827b63 inspector: Redo the actions page
Don't create widgets in bind, instead just set
the new action on the action-editor, and let it
recreate the parts that need to be recreated.
2021-01-21 10:25:13 -05:00
Matthias Clasen db189cfb9f inspector: Reshuffle action editor
Prepare the action editor for being able to change its
actions after creation.
2021-01-21 10:24:31 -05:00
Matthias Clasen 7527f181d5 inspector: Simplify action editor
We are not using the size group anymore, so drop it.
2021-01-21 10:20:21 -05:00
Matthias Clasen c05b418512 inspector: Split out variant editor 2021-01-21 10:19:18 -05:00
Matthias Clasen e97d996fe4 inspector: Redo the shortcuts page
Use a column view here.
2021-01-21 10:19:18 -05:00
Matthias Clasen 0537b167ca inspector: Redo the controllers page
Use a column view, and only show the widgets own
controllers.
2021-01-21 10:19:18 -05:00
Matthias Clasen 40446201ff Merge branch 'ebassi/for-master' into 'master'
Ebassi/for master

Closes #3607

See merge request GNOME/gtk!3100
2021-01-21 04:22:13 +00:00
Matthias Clasen fff6b35821 inspector: Redo the controllers page
Use a column view, and only show the widgets own
controllers.
2021-01-20 18:51:01 -05:00
Emmanuele Bassi 75f2d7583f Abort if the shared memory pool cannot be created
If we cannot allocate memory, we cannot create any windowing system
surface. There's no coming back from that.

Fixes: #3607
2021-01-20 19:10:54 +00:00
Matthias Clasen 1fd8d3b487 Merge branch 'matthiasc/for-master' into 'master'
docs: Update getting started section

Closes #3601

See merge request GNOME/gtk!3099
2021-01-20 15:54:37 +00:00
Emmanuele Bassi a1216599ff Add rename-to annotation for GtkListStore.insert_valuesv()
The vector-based variant should shadow the variadic arguments function
in bindings.
2021-01-20 14:10:17 +00:00
Emmanuele Bassi 8fff0e0fdf docs: Reformat GtkListStore.insert_values() 2021-01-20 14:10:17 +00:00
Emmanuele Bassi 439727a84a Add more directions to the issue templates
Let's hope people read them.
2021-01-20 14:10:17 +00:00
Matthias Clasen 3a18a6dddf docs: Update getting started section
We were still talking about draw signals here,
which don't exist anymore.

Fixes: #3601
2021-01-20 08:01:54 -05:00
Matthias Clasen d7050c63ae Merge branch 'treeview-sort-arrows' into 'master'
Redo arrow icons in various widgets

Closes #3577

See merge request GNOME/gtk!3097
2021-01-19 21:24:04 +00:00
Balázs Meskó b7c88ec87d Update Hungarian translation 2021-01-19 20:47:20 +00:00
Matthias Clasen 5985b62f60 columnview: Redo indicator arrows
Use the same approach as GtkTreeViewColumn for sort
indicators. Luckily, the same css works for both.
2021-01-19 14:24:19 -05:00
Matthias Clasen e7c29b989c menbutton: Redo indicator arrows
Instead of hardcoding icon names in the widget, use
arrow.none, arrow.up, arrow.down, arrow.left, arrow.right
styles and set the icon to use with -gtk-icon-source. This
lets themes change the icons that are used here, without
forcing all uses of pan-up/down/start/end-symbolic to be
treated the same.

Document this in the menubutton CSS docs.
2021-01-19 14:02:23 -05:00
Matthias Clasen 2100e427d9 treeviewcolumn: Redo sort arrows
Instead of hardcoding icon names in the widget, use
sort-indicator.ascending and sort-indicator.descending styles
and set the icon to use with -gtk-icon-source. This lets themes
change the icon that is used here, without forcing all uses of
pan-up/down-symbolic to be treated the same.

Document this in the treeview CSS docs.

Fixes: #3577
2021-01-19 14:02:16 -05:00
Matthias Clasen 2550d6dc63 Merge branch 'wip/kalev/dist-HighContrast-dark' into 'master'
dist: Fix css theme disting after HighContrast-dark changes

See merge request GNOME/gtk!3095
2021-01-19 12:08:21 +00:00
Matthias Clasen ca72fae884 Merge branch 'issue-2436-gtk4' into 'master'
macOS: fix #2436 raise transient window on focus

Closes #2436

See merge request GNOME/gtk!3094
2021-01-19 11:56:54 +00:00
Matthias Clasen 4fc1af14a7 Merge branch 'wip/kalev/NEWS.pre-4.0' into 'master'
Split NEWS for pre-4.0 changes

See merge request GNOME/gtk!3096
2021-01-19 11:43:58 +00:00
Kalev Lember 1a30ec6da6 dist: Fix css theme disting after HighContrast-dark changes
Commit f60d245e32 renamed it from
HighContrast-inverse.css to HighContrast-dark.css.
2021-01-19 10:50:30 +01:00
Kalev Lember e77d519482 Split NEWS for pre-4.0 changes
Similar to commit 87e9f0895b that did the
same for older releases, this commit splits out pre-4.0 changes to
separate NEWS.pre-4.0 file.
2021-01-19 10:40:09 +01:00
Thomas Holder 59806eee38 macOS: fix #2436 raise transient window on focus
Ported from gtk-3-24 e278f38905

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/2436
2021-01-19 09:31:00 +01:00
Alexander Mikhaylenko 5968b10b0b listitemwidget: Activate on release instead of press
Single click activation should only be done on release and not on press,
otherwise it breaks touch scrolling. Double-click activation still can be
done on press.

This matches the GtkListBox behavior as well.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3345
2021-01-19 12:36:32 +05:00
Matthias Clasen e6f0103940 Merge branch 'version-bump' into 'master'
Version bump

See merge request GNOME/gtk!3093
2021-01-19 04:48:26 +00:00
Matthias Clasen cbaad3dbd9 Add version macros for 4.2
These will be needed for adding new API.
2021-01-18 23:10:18 -05:00
Matthias Clasen ee43a6a603 Bump version to 4.1
master is now open for 4.2 API additions.

Includes an update for the one test we have that
has the version number in its expected output.
2021-01-18 23:09:44 -05:00
Matthias Clasen 1ac1147ecb Merge branch 'check_button_activate' into 'master'
Add activate signal to GtkCheckButton

Closes #3525 and #3550

See merge request GNOME/gtk!3012
2021-01-19 04:06:01 +00:00
Matthias Clasen 1edbc1f1f9 Merge branch 'wip/jtojnar/fix-pc-vulcan' into 'master'
build: Use Meson’s module for building .pc files

Closes #3517

See merge request GNOME/gtk!3005
2021-01-19 04:04:34 +00:00
Yetizone 601dfeeff9 checkbutton: Add activate signal to work with gtk_widget_activate()
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3525
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3550
2021-01-04 17:25:53 +02:00
Jan Tojnar 2c9f2325e2 build: Use Meson’s module for building .pc files
Using the module will prevent trivial bugs caused by incorrect string concatenation.

This is just a literal translation. In the future we might rely on Meson auto-detecting fields from library declaration.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3517
2020-12-27 06:27:59 +01:00
296 changed files with 20679 additions and 18255 deletions
+1 -1
View File
@@ -24,7 +24,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:v25"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v27"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v25"
+1
View File
@@ -65,6 +65,7 @@ RUN dnf -y install \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
mesa-libGLES-devel \
mesa-libwayland-egl-devel \
ninja-build \
pango-devel \
+1 -1
View File
@@ -1,4 +1,4 @@
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v25
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v27
# Enable sudo for wheel users
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers
+2 -1
View File
@@ -8,7 +8,8 @@ builddir=$1
backend=$2
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0
export G_SLICE=always-malloc
case "${backend}" in
x11)
+12
View File
@@ -1,4 +1,13 @@
<!--
Please, read the CONTRIBUTING.md guide on how to file a new issue.
https://gitlab.gnome.org/GNOME/gtk/-/blob/master/CONTRIBUTING.md
-->
## Steps to reproduce
<!--
Please, explain the sequence of actions necessary to reproduce the
bug
-->
1. ...
2. ...
@@ -32,5 +41,8 @@
## Additional information
<!--
- Screenshots or screen recordings are useful for visual errors
- Attaching a screenshot or a video without explaining the current
behavior and the actions necessary to reproduce the bug will lead
to the bug being closed
- Please report any warning or message printed on the terminal
-->
+10
View File
@@ -1,4 +1,14 @@
<!--
Please, read the CONTRIBUTING.md guide on how to file a new issue.
https://gitlab.gnome.org/GNOME/gtk/-/blob/master/CONTRIBUTING.md
-->
## Steps to reproduce
<!--
Please, explain the sequence of actions necessary to reproduce the
crash
-->
1. ...
2. ...
+55 -9180
View File
File diff suppressed because it is too large Load Diff
+9178
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7,7 +7,7 @@ import subprocess
stylesheets = [ 'gtk/theme/Adwaita/Adwaita.css',
'gtk/theme/Adwaita/Adwaita-dark.css',
'gtk/theme/HighContrast/HighContrast.css',
'gtk/theme/HighContrast/HighContrast-inverse.css' ]
'gtk/theme/HighContrast/HighContrast-dark.css' ]
sourceroot = os.environ.get('MESON_SOURCE_ROOT')
distroot = os.environ.get('MESON_DIST_ROOT')
+21 -1
View File
@@ -279,11 +279,31 @@ drag_prepare_texture (GtkDragSource *source,
GtkWidget *widget)
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
GtkSnapshot *snapshot;
double width, height;
GskRenderNode *node;
GskRenderer *renderer;
GdkTexture *texture;
GdkContentProvider *ret;
if (!GDK_IS_PAINTABLE (paintable))
return NULL;
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
snapshot = gtk_snapshot_new ();
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
renderer = gtk_native_get_renderer (gtk_widget_get_native (widget));
texture = gsk_renderer_render_texture (renderer, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
ret = gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, texture);
g_object_unref (texture);
gsk_render_node_unref (node);
return ret;
}
static GdkContentProvider *
+1
View File
@@ -13,6 +13,7 @@
<property name="right-margin">20</property>
<property name="top-margin">20</property>
<property name="bottom-margin">20</property>
<property name="monospace">1</property>
<property name="buffer">
<object class="GtkTextBuffer" id="buffer"/>
</property>
+31
View File
@@ -700,6 +700,16 @@ out:
g_free (source_dir);
}
static void
dark_mode_cb (GtkToggleButton *button,
GParamSpec *pspec,
NodeEditorWindow *self)
{
g_object_set (gtk_widget_get_settings (GTK_WIDGET (self)),
"gtk-application-prefer-dark-theme", gtk_toggle_button_get_active (button),
NULL);
}
static void
node_editor_window_finalize (GObject *object)
{
@@ -814,6 +824,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
}
static GtkWidget *
@@ -910,6 +921,26 @@ node_editor_window_init (NodeEditorWindow *self)
self->text_buffer = gtk_text_buffer_new (self->tag_table);
g_signal_connect (self->text_buffer, "changed", G_CALLBACK (text_changed), self);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (self->text_view), self->text_buffer);
/* Default */
gtk_text_buffer_set_text (self->text_buffer,
"shadow {\n"
" child: texture {\n"
" bounds: 0 0 128 128;\n"
" texture: url(\"resource:///org/gtk/gtk4/node-editor/icons/apps/org.gtk.gtk4.NodeEditor.Devel.svg\");\n"
" }\n"
" shadows: rgba(0,0,0,0.5) 0 1 12;\n"
"}\n"
"\n"
"transform {\n"
" child: text {\n"
" color: rgb(46,52,54);\n"
" font: \"Cantarell Bold 11\";\n"
" glyphs: \"GTK Node Editor\";\n"
" offset: 8 14.418;\n"
" }\n"
" transform: translate(0, 140);\n"
"}", -1);
}
NodeEditorWindow *
+9
View File
@@ -139,6 +139,15 @@
<property name="icon-name">open-menu-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="dark_bg_button">
<property name="valign">center</property>
<property name="has-frame">0</property>
<property name="icon-name">display-brightness-symbolic</property>
<property name="tooltip-text" translatable="yes">Use a dark background</property>
<signal name="notify::active" handler="dark_mode_cb" swapped="0"/>
</object>
</child>
</object>
</child>
<child>
+34 -8
View File
@@ -18,9 +18,9 @@ Length
Percentage
: %, calc()
Angle
: deg | grad | turn, calc()
: deg, grad, turn, calc()
Time
: s | ms, calc()
: s, ms, calc()
Length values with the em or ex units are resolved using the font
size value, unless they occur in setting the font-size itself, in
@@ -32,7 +32,7 @@ not quite the same as the CSS definition of rem.
The calc() notation adds considerable expressive power. There are limits
on what types can be combined in such an expression (e.g. it does not make
sense to add a number and a time). For the full details, see the
[CSS3 VAlues and Units](https://www.w3.org/TR/css3-values/#calc-notation)
[CSS3 Values and Units](https://www.w3.org/TR/css3-values/#calc-notation)
spec.
A common pattern among shorthand properties (called 'four sides') is one
@@ -80,6 +80,31 @@ and in some cases a number as arguments.
## Images
CSS allows to specify images in various forms, the most simple one being
a url for an image file. Beyond that, images can be specified as
`linear-gradient(Angle, ColorStops)`
`repeating-linear-gradient(Angle, ColorStops)`
: creates a linear gradient.
`radial-gradient(Shape, ColorStops)`
`repeating-radial-gradient(Shape, ColorStops)`
: creates a radial gradient.
`conic-gradient(Angle, ColorStops)`
: creates a conic gradient.
`cross-fade(Percentage Image,…)`
: combines two or more images.
`image(Image,… Color)`
: falls back to the first valid image, or to a solid color.
`filter(Image, Filters)`
: applies filters to an image.
For more details, see [CSS Image Level 4](https://www.w3.org/TR/css-images-4/).
GTK extends the CSS syntax for images and also uses it for specifying icons.
To load a themed icon, use
@@ -151,7 +176,7 @@ done with
|caret-color|[CSS Basic User Interface Level 3](https://www.w3.org/TR/css3-ui/#caret-color) | CSS allows an auto value |
|-gtk-secondary-caret-color|[Color](https://www.w3.org/TR/css-color-3/#valuea-def-color) | used for the secondary caret in bidirectional text |
|letter-spacing| [CSS Text Level 3](https://www.w3.org/TR/css3-text/#letter-spacing) | |
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | CSS allows overline |
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | |
|text-decoration-color| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-color-property) | |
|text-decoration-style| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-style-property) | CSS allows dashed and dotted |
|text-shadow| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-shadow-property) | |
@@ -159,11 +184,12 @@ done with
|-gtk-icon-source| [Image](https://www.w3.org/TR/css-backgrounds-3/#typedef-image), `builtin` or `none` | used for builtin icons in buttons and expanders |
|-gtk-icon-size| [Length](https://www.w3.org/TR/css3-values/#length-value) | size used for builtin icons in buttons and expanders |
|-gtk-icon-style| `requested`, `regular` or `symbolic` | preferred style for application-loaded icons |
|-gtk-icon-transform| [Transform list](https://drafts.csswg.org/css-transforms-1/#typedef-transform-list) or `none` | applied to builtin and application-loaded icons |
|-gtk-icon-transform| [Transform list](https://www.w3.org/TR/css-transforms-1/#typedef-transform-list) or `none` | applied to builtin and application-loaded icons |
|-gtk-icon-palette| Color palette, as explained above | used to recolor symbolic icons |
|-gtk-icon-shadow| [Shadow](https://www.w3.org/TR/css-backgrounds-3/#typedef-shadow) or `none` | applied to builtin and application-loaded icons |
|-gtk-icon-filter| [Filter value list](https://www.w3.org/TR/filter-effects-1/#typedef-filter-value-list) or `none` | applied to builtin and application-loaded icons |
|transform| [CSS Transforms Level 2](https://drafts.csswg.org/css-transforms-2/) | |
|transform| [CSS Transforms Level 1](https://www.w3.org/TR/css-transforms-1/#transform-property) | |
|transform-origin| [CSS Transforms Level 1](https://www.w3.org/TR/css-transforms-1/#transform-origin-property) | CSS allows specifying a z component|
|min-width| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#min-width) | CSS allows percentages |
|min-height| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#min-height) | CSS allows percentages |
|margin-top| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#margin-top) | CSS allows percentages or auto |
@@ -217,7 +243,7 @@ done with
|background-size| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-size) | |
|background-position| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-position) | |
|background-repeat| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-repeat) | |
|background-image| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-image) | not supported: urls without quotes, colors in crossfades |
|background-image| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-image) | not supported: urls without quotes |
|box-shadow| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#box-shadow) | |
|background-blend-mode| [CSS Compositing and Blending Level 1](https://www.w3.org/TR/compositing-1/#propdef-background-blend-mode) | only affects multiple backgrounds |
|background| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background) | |
@@ -235,4 +261,4 @@ done with
|animation-delay| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation-delay) | |
|animation-fill-mode| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation-fill-mode) | |
|animation| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation) | |
|border-spacing| [CSS Table Level 3](https://www.w3.org/TR/css-tables-3/#border-spacing-property) | respected by GtkBox and GtkGrid |
|border-spacing| [CSS Table Level 3](https://www.w3.org/TR/css-tables-3/#border-spacing-property) | respected by GtkBoxLayout, GtkGridLayout, GtkCenterLayout |
+8 -9
View File
@@ -343,20 +343,19 @@ Many widgets, like buttons, do all their drawing themselves. You just tell
them the label you want to see, and they figure out what font to use, draw
the button outline and focus rectangle, etc. Sometimes, it is necessary to
do some custom drawing. In that case, a GtkDrawingArea might be the right
widget to use. It offers a canvas on which you can draw by connecting to
the ::draw signal.
widget to use. It offers a canvas on which you can draw by setting its
draw function.
The contents of a widget often need to be partially or fully redrawn,
e.g. when another window is moved and uncovers part of the widget, or
when the window containing it is resized. It is also possible to explicitly
cause part or all of the widget to be redrawn, by calling
gtk_widget_queue_draw() or its variants. GTK takes care of most of the
details by providing a ready-to-use cairo context to the ::draw signal
handler.
cause a widget to be redrawn, by calling gtk_widget_queue_draw(). GTK takes
care of most of the details by providing a ready-to-use cairo context to the
draw function.
The following example shows a ::draw signal handler. It is a bit more
complicated than the previous examples, since it also demonstrates
input event handling by means of event controllers.
The following example shows how to use a draw function with GtkDrawingArea.
It is a bit more complicated than the previous examples, since it also
demonstrates input event handling with event controllers.
![Drawing](drawing.png)
-1
View File
@@ -1831,7 +1831,6 @@ GtkIMContextSimple
gtk_im_context_simple_new
gtk_im_context_simple_add_table
gtk_im_context_simple_add_compose_file
GTK_MAX_COMPOSE_LEN
<SUBSECTION Standard>
GTK_IM_CONTEXT_SIMPLE
GTK_IS_IM_CONTEXT_SIMPLE
+5
View File
@@ -1079,6 +1079,11 @@ that wants to override the default handling, you can provide an
implementation of the default.activate action in your widgets' action
groups.
### Stop using gtk_widget_grab_default()
The function gtk_widget_grab_default() has been removed. If you need
to mark a widget as default, use gtk_window_set_default_widget() directly.
### Stop setting ::has-default and ::has-focus in .ui files
The special handling for the ::has-default and ::has-focus properties
-293
View File
@@ -1,293 +0,0 @@
#include <gtk/gtk.h>
#include "exampleapp.h"
#include "exampleappwin.h"
struct _ExampleAppWindow
{
GtkApplicationWindow parent;
GSettings *settings;
GtkWidget *stack;
GtkWidget *search;
GtkWidget *searchbar;
GtkWidget *searchentry;
GtkWidget *gears;
GtkWidget *sidebar;
GtkWidget *words;
GtkWidget *lines;
GtkWidget *lines_label;
};
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
static void
search_text_changed (GtkEntry *entry,
ExampleAppWindow *win)
{
const char *text;
GtkWidget *tab;
GtkWidget *view;
GtkTextBuffer *buffer;
GtkTextIter start, match_start, match_end;
text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (text[0] == '\0')
return;
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
/* Very simple-minded search implementation */
gtk_text_buffer_get_start_iter (buffer, &start);
if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
&match_start, &match_end, NULL))
{
gtk_text_buffer_select_range (buffer, &match_start, &match_end);
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &match_start,
0.0, FALSE, 0.0, 0.0);
}
}
static void
find_word (GtkButton *button,
ExampleAppWindow *win)
{
const char *word;
word = gtk_button_get_label (button);
gtk_editable_set_text (GTK_EDITABLE (win->searchentry), word);
}
static void
update_words (ExampleAppWindow *win)
{
GHashTable *strings;
GHashTableIter iter;
GtkWidget *tab, *view, *row;
GtkTextBuffer *buffer;
GtkTextIter start, end;
char *word, *key;
GtkWidget *child;
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
if (tab == NULL)
return;
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
gtk_text_buffer_get_start_iter (buffer, &start);
while (!gtk_text_iter_is_end (&start))
{
while (!gtk_text_iter_starts_word (&start))
{
if (!gtk_text_iter_forward_char (&start))
goto done;
}
end = start;
if (!gtk_text_iter_forward_word_end (&end))
goto done;
word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
g_hash_table_add (strings, g_utf8_strdown (word, -1));
g_free (word);
start = end;
}
done:
while ((child = gtk_widget_get_first_child (win->words)))
gtk_list_box_remove (GTK_LIST_BOX (win->words), child);
g_hash_table_iter_init (&iter, strings);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
{
row = gtk_button_new_with_label (key);
g_signal_connect (row, "clicked",
G_CALLBACK (find_word), win);
gtk_box_append (GTK_BOX (win->words), row);
}
g_hash_table_unref (strings);
}
static void
update_lines (ExampleAppWindow *win)
{
GtkWidget *tab, *view;
GtkTextBuffer *buffer;
int count;
char *lines;
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
if (tab == NULL)
return;
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
count = gtk_text_buffer_get_line_count (buffer);
lines = g_strdup_printf ("%d", count);
gtk_label_set_text (GTK_LABEL (win->lines), lines);
g_free (lines);
}
static void
visible_child_changed (GObject *stack,
GParamSpec *pspec,
ExampleAppWindow *win)
{
if (gtk_widget_in_destruction (GTK_WIDGET (stack)))
return;
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (win->searchbar), FALSE);
update_words (win);
update_lines (win);
}
static void
words_changed (GObject *sidebar,
GParamSpec *pspec,
ExampleAppWindow *win)
{
update_words (win);
}
static void
example_app_window_init (ExampleAppWindow *win)
{
GtkBuilder *builder;
GMenuModel *menu;
GAction *action;
gtk_widget_init_template (GTK_WIDGET (win));
win->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (win->settings, "transition",
win->stack, "transition-type",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (win->settings, "show-words",
win->sidebar, "reveal-child",
G_SETTINGS_BIND_DEFAULT);
g_object_bind_property (win->search, "active",
win->searchbar, "search-mode-enabled",
G_BINDING_BIDIRECTIONAL);
g_signal_connect (win->sidebar, "notify::reveal-child",
G_CALLBACK (words_changed), win);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
action = g_settings_create_action (win->settings, "show-words");
g_action_map_add_action (G_ACTION_MAP (win), action);
g_object_unref (action);
action = (GAction*) g_property_action_new ("show-lines", win->lines, "visible");
g_action_map_add_action (G_ACTION_MAP (win), action);
g_object_unref (action);
g_object_bind_property (win->lines, "visible",
win->lines_label, "visible",
G_BINDING_DEFAULT);
g_object_set (gtk_settings_get_default (), "gtk-shell-shows-app-menu", FALSE, NULL);
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
}
static void
example_app_window_dispose (GObject *object)
{
ExampleAppWindow *win;
win = EXAMPLE_APP_WINDOW (object);
g_clear_object (&win->settings);
G_OBJECT_CLASS (example_app_window_parent_class)->dispose (object);
}
static void
example_app_window_class_init (ExampleAppWindowClass *class)
{
G_OBJECT_CLASS (class)->dispose = example_app_window_dispose;
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchentry);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, words);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, sidebar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines_label);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), visible_child_changed);
}
ExampleAppWindow *
example_app_window_new (ExampleApp *app)
{
return g_object_new (EXAMPLE_APP_WINDOW_TYPE, "application", app, NULL);
}
void
example_app_window_open (ExampleAppWindow *win,
GFile *file)
{
char *basename;
GtkWidget *scrolled, *view;
char *contents;
gsize length;
GtkTextBuffer *buffer;
GtkTextTag *tag;
GtkTextIter start_iter, end_iter;
basename = g_file_get_basename (file);
scrolled = gtk_scrolled_window_new ();
gtk_widget_set_hexpand (scrolled, TRUE);
gtk_widget_set_vexpand (scrolled, TRUE);
view = gtk_text_view_new ();
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), view);
gtk_stack_add_titled (GTK_STACK (win->stack), scrolled, basename, basename);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
{
gtk_text_buffer_set_text (buffer, contents, length);
g_free (contents);
}
tag = gtk_text_buffer_create_tag (buffer, NULL, NULL);
g_settings_bind (win->settings, "font",
tag, "font",
G_SETTINGS_BIND_DEFAULT);
gtk_text_buffer_get_start_iter (buffer, &start_iter);
gtk_text_buffer_get_end_iter (buffer, &end_iter);
gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter);
g_free (basename);
gtk_widget_set_sensitive (win->search, TRUE);
update_words (win);
update_lines (win);
}
+1 -1
View File
@@ -173,7 +173,7 @@ stash_desktop_startup_notification_id (void)
if (!g_utf8_validate (desktop_startup_id, -1, NULL))
g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
else
startup_notification_id = g_strdup (desktop_startup_id ? desktop_startup_id : "");
startup_notification_id = g_strdup (desktop_startup_id);
}
/* Clear the environment variable so it won't be inherited by
+16 -4
View File
@@ -2960,8 +2960,8 @@ gdk_surface_request_motion (GdkSurface *surface)
* gdk_surface_translate_coordinates:
* @from: the origin surface
* @to: the target surface
* @x: coordinates to translate
* @y: coordinates to translate
* @x: (inout): coordinates to translate
* @y: (inout): coordinates to translate
*
* Translates the given coordinates from being
* relative to the @from surface to being relative
@@ -2980,9 +2980,18 @@ gdk_surface_translate_coordinates (GdkSurface *from,
double *x,
double *y)
{
double in_x, in_y, out_x, out_y;
int x1, y1, x2, y2;
GdkSurface *f, *t;
g_return_val_if_fail (GDK_IS_SURFACE (from), FALSE);
g_return_val_if_fail (GDK_IS_SURFACE (to), FALSE);
g_return_val_if_fail (x != NULL, FALSE);
g_return_val_if_fail (y != NULL, FALSE);
in_x = *x;
in_y = *y;
x1 = 0;
y1 = 0;
f = from;
@@ -3006,8 +3015,11 @@ gdk_surface_translate_coordinates (GdkSurface *from,
if (f != t)
return FALSE;
*x += x1 - x2;
*y += y1 - y2;
out_x = in_x + (x1 - x2);
out_y = in_y + (y1 - y2);
*x = out_x;
*y = out_y;
return TRUE;
}
-17
View File
@@ -149,12 +149,6 @@ gdk_toplevel_size_validate (GdkToplevelSize *size)
{
int geometry_width, geometry_height;
if (size->min_width > size->bounds_width ||
size->min_height > size->bounds_height)
g_warning ("GdkToplevelSize: min_size (%d, %d) exceeds bounds (%d, %d)",
size->min_width, size->min_height,
size->bounds_width, size->bounds_height);
geometry_width = size->width;
geometry_height = size->height;
if (size->shadow.is_valid)
@@ -162,15 +156,4 @@ gdk_toplevel_size_validate (GdkToplevelSize *size)
geometry_width -= size->shadow.left + size->shadow.right;
geometry_height -= size->shadow.top + size->shadow.bottom;
}
if (geometry_width > size->bounds_width ||
geometry_height > size->bounds_height)
g_warning ("GdkToplevelSize: geometry size (%d, %d) exceeds bounds (%d, %d)",
size->width, size->height,
size->bounds_width, size->bounds_height);
if (size->min_width > size->width ||
size->min_height > size->height)
g_warning ("GdkToplevelSize: min_size (%d, %d) exceeds size (%d, %d)",
size->min_width, size->min_height,
size->width, size->height);
}
+23
View File
@@ -78,6 +78,14 @@
*/
#define GDK_VERSION_4_0 (G_ENCODE_VERSION (4, 0))
/**
* GDK_VERSION_4_2:
*
* A macro that evaluates to the 4.2 version of GDK, in a format
* that can be used by the C pre-processor.
*/
#define GDK_VERSION_4_2 (G_ENCODE_VERSION (4, 2))
/* evaluates to the current stable version; for development cycles,
* this means the next stable target, with a hard backstop to the
@@ -175,4 +183,19 @@
# define GDK_DEPRECATED_IN_4_0_FOR(f) _GDK_EXTERN
#endif
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_4_2
# define GDK_AVAILABLE_IN_4_2 GDK_UNAVAILABLE(4, 2)
#else
# define GDK_AVAILABLE_IN_4_2 _GDK_EXTERN
#endif
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_2
# define GDK_DEPRECATED_IN_4_2 GDK_DEPRECATED
# define GDK_DEPRECATED_IN_4_2_FOR(f) GDK_DEPRECATED_FOR(f)
#else
# define GDK_DEPRECATED_IN_4_2 _GDK_EXTERN
# define GDK_DEPRECATED_IN_4_2_FOR(f) _GDK_EXTERN
#endif
#endif /* __GDK_VERSION_MACROS_H__ */
+17
View File
@@ -547,6 +547,20 @@ _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
_gdk_macos_display_clear_sorting (self);
}
/* Raises a transient window.
*/
static void
raise_transient (GdkMacosSurface *surface)
{
GdkMacosSurface *parent_surface = GDK_MACOS_SURFACE (GDK_SURFACE (surface)->transient_for);
NSWindow *parent = _gdk_macos_surface_get_native (parent_surface);
NSWindow *window = _gdk_macos_surface_get_native (surface);
[parent removeChildWindow:window];
[parent addChildWindow:window ordered:NSWindowAbove];
}
void
_gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
GdkMacosSurface *surface)
@@ -559,6 +573,9 @@ _gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
g_queue_push_head_link (&self->main_surfaces, &surface->main);
if (GDK_SURFACE (surface)->transient_for)
raise_transient (surface);
_gdk_macos_display_clear_sorting (self);
}
+8 -6
View File
@@ -94,7 +94,7 @@
#define MIN_SYSTEM_BELL_DELAY_MS 20
#define GTK_SHELL1_VERSION 3
#define GTK_SHELL1_VERSION 4
#define OUTPUT_VERSION_WITH_DONE 2
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
@@ -1350,21 +1350,23 @@ _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display,
data->buffer = NULL;
data->scale = scale;
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width*scale);
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width * scale);
data->pool = create_shm_pool (display->shm,
height*scale*stride,
height * scale * stride,
&data->buf_length,
&data->buf);
if (G_UNLIKELY (data->pool == NULL))
g_error ("Unable to create shared memory pool");
surface = cairo_image_surface_create_for_data (data->buf,
CAIRO_FORMAT_ARGB32,
width*scale,
height*scale,
width * scale,
height * scale,
stride);
data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
width*scale, height*scale,
width * scale, height * scale,
stride, WL_SHM_FORMAT_ARGB8888);
cairo_surface_set_user_data (surface, &gdk_wayland_shm_surface_cairo_key,
+23 -1
View File
@@ -2223,6 +2223,24 @@ gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel)
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
}
void
gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
if (!display_wayland->server_decoration_manager)
return;
impl->display_server.server_decoration =
org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
impl->display_server.wl_surface);
if (impl->display_server.server_decoration)
org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER);
}
gboolean
gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel)
{
@@ -2949,7 +2967,11 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
if (impl->display_server.gtk_surface)
{
gtk_surface1_destroy (impl->display_server.gtk_surface);
if (display_wayland->gtk_shell_version >=
GTK_SURFACE1_RELEASE_SINCE_VERSION)
gtk_surface1_release (impl->display_server.gtk_surface);
else
gtk_surface1_destroy (impl->display_server.gtk_surface);
impl->display_server.gtk_surface = NULL;
impl->application.was_set = FALSE;
}
+1
View File
@@ -33,6 +33,7 @@ void gdk_wayland_toplevel_set_dbus_properties (GdkTopl
const char *unique_bus_name);
void gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel);
void gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel);
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
+5 -2
View File
@@ -1,6 +1,6 @@
<protocol name="gtk">
<interface name="gtk_shell1" version="3">
<interface name="gtk_shell1" version="4">
<description summary="gtk specific extensions">
gtk_shell is a protocol extension providing additional features for
clients implementing it.
@@ -35,7 +35,7 @@
</request>
</interface>
<interface name="gtk_surface1" version="3">
<interface name="gtk_surface1" version="4">
<request name="set_dbus_properties">
<arg name="application_id" type="string" allow-null="true"/>
<arg name="app_menu_path" type="string" allow-null="true"/>
@@ -82,6 +82,9 @@
<request name="request_focus" since="3">
<arg name="startup_id" type="string" allow-null="true"/>
</request>
<!-- Version 4 additions -->
<request name="release" type="destructor" since="4"/>
</interface>
</protocol>
+46 -5
View File
@@ -39,6 +39,7 @@
#include "gdkscreen-x11.h"
#include "gdkselectioninputstream-x11.h"
#include "gdkselectionoutputstream-x11.h"
#include "gdktextlistconverter-x11.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -103,6 +104,49 @@ static const struct {
G_DEFINE_TYPE (GdkX11Drop, gdk_x11_drop, GDK_TYPE_DROP)
static GInputStream *
text_list_convert (GdkDisplay *display,
GInputStream *stream,
const char *encoding,
int format)
{
GInputStream *converter_stream;
GConverter *converter;
converter = gdk_x11_text_list_converter_to_utf8_new (display, encoding, format);
converter_stream = g_converter_input_stream_new (stream, converter);
g_object_unref (converter);
g_object_unref (stream);
return converter_stream;
}
static GInputStream *
no_convert (GdkDisplay *display,
GInputStream *stream,
const char *encoding,
int format)
{
return stream;
}
static const struct {
const char *x_target;
const char *mime_type;
GInputStream * (* convert) (GdkDisplay *, GInputStream *, const char *, int);
const char *type;
int format;
} special_targets[] = {
{ "UTF8_STRING", "text/plain;charset=utf-8", no_convert, "UTF8_STRING", 8 },
{ "COMPOUND_TEXT", "text/plain;charset=utf-8", text_list_convert, "COMPOUND_TEXT", 8 },
{ "TEXT", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 },
{ "STRING", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 },
{ "TARGETS", NULL, NULL, "ATOM", 32 },
{ "TIMESTAMP", NULL, NULL, "INTEGER", 32 },
{ "SAVE_TARGETS", NULL, NULL, "NULL", 32 }
};
static void
gdk_x11_drop_read_got_stream (GObject *source,
GAsyncResult *res,
@@ -145,9 +189,9 @@ gdk_x11_drop_read_got_stream (GObject *source,
}
else
{
#if 0
gsize i;
const char *mime_type = ((GSList *) g_task_get_task_data (task))->data;
GdkDrop *drop = GDK_DROP (g_task_get_source_object (task));
for (i = 0; i < G_N_ELEMENTS (special_targets); i++)
{
@@ -155,15 +199,12 @@ gdk_x11_drop_read_got_stream (GObject *source,
{
g_assert (special_targets[i].mime_type != NULL);
GDK_DISPLAY_NOTE (CLIPBOARD, g_printerr ("%s: reading with converter from %s to %s\n",
cb->selection, mime_type, special_targets[i].mime_type));
mime_type = g_intern_string (special_targets[i].mime_type);
g_task_set_task_data (task, g_slist_prepend (NULL, (gpointer) mime_type), (GDestroyNotify) g_slist_free);
stream = special_targets[i].convert (cb, stream, type, format);
stream = special_targets[i].convert (gdk_drop_get_display (drop), stream, type, format);
break;
}
}
#endif
GDK_NOTE (DND, g_printerr ("reading DND as %s now\n",
(const char *)((GSList *) g_task_get_task_data (task))->data));
+1 -1
View File
@@ -1383,7 +1383,7 @@ gdk_x11_keymap_translate_keyboard_state (GdkKeymap *keymap,
tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
group, state,
level, effective_group);
effective_group, level);
}
if (consumed_modifiers)
+3 -3
View File
@@ -149,10 +149,10 @@ render_glyph (GlyphCacheKey *key,
glyph_info.glyph = key->data.glyph;
glyph_info.geometry.width = value->draw_width * 1024;
if (glyph_info.glyph & PANGO_GLYPH_UNKNOWN_FLAG)
glyph_info.geometry.x_offset = 0;
glyph_info.geometry.x_offset = 250 * key->data.xshift;
else
glyph_info.geometry.x_offset = - value->draw_x * 1024;
glyph_info.geometry.y_offset = - value->draw_y * 1024;
glyph_info.geometry.x_offset = 250 * key->data.xshift - value->draw_x * 1024;
glyph_info.geometry.y_offset = 250 * key->data.yshift - value->draw_y * 1024;
glyph_string.num_glyphs = 1;
glyph_string.glyphs = &glyph_info;
+49 -36
View File
@@ -1452,6 +1452,7 @@ render_linear_gradient_node (GskGLRenderer *self,
ops_set_linear_gradient (builder,
n_color_stops,
stops,
gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE,
builder->dx + start->x,
builder->dy + start->y,
builder->dx + end->x,
@@ -1485,6 +1486,7 @@ render_radial_gradient_node (GskGLRenderer *self,
ops_set_radial_gradient (builder,
n_color_stops,
stops,
gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE,
builder->dx + center->x,
builder->dy + center->y,
start, end,
@@ -1510,7 +1512,7 @@ render_conic_gradient_node (GskGLRenderer *self,
{
const GskColorStop *stops = gsk_conic_gradient_node_get_color_stops (node, NULL);
const graphene_point_t *center = gsk_conic_gradient_node_get_center (node);
const float rotation = gsk_conic_gradient_node_get_rotation (node);
const float angle = gsk_conic_gradient_node_get_angle (node);
ops_set_program (builder, &self->programs->conic_gradient_program);
ops_set_conic_gradient (builder,
@@ -1518,7 +1520,7 @@ render_conic_gradient_node (GskGLRenderer *self,
stops,
builder->dx + center->x,
builder->dy + center->y,
rotation);
angle);
load_vertex_data (ops_draw (builder, NULL), &node->bounds, builder);
}
@@ -3041,14 +3043,19 @@ apply_linear_gradient_op (const Program *program,
op->n_color_stops.value * 5,
(float *)op->color_stops.value);
glUniform2f (program->linear_gradient.start_point_location, op->start_point[0], op->start_point[1]);
glUniform2f (program->linear_gradient.end_point_location, op->end_point[0], op->end_point[1]);
glUniform4f (program->linear_gradient.points_location,
op->start_point[0], op->start_point[1],
op->end_point[0] - op->start_point[0], op->end_point[1] - op->start_point[1]);
glUniform1i (program->linear_gradient.repeat_location, op->repeat);
}
static inline void
apply_radial_gradient_op (const Program *program,
const OpRadialGradient *op)
{
float scale;
float bias;
OP_PRINT (" -> Radial gradient");
if (op->n_color_stops.send)
glUniform1i (program->radial_gradient.num_color_stops_location, op->n_color_stops.value);
@@ -3058,16 +3065,23 @@ apply_radial_gradient_op (const Program *program,
op->n_color_stops.value * 5,
(float *)op->color_stops.value);
glUniform1f (program->radial_gradient.start_location, op->start);
glUniform1f (program->radial_gradient.end_location, op->end);
glUniform2f (program->radial_gradient.radius_location, op->radius[0], op->radius[1]);
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
scale = 1.0f / (op->end - op->start);
bias = -op->start * scale;
glUniform1i (program->radial_gradient.repeat_location, op->repeat);
glUniform2f (program->radial_gradient.range_location, scale, bias);
glUniform4f (program->radial_gradient.geometry_location,
op->center[0], op->center[1],
1.0f / op->radius[0], 1.0f / op->radius[1]);
}
static inline void
apply_conic_gradient_op (const Program *program,
const OpConicGradient *op)
{
float bias;
float scale;
OP_PRINT (" -> Conic gradient");
if (op->n_color_stops.send)
glUniform1i (program->conic_gradient.num_color_stops_location, op->n_color_stops.value);
@@ -3077,8 +3091,9 @@ apply_conic_gradient_op (const Program *program,
op->n_color_stops.value * 5,
(float *)op->color_stops.value);
glUniform1f (program->conic_gradient.rotation_location, op->rotation);
glUniform2f (program->conic_gradient.center_location, op->center[0], op->center[1]);
scale = 0.5f * M_1_PI;
bias = op->angle * scale + 2.0f;
glUniform4f (program->conic_gradient.geometry_location, op->center[0], op->center[1], scale, bias);
}
static inline void
@@ -3368,22 +3383,20 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
/* linear gradient */
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, num_color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, start_point);
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, end_point);
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, repeat);
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, points);
/* radial gradient */
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, num_color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, center);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, start);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, repeat);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, geometry);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, range);
/* conic gradient */
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, num_color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, center);
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, rotation);
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, geometry);
/* blur */
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
@@ -3729,10 +3742,12 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
break;
case GSK_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
render_linear_gradient_node (self, node, builder);
break;
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
render_radial_gradient_node (self, node, builder);
break;
@@ -3799,8 +3814,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
render_gl_shader_node (self, node, builder);
break;
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_CAIRO_NODE:
default:
{
@@ -3820,7 +3833,7 @@ add_offscreen_ops (GskGLRenderer *self,
{
const float dx = builder->dx;
const float dy = builder->dy;
float width, height;
float scaled_width, scaled_height;
float scale_x;
float scale_y;
int render_target;
@@ -3876,8 +3889,6 @@ add_offscreen_ops (GskGLRenderer *self,
return TRUE;
}
width = bounds->size.width;
height = bounds->size.height;
scale_x = builder->scale_x;
scale_y = builder->scale_y;
@@ -3888,23 +3899,23 @@ add_offscreen_ops (GskGLRenderer *self,
{
const int max_texture_size = gsk_gl_driver_get_max_texture_size (self->gl_driver);
width = ceilf (width * scale_x);
if (width > max_texture_size)
scaled_width = ceilf (bounds->size.width * scale_x);
if (scaled_width > max_texture_size)
{
scale_x *= (float)max_texture_size / width;
width = max_texture_size;
scale_x *= (float)max_texture_size / scaled_width;
scaled_width = max_texture_size;
}
height = ceilf (height * scale_y);
if (height > max_texture_size)
scaled_height = ceilf (bounds->size.height * scale_y);
if (scaled_height > max_texture_size)
{
scale_y *= (float)max_texture_size / height;
height = max_texture_size;
scale_y *= (float)max_texture_size / scaled_height;
scaled_height = max_texture_size;
}
}
gsk_gl_driver_create_render_target (self->gl_driver,
width, height,
scaled_width, scaled_height,
filter, filter,
&texture_id, &render_target);
if (gdk_gl_context_has_debug (self->gl_context))
@@ -3919,9 +3930,11 @@ add_offscreen_ops (GskGLRenderer *self,
render_target);
}
viewport = GRAPHENE_RECT_INIT ((bounds->origin.x + dx) * scale_x,
(bounds->origin.y + dy) * scale_y,
width, height);
ops_transform_bounds_modelview (builder, bounds, &viewport);
/* Code above will scale the size with the scale we use in the render ops,
* but for the viewport size, we need our own size limited by the texture size */
viewport.size.width = scaled_width;
viewport.size.height = scaled_height;
init_projection_matrix (&item_proj, &viewport);
prev_render_target = ops_set_render_target (builder, render_target);
@@ -3949,7 +3962,7 @@ add_offscreen_ops (GskGLRenderer *self,
g_type_name_from_instance ((GTypeInstance *) child_node),
child_node,
k ++),
width, height);
scaled_width, scaled_height);
}
#endif
+6 -2
View File
@@ -859,6 +859,7 @@ void
ops_set_linear_gradient (RenderOpBuilder *self,
guint n_color_stops,
const GskColorStop *color_stops,
gboolean repeat,
float start_x,
float start_y,
float end_x,
@@ -912,6 +913,7 @@ ops_set_linear_gradient (RenderOpBuilder *self,
sizeof (GskColorStop) * real_n_color_stops);
}
op->repeat = repeat;
op->start_point[0] = start_x;
op->start_point[1] = start_y;
op->end_point[0] = end_x;
@@ -922,6 +924,7 @@ void
ops_set_radial_gradient (RenderOpBuilder *self,
guint n_color_stops,
const GskColorStop *color_stops,
gboolean repeat,
float center_x,
float center_y,
float start,
@@ -945,6 +948,7 @@ ops_set_radial_gradient (RenderOpBuilder *self,
op->radius[1] = vradius;
op->start = start;
op->end = end;
op->repeat = repeat;
}
void
@@ -953,7 +957,7 @@ ops_set_conic_gradient (RenderOpBuilder *self,
const GskColorStop *color_stops,
float center_x,
float center_y,
float rotation)
float angle)
{
const guint real_n_color_stops = MIN (GL_MAX_GRADIENT_STOPS, n_color_stops);
OpConicGradient *op;
@@ -967,6 +971,6 @@ ops_set_conic_gradient (RenderOpBuilder *self,
op->color_stops.send = true;
op->center[0] = center_x;
op->center[1] = center_y;
op->rotation = rotation;
op->angle = angle;
}
+9 -9
View File
@@ -118,22 +118,20 @@ struct _Program
struct {
int num_color_stops_location;
int color_stops_location;
int start_point_location;
int end_point_location;
int points_location;
int repeat_location;
} linear_gradient;
struct {
int num_color_stops_location;
int color_stops_location;
int center_location;
int start_location;
int end_location;
int radius_location;
int geometry_location;
int range_location;
int repeat_location;
} radial_gradient;
struct {
int num_color_stops_location;
int color_stops_location;
int center_location;
int rotation_location;
int geometry_location;
} conic_gradient;
struct {
int blur_radius_location;
@@ -319,6 +317,7 @@ void ops_set_unblurred_outset_shadow (RenderOpBuilder *se
void ops_set_linear_gradient (RenderOpBuilder *self,
guint n_color_stops,
const GskColorStop *color_stops,
gboolean repeat,
float start_x,
float start_y,
float end_x,
@@ -326,6 +325,7 @@ void ops_set_linear_gradient (RenderOpBuilder *self,
void ops_set_radial_gradient (RenderOpBuilder *self,
guint n_color_stops,
const GskColorStop *color_stops,
gboolean repeat,
float center_x,
float center_y,
float start,
@@ -337,7 +337,7 @@ void ops_set_conic_gradient (RenderOpBuilder *self,
const GskColorStop *color_stops,
float center_x,
float center_y,
float rotation);
float angle);
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
const GskQuadVertex vertex_data[GL_N_VERTICES]);
+10 -6
View File
@@ -64,8 +64,10 @@ prepend_line_numbers (char *code,
}
static gboolean
check_shader_error (int shader_id,
GError **error)
check_shader_error (int shader_id,
int shader_type,
const char *resource_path,
GError **error)
{
int status;
int log_len;
@@ -91,7 +93,9 @@ check_shader_error (int shader_id,
prepend_line_numbers (code, s);
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
"Compilation failure in shader.\nSource Code: %s\n\nError Message:\n%s\n\n",
"Compilation failure in %s shader %s.\nSource Code:\n%s\n\nError Message:\n%s\n\n",
(shader_type == GL_FRAGMENT_SHADER ? "fragment" : "vertex"),
resource_path,
s->str,
buffer);
@@ -184,7 +188,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
});
glCompileShader (vertex_id);
if (!check_shader_error (vertex_id, error))
if (!check_shader_error (vertex_id, GL_VERTEX_SHADER, resource_path, error))
{
glDeleteShader (vertex_id);
goto out;
@@ -218,7 +222,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
});
glCompileShader (fragment_id);
if (!check_shader_error (fragment_id, error))
if (!check_shader_error (fragment_id, GL_FRAGMENT_SHADER, resource_path, error))
{
glDeleteShader (fragment_id);
goto out;
@@ -230,7 +234,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
glAttachShader (program_id, vertex_id);
glAttachShader (program_id, fragment_id);
glBindAttribLocation (program_id, 0, "aPosition");
glBindAttribLocation (program_id, 1, "vUv");
glBindAttribLocation (program_id, 1, "aUv");
glLinkProgram (program_id);
glDetachShader (program_id, vertex_id);
glDetachShader (program_id, fragment_id);
+3 -1
View File
@@ -146,6 +146,7 @@ typedef struct
IntUniformValue n_color_stops;
float start_point[2];
float end_point[2];
gboolean repeat;
} OpLinearGradient;
typedef struct
@@ -156,6 +157,7 @@ typedef struct
float end;
float radius[2];
float center[2];
gboolean repeat;
} OpRadialGradient;
typedef struct
@@ -163,7 +165,7 @@ typedef struct
ColorStopUniformValue color_stops;
IntUniformValue n_color_stops;
float center[2];
float rotation;
float angle;
} OpConicGradient;
typedef struct
+2
View File
@@ -257,6 +257,8 @@ const graphene_point_t * gsk_conic_gradient_node_get_center (GskRenderNo
GDK_AVAILABLE_IN_ALL
float gsk_conic_gradient_node_get_rotation (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
float gsk_conic_gradient_node_get_angle (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
gsize gsk_conic_gradient_node_get_n_color_stops (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
const GskColorStop * gsk_conic_gradient_node_get_color_stops (GskRenderNode *node,
+27
View File
@@ -782,6 +782,7 @@ struct _GskConicGradientNode
graphene_point_t center;
float rotation;
float angle;
gsize n_stops;
GskColorStop *stops;
@@ -1023,6 +1024,12 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
self->angle = 90.f - self->rotation;
self->angle = G_PI * self->angle / 180.f;
self->angle = fmodf (self->angle, 2.f * G_PI);
if (self->angle < 0.f)
self->angle += 2.f * G_PI;
return node;
}
@@ -1095,6 +1102,26 @@ gsk_conic_gradient_node_get_rotation (GskRenderNode *node)
return self->rotation;
}
/**
* gsk_conic_gradient_node_get_angle:
* @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
*
* Retrieves the angle for the gradient in radians, normalized in [0, 2 * PI]
*
* The angle is starting at the top and going clockwise, as expressed
* in the css specification:
* angle = 90 - gsk_conic_gradient_node_get_rotation()
*
* Returns: the angle for the gradient
*/
float
gsk_conic_gradient_node_get_angle (GskRenderNode *node)
{
GskConicGradientNode *self = (GskConicGradientNode *) node;
return self->angle;
}
/*** GSK_BORDER_NODE ***/
/**
+7 -5
View File
@@ -689,14 +689,16 @@ create_ascii_glyphs (PangoFont *font)
for (i = MIN_ASCII_GLYPH; i < MAX_ASCII_GLYPH; i++)
{
const char text[2] = { i, 0 };
PangoShapeFlags flags = 0;
pango_shape_with_flags (text,
1,
text,
1,
if (cairo_version () < CAIRO_VERSION_ENCODE (1, 17, 4))
flags = PANGO_SHAPE_ROUND_POSITIONS;
pango_shape_with_flags (text, 1,
text, 1,
&not_a_hack,
glyph_string,
PANGO_SHAPE_ROUND_POSITIONS);
flags);
if (glyph_string->num_glyphs != 1)
{
+47 -43
View File
@@ -1,34 +1,17 @@
// VERTEX_SHADER
uniform vec2 u_center;
uniform float u_rotation;
uniform float u_color_stops[6 * 5];
uniform int u_num_color_stops;
uniform vec4 u_geometry;
const float PI = 3.1415926535897932384626433832795;
_OUT_ vec2 center;
_OUT_ float rotation;
_OUT_ vec4 color_stops[6];
_OUT_ float color_offsets[6];
_NOPERSPECTIVE_ _OUT_ vec2 coord;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
// The -90 is because conics point to the top by default
rotation = mod (u_rotation - 90.0, 360.0);
if (rotation < 0.0)
rotation += 360.0;
rotation = PI / 180.0 * rotation;
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_geometry.xy;
center = (u_modelview * vec4(u_center, 0, 1)).xy;
for (int i = 0; i < u_num_color_stops; i ++) {
color_offsets[i] = u_color_stops[(i * 5) + 0];
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
u_color_stops[(i * 5) + 2],
u_color_stops[(i * 5) + 3],
u_color_stops[(i * 5) + 4]));
}
coord = vec2(dot(mv0, offset),
dot(mv1, offset));
}
// FRAGMENT_SHADER:
@@ -38,32 +21,53 @@ uniform int u_num_color_stops;
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif
const float PI = 3.1415926535897932384626433832795;
uniform vec4 u_geometry;
uniform float u_color_stops[6 * 5];
_IN_ vec2 center;
_IN_ float rotation;
_IN_ vec4 color_stops[6];
_IN_ float color_offsets[6];
_NOPERSPECTIVE_ _IN_ vec2 coord;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
// Position relative to center
vec2 pos = gsk_get_frag_coord() - center;
// direction of point in range [-PI, PI]
float angle = atan (pos.y, pos.x);
// rotate, it's now [-2 * PI, PI]
angle -= rotation;
vec2 pos = floor(coord);
float angle = atan(pos.y, pos.x);
// fract() does the modulo here, so now we have progress
// into the current conic
float offset = fract (angle / 2.0 / PI + 2.0);
float offset = fract(angle * u_geometry.z + u_geometry.w);
vec4 color = color_stops[0];
for (int i = 1; i < u_num_color_stops; i ++) {
if (offset >= color_offsets[i - 1]) {
float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(color * u_alpha);
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}
+70 -45
View File
@@ -1,35 +1,41 @@
// VERTEX_SHADER
uniform vec2 u_start_point;
uniform vec2 u_end_point;
uniform float u_color_stops[6 * 5];
uniform int u_num_color_stops;
uniform vec4 u_points;
_OUT_ vec2 startPoint;
_OUT_ vec2 endPoint;
_OUT_ float maxDist;
_OUT_ vec2 gradient;
_OUT_ float gradientLength;
_OUT_ vec4 color_stops[6];
_OUT_ float color_offsets[6];
_NOPERSPECTIVE_ _OUT_ vec4 info;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
startPoint = (u_modelview * vec4(u_start_point, 0, 1)).xy;
endPoint = (u_modelview * vec4(u_end_point, 0, 1)).xy;
maxDist = length(endPoint - startPoint);
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_points.xy;
vec2 coord = vec2(dot(mv0, offset),
dot(mv1, offset));
// Gradient direction
gradient = endPoint - startPoint;
gradientLength = length(gradient);
// Original equation:
// VS | maxDist = length(end - start);
// VS | gradient = end - start;
// VS | gradientLength = length(gradient);
// FS | pos = frag_coord - start
// FS | proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient
// FS | offset = length(proj) / maxDist
for (int i = 0; i < u_num_color_stops; i ++) {
color_offsets[i] = u_color_stops[(i * 5) + 0];
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
u_color_stops[(i * 5) + 2],
u_color_stops[(i * 5) + 3],
u_color_stops[(i * 5) + 4]));
}
// Simplified formula derivation:
// 1. Notice that maxDist = gradientLength:
// offset = length(proj) / gradientLength
// 2. Let gnorm = gradient / gradientLength, then:
// proj = (dot(gnorm * gradientLength, pos) / (gradientLength * gradientLength)) * (gnorm * gradientLength) =
// = dot(gnorm, pos) * gnorm
// 3. Since gnorm is unit length then:
// length(proj) = length(dot(gnorm, pos) * gnorm) = dot(gnorm, pos)
// 4. We can avoid the FS division by passing a scaled pos from the VS:
// offset = dot(gnorm, pos) / gradientLength = dot(gnorm, pos / gradientLength)
// 5. 1.0 / length(gradient) is inversesqrt(dot(gradient, gradient)) in GLSL
vec2 gradient = vec2(dot(mv0, u_points.zw),
dot(mv1, u_points.zw));
float rcp_gradient_length = inversesqrt(dot(gradient, gradient));
info = rcp_gradient_length * vec4(coord, gradient);
}
// FRAGMENT_SHADER:
@@ -39,32 +45,51 @@ uniform int u_num_color_stops;
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif
_IN_ vec2 startPoint;
_IN_ vec2 endPoint;
_IN_ float maxDist;
_IN_ vec2 gradient;
_IN_ float gradientLength;
_IN_ vec4 color_stops[6];
_IN_ float color_offsets[6];
uniform float u_color_stops[6 * 5];
uniform bool u_repeat;
_NOPERSPECTIVE_ _IN_ vec4 info;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
// Position relative to startPoint
vec2 pos = gsk_get_frag_coord() - startPoint;
float offset = dot(info.xy, info.zw);
// Current pixel, projected onto the line between the start point and the end point
// The projection will be relative to the start point!
vec2 proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient;
if (u_repeat) {
offset = fract(offset);
}
// Offset of the current pixel
float offset = length(proj) / maxDist;
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
vec4 color = color_stops[0];
for (int i = 1; i < u_num_color_stops; i ++) {
if (offset >= color_offsets[i - 1]) {
float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(color * u_alpha);
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}
+10
View File
@@ -5,10 +5,12 @@ precision highp float;
#if defined(GSK_GLES) || defined(GSK_LEGACY)
#define _OUT_ varying
#define _IN_ varying
#define _NOPERSPECTIVE_
#define _GSK_ROUNDED_RECT_UNIFORM_ vec4[3]
#else
#define _OUT_ out
#define _IN_ in
#define _NOPERSPECTIVE_ noperspective
#define _GSK_ROUNDED_RECT_UNIFORM_ GskRoundedRect
#endif
@@ -39,3 +41,11 @@ gsk_create_rect(vec4[3] data)
vec4 gsk_premultiply(vec4 c) {
return vec4(c.rgb * c.a, c.a);
}
vec4 gsk_scaled_premultiply(vec4 c, float s) {
// Fast version of gsk_premultiply(c) * s
// 4 muls instead of 7
float a = s * c.a;
return vec4(c.rgb * a, a);
}
+44 -54
View File
@@ -1,31 +1,18 @@
// VERTEX_SHADER
uniform float u_start;
uniform float u_end;
uniform float u_color_stops[6 * 5];
uniform int u_num_color_stops;
uniform vec2 u_radius;
uniform vec2 u_center;
uniform vec4 u_geometry;
_OUT_ vec2 center;
_OUT_ vec4 color_stops[6];
_OUT_ float color_offsets[6];
_OUT_ float start;
_OUT_ float end;
_NOPERSPECTIVE_ _OUT_ vec2 coord;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
center = (u_modelview * vec4(u_center, 0, 1)).xy;
start = u_start;
end = u_end;
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_geometry.xy;
vec2 dir = vec2(dot(mv0, offset),
dot(mv1, offset));
for (int i = 0; i < u_num_color_stops; i ++) {
color_offsets[i] = u_color_stops[(i * 5) + 0];
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
u_color_stops[(i * 5) + 2],
u_color_stops[(i * 5) + 3],
u_color_stops[(i * 5) + 4]));
}
coord = dir * u_geometry.zw;
}
// FRAGMENT_SHADER:
@@ -35,50 +22,53 @@ uniform int u_num_color_stops;
uniform highp int u_num_color_stops;
#endif
uniform vec2 u_radius;
uniform float u_end;
uniform bool u_repeat;
uniform vec2 u_range;
uniform float u_color_stops[6 * 5];
_IN_ vec2 center;
_IN_ vec4 color_stops[6];
_IN_ float color_offsets[6];
_IN_ float start;
_IN_ float end;
_NOPERSPECTIVE_ _IN_ vec2 coord;
// The offsets in the color stops are relative to the
// start and end values of the gradient.
float abs_offset(float offset) {
return start + ((end - start) * offset);
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
vec2 pixel = gsk_get_frag_coord();
vec2 rel = (center - pixel) / (u_radius);
float d = sqrt(dot(rel, rel));
// Reverse scale
float offset = length(coord) * u_range.x + u_range.y;
if (d < abs_offset (color_offsets[0])) {
gskSetOutputColor(color_stops[0] * u_alpha);
if (u_repeat) {
offset = fract(offset);
}
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
if (d > end) {
gskSetOutputColor(color_stops[u_num_color_stops - 1] * u_alpha);
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
vec4 color = vec4(0, 0, 0, 0);
for (int i = 1; i < u_num_color_stops; i++) {
float last_offset = abs_offset(color_offsets[i - 1]);
float this_offset = abs_offset(color_offsets[i]);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
// We have color_stops[i - 1] at last_offset and color_stops[i] at this_offset.
// We now need to map `d` between those two offsets and simply mix linearly between them
if (d >= last_offset && d <= this_offset) {
float f = (d - last_offset) / (this_offset - last_offset);
color = mix(color_stops[i - 1], color_stops[i], f);
break;
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(color * u_alpha);
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}
+1 -1
View File
@@ -718,7 +718,7 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self,
}
else
{
for (gsize r = 0; r < regions[i].height; i++)
for (gsize r = 0; r < regions[i].height; r++)
memcpy (m + r * regions[i].width * 4, regions[i].data + r * regions[i].stride, regions[i].width * 4);
}
+2 -6
View File
@@ -68,10 +68,8 @@ action_handle_method (GtkAtSpiContext *self,
g_variant_get (parameters, "(i)", &idx);
const Action *action = &actions[idx];
if (idx >= 0 && idx < n_actions)
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->name));
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].name));
else
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
@@ -129,10 +127,8 @@ action_handle_method (GtkAtSpiContext *self,
g_variant_get (parameters, "(i)", &idx);
const Action *action = &actions[idx];
if (idx >= 0 && idx < n_actions)
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->keybinding));
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].keybinding));
else
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
+15 -1
View File
@@ -58,6 +58,9 @@ struct _GtkAtSpiCache
/* HashTable<GtkAtSpiContext, str> */
GHashTable *contexts_to_path;
/* Re-entrancy guard */
gboolean in_get_items;
};
enum
@@ -250,10 +253,17 @@ handle_cache_method (GDBusConnection *connection,
{
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(" GET_ITEMS_SIGNATURE ")"));
/* Prevent the emission os signals while collecting accessible
* objects as the result of walking the accessible tree
*/
self->in_get_items = TRUE;
g_variant_builder_open (&builder, G_VARIANT_TYPE (GET_ITEMS_SIGNATURE));
collect_cached_objects (self, &builder);
g_variant_builder_close (&builder);
self->in_get_items = FALSE;
g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
}
}
@@ -371,7 +381,11 @@ gtk_at_spi_cache_add_context (GtkAtSpiCache *self,
GTK_NOTE (A11Y, g_message ("Adding context '%s' to cache", path_key));
emit_add_accessible (self, context);
/* GetItems is safe from re-entrancy, but we still don't want to
* emit an unnecessary signal while we're collecting ATContexts
*/
if (!self->in_get_items)
emit_add_accessible (self, context);
}
void
+1 -7
View File
@@ -63,17 +63,12 @@ xml += '\n'
for f in get_files('theme/HighContrast/assets', '.svg'):
xml += ' <file>theme/HighContrast/assets/{0}</file>\n'.format(f)
for f in get_files('gesture', '.symbolic.png'):
xml += ' <file alias=\'icons/64x64/actions/{0}\'>gesture/{0}</file>\n'.format(f)
xml += '\n'
for f in get_files('ui', '.ui'):
xml += ' <file preprocess=\'xml-stripblanks\'>ui/{0}</file>\n'.format(f)
xml += '\n'
for s in ['16x16', '24x24', '32x32', '48x48', 'scalable']:
for s in ['16x16', '32x32', '64x64', 'scalable']:
for c in ['actions', 'categories', 'emblems', 'emotes', 'devices', 'mimetypes', 'places', 'status']:
icons_dir = 'icons/{0}/{1}'.format(s,c)
if os.path.exists(os.path.join(srcdir,icons_dir)):
@@ -86,7 +81,6 @@ for f in get_files('inspector', '.ui'):
xml += ' <file preprocess=\'xml-stripblanks\'>inspector/{0}</file>\n'.format(f)
xml += '''
<file>inspector/logo.png</file>
<file>inspector/inspector.css</file>
<file>emoji/en.data</file>
</gresource>
-17
View File
@@ -1,17 +0,0 @@
The catalog in this directory defines some widgets that are private
to GTK and is needed to edit .ui files defining composite classes
in GTK.
In order to edit any composite classes in GTK, startup Glade
in the following way, example:
cd /path/to/gtk/
GLADE_CATALOG_SEARCH_PATH=`pwd`/gtk/glade glade gtk/ui/gtkfilechooserwidget.ui
Documentation for updating this catalog can be found here:
https://developer.gnome.org/gladeui/stable/
Note also that when including private GTK widgets as components, it is
important to call g_type_ensure () to register the type explicitly
before calling gtk_container_init_template(), otherwise GtkBuilder will
not be able to properly load the type.
-33
View File
@@ -1,33 +0,0 @@
<glade-catalog name="gtkprivate"
version="3.96"
depends="gtk4"
library="gtk-4">
<init-function>gtk_glade_catalog_init</init-function>
<glade-widget-classes>
<!-- base GTK private widgets -->
<glade-widget-class name="GtkPathBar" generic-name="pathbar" title="Path Bar" icon-name="widget-gtk-toolbar"/>
<glade-widget-class name="GtkColorEditor" generic-name="coloreditor" title="Color Editor" icon-name="widget-gtk-colorselection"/>
<glade-widget-class name="GtkColorSwatch" generic-name="colorswatch" title="Color Swatch" icon-name="widget-gtk-colorselection"/>
<glade-widget-class name="GtkColorPlane" generic-name="colorplane" title="Color Plane" icon-name="widget-gtk-colorselection"/>
<glade-widget-class name="GtkColorScale" generic-name="colorscale" title="Color Scale" icon-name="widget-gtk-colorselection"/>
<!-- gtkunixprint private widgets -->
<glade-widget-class name="GtkPrinterOptionWidget" generic-name="printeroptionwidget" title="Printer Option Widget"
icon-name="widget-gtk-frame">
<properties>
<property id="orientation" default="GTK_ORIENTATION_HORIZONTAL"/>
<property id="size" disabled="True"/>
</properties>
</glade-widget-class>
</glade-widget-classes>
<glade-widget-group name="gtk-private" title="Private GTK Classes">
<glade-widget-class-ref name="GtkPathBar"/>
<glade-widget-class-ref name="GtkColorEditor"/>
<glade-widget-class-ref name="GtkColorSwatch"/>
<glade-widget-class-ref name="GtkColorPlane"/>
<glade-widget-class-ref name="GtkColorScale"/>
<glade-widget-class-ref name="GtkPrinterOptionWidget"/>
</glade-widget-group>
</glade-catalog>
-1
View File
@@ -67,7 +67,6 @@
#include "gtkprivate.h"
#include "gtktypebuiltins.h"
#include "gtksizerequest.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
+1 -1
View File
@@ -25,9 +25,9 @@
#include "gtkorientable.h"
#include "gtkprivate.h"
#include "gtksizerequest.h"
#include "gtkstylecontextprivate.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
/**
* SECTION:gtkboxlayout
+5 -4
View File
@@ -20,7 +20,7 @@
#include "config.h"
#include "gtkstylecontextprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkbuiltiniconprivate.h"
#include "gtkwidgetprivate.h"
@@ -80,10 +80,11 @@ gtk_builtin_icon_measure (GtkWidget *widget,
int *minimum_baseline,
int *natural_baseline)
{
GtkCssValue *icon_size;
GtkCssStyle *style;
icon_size = _gtk_style_context_peek_property (gtk_widget_get_style_context (widget), GTK_CSS_PROPERTY_ICON_SIZE);
*minimum = *natural = _gtk_css_number_value_get (icon_size, 100);
style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
*minimum = *natural = _gtk_css_number_value_get (style->icon->icon_size, 100);
}
static void
-4
View File
@@ -310,14 +310,10 @@ click_pressed_cb (GtkGestureClick *gesture,
{
GtkButton *button = GTK_BUTTON (widget);
GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
GdkEventSequence *sequence;
if (gtk_widget_get_focus_on_click (widget) && !gtk_widget_has_focus (widget))
gtk_widget_grab_focus (widget);
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
gtk_gesture_set_sequence_state (GTK_GESTURE (gesture), sequence, GTK_EVENT_SEQUENCE_CLAIMED);
if (!priv->activate_timeout)
priv->button_down = TRUE;
}
-1
View File
@@ -103,7 +103,6 @@
#include "gtkprivate.h"
#include "gtkrendericonprivate.h"
#include "gtksnapshot.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkgestureclick.h"
#include "gtkgesturedrag.h"
+6 -5
View File
@@ -23,8 +23,8 @@
#include "gtklayoutchild.h"
#include "gtkprivate.h"
#include "gtksizerequest.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
/**
* SECTION:gtkcenterlayout
@@ -58,12 +58,13 @@ G_DEFINE_TYPE (GtkCenterLayout, gtk_center_layout, GTK_TYPE_LAYOUT_MANAGER)
static int
get_spacing (GtkCenterLayout *self,
GtkStyleContext *style_context)
GtkCssNode *node)
{
GtkCssStyle *style = gtk_css_node_get_style (node);
GtkCssValue *border_spacing;
int css_spacing;
border_spacing = _gtk_style_context_peek_property (style_context, GTK_CSS_PROPERTY_BORDER_SPACING);
border_spacing = style->size->border_spacing;
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
css_spacing = _gtk_css_position_value_get_x (border_spacing, 100);
else
@@ -226,7 +227,7 @@ gtk_center_layout_measure_orientation (GtkCenterLayout *self,
int spacing;
int i;
spacing = get_spacing (self, _gtk_widget_get_style_context (widget));
spacing = get_spacing (self, gtk_widget_get_css_node (widget));
for (i = 0; i < 3; i ++)
{
@@ -386,7 +387,7 @@ gtk_center_layout_allocate (GtkLayoutManager *layout_manager,
int i;
int spacing;
spacing = get_spacing (self, _gtk_widget_get_style_context (widget));
spacing = get_spacing (self, gtk_widget_get_css_node (widget));
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
{
+53 -3
View File
@@ -34,7 +34,8 @@
#include "gtkintl.h"
#include "gtklabel.h"
#include "gtkprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkshortcuttrigger.h"
#include "gtkcssnodeprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkmodelbuttonprivate.h"
@@ -94,6 +95,7 @@ enum {
enum {
TOGGLED,
ACTIVATE,
LAST_SIGNAL
};
@@ -276,8 +278,6 @@ click_pressed_cb (GtkGestureClick *gesture,
{
if (gtk_widget_get_focus_on_click (widget) && !gtk_widget_has_focus (widget))
gtk_widget_grab_focus (widget);
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
}
static void
@@ -293,6 +293,8 @@ click_released_cb (GtkGestureClick *gesture,
if (priv->active && (priv->group_prev || priv->group_next))
return;
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
gtk_check_button_set_active (self, !priv->active);
if (priv->action_helper)
@@ -442,11 +444,26 @@ gtk_check_button_focus (GtkWidget *widget,
}
}
static void
gtk_check_button_real_activate (GtkCheckButton *check_button)
{
gtk_check_button_set_active (check_button,
!gtk_check_button_get_active (check_button));
}
static void
gtk_check_button_class_init (GtkCheckButtonClass *class)
{
const guint activate_keyvals[] = {
GDK_KEY_space,
GDK_KEY_KP_Space,
GDK_KEY_Return,
GDK_KEY_ISO_Enter,
GDK_KEY_KP_Enter
};
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkShortcutAction *activate_action;
object_class->dispose = gtk_check_button_dispose;
object_class->set_property = gtk_check_button_set_property;
@@ -454,6 +471,8 @@ gtk_check_button_class_init (GtkCheckButtonClass *class)
widget_class->focus = gtk_check_button_focus;
class->activate = gtk_check_button_real_activate;
props[PROP_ACTIVE] =
g_param_spec_boolean ("active",
P_("Active"),
@@ -507,6 +526,37 @@ gtk_check_button_class_init (GtkCheckButtonClass *class)
NULL,
G_TYPE_NONE, 0);
/**
* GtkCheckButton::activate:
* @widget: the object which received the signal.
*
* The ::activate signal on GtkCheckButton is an action signal and
* emitting it causes the button to animate press then release.
* Applications should never connect to this signal, but use the
* #GtkCheckButton::toggled signal.
*/
signals[ACTIVATE] =
g_signal_new (I_ ("activate"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkCheckButtonClass, activate),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
gtk_widget_class_set_activate_signal (widget_class, signals[ACTIVATE]);
activate_action = gtk_signal_action_new ("activate");
for (guint i = 0; i < G_N_ELEMENTS (activate_keyvals); i++)
{
GtkShortcut *activate_shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (activate_keyvals[i], 0),
g_object_ref (activate_action));
gtk_widget_class_add_shortcut (widget_class, activate_shortcut);
g_object_unref (activate_shortcut);
}
g_object_unref (activate_action);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
gtk_widget_class_set_css_name (widget_class, I_("checkbutton"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_CHECKBOX);
+2 -1
View File
@@ -56,9 +56,10 @@ struct _GtkCheckButtonClass
GtkWidgetClass parent_class;
void (* toggled) (GtkCheckButton *check_button);
void (* activate) (GtkCheckButton *check_button);
/*< private >*/
gpointer padding[8];
gpointer padding[7];
};
-1
View File
@@ -34,7 +34,6 @@
#include "gtkpopovermenu.h"
#include "gtkprivate.h"
#include "gtksnapshot.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerkey.h"
#include "gtknative.h"
+2 -2
View File
@@ -39,7 +39,7 @@
#include "gtkadjustment.h"
#include "gtkgesturedrag.h"
#include "gtkeventcontrollermotion.h"
#include "gtkdragsource.h"
#include "gtkdragsourceprivate.h"
#include "gtkeventcontrollerkey.h"
#include "gtkgestureclick.h"
@@ -1128,7 +1128,7 @@ header_drag_update (GtkGestureDrag *gesture,
if (!self->in_column_resize && !self->in_column_reorder)
{
if (gtk_drag_check_threshold (GTK_WIDGET (self), 0, 0, offset_x, 0))
if (gtk_drag_check_threshold_double (GTK_WIDGET (self), 0, 0, offset_x, 0))
{
GtkColumnViewColumn *column;
GtkWidget *header;
+10 -10
View File
@@ -28,7 +28,7 @@
#include "gtklabel.h"
#include "gtkwidgetprivate.h"
#include "gtkbox.h"
#include "gtkimage.h"
#include "gtkbuiltiniconprivate.h"
#include "gtkgestureclick.h"
#include "gtkpopovermenu.h"
#include "gtknative.h"
@@ -266,7 +266,7 @@ gtk_column_view_title_init (GtkColumnViewTitle *self)
self->title = gtk_label_new (NULL);
gtk_box_append (GTK_BOX (self->box), self->title);
self->sort = gtk_image_new ();
self->sort = gtk_builtin_icon_new ("sort-indicator");
gtk_box_append (GTK_BOX (self->box), self->sort);
gesture = gtk_gesture_click_new ();
@@ -308,15 +308,15 @@ gtk_column_view_title_update (GtkColumnViewTitle *self)
active = gtk_column_view_sorter_get_sort_column (view_sorter, &inverted);
gtk_widget_show (self->sort);
if (self->column == active)
{
if (inverted)
gtk_image_set_from_icon_name (GTK_IMAGE (self->sort), "pan-down-symbolic");
else
gtk_image_set_from_icon_name (GTK_IMAGE (self->sort), "pan-up-symbolic");
}
gtk_widget_remove_css_class (self->sort, "ascending");
gtk_widget_remove_css_class (self->sort, "descending");
gtk_widget_remove_css_class (self->sort, "unsorted");
if (self->column != active)
gtk_widget_add_css_class (self->sort, "unsorted");
else if (inverted)
gtk_widget_add_css_class (self->sort, "descending");
else
gtk_image_clear (GTK_IMAGE (self->sort));
gtk_widget_add_css_class (self->sort, "ascending");
}
else
gtk_widget_hide (self->sort);
+567 -177
View File
@@ -26,16 +26,17 @@
#include "gtkcomposetable.h"
#include "gtkimcontextsimple.h"
#include "gtkimcontextsimpleprivate.h"
#define GTK_COMPOSE_TABLE_MAGIC "GtkComposeTable"
#define GTK_COMPOSE_TABLE_VERSION (1)
#define GTK_COMPOSE_TABLE_VERSION (2)
/* Maximum length of sequences we parse */
#define MAX_COMPOSE_LEN 20
typedef struct {
gunichar *sequence;
gunichar value[2];
char *comment;
gunichar *sequence;
char *value;
} GtkComposeData;
@@ -43,7 +44,7 @@ static void
gtk_compose_data_free (GtkComposeData *compose_data)
{
g_free (compose_data->sequence);
g_free (compose_data->comment);
g_free (compose_data->value);
g_slice_free (GtkComposeData, compose_data);
}
@@ -76,58 +77,82 @@ parse_compose_value (GtkComposeData *compose_data,
const char *val,
const char *line)
{
char **words = g_strsplit (val, "\"", 3);
gunichar uch;
char *word;
const char *p;
gsize len;
GString *value;
gunichar ch;
char *endp;
if (g_strv_length (words) < 3)
len = strlen (val);
if (val[0] != '"' || val[len - 1] != '"')
{
g_warning ("Need to double-quote the value: %s: %s", val, line);
goto fail;
}
uch = g_utf8_get_char (words[1]);
word = g_strndup (val + 1, len - 2);
if (uch == 0)
{
g_warning ("Invalid value: %s: %s", val, line);
goto fail;
}
else if (uch == '\\')
{
uch = words[1][1];
value = g_string_new ("");
/* The escaped string "\"" is separated with '\\' and '"'. */
if (uch == '\0' && words[2][0] == '"')
uch = '"';
/* The escaped octal */
else if (uch >= '0' && uch <= '8')
uch = g_ascii_strtoll(words[1] + 1, NULL, 8);
/* If we need to handle other escape sequences. */
else if (uch != '\\')
p = word;
while (*p)
{
if (*p == '\\')
{
g_warning ("Invalid escape sequence: %s: %s", val, line);
if (p[1] == '"')
{
g_string_append_c (value, '"');
p += 2;
}
else if (p[1] == '\\')
{
g_string_append_c (value, '\\');
p += 2;
}
else if (p[1] >= '0' && p[1] < '8')
{
ch = g_ascii_strtoll (p + 1, &endp, 8);
if (ch == 0)
{
g_warning ("Invalid escape sequence: %s: %s", val, line);
goto fail;
}
g_string_append_unichar (value, ch);
p = endp;
}
else if (p[1] == 'x' || p[1] == 'X')
{
ch = g_ascii_strtoll (p + 2, &endp, 16);
if (ch == 0)
{
g_warning ("Invalid escape sequence: %s: %s", val, line);
goto fail;
}
g_string_append_unichar (value, ch);
p = endp;
}
else
{
g_warning ("Invalid escape sequence: %s: %s", val, line);
goto fail;
}
}
else
{
ch = g_utf8_get_char (p);
g_string_append_unichar (value, ch);
p = g_utf8_next_char (p);
}
}
if (g_utf8_get_char (g_utf8_next_char (words[1])) > 0)
{
g_warning ("GTK supports to output one char only: %s: %s", val, line);
goto fail;
}
compose_data->value = g_string_free (value, FALSE);
compose_data->value[1] = uch;
if (uch == '"')
compose_data->comment = g_strdup (g_strstrip (words[2] + 1));
else
compose_data->comment = g_strdup (g_strstrip (words[2]));
g_strfreev (words);
g_free (word);
return TRUE;
fail:
g_strfreev (words);
return FALSE;
}
@@ -189,10 +214,10 @@ parse_compose_sequence (GtkComposeData *compose_data,
}
g_strfreev (words);
if (0 == n || n >= GTK_MAX_COMPOSE_LEN)
if (0 == n || n > MAX_COMPOSE_LEN)
{
g_warning ("The max number of sequences is %d: %s",
GTK_MAX_COMPOSE_LEN, line);
g_warning ("Suspicious compose sequence length (%d). Are you sure this is right?: %s",
n, line);
return FALSE;
}
@@ -214,7 +239,10 @@ parse_compose_line (GList **compose_list,
return;
if (g_str_has_prefix (line, "include "))
return;
{
g_warning ("include in Compose files not supported: %s", line);
return;
}
components = g_strsplit (line, ":", 2);
@@ -244,6 +272,8 @@ fail:
gtk_compose_data_free (compose_data);
}
extern const GtkComposeTableCompact gtk_compose_table_compact;
static GList *
gtk_compose_list_parse_file (const char *compose_file)
{
@@ -279,18 +309,19 @@ gtk_compose_list_check_duplicated (GList *compose_list)
for (list = compose_list; list != NULL; list = list->next)
{
static guint16 keysyms[GTK_MAX_COMPOSE_LEN + 1];
static guint16 keysyms[MAX_COMPOSE_LEN + 1];
int i;
int n_compose = 0;
gboolean compose_finish;
gunichar output_char;
char buf[8] = { 0, };
compose_data = list->data;
for (i = 0; i < GTK_MAX_COMPOSE_LEN + 1; i++)
for (i = 0; i < MAX_COMPOSE_LEN + 1; i++)
keysyms[i] = 0;
for (i = 0; i < GTK_MAX_COMPOSE_LEN + 1; i++)
for (i = 0; i < MAX_COMPOSE_LEN + 1; i++)
{
gunichar codepoint = compose_data->sequence[i];
keysyms[i] = (guint16) codepoint;
@@ -301,20 +332,21 @@ gtk_compose_list_check_duplicated (GList *compose_list)
n_compose++;
}
if (gtk_check_compact_table (&gtk_compose_table_compact,
keysyms,
n_compose,
&compose_finish,
NULL,
&output_char) &&
if (gtk_compose_table_compact_check (&gtk_compose_table_compact,
keysyms, n_compose,
&compose_finish,
NULL,
&output_char) &&
compose_finish)
{
if (compose_data->value[1] == output_char)
g_unichar_to_utf8 (output_char, buf);
if (strcmp (compose_data->value, buf) == 0)
removed_list = g_list_prepend (removed_list, compose_data);
}
else if (gtk_check_algorithmically (keysyms, n_compose, &output_char))
{
if (compose_data->value[1] == output_char)
g_unichar_to_utf8 (output_char, buf);
if (strcmp (compose_data->value, buf) == 0)
removed_list = g_list_prepend (removed_list, compose_data);
}
}
@@ -343,7 +375,7 @@ gtk_compose_list_check_uint16 (GList *compose_list)
int i;
compose_data = list->data;
for (i = 0; i < GTK_MAX_COMPOSE_LEN; i++)
for (i = 0; i < MAX_COMPOSE_LEN; i++)
{
gunichar codepoint = compose_data->sequence[i];
@@ -384,7 +416,7 @@ gtk_compose_list_format_for_gtk (GList *compose_list,
for (list = compose_list; list != NULL; list = list->next)
{
compose_data = list->data;
for (i = 0; i < GTK_MAX_COMPOSE_LEN + 1; i++)
for (i = 0; i < MAX_COMPOSE_LEN + 1; i++)
{
codepoint = compose_data->sequence[i];
if (codepoint == 0)
@@ -401,17 +433,6 @@ gtk_compose_list_format_for_gtk (GList *compose_list,
if (p_n_index_stride)
*p_n_index_stride = max_compose_len + 2;
for (list = compose_list; list != NULL; list = list->next)
{
compose_data = list->data;
codepoint = compose_data->value[1];
if (codepoint > 0xffff)
{
compose_data->value[0] = codepoint / 0x10000;
compose_data->value[1] = codepoint - codepoint / 0x10000 * 0x10000;
}
}
return compose_list;
}
@@ -436,61 +457,6 @@ gtk_compose_data_compare (gpointer a,
return 0;
}
static void
gtk_compose_list_print (GList *compose_list,
int max_compose_len,
int n_index_stride)
{
GList *list;
int i, j;
GtkComposeData *compose_data;
int total_size = 0;
gunichar upper;
gunichar lower;
const char *comment;
const char *keyval;
for (list = compose_list; list != NULL; list = list->next)
{
compose_data = list->data;
g_printf (" ");
for (i = 0; i < max_compose_len; i++)
{
if (compose_data->sequence[i] == 0)
{
for (j = i; j < max_compose_len; j++)
{
if (j == max_compose_len - 1)
g_printf ("0,\n");
else
g_printf ("0, ");
}
break;
}
keyval = gdk_keyval_name (compose_data->sequence[i]);
if (i == max_compose_len - 1)
g_printf ("%s,\n", keyval ? keyval : "(null)");
else
g_printf ("%s, ", keyval ? keyval : "(null)");
}
upper = compose_data->value[0];
lower = compose_data->value[1];
comment = compose_data->comment;
if (list == g_list_last (compose_list))
g_printf (" %#06X, %#06X /* %s */\n", upper, lower, comment);
else
g_printf (" %#06X, %#06X, /* %s */\n", upper, lower, comment);
total_size += n_index_stride;
}
g_printerr ("TOTAL_SIZE: %d\nMAX_COMPOSE_LEN: %d\nN_INDEX_STRIDE: %d\n",
total_size, max_compose_len, n_index_stride);
}
/* Implemented from g_str_hash() */
static guint32
gtk_compose_table_data_hash (gconstpointer v, int length)
@@ -546,6 +512,7 @@ gtk_compose_table_serialize (GtkComposeTable *compose_table,
guint16 max_seq_len = compose_table->max_seq_len;
guint16 index_stride = max_seq_len + 2;
guint16 n_seqs = compose_table->n_seqs;
guint16 n_chars = compose_table->n_chars;
guint32 i;
g_return_val_if_fail (compose_table != NULL, NULL);
@@ -553,44 +520,34 @@ gtk_compose_table_serialize (GtkComposeTable *compose_table,
g_return_val_if_fail (index_stride > 0, NULL);
length = strlen (header);
total_length = length + sizeof (guint16) * (3 + index_stride * n_seqs);
total_length = length + sizeof (guint16) * (4 + index_stride * n_seqs) + n_chars;
if (count)
*count = total_length;
p = contents = g_slice_alloc (total_length);
p = contents = g_malloc (total_length);
memcpy (p, header, length);
p += length;
/* Copy by byte for endian */
#define BYTE_COPY_FROM_BUF(element) \
bytes = GUINT16_TO_BE ((element)); \
memcpy (p, &bytes, length); \
p += length; \
if (p - contents > total_length) \
{ \
g_warning ("data size %lld is bigger than %" G_GSIZE_FORMAT, \
(long long) (p - contents), total_length); \
g_free (contents); \
if (count) \
{ \
*count = 0; \
} \
return NULL; \
}
#define APPEND_GUINT16(elt) \
bytes = GUINT16_TO_BE (elt); \
memcpy (p, &bytes, sizeof (guint16)); \
p += sizeof (guint16);
length = sizeof (guint16);
BYTE_COPY_FROM_BUF (version);
BYTE_COPY_FROM_BUF (max_seq_len);
BYTE_COPY_FROM_BUF (n_seqs);
APPEND_GUINT16 (version);
APPEND_GUINT16 (max_seq_len);
APPEND_GUINT16 (n_seqs);
APPEND_GUINT16 (n_chars);
for (i = 0; i < (guint32) index_stride * n_seqs; i++)
{
BYTE_COPY_FROM_BUF (compose_table->data[i]);
APPEND_GUINT16 (compose_table->data[i]);
}
#undef BYTE_COPY_FROM_BUF
if (compose_table->n_chars > 0)
memcpy (p, compose_table->char_data, compose_table->n_chars);
#undef APPEND_GUINT16
return contents;
}
@@ -614,16 +571,17 @@ gtk_compose_table_load_cache (const char *compose_file)
GStatBuf original_buf;
GStatBuf cache_buf;
gsize total_length;
gsize length;
GError *error = NULL;
guint16 bytes;
guint16 version;
guint16 max_seq_len;
guint16 index_stride;
guint16 n_seqs;
guint16 n_chars;
guint32 i;
guint16 *gtk_compose_seqs = NULL;
GtkComposeTable *retval;
char *char_data = NULL;
hash = g_str_hash (compose_file);
if ((path = gtk_compose_hash_get_cache_path (hash)) == NULL)
@@ -642,16 +600,10 @@ gtk_compose_table_load_cache (const char *compose_file)
goto out_load_cache;
}
/* Copy by byte for endian */
#define BYTE_COPY_TO_BUF(element) \
memcpy (&bytes, p, length); \
element = GUINT16_FROM_BE (bytes); \
p += length; \
if (p - contents > total_length) \
{ \
g_warning ("Broken cache content %s in %s", path, #element); \
goto out_load_cache; \
}
#define GET_GUINT16(elt) \
memcpy (&bytes, p, sizeof (guint16)); \
elt = GUINT16_FROM_BE (bytes); \
p += sizeof (guint16);
p = contents;
if (g_ascii_strncasecmp (p, GTK_COMPOSE_TABLE_MAGIC,
@@ -660,6 +612,7 @@ gtk_compose_table_load_cache (const char *compose_file)
g_warning ("The file is not a GtkComposeTable cache file %s", path);
goto out_load_cache;
}
p += strlen (GTK_COMPOSE_TABLE_MAGIC);
if (p - contents > total_length)
{
@@ -667,9 +620,7 @@ gtk_compose_table_load_cache (const char *compose_file)
goto out_load_cache;
}
length = sizeof (guint16);
BYTE_COPY_TO_BUF (version);
GET_GUINT16 (version);
if (version != GTK_COMPOSE_TABLE_VERSION)
{
g_warning ("cache version is different %u != %u",
@@ -677,8 +628,9 @@ gtk_compose_table_load_cache (const char *compose_file)
goto out_load_cache;
}
BYTE_COPY_TO_BUF (max_seq_len);
BYTE_COPY_TO_BUF (n_seqs);
GET_GUINT16 (max_seq_len);
GET_GUINT16 (n_seqs);
GET_GUINT16 (n_chars);
if (max_seq_len == 0 || n_seqs == 0)
{
@@ -691,13 +643,22 @@ gtk_compose_table_load_cache (const char *compose_file)
for (i = 0; i < (guint32) index_stride * n_seqs; i++)
{
BYTE_COPY_TO_BUF (gtk_compose_seqs[i]);
GET_GUINT16 (gtk_compose_seqs[i]);
}
if (n_chars > 0)
{
char_data = g_new (char, n_chars + 1);
memcpy (char_data, p, n_chars);
char_data[n_chars] = '\0';
}
retval = g_new0 (GtkComposeTable, 1);
retval->data = gtk_compose_seqs;
retval->max_seq_len = max_seq_len;
retval->n_seqs = n_seqs;
retval->char_data = char_data;
retval->n_chars = n_chars;
retval->id = hash;
g_free (contents);
@@ -705,10 +666,11 @@ gtk_compose_table_load_cache (const char *compose_file)
return retval;
#undef BYTE_COPY_TO_BUF
#undef GET_GUINT16
out_load_cache:
g_free (gtk_compose_seqs);
g_free (char_data);
g_free (contents);
g_free (path);
return NULL;
@@ -739,7 +701,7 @@ gtk_compose_table_save_cache (GtkComposeTable *compose_table)
}
out_save_cache:
g_slice_free1 (length, contents);
g_free (contents);
g_free (path);
}
@@ -756,6 +718,8 @@ gtk_compose_table_new_with_list (GList *compose_list,
GList *list;
GtkComposeData *compose_data;
GtkComposeTable *retval = NULL;
gunichar codepoint;
GString *char_data;
g_return_val_if_fail (compose_list != NULL, NULL);
@@ -763,6 +727,8 @@ gtk_compose_table_new_with_list (GList *compose_list,
gtk_compose_seqs = g_new0 (guint16, length * n_index_stride);
char_data = g_string_new ("");
for (list = compose_list; list != NULL; list = list->next)
{
compose_data = list->data;
@@ -776,8 +742,24 @@ gtk_compose_table_new_with_list (GList *compose_list,
}
gtk_compose_seqs[n++] = (guint16) compose_data->sequence[i];
}
gtk_compose_seqs[n++] = (guint16) compose_data->value[0];
gtk_compose_seqs[n++] = (guint16) compose_data->value[1];
if (g_utf8_strlen (compose_data->value, -1) > 1)
{
if (char_data->len > 0)
g_string_append_c (char_data, 0);
codepoint = char_data->len | (1 << 31);
g_string_append (char_data, compose_data->value);
}
else
{
codepoint = g_utf8_get_char (compose_data->value);
g_assert ((codepoint & (1 << 31)) == 0);
}
gtk_compose_seqs[n++] = (codepoint & 0xffff0000) >> 16;
gtk_compose_seqs[n++] = codepoint & 0xffff;
}
retval = g_new0 (GtkComposeTable, 1);
@@ -785,6 +767,8 @@ gtk_compose_table_new_with_list (GList *compose_list,
retval->max_seq_len = max_compose_len;
retval->n_seqs = length;
retval->id = hash;
retval->n_chars = char_data->len;
retval->char_data = g_string_free (char_data, FALSE);
return retval;
}
@@ -816,9 +800,6 @@ gtk_compose_table_new_with_file (const char *compose_file)
return NULL;
}
if (g_getenv ("GTK_COMPOSE_TABLE_PRINT") != NULL)
gtk_compose_list_print (compose_list, max_compose_len, n_index_stride);
compose_table = gtk_compose_table_new_with_list (compose_list,
max_compose_len,
n_index_stride,
@@ -841,9 +822,10 @@ gtk_compose_table_list_add_array (GSList *compose_tables,
guint16 *gtk_compose_seqs = NULL;
g_return_val_if_fail (data != NULL, compose_tables);
g_return_val_if_fail (max_seq_len <= GTK_MAX_COMPOSE_LEN, compose_tables);
g_return_val_if_fail (max_seq_len >= 0, compose_tables);
g_return_val_if_fail (n_seqs >= 0, compose_tables);
n_index_stride = MIN (max_seq_len, GTK_MAX_COMPOSE_LEN) + 2;
n_index_stride = max_seq_len + 2;
if (!g_size_checked_mul (&length, n_index_stride, n_seqs))
{
g_critical ("Overflow in the compose sequences");
@@ -864,12 +846,14 @@ gtk_compose_table_list_add_array (GSList *compose_tables,
compose_table->max_seq_len = max_seq_len;
compose_table->n_seqs = n_seqs;
compose_table->id = hash;
compose_table->char_data = NULL;
compose_table->n_chars = 0;
return g_slist_prepend (compose_tables, compose_table);
}
GSList *
gtk_compose_table_list_add_file (GSList *compose_tables,
gtk_compose_table_list_add_file (GSList *compose_tables,
const char *compose_file)
{
guint32 hash;
@@ -891,3 +875,409 @@ gtk_compose_table_list_add_file (GSList *compose_tables,
gtk_compose_table_save_cache (compose_table);
return g_slist_prepend (compose_tables, compose_table);
}
static int
compare_seq (const void *key, const void *value)
{
int i = 0;
const guint16 *keysyms = key;
const guint16 *seq = value;
while (keysyms[i])
{
if (keysyms[i] < seq[i])
return -1;
else if (keysyms[i] > seq[i])
return 1;
i++;
}
return 0;
}
/*
* gtk_compose_table_check:
* @table: the table to check
* @compose_buffer: the key vals to match
* @n_compose: number of non-zero key vals in @compose_buffer
* @compose_finish: (out): return location for whether there may be longer matches
* @compose_match: (out): return location for whether there is a match
* @output: (out) (caller-allocates): return location for the match values
*
* Looks for matches for a key sequence in @table.
*
* Returns: %TRUE if there were any matches, %FALSE otherwise
*/
gboolean
gtk_compose_table_check (const GtkComposeTable *table,
const guint16 *compose_buffer,
int n_compose,
gboolean *compose_finish,
gboolean *compose_match,
GString *output)
{
int row_stride = table->max_seq_len + 2;
guint16 *seq;
*compose_finish = FALSE;
*compose_match = FALSE;
g_string_set_size (output, 0);
/* Will never match, if the sequence in the compose buffer is longer
* than the sequences in the table. Further, compare_seq (key, val)
* will overrun val if key is longer than val.
*/
if (n_compose > table->max_seq_len)
return FALSE;
seq = bsearch (compose_buffer,
table->data, table->n_seqs,
sizeof (guint16) * row_stride,
compare_seq);
if (seq)
{
guint16 *prev_seq;
/* Back up to the first sequence that matches to make sure
* we find the exact match if there is one.
*/
while (seq > table->data)
{
prev_seq = seq - row_stride;
if (compare_seq (compose_buffer, prev_seq) != 0)
break;
seq = prev_seq;
}
if (n_compose == table->max_seq_len ||
seq[n_compose] == 0) /* complete sequence */
{
guint16 *next_seq;
gunichar value;
value = (seq[table->max_seq_len] << 16) | seq[table->max_seq_len + 1];
if ((value & (1 << 31)) != 0)
g_string_append (output, &table->char_data[value & ~(1 << 31)]);
else
g_string_append_unichar (output, value);
*compose_match = TRUE;
/* We found a tentative match. See if there are any longer
* sequences containing this subsequence
*/
next_seq = seq + row_stride;
if (next_seq < table->data + row_stride * table->n_seqs)
{
if (compare_seq (compose_buffer, next_seq) == 0)
return TRUE;
}
*compose_finish = TRUE;
return TRUE;
}
return TRUE;
}
return FALSE;
}
static int
compare_seq_index (const void *key, const void *value)
{
const guint16 *keysyms = key;
const guint16 *seq = value;
if (keysyms[0] < seq[0])
return -1;
else if (keysyms[0] > seq[0])
return 1;
return 0;
}
gboolean
gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
const guint16 *compose_buffer,
int n_compose,
gboolean *compose_finish,
gboolean *compose_match,
gunichar *output_char)
{
int row_stride;
guint16 *seq_index;
guint16 *seq;
int i;
gboolean match;
gunichar value;
if (compose_finish)
*compose_finish = FALSE;
if (compose_match)
*compose_match = FALSE;
if (output_char)
*output_char = 0;
/* Will never match, if the sequence in the compose buffer is longer
* than the sequences in the table. Further, compare_seq (key, val)
* will overrun val if key is longer than val.
*/
if (n_compose > table->max_seq_len)
return FALSE;
seq_index = bsearch (compose_buffer,
table->data,
table->n_index_size,
sizeof (guint16) * table->n_index_stride,
compare_seq_index);
if (!seq_index)
return FALSE;
if (n_compose == 1)
return TRUE;
seq = NULL;
match = FALSE;
value = 0;
for (i = n_compose - 1; i < table->max_seq_len; i++)
{
row_stride = i + 1;
if (seq_index[i + 1] - seq_index[i] > 0)
{
seq = bsearch (compose_buffer + 1,
table->data + seq_index[i],
(seq_index[i + 1] - seq_index[i]) / row_stride,
sizeof (guint16) * row_stride,
compare_seq);
if (seq)
{
if (i == n_compose - 1)
{
value = seq[row_stride - 1];
match = TRUE;
}
else
{
if (output_char)
*output_char = value;
if (match)
{
if (compose_match)
*compose_match = TRUE;
}
return TRUE;
}
}
}
}
if (match)
{
if (compose_match)
*compose_match = TRUE;
if (compose_finish)
*compose_finish = TRUE;
if (output_char)
*output_char = value;
return TRUE;
}
return FALSE;
}
/* Checks if a keysym is a dead key.
* Dead key keysym values are defined in ../gdk/gdkkeysyms.h and the
* first is GDK_KEY_dead_grave. As X.Org is updated, more dead keys
* are added and we need to update the upper limit.
*/
#define IS_DEAD_KEY(k) \
((k) >= GDK_KEY_dead_grave && (k) <= GDK_KEY_dead_greek)
/* This function receives a sequence of Unicode characters and tries to
* normalize it (NFC). We check for the case where the resulting string
* has length 1 (single character).
* NFC normalisation normally rearranges diacritic marks, unless these
* belong to the same Canonical Combining Class.
* If they belong to the same canonical combining class, we produce all
* permutations of the diacritic marks, then attempt to normalize.
*/
static gboolean
check_normalize_nfc (gunichar *combination_buffer,
int n_compose)
{
gunichar *combination_buffer_temp;
char *combination_utf8_temp = NULL;
char *nfc_temp = NULL;
int n_combinations;
gunichar temp_swap;
int i;
combination_buffer_temp = g_alloca (n_compose * sizeof (gunichar));
n_combinations = 1;
for (i = 1; i < n_compose; i++)
n_combinations *= i;
/* Xorg reuses dead_tilde for the perispomeni diacritic mark.
* We check if base character belongs to Greek Unicode block,
* and if so, we replace tilde with perispomeni.
*/
if (combination_buffer[0] >= 0x390 && combination_buffer[0] <= 0x3FF)
{
for (i = 1; i < n_compose; i++ )
if (combination_buffer[i] == 0x303)
combination_buffer[i] = 0x342;
}
memcpy (combination_buffer_temp, combination_buffer, n_compose * sizeof (gunichar) );
for (i = 0; i < n_combinations; i++)
{
g_unicode_canonical_ordering (combination_buffer_temp, n_compose);
combination_utf8_temp = g_ucs4_to_utf8 (combination_buffer_temp, n_compose, NULL, NULL, NULL);
nfc_temp = g_utf8_normalize (combination_utf8_temp, -1, G_NORMALIZE_NFC);
if (g_utf8_strlen (nfc_temp, -1) == 1)
{
memcpy (combination_buffer, combination_buffer_temp, n_compose * sizeof (gunichar) );
g_free (combination_utf8_temp);
g_free (nfc_temp);
return TRUE;
}
g_free (combination_utf8_temp);
g_free (nfc_temp);
if (n_compose > 2)
{
temp_swap = combination_buffer_temp[i % (n_compose - 1) + 1];
combination_buffer_temp[i % (n_compose - 1) + 1] = combination_buffer_temp[(i+1) % (n_compose - 1) + 1];
combination_buffer_temp[(i+1) % (n_compose - 1) + 1] = temp_swap;
}
else
break;
}
return FALSE;
}
gboolean
gtk_check_algorithmically (const guint16 *compose_buffer,
int n_compose,
gunichar *output_char)
{
int i;
gunichar *combination_buffer;
char *combination_utf8, *nfc;
combination_buffer = alloca (sizeof (gunichar) * (n_compose + 1));
if (output_char)
*output_char = 0;
for (i = 0; i < n_compose && IS_DEAD_KEY (compose_buffer[i]); i++)
;
if (i == n_compose)
return TRUE;
if (i > 0 && i == n_compose - 1)
{
combination_buffer[0] = gdk_keyval_to_unicode (compose_buffer[i]);
combination_buffer[n_compose] = 0;
i--;
while (i >= 0)
{
switch (compose_buffer[i])
{
#define CASE(keysym, unicode) \
case GDK_KEY_dead_##keysym: combination_buffer[i+1] = unicode; break
CASE (grave, 0x0300);
CASE (acute, 0x0301);
CASE (circumflex, 0x0302);
CASE (tilde, 0x0303); /* Also used with perispomeni, 0x342. */
CASE (macron, 0x0304);
CASE (breve, 0x0306);
CASE (abovedot, 0x0307);
CASE (diaeresis, 0x0308);
CASE (abovering, 0x30A);
CASE (hook, 0x0309);
CASE (doubleacute, 0x030B);
CASE (caron, 0x030C);
CASE (cedilla, 0x0327);
CASE (ogonek, 0x0328); /* Legacy use for dasia, 0x314.*/
CASE (iota, 0x0345);
CASE (voiced_sound, 0x3099); /* Per Markus Kuhn keysyms.txt file. */
CASE (semivoiced_sound, 0x309A); /* Per Markus Kuhn keysyms.txt file. */
CASE (belowdot, 0x0323);
CASE (horn, 0x031B); /* Legacy use for psili, 0x313 (or 0x343). */
CASE (stroke, 0x335);
CASE (abovecomma, 0x0313); /* Equivalent to psili */
CASE (abovereversedcomma, 0x0314); /* Equivalent to dasia */
CASE (doublegrave, 0x30F);
CASE (belowring, 0x325);
CASE (belowmacron, 0x331);
CASE (belowcircumflex, 0x32D);
CASE (belowtilde, 0x330);
CASE (belowbreve, 0x32e);
CASE (belowdiaeresis, 0x324);
CASE (invertedbreve, 0x32f);
CASE (belowcomma, 0x326);
CASE (lowline, 0x332);
CASE (aboveverticalline, 0x30D);
CASE (belowverticalline, 0x329);
CASE (longsolidusoverlay, 0x338);
CASE (a, 0x363);
CASE (A, 0x363);
CASE (e, 0x364);
CASE (E, 0x364);
CASE (i, 0x365);
CASE (I, 0x365);
CASE (o, 0x366);
CASE (O, 0x366);
CASE (u, 0x367);
CASE (U, 0x367);
CASE (small_schwa, 0x1DEA);
CASE (capital_schwa, 0x1DEA);
#undef CASE
default:
combination_buffer[i+1] = gdk_keyval_to_unicode (compose_buffer[i]);
}
i--;
}
/* If the buffer normalizes to a single character, then modify the order
* of combination_buffer accordingly, if necessary, and return TRUE.
*/
if (check_normalize_nfc (combination_buffer, n_compose))
{
combination_utf8 = g_ucs4_to_utf8 (combination_buffer, -1, NULL, NULL, NULL);
nfc = g_utf8_normalize (combination_utf8, -1, G_NORMALIZE_NFC);
if (output_char)
*output_char = g_utf8_get_char (nfc);
g_free (combination_utf8);
g_free (nfc);
return TRUE;
}
}
return FALSE;
}
+28 -7
View File
@@ -29,8 +29,10 @@ typedef struct _GtkComposeTableCompact GtkComposeTableCompact;
struct _GtkComposeTable
{
guint16 *data;
char *char_data;
int max_seq_len;
int n_seqs;
int n_chars;
guint32 id;
};
@@ -42,13 +44,32 @@ struct _GtkComposeTableCompact
int n_index_stride;
};
GtkComposeTable * gtk_compose_table_new_with_file (const char *compose_file);
GSList *gtk_compose_table_list_add_array (GSList *compose_tables,
const guint16 *data,
int max_seq_len,
int n_seqs);
GSList *gtk_compose_table_list_add_file (GSList *compose_tables,
const char *compose_file);
GtkComposeTable * gtk_compose_table_new_with_file (const char *compose_file);
GSList * gtk_compose_table_list_add_array (GSList *compose_tables,
const guint16 *data,
int max_seq_len,
int n_seqs);
GSList * gtk_compose_table_list_add_file (GSList *compose_tables,
const char *compose_file);
gboolean gtk_compose_table_check (const GtkComposeTable *table,
const guint16 *compose_buffer,
int n_compose,
gboolean *compose_finish,
gboolean *compose_match,
GString *output);
gboolean gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
const guint16 *compose_buffer,
int n_compose,
gboolean *compose_finish,
gboolean *compose_match,
gunichar *output_char);
gboolean gtk_check_algorithmically (const guint16 *compose_buffer,
int n_compose,
gunichar *output);
G_END_DECLS
+4
View File
@@ -440,6 +440,10 @@ gtk_css_animated_style_set_animated_value (GtkCssAnimatedStyle *animated,
unshare_other (animated);
gtk_css_take_value (&style->other->transform, value);
break;
case GTK_CSS_PROPERTY_TRANSFORM_ORIGIN:
unshare_other (animated);
gtk_css_take_value (&style->other->transform_origin, value);
break;
case GTK_CSS_PROPERTY_MIN_WIDTH:
unshare_size (animated);
gtk_css_take_value (&style->size->min_width, value);
+1 -1
View File
@@ -218,7 +218,7 @@ _gtk_css_border_value_parse (GtkCssParser *parser,
}
result->is_computed = TRUE;
for (; i < 4; i++)
for (i = 0; i < 4; i++)
if (result->values[i] && !gtk_css_value_is_computed (result->values[i]))
{
result->is_computed = FALSE;
+93 -51
View File
@@ -545,57 +545,6 @@ _gtk_css_font_stretch_value_get (const GtkCssValue *value)
return value->value;
}
/* GtkTextDecorationLine */
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
"GtkCssTextDecorationLineValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
gtk_css_value_enum_transition,
NULL,
NULL,
gtk_css_value_enum_print
};
static GtkCssValue text_decoration_line_values[] = {
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
};
GtkCssValue *
_gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
{
g_return_val_if_fail (line < G_N_ELEMENTS (text_decoration_line_values), NULL);
return _gtk_css_value_ref (&text_decoration_line_values[line]);
}
GtkCssValue *
_gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser)
{
guint i;
g_return_val_if_fail (parser != NULL, NULL);
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
{
if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
return _gtk_css_value_ref (&text_decoration_line_values[i]);
}
return NULL;
}
GtkTextDecorationLine
_gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
return value->value;
}
/* GtkTextDecorationStyle */
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
@@ -1203,6 +1152,99 @@ gtk_css_value_flags_print (const FlagsValue *values,
}
}
/* GtkTextDecorationLine */
static FlagsValue text_decoration_line_values[] = {
{ GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
{ GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
{ GTK_CSS_TEXT_DECORATION_LINE_OVERLINE, "overline" },
{ GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
};
static void
gtk_css_text_decoration_line_value_print (const GtkCssValue *value,
GString *string)
{
gtk_css_value_flags_print (text_decoration_line_values,
G_N_ELEMENTS (text_decoration_line_values),
value, string);
}
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
"GtkCssTextDecorationLine",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_flags_equal,
gtk_css_value_enum_transition,
NULL,
NULL,
gtk_css_text_decoration_line_value_print
};
static gboolean
text_decoration_line_is_valid (GtkTextDecorationLine line)
{
if ((line & GTK_CSS_TEXT_DECORATION_LINE_NONE) &&
(line != GTK_CSS_TEXT_DECORATION_LINE_NONE))
return FALSE;
return TRUE;
}
GtkCssValue *
_gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
{
GtkCssValue *value;
if (!text_decoration_line_is_valid (line))
return NULL;
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_TEXT_DECORATION_LINE);
value->value = line;
value->name = NULL;
value->is_computed = TRUE;
return value;
}
GtkTextDecorationLine
_gtk_css_text_decoration_line_try_parse_one (GtkCssParser *parser,
GtkTextDecorationLine base)
{
guint i;
GtkTextDecorationLine value = 0;
g_return_val_if_fail (parser != NULL, 0);
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
{
if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
{
value = text_decoration_line_values[i].value;
break;
}
}
if (value == 0)
return base; /* not parsing this value */
if ((base | value) == base)
return 0; /* repeated value */
if (!text_decoration_line_is_valid (base | value))
return 0; /* bad combination */
return base | value;
}
GtkTextDecorationLine
_gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
return value->value;
}
/* GtkCssFontVariantLigature */
static FlagsValue font_variant_ligature_values[] = {
+5 -4
View File
@@ -54,11 +54,12 @@ GtkCssValue * _gtk_css_font_stretch_value_new (PangoStretch stretc
GtkCssValue * _gtk_css_font_stretch_value_try_parse (GtkCssParser *parser);
PangoStretch _gtk_css_font_stretch_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line);
GtkCssValue * _gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser);
GtkTextDecorationLine _gtk_css_text_decoration_line_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line);
GtkTextDecorationLine _gtk_css_text_decoration_line_try_parse_one (GtkCssParser *parser,
GtkTextDecorationLine base);
GtkTextDecorationLine _gtk_css_text_decoration_line_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style);
GtkCssValue * _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style);
GtkCssValue * _gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser);
GtkTextDecorationStyle _gtk_css_text_decoration_style_value_get (const GtkCssValue *value);
+64 -20
View File
@@ -24,6 +24,7 @@
#include "gtkcssfiltervalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssshadowvalueprivate.h"
typedef union _GtkCssFilter GtkCssFilter;
@@ -46,7 +47,7 @@ union _GtkCssFilter {
struct {
GtkCssFilterType type;
GtkCssValue *value;
} brightness, contrast, grayscale, hue_rotate, invert, opacity, saturate, sepia, blur;
} blur, brightness, contrast, drop_shadow, grayscale, hue_rotate, invert, opacity, saturate, sepia;
};
struct _GtkCssValue {
@@ -90,8 +91,10 @@ gtk_css_filter_clear (GtkCssFilter *filter)
case GTK_CSS_FILTER_BLUR:
_gtk_css_value_unref (filter->blur.value);
break;
case GTK_CSS_FILTER_NONE:
case GTK_CSS_FILTER_DROP_SHADOW:
_gtk_css_value_unref (filter->drop_shadow.value);
break;
case GTK_CSS_FILTER_NONE:
default:
g_assert_not_reached ();
break;
@@ -131,8 +134,10 @@ gtk_css_filter_init_identity (GtkCssFilter *filter,
case GTK_CSS_FILTER_BLUR:
filter->blur.value = _gtk_css_number_value_new (0, GTK_CSS_PX);
break;
case GTK_CSS_FILTER_NONE:
case GTK_CSS_FILTER_DROP_SHADOW:
filter->drop_shadow.value = gtk_css_shadow_value_new_filter ();
break;
case GTK_CSS_FILTER_NONE:
default:
g_assert_not_reached ();
break;
@@ -347,8 +352,11 @@ gtk_css_filter_compute (GtkCssFilter *dest,
dest->blur.value = _gtk_css_value_compute (src->blur.value, property_id, provider, style, parent_style);
return dest->blur.value == src->blur.value;
case GTK_CSS_FILTER_NONE:
case GTK_CSS_FILTER_DROP_SHADOW:
dest->drop_shadow.value = _gtk_css_value_compute (src->drop_shadow.value, property_id, provider, style, parent_style);
return dest->drop_shadow.value == src->drop_shadow.value;
case GTK_CSS_FILTER_NONE:
default:
g_assert_not_reached ();
return FALSE;
@@ -428,8 +436,10 @@ gtk_css_filter_equal (const GtkCssFilter *filter1,
case GTK_CSS_FILTER_BLUR:
return _gtk_css_value_equal (filter1->blur.value, filter2->blur.value);
case GTK_CSS_FILTER_NONE:
case GTK_CSS_FILTER_DROP_SHADOW:
return _gtk_css_value_equal (filter1->drop_shadow.value, filter2->drop_shadow.value);
case GTK_CSS_FILTER_NONE:
default:
g_assert_not_reached ();
return FALSE;
@@ -517,8 +527,11 @@ gtk_css_filter_transition (GtkCssFilter *result,
result->blur.value = _gtk_css_value_transition (start->blur.value, end->blur.value, property_id, progress);
break;
case GTK_CSS_FILTER_NONE:
case GTK_CSS_FILTER_DROP_SHADOW:
result->drop_shadow.value = _gtk_css_value_transition (start->drop_shadow.value, end->drop_shadow.value, property_id, progress);
break;
case GTK_CSS_FILTER_NONE:
default:
g_assert_not_reached ();
break;
@@ -663,8 +676,13 @@ gtk_css_filter_print (const GtkCssFilter *filter,
g_string_append (string, ")");
break;
case GTK_CSS_FILTER_NONE:
case GTK_CSS_FILTER_DROP_SHADOW:
g_string_append (string, "drop-shadow(");
_gtk_css_value_print (filter->drop_shadow.value, string);
g_string_append (string, ")");
break;
case GTK_CSS_FILTER_NONE:
default:
g_assert_not_reached ();
break;
@@ -709,12 +727,12 @@ static GtkCssValue *
gtk_css_filter_value_alloc (guint n_filters)
{
GtkCssValue *result;
g_return_val_if_fail (n_filters > 0, NULL);
result = _gtk_css_value_alloc (&GTK_CSS_VALUE_FILTER, sizeof (GtkCssValue) + sizeof (GtkCssFilter) * (n_filters - 1));
result->n_filters = n_filters;
return result;
}
@@ -737,7 +755,7 @@ gtk_css_filter_parse_number (GtkCssParser *parser,
{
GtkCssValue **values = data;
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
if (values[n] == NULL)
return 0;
@@ -751,7 +769,7 @@ gtk_css_filter_parse_length (GtkCssParser *parser,
{
GtkCssValue **values = data;
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_POSITIVE_ONLY);
if (values[n] == NULL)
return 0;
@@ -772,6 +790,20 @@ gtk_css_filter_parse_angle (GtkCssParser *parser,
return 1;
}
static guint
gtk_css_filter_parse_shadow (GtkCssParser *parser,
guint n,
gpointer data)
{
GtkCssValue **values = data;
values[n] = gtk_css_shadow_value_parse_filter (parser);
if (values[n] == NULL)
return 0;
return 1;
}
GtkCssValue *
gtk_css_filter_value_parse (GtkCssParser *parser)
{
@@ -861,6 +893,14 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
filter.type = GTK_CSS_FILTER_SEPIA;
computed = computed && gtk_css_value_is_computed (filter.sepia.value);
}
else if (gtk_css_parser_has_function (parser, "drop-shadow"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_shadow, &filter.drop_shadow.value))
goto fail;
filter.type = GTK_CSS_FILTER_DROP_SHADOW;
computed = computed && gtk_css_value_is_computed (filter.drop_shadow.value);
}
else
{
break;
@@ -899,7 +939,6 @@ gtk_css_filter_value_push_snapshot (const GtkCssValue *filter,
graphene_matrix_t matrix;
graphene_vec4_t offset;
int i, j;
double radius;
if (gtk_css_filter_value_is_none (filter))
return;
@@ -909,16 +948,18 @@ gtk_css_filter_value_push_snapshot (const GtkCssValue *filter,
{
j = gtk_css_filter_value_compute_matrix (filter, i, &matrix, &offset);
if (i < j)
gtk_snapshot_push_color_matrix (snapshot,
&matrix,
&offset);
gtk_snapshot_push_color_matrix (snapshot, &matrix, &offset);
if (j < filter->n_filters)
{
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR)
{
radius = _gtk_css_number_value_get (filter->filters[j].blur.value, 100.0);
gtk_snapshot_push_blur (snapshot, radius);
double std_dev = _gtk_css_number_value_get (filter->filters[j].blur.value, 100.0);
gtk_snapshot_push_blur (snapshot, 2 * std_dev);
}
else if (filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW)
{
gtk_css_shadow_value_push_snapshot (filter->filters[j].drop_shadow.value, snapshot);
}
else
g_warning ("Don't know how to handle filter type %d", filter->filters[j].type);
@@ -942,15 +983,18 @@ gtk_css_filter_value_pop_snapshot (const GtkCssValue *filter,
{
for (j = i; j < filter->n_filters; j++)
{
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR)
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR ||
filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW)
break;
}
if (i < j)
gtk_snapshot_pop (snapshot);
if (j < filter->n_filters)
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR)
gtk_snapshot_pop (snapshot);
else if (filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW)
gtk_css_shadow_value_pop_snapshot (filter->filters[j].drop_shadow.value, snapshot);
i = j + 1;
}
+2
View File
@@ -35,6 +35,7 @@
#include "gtk/gtkcssimageurlprivate.h"
#include "gtk/gtkcssimagescaledprivate.h"
#include "gtk/gtkcssimagerecolorprivate.h"
#include "gtk/gtkcssimagefilterprivate.h"
G_DEFINE_ABSTRACT_TYPE (GtkCssImage, _gtk_css_image, G_TYPE_OBJECT)
@@ -524,6 +525,7 @@ gtk_css_image_get_parser_type (GtkCssParser *parser)
{ "repeating-radial-gradient", _gtk_css_image_radial_get_type },
{ "conic-gradient", gtk_css_image_conic_get_type },
{ "cross-fade", gtk_css_image_cross_fade_get_type },
{ "filter", gtk_css_image_filter_get_type },
{ "image", _gtk_css_image_fallback_get_type }
};
guint i;
+17 -3
View File
@@ -25,6 +25,9 @@
#include "gtkcssimagecrossfadeprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssimagefallbackprivate.h"
#include "gtkcsscolorvalueprivate.h"
typedef struct _CrossFadeEntry CrossFadeEntry;
@@ -308,8 +311,19 @@ parse_image (GtkCssParser *parser,
{
GtkCssImage **image = option_data;
*image = _gtk_css_image_new_parse (parser);
if (*image == NULL)
if (_gtk_css_image_can_parse (parser))
*image = _gtk_css_image_new_parse (parser);
else if (gtk_css_color_value_can_parse (parser))
{
GtkCssValue *color;
color = _gtk_css_color_value_parse (parser);
if (color == NULL)
return FALSE;
*image = _gtk_css_image_fallback_new_for_color (color);
}
else
return FALSE;
return TRUE;
@@ -325,7 +339,7 @@ gtk_css_image_cross_fade_parse_arg (GtkCssParser *parser,
GtkCssImage *image = NULL;
GtkCssParseOption options[] =
{
{ (void *) gtk_css_number_value_can_parse, parse_progress, &progress },
{ (void *)gtk_css_number_value_can_parse, parse_progress, &progress },
{ NULL, parse_image, &image },
};
+16 -5
View File
@@ -148,11 +148,11 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
GtkCssValue *computed_color = NULL;
if (fallback->color)
computed_color= _gtk_css_value_compute (fallback->color,
property_id,
provider,
style,
parent_style);
computed_color = _gtk_css_value_compute (fallback->color,
property_id,
provider,
style,
parent_style);
/* image($color) that didn't change */
if (computed_color && !fallback->images &&
@@ -331,3 +331,14 @@ _gtk_css_image_fallback_init (GtkCssImageFallback *image_fallback)
{
image_fallback->used = -1;
}
GtkCssImage *
_gtk_css_image_fallback_new_for_color (GtkCssValue *color)
{
GtkCssImageFallback *image;
image = g_object_new (GTK_TYPE_CSS_IMAGE_FALLBACK, NULL);
image->color = gtk_css_value_ref (color);
return (GtkCssImage *)image;
}
+3 -1
View File
@@ -52,7 +52,9 @@ struct _GtkCssImageFallbackClass
GtkCssImageClass parent_class;
};
GType _gtk_css_image_fallback_get_type (void) G_GNUC_CONST;
GType _gtk_css_image_fallback_get_type (void) G_GNUC_CONST;
GtkCssImage *_gtk_css_image_fallback_new_for_color (GtkCssValue *color);
G_END_DECLS
+216
View File
@@ -0,0 +1,216 @@
/*
* Copyright © 2021 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <math.h>
#include <string.h>
#include "gtkcssimagefilterprivate.h"
#include "gtkcssfiltervalueprivate.h"
G_DEFINE_TYPE (GtkCssImageFilter, gtk_css_image_filter, GTK_TYPE_CSS_IMAGE)
static int
gtk_css_image_filter_get_width (GtkCssImage *image)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
return _gtk_css_image_get_width (self->image);
}
static int
gtk_css_image_filter_get_height (GtkCssImage *image)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
return _gtk_css_image_get_height (self->image);
}
static gboolean
gtk_css_image_filter_equal (GtkCssImage *image1,
GtkCssImage *image2)
{
GtkCssImageFilter *filter1 = GTK_CSS_IMAGE_FILTER (image1);
GtkCssImageFilter *filter2 = GTK_CSS_IMAGE_FILTER (image2);
return _gtk_css_image_equal (filter1->image, filter2->image) &&
_gtk_css_value_equal (filter1->filter, filter2->filter);
}
static gboolean
gtk_css_image_filter_is_dynamic (GtkCssImage *image)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
return gtk_css_image_is_dynamic (self->image);
}
static GtkCssImage *
gtk_css_image_filter_get_dynamic_image (GtkCssImage *image,
gint64 monotonic_time)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
return gtk_css_image_filter_new (gtk_css_image_get_dynamic_image (self->image, monotonic_time),
self->filter);
}
static void
gtk_css_image_filter_snapshot (GtkCssImage *image,
GtkSnapshot *snapshot,
double width,
double height)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
gtk_css_filter_value_push_snapshot (self->filter, snapshot);
gtk_css_image_snapshot (self->image, snapshot, width, height);
gtk_css_filter_value_pop_snapshot (self->filter, snapshot);
}
static guint
gtk_css_image_filter_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkCssImageFilter *self = data;
switch (arg)
{
case 0:
self->image = _gtk_css_image_new_parse (parser);
if (self->image == NULL)
return 0;
return 1;
case 1:
self->filter = gtk_css_filter_value_parse (parser);
if (self->filter == NULL)
return 0;
return 1;
default:
g_assert_not_reached ();
return 0;
}
}
static gboolean
gtk_css_image_filter_parse (GtkCssImage *image,
GtkCssParser *parser)
{
if (!gtk_css_parser_has_function (parser, "filter"))
{
gtk_css_parser_error_syntax (parser, "Expected 'filter('");
return FALSE;
}
return gtk_css_parser_consume_function (parser, 2, 2, gtk_css_image_filter_parse_arg, image);
}
static void
gtk_css_image_filter_print (GtkCssImage *image,
GString *string)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
g_string_append (string, "filter(");
_gtk_css_image_print (self->image, string);
g_string_append (string, ",");
_gtk_css_value_print (self->filter, string);
g_string_append (string, ")");
}
static GtkCssImage *
gtk_css_image_filter_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
return gtk_css_image_filter_new (_gtk_css_image_compute (self->image, property_id, provider, style, parent_style),
_gtk_css_value_compute (self->filter, property_id, provider, style, parent_style));
}
static void
gtk_css_image_filter_dispose (GObject *object)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (object);
g_clear_object (&self->image);
g_clear_pointer (&self->filter, _gtk_css_value_unref);
G_OBJECT_CLASS (gtk_css_image_filter_parent_class)->dispose (object);
}
static gboolean
gtk_css_image_filter_is_computed (GtkCssImage *image)
{
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
return gtk_css_image_is_computed (self->image) &&
gtk_css_value_is_computed (self->filter);
}
static void
gtk_css_image_filter_class_init (GtkCssImageFilterClass *klass)
{
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
image_class->get_width = gtk_css_image_filter_get_width;
image_class->get_height = gtk_css_image_filter_get_height;
image_class->compute = gtk_css_image_filter_compute;
image_class->equal = gtk_css_image_filter_equal;
image_class->snapshot = gtk_css_image_filter_snapshot;
image_class->is_dynamic = gtk_css_image_filter_is_dynamic;
image_class->get_dynamic_image = gtk_css_image_filter_get_dynamic_image;
image_class->parse = gtk_css_image_filter_parse;
image_class->print = gtk_css_image_filter_print;
image_class->is_computed = gtk_css_image_filter_is_computed;
object_class->dispose = gtk_css_image_filter_dispose;
}
static void
gtk_css_image_filter_init (GtkCssImageFilter *self)
{
}
GtkCssImage *
gtk_css_image_filter_new (GtkCssImage *image,
GtkCssValue *filter)
{
GtkCssImageFilter *self;
g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL);
self = g_object_new (GTK_TYPE_CSS_IMAGE_FILTER, NULL);
self->image = g_object_ref (image);
self->filter = gtk_css_value_ref (filter);
return GTK_CSS_IMAGE (self);
}
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright © 2021 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#ifndef __GTK_CSS_IMAGE_FILTER_PRIVATE_H__
#define __GTK_CSS_IMAGE_FILTER_PRIVATE_H__
#include "gtk/gtkcssimageprivate.h"
#include "gtk/gtkcssvalueprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_IMAGE_FILTER (gtk_css_image_filter_get_type ())
#define GTK_CSS_IMAGE_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_FILTER, GtkCssImageFilter))
#define GTK_CSS_IMAGE_FILTER_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_FILTER, GtkCssImageFilterClass))
#define GTK_IS_CSS_IMAGE_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMAGE_FILTER))
#define GTK_IS_CSS_IMAGE_FILTER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_IMAGE_FILTER))
#define GTK_CSS_IMAGE_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_IMAGE_FILTER, GtkCssImageFilterClass))
typedef struct _GtkCssImageFilter GtkCssImageFilter;
typedef struct _GtkCssImageFilterClass GtkCssImageFilterClass;
struct _GtkCssImageFilter
{
GtkCssImage parent;
GtkCssImage *image;
GtkCssValue *filter;
};
struct _GtkCssImageFilterClass
{
GtkCssImageClass parent_class;
};
GType gtk_css_image_filter_get_type (void) G_GNUC_CONST;
GtkCssImage * gtk_css_image_filter_new (GtkCssImage *image,
GtkCssValue *filter);
G_END_DECLS
#endif /* __GTK_CSS_IMAGE_FILTER_PRIVATE_H__ */
+1 -1
View File
@@ -20,7 +20,7 @@
#include "gtkcssinheritvalueprivate.h"
#include "gtkcssinitialvalueprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkcssstyleprivate.h"
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
-1
View File
@@ -30,7 +30,6 @@
#include "gtkcssshorthandpropertyprivate.h"
#include "gtksettingsprivate.h"
#include "gtkstyleprovider.h"
#include "gtkstylecontextprivate.h"
#include "gtkstylepropertyprivate.h"
#include "gtkstyleproviderprivate.h"
#include "gtkmarshalers.h"
+1 -4
View File
@@ -1073,11 +1073,8 @@ parse_n_plus_b (GtkCssParser *parser,
*a = 0;
return TRUE;
}
gtk_css_parser_error_syntax (parser, "Not a valid an+b type");
return FALSE;
}
static gboolean
parse_a_n_plus_b (GtkCssParser *parser,
int seen_sign,
+91 -32
View File
@@ -25,7 +25,6 @@
#include "gtkcssnumbervalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtksnapshotprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkpango.h"
#include "gsk/gskcairoblurprivate.h"
@@ -45,12 +44,14 @@ typedef struct {
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
guint is_filter : 1; /* values stored in radius are std_dev, for drop-shadow */
guint n_shadows;
ShadowValue shadows[1];
};
static GtkCssValue * gtk_css_shadow_value_new (ShadowValue *shadows,
guint n_shadows);
guint n_shadows,
gboolean is_filter);
static void
shadow_value_for_transition (ShadowValue *result,
@@ -134,7 +135,7 @@ gtk_css_value_shadow_compute (GtkCssValue *value,
shadows[i].inset = shadow->inset;
}
return gtk_css_shadow_value_new (shadows, value->n_shadows);
return gtk_css_shadow_value_new (shadows, value->n_shadows, value->is_filter);
}
static gboolean
@@ -152,11 +153,11 @@ gtk_css_value_shadow_equal (const GtkCssValue *value1,
const ShadowValue *shadow2 = &value2->shadows[i];
if (shadow1->inset != shadow2->inset ||
_gtk_css_value_equal (shadow1->hoffset, shadow2->hoffset) ||
_gtk_css_value_equal (shadow1->voffset, shadow2->voffset) ||
_gtk_css_value_equal (shadow1->radius, shadow2->radius) ||
_gtk_css_value_equal (shadow1->spread, shadow2->spread) ||
_gtk_css_value_equal (shadow1->color, shadow2->color))
!_gtk_css_value_equal (shadow1->hoffset, shadow2->hoffset) ||
!_gtk_css_value_equal (shadow1->voffset, shadow2->voffset) ||
!_gtk_css_value_equal (shadow1->radius, shadow2->radius) ||
!_gtk_css_value_equal (shadow1->spread, shadow2->spread) ||
!_gtk_css_value_equal (shadow1->color, shadow2->color))
return FALSE;
}
@@ -173,9 +174,6 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
guint i, len;
ShadowValue *shadows;
if (start->n_shadows != end->n_shadows)
return NULL;
if (start->n_shadows > end->n_shadows)
len = start->n_shadows;
else
@@ -231,7 +229,7 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
}
}
return gtk_css_shadow_value_new (shadows, len);
return gtk_css_shadow_value_new (shadows, len, start->is_filter);
}
static void
@@ -288,7 +286,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_SHADOW = {
gtk_css_value_shadow_print
};
static GtkCssValue shadow_none_singleton = { &GTK_CSS_VALUE_SHADOW, 1, TRUE, 0 };
static GtkCssValue shadow_none_singleton = { &GTK_CSS_VALUE_SHADOW, 1, TRUE, FALSE, 0 };
GtkCssValue *
gtk_css_shadow_value_new_none (void)
@@ -298,7 +296,8 @@ gtk_css_shadow_value_new_none (void)
static GtkCssValue *
gtk_css_shadow_value_new (ShadowValue *shadows,
guint n_shadows)
guint n_shadows,
gboolean is_filter)
{
GtkCssValue *retval;
guint i;
@@ -308,6 +307,7 @@ gtk_css_shadow_value_new (ShadowValue *shadows,
retval = _gtk_css_value_alloc (&GTK_CSS_VALUE_SHADOW, sizeof (GtkCssValue) + sizeof (ShadowValue) * (n_shadows - 1));
retval->n_shadows = n_shadows;
retval->is_filter = is_filter;
memcpy (retval->shadows, shadows, sizeof (ShadowValue) * n_shadows);
@@ -330,6 +330,21 @@ gtk_css_shadow_value_new (ShadowValue *shadows,
return retval;
}
GtkCssValue *
gtk_css_shadow_value_new_filter (void)
{
ShadowValue value;
value.inset = FALSE;
value.hoffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.voffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.radius = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.spread = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.color = _gtk_css_color_value_new_current_color ();
return gtk_css_shadow_value_new (&value, 1, TRUE);
}
enum {
HOFFSET,
VOFFSET,
@@ -420,9 +435,9 @@ parse_color (GtkCssParser *parser,
}
static gboolean
_gtk_css_shadow_value_parse_one (GtkCssParser *parser,
gboolean box_shadow_mode,
ShadowValue *result)
gtk_css_shadow_value_parse_one (GtkCssParser *parser,
gboolean box_shadow_mode,
ShadowValue *result)
{
GtkCssValue *values[N_VALUES] = { NULL, };
GtkCssValue *color = NULL;
@@ -468,8 +483,8 @@ fail:
#define MAX_SHADOWS 64
GtkCssValue *
_gtk_css_shadow_value_parse (GtkCssParser *parser,
gboolean box_shadow_mode)
gtk_css_shadow_value_parse (GtkCssParser *parser,
gboolean box_shadow_mode)
{
ShadowValue shadows[MAX_SHADOWS];
int n_shadows = 0;
@@ -479,7 +494,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser,
return gtk_css_shadow_value_new_none ();
do {
if (_gtk_css_shadow_value_parse_one (parser, box_shadow_mode, &shadows[n_shadows]))
if (gtk_css_shadow_value_parse_one (parser, box_shadow_mode, &shadows[n_shadows]))
n_shadows++;
if (n_shadows > MAX_SHADOWS)
@@ -489,7 +504,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser,
}
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
return gtk_css_shadow_value_new (shadows, n_shadows);
return gtk_css_shadow_value_new (shadows, n_shadows, FALSE);
fail:
for (i = 0; i < n_shadows; i++)
@@ -501,6 +516,17 @@ fail:
return NULL;
}
GtkCssValue *
gtk_css_shadow_value_parse_filter (GtkCssParser *parser)
{
ShadowValue shadow;
if (gtk_css_shadow_value_parse_one (parser, FALSE, &shadow))
return gtk_css_shadow_value_new (&shadow, 1, TRUE);
else
return NULL;
}
void
gtk_css_shadow_value_get_extents (const GtkCssValue *value,
GtkBorder *border)
@@ -516,6 +542,8 @@ gtk_css_shadow_value_get_extents (const GtkCssValue *value,
spread = _gtk_css_number_value_get (shadow->spread, 0);
radius = _gtk_css_number_value_get (shadow->radius, 0);
if (value->is_filter)
radius = radius * 2;
clip_radius = gsk_cairo_blur_compute_pixels (radius);
hoffset = _gtk_css_number_value_get (shadow->hoffset, 0);
voffset = _gtk_css_number_value_get (shadow->voffset, 0);
@@ -533,6 +561,8 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *value,
const GskRoundedRect *border_box)
{
guint i;
double dx, dy, spread, radius;
const GdkRGBA *color;
g_return_if_fail (value->class == &GTK_CSS_VALUE_SHADOW);
@@ -543,17 +573,20 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *value,
if (shadow->inset)
continue;
color = gtk_css_color_value_get_rgba (shadow->color);
/* We don't need to draw invisible shadows */
if (gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color)))
if (gdk_rgba_is_clear (color))
continue;
gtk_snapshot_append_outset_shadow (snapshot,
border_box,
gtk_css_color_value_get_rgba (shadow->color),
_gtk_css_number_value_get (shadow->hoffset, 0),
_gtk_css_number_value_get (shadow->voffset, 0),
_gtk_css_number_value_get (shadow->spread, 0),
_gtk_css_number_value_get (shadow->radius, 0));
dx = _gtk_css_number_value_get (shadow->hoffset, 0);
dy = _gtk_css_number_value_get (shadow->voffset, 0);
spread = _gtk_css_number_value_get (shadow->spread, 0);
radius = _gtk_css_number_value_get (shadow->radius, 0);
if (value->is_filter)
radius = 2 * radius;
gtk_snapshot_append_outset_shadow (snapshot, border_box, color, dx, dy, spread, radius);
}
}
@@ -575,15 +608,18 @@ gtk_css_shadow_value_snapshot_inset (const GtkCssValue *value,
if (!shadow->inset)
continue;
color = gtk_css_color_value_get_rgba (shadow->color);
/* We don't need to draw invisible shadows */
if (gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color)))
if (gdk_rgba_is_clear (color))
continue;
dx = _gtk_css_number_value_get (shadow->hoffset, 0);
dy = _gtk_css_number_value_get (shadow->voffset, 0);
spread = _gtk_css_number_value_get (shadow->spread, 0);
radius = _gtk_css_number_value_get (shadow->radius, 0);
color = gtk_css_color_value_get_rgba (shadow->color);
if (value->is_filter)
radius = 2 * radius;
/* These are trivial to do with a color node */
if (spread == 0 && radius == 0 &&
@@ -679,7 +715,6 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
gboolean need_shadow = FALSE;
guint i;
/* TODO: We can save this as a flag once and then reuse it */
for (i = 0; i < value->n_shadows; i++)
{
const ShadowValue *shadow = &value->shadows[i];
@@ -703,6 +738,8 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
shadows[i].dy = _gtk_css_number_value_get (shadow->voffset, 0);
shadows[i].color = *gtk_css_color_value_get_rgba (shadow->color);
shadows[i].radius = _gtk_css_number_value_get (shadow->radius, 0);
if (value->is_filter)
shadows[i].radius *= 2;
}
gtk_snapshot_push_shadow (snapshot, shadows, value->n_shadows);
@@ -710,3 +747,25 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
return need_shadow;
}
void
gtk_css_shadow_value_pop_snapshot (const GtkCssValue *value,
GtkSnapshot *snapshot)
{
gboolean need_shadow = FALSE;
guint i;
for (i = 0; i < value->n_shadows; i++)
{
const ShadowValue *shadow = &value->shadows[i];
if (!gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color)))
{
need_shadow = TRUE;
break;
}
}
if (need_shadow)
gtk_snapshot_pop (snapshot);
}
+6 -2
View File
@@ -34,10 +34,12 @@
G_BEGIN_DECLS
GtkCssValue * gtk_css_shadow_value_new_none (void);
GtkCssValue * gtk_css_shadow_value_new_none (void);
GtkCssValue * gtk_css_shadow_value_new_filter (void);
GtkCssValue * _gtk_css_shadow_value_parse (GtkCssParser *parser,
GtkCssValue * gtk_css_shadow_value_parse (GtkCssParser *parser,
gboolean box_shadow_mode);
GtkCssValue * gtk_css_shadow_value_parse_filter (GtkCssParser *parser);
void gtk_css_shadow_value_get_extents (const GtkCssValue *shadow,
GtkBorder *border);
@@ -53,6 +55,8 @@ gboolean gtk_css_shadow_value_is_none (const GtkCssValue
gboolean gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
GtkSnapshot *snapshot);
void gtk_css_shadow_value_pop_snapshot (const GtkCssValue *value,
GtkSnapshot *snapshot);
G_END_DECLS
+25 -5
View File
@@ -865,16 +865,26 @@ parse_text_decoration (GtkCssShorthandProperty *shorthand,
GtkCssValue **values,
GtkCssParser *parser)
{
GtkTextDecorationLine line = 0;
do
{
if (values[0] == NULL &&
(values[0] = _gtk_css_text_decoration_line_value_try_parse (parser)))
GtkTextDecorationLine parsed_line;
parsed_line = _gtk_css_text_decoration_line_try_parse_one (parser, line);
if (parsed_line == 0 && line != 0)
{
if (values[0] == NULL)
return FALSE;
gtk_css_parser_error_value (parser, "Invalid combination of text-decoration-line values");
return FALSE;
}
if (parsed_line != line)
{
line = parsed_line;
}
else if (values[1] == NULL &&
(values[1] = _gtk_css_text_decoration_style_value_try_parse (parser)))
(values[1] = _gtk_css_text_decoration_style_value_try_parse (parser)))
{
if (values[1] == NULL)
return FALSE;
@@ -895,6 +905,16 @@ parse_text_decoration (GtkCssShorthandProperty *shorthand,
}
while (!value_is_done_parsing (parser));
if (line != 0)
{
values[0] = _gtk_css_text_decoration_line_value_new (line);
if (values[0] == NULL)
{
gtk_css_parser_error_value (parser, "Invalid combination of text-decoration-line values");
return FALSE;
}
}
return TRUE;
}
+5
View File
@@ -163,6 +163,7 @@ static const int other_props[] = {
GTK_CSS_PROPERTY_ICON_TRANSFORM,
GTK_CSS_PROPERTY_ICON_FILTER,
GTK_CSS_PROPERTY_TRANSFORM,
GTK_CSS_PROPERTY_TRANSFORM_ORIGIN,
GTK_CSS_PROPERTY_OPACITY,
GTK_CSS_PROPERTY_FILTER,
};
@@ -593,6 +594,9 @@ gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle,
case GTK_CSS_PROPERTY_TRANSFORM:
gtk_css_take_value (&style->other->transform, value);
break;
case GTK_CSS_PROPERTY_TRANSFORM_ORIGIN:
gtk_css_take_value (&style->other->transform_origin, value);
break;
case GTK_CSS_PROPERTY_MIN_WIDTH:
gtk_css_take_value (&style->size->min_width, value);
break;
@@ -880,6 +884,7 @@ gtk_css_other_create_initial_values (void)
values->icon_transform = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ICON_TRANSFORM, NULL, NULL, NULL);
values->icon_filter = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ICON_FILTER, NULL, NULL, NULL);
values->transform = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSFORM, NULL, NULL, NULL);
values->transform_origin = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSFORM_ORIGIN, NULL, NULL, NULL);
values->opacity = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_OPACITY, NULL, NULL, NULL);
values->filter = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_FILTER, NULL, NULL, NULL);
+20 -8
View File
@@ -235,6 +235,8 @@ gtk_css_style_get_value (GtkCssStyle *style,
return style->size->border_spacing;
case GTK_CSS_PROPERTY_TRANSFORM:
return style->other->transform;
case GTK_CSS_PROPERTY_TRANSFORM_ORIGIN:
return style->other->transform_origin;
case GTK_CSS_PROPERTY_MIN_WIDTH:
return style->size->min_width;
case GTK_CSS_PROPERTY_MIN_HEIGHT:
@@ -395,6 +397,12 @@ get_pango_underline_from_style (GtkTextDecorationStyle style)
g_return_val_if_reached (PANGO_UNDERLINE_SINGLE);
}
static PangoOverline
get_pango_overline_from_style (GtkTextDecorationStyle style)
{
return PANGO_OVERLINE_SINGLE;
}
static PangoAttrList *
add_pango_attr (PangoAttrList *attrs,
PangoAttribute *attr)
@@ -443,25 +451,29 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
? style->font_variant->text_decoration_color
: style->core->color);
switch (decoration_line)
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE)
{
case GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE:
attrs = add_pango_attr (attrs, pango_attr_underline_new (get_pango_underline_from_style (decoration_style)));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_underline_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
break;
case GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH:
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_OVERLINE)
{
attrs = add_pango_attr (attrs, pango_attr_overline_new (get_pango_overline_from_style (decoration_style)));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_overline_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH)
{
attrs = add_pango_attr (attrs, pango_attr_strikethrough_new (TRUE));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_strikethrough_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
break;
case GTK_CSS_TEXT_DECORATION_LINE_NONE:
default:
break;
}
/* letter-spacing */
+1
View File
@@ -208,6 +208,7 @@ struct _GtkCssOtherValues {
GtkCssValue *icon_transform;
GtkCssValue *icon_filter;
GtkCssValue *transform;
GtkCssValue *transform_origin;
GtkCssValue *opacity;
GtkCssValue *filter;
};
+42 -13
View File
@@ -317,14 +317,38 @@ parse_letter_spacing (GtkCssStyleProperty *property,
return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
}
static gboolean
value_is_done_parsing (GtkCssParser *parser)
{
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
}
static GtkCssValue *
parse_text_decoration_line (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = _gtk_css_text_decoration_line_value_try_parse (parser);
GtkCssValue *value = NULL;
GtkTextDecorationLine line;
line = 0;
do {
GtkTextDecorationLine parsed;
parsed = _gtk_css_text_decoration_line_try_parse_one (parser, line);
if (parsed == 0 || parsed == line)
{
gtk_css_parser_error_syntax (parser, "Not a valid value");
return NULL;
}
line = parsed;
} while (!value_is_done_parsing (parser));
value = _gtk_css_text_decoration_line_value_new (line);
if (value == NULL)
gtk_css_parser_error_syntax (parser, "unknown text decoration line value");
gtk_css_parser_error_syntax (parser, "Invalid combination of values");
return value;
}
@@ -353,15 +377,6 @@ parse_font_kerning (GtkCssStyleProperty *property,
return value;
}
static gboolean
value_is_done_parsing (GtkCssParser *parser)
{
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
}
static GtkCssValue *
parse_font_variant_ligatures (GtkCssStyleProperty *property,
GtkCssParser *parser)
@@ -497,14 +512,14 @@ static GtkCssValue *
box_shadow_value_parse (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
return _gtk_css_shadow_value_parse (parser, TRUE);
return gtk_css_shadow_value_parse (parser, TRUE);
}
static GtkCssValue *
shadow_value_parse (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
return _gtk_css_shadow_value_parse (parser, FALSE);
return gtk_css_shadow_value_parse (parser, FALSE);
}
static GtkCssValue *
@@ -790,6 +805,13 @@ background_position_parse (GtkCssStyleProperty *property,
return _gtk_css_array_value_parse (parser, _gtk_css_position_value_parse);
}
static GtkCssValue *
transform_origin_parse (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
return _gtk_css_position_value_parse (parser);
}
/*** REGISTRATION ***/
G_STATIC_ASSERT (GTK_CSS_PROPERTY_COLOR == 0);
@@ -1248,6 +1270,13 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TRANSFORM,
transform_value_parse,
_gtk_css_transform_value_new_none ());
gtk_css_style_property_register ("transform-origin",
GTK_CSS_PROPERTY_TRANSFORM_ORIGIN,
GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_TRANSFORM,
transform_origin_parse,
_gtk_css_position_value_new (_gtk_css_number_value_new (50, GTK_CSS_PERCENT),
_gtk_css_number_value_new (50, GTK_CSS_PERCENT)));
gtk_css_style_property_register ("min-width",
GTK_CSS_PROPERTY_MIN_WIDTH,
GTK_STYLE_PROPERTY_ANIMATED,
+5 -3
View File
@@ -254,6 +254,7 @@ enum { /*< skip >*/
GTK_CSS_PROPERTY_ICON_FILTER,
GTK_CSS_PROPERTY_BORDER_SPACING,
GTK_CSS_PROPERTY_TRANSFORM,
GTK_CSS_PROPERTY_TRANSFORM_ORIGIN,
GTK_CSS_PROPERTY_MIN_WIDTH,
GTK_CSS_PROPERTY_MIN_HEIGHT,
GTK_CSS_PROPERTY_TRANSITION_PROPERTY,
@@ -324,9 +325,10 @@ typedef enum /*< skip >*/ {
} GtkCssFontSize;
typedef enum /*< skip >*/ {
GTK_CSS_TEXT_DECORATION_LINE_NONE,
GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE,
GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH
GTK_CSS_TEXT_DECORATION_LINE_NONE = 1 << 0,
GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE = 1 << 1,
GTK_CSS_TEXT_DECORATION_LINE_OVERLINE = 1 << 2,
GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH = 1 << 3
} GtkTextDecorationLine;
typedef enum /*< skip >*/ {
+2 -2
View File
@@ -260,8 +260,8 @@ _gtk_css_value_transition (GtkCssValue *start,
guint property_id,
double progress)
{
gtk_internal_return_val_if_fail (start != NULL, FALSE);
gtk_internal_return_val_if_fail (end != NULL, FALSE);
gtk_internal_return_val_if_fail (start != NULL, NULL);
gtk_internal_return_val_if_fail (end != NULL, NULL);
if (start->class != end->class)
return NULL;
+25 -25
View File
@@ -48,20 +48,32 @@
* SECTION:gtkdialog
* @Short_description: Create popup windows
* @Title: GtkDialog
* @See_also: #GtkBox, #GtkWindow, #GtkButton
* @See_also: #GtkWindow, #GtkMessageDialog
*
* Dialog boxes are a convenient way to prompt the user for a small amount
* Dialogs are a convenient way to prompt the user for a small amount
* of input, e.g. to display a message, ask a question, or anything else
* that does not require extensive effort on the users part.
*
* GTK treats a dialog as a window split vertically. The top section is a
* #GtkBox, and is where widgets such as a #GtkLabel or a #GtkEntry should
* be packed. The bottom area is known as the
* action area. This is generally used for
* packing buttons into the dialog which may perform functions such as
* cancel, ok, or apply.
* The main area of a GtkDialog is called the "content area", and is yours
* to populate with widgets such a #GtkLabel or #GtkEntry, to present
* your information, questions, or tasks to the user. In addition, dialogs
* allow you to add "action widgets". Most commonly, action widgets are
* buttons. Depending on the platform, action widgets may be presented
* in the header bar at the top of the window, or at the bottom of the window.
* To add action widgets, use GtkDialog using gtk_dialog_new_with_buttons(),
* gtk_dialog_add_button(), gtk_dialog_add_buttons(), or
* gtk_dialog_add_action_widget().
*
* #GtkDialog boxes are created with a call to gtk_dialog_new() or
* Clicking a button that was added as an action widget will emit the
* #GtkDialog::response signal with a response ID that you specified.
* GTK will never assign a meaning to positive response IDs; these are
* entirely user-defined. But for convenience, you can use the response
* IDs in the #GtkResponseType enumeration (these all have values less
* than zero). If a dialog receives a delete event, the
* #GtkDialog::response signal will be emitted with the
* #GTK_RESPONSE_DELETE_EVENT response ID.
*
* Dialogs are created with a call to gtk_dialog_new() or
* gtk_dialog_new_with_buttons(). gtk_dialog_new_with_buttons() is
* recommended; it allows you to set the dialog title, some convenient
* flags, and add simple buttons.
@@ -72,20 +84,9 @@
* gtk_dialog_new() into a #GtkWindow. When using gtk_dialog_new_with_buttons()
* you can also pass the #GTK_DIALOG_MODAL flag to make a dialog modal.
*
* If you add buttons to #GtkDialog using gtk_dialog_new_with_buttons(),
* gtk_dialog_add_button(), gtk_dialog_add_buttons(), or
* gtk_dialog_add_action_widget(), clicking the button will emit a signal
* called #GtkDialog::response with a response ID that you specified. GTK
* will never assign a meaning to positive response IDs; these are entirely
* user-defined. But for convenience, you can use the response IDs in the
* #GtkResponseType enumeration (these all have values less than zero). If
* a dialog receives a delete event, the #GtkDialog::response signal will
* be emitted with a response ID of #GTK_RESPONSE_DELETE_EVENT.
*
* For the simple dialog in the following example, in reality youd probably
* use #GtkMessageDialog to save yourself some effort. But youd need to
* create the dialog contents manually if you had more than a simple message
* in the dialog.
* For the simple dialog in the following example, a #GtkMessageDialog would
* save some effort. But youd need to create the dialog contents manually if
* you had more than a simple message in the dialog.
*
* An example for simple GtkDialog usage:
* |[<!-- language="C" -->
@@ -124,8 +125,7 @@
* # GtkDialog as GtkBuildable
*
* The GtkDialog implementation of the #GtkBuildable interface exposes the
* @content_area and @action_area as internal children with the names
* content_area and action_area.
* @content_area as an internal child with the name content_area.
*
* GtkDialog supports a custom <action-widgets> element, which can contain
* multiple <action-widget> elements. The response attribute specifies a
+19 -2
View File
@@ -24,7 +24,7 @@
#include "config.h"
#include "gtkdragsource.h"
#include "gtkdragsourceprivate.h"
#include "gtkgesturedrag.h"
#include "gtkgesturesingleprivate.h"
@@ -292,7 +292,7 @@ gtk_drag_source_update (GtkGesture *gesture,
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
if (gtk_drag_check_threshold (widget, source->start_x, source->start_y, x, y))
if (gtk_drag_check_threshold_double (widget, source->start_x, source->start_y, x, y))
{
gtk_drag_source_drag_begin (source);
}
@@ -796,3 +796,20 @@ gtk_drag_check_threshold (GtkWidget *widget,
return (ABS (current_x - start_x) > drag_threshold ||
ABS (current_y - start_y) > drag_threshold);
}
gboolean
gtk_drag_check_threshold_double (GtkWidget *widget,
double start_x,
double start_y,
double current_x,
double current_y)
{
int drag_threshold;
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
drag_threshold = gtk_settings_get_dnd_drag_threshold (gtk_widget_get_settings (widget));
return (ABS (current_x - start_x) > drag_threshold ||
ABS (current_y - start_y) > drag_threshold);
}
+33
View File
@@ -0,0 +1,33 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2020 Alexander Mikhaylenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_DRAG_SOURCE_PRIVATE_H__
#define __GTK_DRAG_SOURCE_PRIVATE_H__
#include "gtkdragsource.h"
G_BEGIN_DECLS
gboolean gtk_drag_check_threshold_double (GtkWidget *widget,
double start_x,
double start_y,
double current_x,
double current_y);
G_END_DECLS
#endif /* __GTK_DRAG_SOURCE_PRIVATE_H__ */
+22 -3
View File
@@ -1081,16 +1081,35 @@ keynav_failed (GtkWidget *box,
GtkEmojiChooser *chooser)
{
EmojiSection *next;
GtkWidget *focus;
GtkWidget *focus;
GtkWidget *child;
GtkWidget *sibling;
int i;
int column;
int n_columns = 7;
int child_x;
focus = gtk_root_get_focus (gtk_widget_get_root (box));
if (focus == NULL)
return FALSE;
/* determine the number of columns */
child_x = -1;
for (i = 0; i < 20; i++)
{
GtkAllocation alloc;
gtk_widget_get_allocation (GTK_WIDGET (gtk_flow_box_get_child_at_index (GTK_FLOW_BOX (box), i)),
&alloc);
if (alloc.x > child_x)
child_x = alloc.x;
else
{
n_columns = i;
break;
}
}
child = gtk_widget_get_ancestor (focus, GTK_TYPE_EMOJI_CHOOSER_CHILD);
i = 0;
@@ -1099,7 +1118,7 @@ keynav_failed (GtkWidget *box,
sibling = gtk_widget_get_next_sibling (sibling))
i++;
column = i % 7;
column = i % n_columns;
if (direction == GTK_DIR_DOWN)
{
@@ -1131,7 +1150,7 @@ keynav_failed (GtkWidget *box,
sibling;
sibling = gtk_widget_get_next_sibling (sibling), i++)
{
if ((i % 7) == column)
if ((i % n_columns) == column)
child = sibling;
}
if (child)
+7 -8
View File
@@ -54,7 +54,6 @@
#include "gtkprogressbar.h"
#include "gtksettings.h"
#include "gtksnapshot.h"
#include "gtkstylecontextprivate.h"
#include "gtktextprivate.h"
#include "gtktexthandleprivate.h"
#include "gtktextutil.h"
@@ -66,7 +65,7 @@
#include "gtkwindow.h"
#include "gtknative.h"
#include "gtkgestureclick.h"
#include "gtkdragsource.h"
#include "gtkdragsourceprivate.h"
#include "gtkdragicon.h"
#include "gtkwidgetpaintable.h"
@@ -1587,32 +1586,33 @@ icon_released_cb (GtkGestureClick *gesture,
static void
icon_drag_update_cb (GtkGestureDrag *gesture,
double x,
double y,
double offset_x,
double offset_y,
GtkEntry *entry)
{
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
double start_x, start_y;
GtkEntryIconPosition pos;
EntryIconInfo *icon_info;
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
pos = get_icon_position_from_controller (entry, GTK_EVENT_CONTROLLER (gesture));
icon_info = priv->icons[pos];
if (icon_info->content != NULL &&
gtk_drag_check_threshold (icon_info->widget, start_x, start_y, x, y))
gtk_drag_check_threshold_double (icon_info->widget, 0, 0, offset_x, offset_y))
{
GdkPaintable *paintable;
GdkSurface *surface;
GdkDevice *device;
GdkDrag *drag;
double start_x, start_y;
icon_info->in_drag = TRUE;
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (entry)));
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
drag = gdk_drag_begin (surface, device, icon_info->content, icon_info->actions, start_x, start_y);
paintable = gtk_widget_paintable_new (icon_info->widget);
gtk_drag_icon_set_from_paintable (drag, paintable, -2, -2);
@@ -2232,7 +2232,6 @@ gtk_entry_get_overwrite_mode (GtkEntry *entry)
*
* This is equivalent to getting @entry's #GtkEntryBuffer and
* calling gtk_entry_buffer_set_max_length() on it.
* ]|
**/
void
gtk_entry_set_max_length (GtkEntry *entry,
-1
View File
@@ -127,7 +127,6 @@
#include "gtkmarshalers.h"
#include "gtkmain.h"
#include "gtkprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include <string.h>
+5
View File
@@ -60,6 +60,11 @@
* Showing, hiding and running the dialog is handled by the #GtkNativeDialog
* functions.
*
* Note that unlike #GtkFileChooserDialog, #GtkFileChooserNative objects are
* not toplevel widgets, and GTK does not keep them alive. It is your
* responsibility to keep a reference until you are done with the
* object.
* ## Typical usage ## {#gtkfilechoosernative-typical-usage}
*
* In the simplest of cases, you can the following code to use
-1
View File
@@ -66,7 +66,6 @@
#include "gtkshow.h"
#include "gtkmain.h"
#include "gtkscrollable.h"
#include "gtkstylecontextprivate.h"
#include "gtkpopover.h"
#include "gtkrevealer.h"
#include "gtkspinner.h"
-1
View File
@@ -45,7 +45,6 @@
#include "gtkscrolledwindow.h"
#include "gtksearchentry.h"
#include "gtkspinbutton.h"
#include "gtkstylecontextprivate.h"
#include "gtktextview.h"
#include "gtkwidgetprivate.h"
#include "gtksettings.h"
-2
View File
@@ -31,8 +31,6 @@
#include "gtkintl.h"
#include "gtkbuildable.h"
#include "gtkwidgetprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtklabel.h"
/**
+5 -2
View File
@@ -991,6 +991,7 @@ gtk_gesture_set_sequence_state (GtkGesture *gesture,
{
GtkGesturePrivate *priv;
PointData *data;
GtkEventSequenceState current_state;
g_return_val_if_fail (GTK_IS_GESTURE (gesture), FALSE);
g_return_val_if_fail (state >= GTK_EVENT_SEQUENCE_NONE &&
@@ -1014,11 +1015,13 @@ gtk_gesture_set_sequence_state (GtkGesture *gesture,
data->state != GTK_EVENT_SEQUENCE_NONE)
return FALSE;
current_state = data->state;
data->state = state;
if (state == GTK_EVENT_SEQUENCE_DENIED &&
data->state == GTK_EVENT_SEQUENCE_CLAIMED)
current_state == GTK_EVENT_SEQUENCE_CLAIMED)
_gtk_gesture_cancel_sequence (gesture, sequence);
data->state = state;
gtk_widget_cancel_event_sequence (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)),
gesture, sequence, state);
g_signal_emit (gesture, signals[SEQUENCE_STATE_CHANGED], 0,
+2 -2
View File
@@ -37,7 +37,7 @@
#include "gtkgesturelongpressprivate.h"
#include "gtkgestureprivate.h"
#include "gtkmarshalers.h"
#include "gtkdragsource.h"
#include "gtkdragsourceprivate.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
@@ -159,7 +159,7 @@ gtk_gesture_long_press_update (GtkGesture *gesture,
priv = gtk_gesture_long_press_get_instance_private (GTK_GESTURE_LONG_PRESS (gesture));
gtk_gesture_get_point (gesture, sequence, &x, &y);
if (gtk_drag_check_threshold (widget, priv->initial_x, priv->initial_y, x, y))
if (gtk_drag_check_threshold_double (widget, priv->initial_x, priv->initial_y, x, y))
{
if (priv->timeout_id)
{
-56
View File
@@ -1,56 +0,0 @@
/* gtkgladecatalog.c
*
* Copyright (C) 2013 Openismus GmbH
*
* Authors:
* Tristan Van Berkom <tristanvb@openismus.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkpathbar.h"
#include "gtkplacesviewprivate.h"
#include "gtkcolorswatchprivate.h"
#include "gtkcolorplaneprivate.h"
#include "gtkcolorscaleprivate.h"
#include "gtkcoloreditorprivate.h"
#ifdef G_OS_UNIX
# include "gtkprinteroptionwidget.h"
#endif
_GDK_EXTERN
void gtk_glade_catalog_init (const char *catalog_name);
/* This function is referred to in gtk/glade/gtk-private-widgets.xml
* and is used to ensure the private types for use in Glade while
* editing UI files that define GTKs various composite widget classes.
*/
void
gtk_glade_catalog_init (const char *catalog_name)
{
g_type_ensure (GTK_TYPE_PATH_BAR);
g_type_ensure (GTK_TYPE_PLACES_VIEW);
g_type_ensure (GTK_TYPE_COLOR_SWATCH);
g_type_ensure (GTK_TYPE_COLOR_PLANE);
g_type_ensure (GTK_TYPE_COLOR_SCALE);
g_type_ensure (GTK_TYPE_COLOR_EDITOR);
#ifdef G_OS_UNIX
g_type_ensure (GTK_TYPE_PRINTER_OPTION_WIDGET);
#endif
}
+60 -1
View File
@@ -29,7 +29,7 @@
#include "gtkorientable.h"
#include "gtkprivate.h"
#include "gtksizerequest.h"
#include "gtkstylecontextprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkwidgetprivate.h"
@@ -48,6 +48,65 @@
* from the grid, use gtk_grid_remove(). The behaviour of GtkGrid when
* several children occupy the same grid cell is undefined.
*
* # GtkGrid as GtkBuildable
*
* Every child in a GtkGrid has access to a custom #GtkBuildable element, called ´<layout>´.
* It can by used to specify a position in the grid and optionally spans.
* All properties that can be used in the ´<layout>´ element are implemented by #GtkGridLayoutChild.
*
* It is implemented by #GtkWidget using #GtkLayoutManager.
*
* To showcase it, here is a simple example:
*
* |[
* <object class="GtkGrid" id="my_grid">
* <child>
* <object class="GtkButton" id="button1">
* <property name="label">Button 1</property>
* <layout>
* <property name="column">0</property>
* <property name="row">0</property>
* </layout>
* </object>
* </child>
* <child>
* <object class="GtkButton" id="button2">
* <property name="label">Button 2</property>
* <layout>
* <property name="column">1</property>
* <property name="row">0</property>
* </layout>
* </object>
* </child>
* <child>
* <object class="GtkButton" id="button3">
* <property name="label">Button 3</property>
* <layout>
* <property name="column">2</property>
* <property name="row">0</property>
* <property name="row-span">2</property>
* </layout>
* </object>
* </child>
* <child>
* <object class="GtkButton" id="button4">
* <property name="label">Button 4</property>
* <layout>
* <property name="column">0</property>
* <property name="row">1</property>
* <property name="column-span">2</property>
* </layout>
* </object>
* </child>
* </object>
* ]|
*
* It organizes the first two buttons side-by-side in one cell each.
* The third button is in the last column but spans across two rows.
* This is defined by the ´row-span´ property.
* The last button is located in the second row and spans across two columns,
* which is defined by the ´column-span´ property.
*
* # CSS nodes
*
* GtkGrid uses a single CSS node with name `grid`.
+1 -1
View File
@@ -51,8 +51,8 @@
#include "gtkorientable.h"
#include "gtkprivate.h"
#include "gtksizerequest.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
/* {{{ GtkGridLayoutChild */
typedef struct {

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