Compare commits

..

151 Commits

Author SHA1 Message Date
Matthias Clasen 05e8057b5b Fix gtk_column_view_sort_by_column
We must clear the current sort columns before
setting the new one, to prevent double arrows
in the headers.

Fixes: #4696
2022-04-18 20:37:04 -04:00
Matthias Clasen e89365e9e3 gtk-builder-tool: Error out if screenshooting fails
If we don't produce a texture for whatever reason,
apologize and fail.
2022-04-18 11:16:05 -04:00
Timm Bäder 6484807719 Merge branch 'badcel/fix-typo' into 'main'
docs: Fix typo in description of GtkExpression

See merge request GNOME/gtk!4647
2022-04-18 09:27:05 +00:00
Marcel Tiede 527ff05107 docs: Fix typo in description of GtkExpression 2022-04-18 06:20:19 +00:00
Matthias Clasen b89cfdb77f Merge branch 'screenshot-command' into 'main'
gtk-builder-tool: Add a screenshot command

See merge request GNOME/gtk!4645
2022-04-17 17:40:46 +00:00
Matthias Clasen 499687a11d gtk-builder-tool: Add a screenshot command
This is an obvious variation of the preview
command. It can save a .ui file as either
.png or .node.
2022-04-17 12:57:46 -04:00
Matthias Clasen c5e26dd591 gtk-builder-tool: Reshuffle --help
Use GOptionContext better.
2022-04-17 12:57:46 -04:00
Matthias Clasen bc17d1d5ea Merge branch 'wip/exalm/scrolled-window' into 'main'
scrolledwindow: Pick up gtk-overlay-scrolling changes on the fly

See merge request GNOME/gtk!4642
2022-04-17 16:07:59 +00:00
Matthias Clasen b88ac0890e gtk-builder-tool: Small reshuffle
Move the display check into the preview command.
2022-04-17 11:23:00 -04:00
Matthias Clasen d30baf34b3 Merge branch 'filechooser-entry-popup' into 'main'
filechooser: Prevent random completion popups

See merge request GNOME/gtk!4643
2022-04-17 03:51:32 +00:00
Matthias Clasen b927ad2c87 Merge branch 'filechooser-save-sensitive' into 'main'
filechooser: Small fix for save mode

Closes #4851

See merge request GNOME/gtk!4644
2022-04-17 03:31:39 +00:00
Matthias Clasen 4540dac11a filechooser: Prevent random completion popups
It is very irritating when the entry completion popup
appears not in response to user input in the entry.
In particular, when that happens right as the dialog
is shown.

To prevent that, temporarily disable completion
when setting the entry text programmatically.
2022-04-16 23:29:04 -04:00
Matthias Clasen aa9cac695d filechooser: Small fix for save mode
When changing folders, we were making the select
button insensitive when there's no files around.
That doesn't make sense in save mode when we don't
want to select a file but create one.

Fixes: #4851
2022-04-16 22:00:22 -04:00
Alexander Mikhaylenko 52412ca944 scrolledwindow: Pick up gtk-overlay-scrolling changes on the fly 2022-04-16 16:56:17 +04:00
Alexander Mikhaylenko cd82b18cfd scrolledwindow: Fix :kinetic-scrolling setter 2022-04-16 16:30:33 +04:00
Matthias Clasen da5bb6ff22 Merge branch 'wip/exalm/tooltip' into 'main'
tooltipwindow: Don't restrict minimum tooltip label length

Closes #3741

See merge request GNOME/gtk!4640
2022-04-16 00:07:21 +00:00
Alexander Mikhaylenko 7871f1e13b tooltipwindow: Don't restrict minimum tooltip label length
We only care about wrapping at that length, we still want short tooltips
for short labels.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3741
2022-04-16 03:48:21 +04:00
Alexander Mikhaylenko dd18c7dedf tooltipwindow: Remove a duplicate gtk_widget_class_set_css_name() call 2022-04-16 03:28:50 +04:00
Matthias Clasen a34a6e9b84 Merge branch 'ebassi/for-main' into 'main'
docs: Fix the GtkPaned style

See merge request GNOME/gtk!4637
2022-04-15 00:09:42 +00:00
Emmanuele Bassi 0a5f29c9eb Mark nullable arguments in GtkPaned
The set_start_child() and set_end_child() methods take NULL for the
child argument, as a way to remove the child from the paned widget.
2022-04-14 22:44:17 +01:00
Emmanuele Bassi 417be0719b docs: Fix the GtkPaned style
Use proper links to properties and methods, and drop gtk-doc'isms.
2022-04-14 22:43:40 +01:00
Matthias Clasen 3263a26cad Merge branch 'fix_tooltip' into 'main'
label: Maintain value for `has-tooltip` for labels with links

See merge request GNOME/gtk!4635
2022-04-14 18:00:43 +00:00
Matthias Clasen 00916c2b47 Merge branch 'fix_link_tabs' into 'main'
label: Move focus out of widget after last link

Closes #4681

See merge request GNOME/gtk!4636
2022-04-14 11:36:19 +00:00
Julian Sparber e3320633a6 label: Move focus out of widget after last link
This allows the user to navigate via tab the links in a label and exits
the widget after the last link, when moving forward, and first link,
when moving backward.

This also ensures that ellipsised links arn't focused.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4681
2022-04-14 12:48:20 +02:00
Julian Sparber 764a8cea59 label: Maintain value for has-tooltip for labels with links
The `has-tooltip` property gets set to `false` for label with links if no
link is selected. This makes sure to only change the property to `true`
but never to `false`.
2022-04-13 19:05:53 +02:00
Benjamin Otte a2599c2bb9 Merge branch 'clarify-scrollable-docs' into 'main'
scrollable: Clarify when to set adjustment props

See merge request GNOME/gtk!4632
2022-04-12 23:48:55 +00:00
Ivan Molodetskikh e2675306e1 scrollable: Clarify when to set adjustment props
Instead of populating the properties right away (when the widget might
not have been allocated yet, and hence cannot know the right values),
the widget should queue an allocation, where it will populate the
values.
2022-04-12 17:22:51 +03:00
Benjamin Otte 7d1429cb91 Merge branch 'gles-win32' into 'main'
Inspector: Fix running on Windows with GLES (was: fix running GL demos with GLES on Windows)

See merge request GNOME/gtk!4595
2022-04-08 22:00:33 +00:00
Matthias Clasen f13a018739 Merge branch 'matthiasc/for-main' into 'main'
gsk/gl: Typo fix

See merge request GNOME/gtk!4628
2022-04-08 16:14:43 +00:00
Matthias Clasen 84b3b1fab5 gsk/gl: Typo fix 2022-04-08 11:20:12 -04:00
Luca Bacci 048bb6db6f Merge branch 'gdk-win32-fix-mouse-move-crossing-events' into 'main'
GdkWin32: Mouse events fixes

Closes #4722 and #4813

See merge request GNOME/gtk!4620
2022-04-08 08:31:14 +00:00
Matthias Clasen 8c548d5579 Merge branch 'nonoverlapping-containers' into 'main'
gsk/gl: Avoid offscreening in more cases

See merge request GNOME/gtk!4619
2022-04-07 14:32:53 +00:00
Matthias Clasen 09d5ec1b08 Merge branch 'n-docs-fixes' into 'main'
More doc fixes

See merge request GNOME/gtk!4618
2022-04-07 14:05:40 +00:00
Matthias Clasen 28bba484da Merge branch 'matthiasc/for-main' into 'main'
gl: Don't leak big glyphs

See merge request GNOME/gtk!4626
2022-04-07 11:46:11 +00:00
Matthias Clasen 191558cfa4 gtk-demo: Small fixup to the cursors demo 2022-04-07 07:01:29 -04:00
Luca Bacci cb0c1b3f08 GdkWin32: Generate crossing event after button release
Fixes #4813
2022-04-06 20:27:46 +02:00
Luca Bacci 91f200167e GdkWin32: Correct generation of crossing events when holding an implicit grab
Fixes #4722
2022-04-06 20:27:32 +02:00
Luca Bacci 2b6fb005a8 GdkWin32: Report serial for events 2022-04-06 19:45:50 +02:00
Matthias Clasen af6bec7539 Merge branch 'push-history-position-fix' into 'main'
gdk: always populate GDK_AXIS_{X,Y} in merged event history

Closes #4809

See merge request GNOME/gtk!4623
2022-04-06 15:56:26 +00:00
Matthias Clasen 38362c2803 Merge branch 'wip/carlosg/osk-activation' into 'main'
imwayland: Connect OSK activating gesture to parent widget on editables

Closes #4795

See merge request GNOME/gtk!4624
2022-04-06 15:44:43 +00:00
Carlos Garnacho eb7c78aa48 imwayland: Do not defer commit() after set_surrounding_text()
For reasons that only apply to the old serial handling, asking for
the surrounding after IM changes resulted in lazy handling of
commit() afterwards.

With the recent interpretation of serials, this problem became more
apparent, since it is in fact very likely that the last interaction
step after an IM change is notifying of the changed surrounding
text after the IM change was applied.

Make handling of surrounding text similar to caret position changes,
always commit() after the state change, but skip through non-changes.

This makes the compositor state fully up-to-date after an IM change.
2022-04-06 13:52:05 +02:00
Carlos Garnacho 7ab39b5461 imwayland: Connect OSK activating gesture to parent widget on editables
The gesture as connected currently on the child GtkText is easily overridden
by the parent editables (and gently done so in the attempt to consume all
clicks).

Connect this gesture to the parent editable widget in these cases, so the
gesture can cohabit with the click-consuming one. It's not part of the same
group, but it won't be abruptly cancelled.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4795
2022-04-06 13:52:05 +02:00
Hemidark 0c44851848 gdk: always populate GDK_AXIS_{X,Y} in merged event history
Since GdkTimeCoord stores only axis values, prior to this change,
if a device didn't report GDK_AXIS_X or GDK_AXIS_Y, the history
attached to merged motion events wouldn't contain any positional
information.

Commit 6012276093 already addressed
this issue for devices without tools by storing the event position
in GdkTimeCoord using GDK_AXIS_X and GDK_AXIS_Y and augmenting the
GdkTimeCoord's axis bitmask accordingly.

This change generalizes that workaround to all devices. Note that
if a device DOES report values for GDK_AXIS_X and GDK_AXIS_Y, those
values won't be overwritten.

Closes #4809
2022-04-05 15:35:12 -07:00
Matthias Clasen d72ed045df gsk/gl: Use pre-collected opacity information
We now collect this information during node
construction, so use it here.

The concrete change here is that we now avoid
offscreens for container nodes with multiple children,
as long as they don't overlap. In particular, this
avoid offscreens for ellipsized dim labels.
2022-04-05 14:57:38 -04:00
Matthias Clasen 38eb182947 gsk: Collect opacity information
Collect information about whether to use offscreens
for opacity during node construction, so we don't
need to walk the tree repeatedly, later.
2022-04-05 14:57:38 -04:00
Matthias Clasen 0eba21b2b5 gsk: Track disjointness of container nodes
This can be used to optimize some things in the
GL renderer.
2022-04-05 14:57:38 -04:00
Matthias Clasen 21cba193ad Merge branch 'blurry-offscreen' into 'main'
gsk/gl: Always align offscreen rendering with the pixel grid

Closes #3833

See merge request GNOME/gtk!4621
2022-04-05 12:25:59 +00:00
Matthias Clasen ee7c83e15a Merge branch 'matthiasc/for-main' into 'main'
gl: Don't leak big glyphs

See merge request GNOME/gtk!4622
2022-04-05 03:15:53 +00:00
Matthias Clasen 48dbbbc099 gl: Don't leak big glyphs
We were never resetting the accessed bit of
glyphs that are big enough to be stored individually,
so these would just accumulate and never be dropped.
2022-04-04 23:00:45 -04:00
Sebastian Keller 1c733857b3 testsuite: Add unaligned-offscreen test
Tests whether text rendered to an offscreen node unaligned with the
pixel grid introduces blurriness.
2022-04-04 23:48:58 +02:00
Sebastian Keller 85a6517d65 gsk/gl: Always align offscreen rendering with the pixel grid
This fixes two issues with the offscreen rendering code for nodes with
bounds not aligned with the pixel grid:

1.) When drawing to an offscreen buffer the size of the offscreen buffer
was rounded up, but then later when used as texture the vertices
correspond to the original bounds with the unrounded size. This could
then result in the offscreen texture being drawn onscreen at a slightly
smaller size, which then lead to it being visually shifted and blurry.

This is fixed by adjusting the u/v coordinates to ignore the padding
region in the offscreen texture that got added by the size increase from
rounding.

2.) The viewport used when rendering to the offscreen buffer was not
aligned with the pixel grid for nodes at coordinates not aligned with
the pixel grid. Then because the content of the offscreen buffer is not
aligned with the pixel grid and later when used as textures sampling
from it will result in interpolated values for an onscreen pixel. This
could also result in shifting and blurriness, especially for nested
offscreen rendering at different offsets.

This is fixed by adding similar padding at the beginning of the
texture and also adjusting the u/v coordinates to ignore this region.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3833
2022-04-04 21:40:01 +02:00
Christian Hergert d75147db0a Merge branch 'sumibi-yakitori/fix-minimize-window-macos' into 'main'
macos: Fix problem that window cannot be minimized by user operation

Closes #4811

See merge request GNOME/gtk!4613
2022-04-04 18:53:19 +00:00
sumibi-yakitori d3cf7088b3 macos: Skip running showAndMakeKey when a window is minimized by user action
When a window is minimized by user action, the `showAndMakeKey` method is not executed when idle. This prevents the window from being un-minimized immediately.
And allow programmatic minimization of a window by un-minimizing them in `_gdk_macos_toplevel_surface_present`

Closes #4811
2022-04-05 01:06:44 +09:00
Maximiliano Sandoval R ffa7185397 application: Add link and inline code blocks 2022-04-04 14:11:16 +02:00
Maximiliano Sandoval R d7fe62817c filter: Add link to FilterListmodel 2022-04-04 14:10:56 +02:00
Maximiliano Sandoval R a034bdb17e texttag: Correct typo
Does not generate a gir docstring without it.
2022-04-04 14:10:18 +02:00
Matthias Clasen af20f7e9b5 gl: Don't leak big glyphs
We were never resetting the accessed bit of
glyphs that are big enough to be stored individually,
so these would just accumulate and never be dropped.
2022-04-03 20:25:22 -04:00
Christian Hergert 15b7a4572b Merge branch 'sumibi-yakitori/fix-maximize-window-macos' into 'main'
macos: prohibit fullscreen transition if in transtion

This prevents performing additional fullscreen transitions while
a transition is already in progress.

Closes #4808

See merge request GNOME/gtk!4612
2022-04-03 22:14:52 +00:00
sumibi-yakitori 146bb70c2e macos: prohibit fullscreen transition if in transtion
This prevents performing additional fullscreen transitions while
a transition is already in progress.
2022-04-03 22:14:52 +00:00
Matthias Clasen 494de142f6 Merge branch 'matthiasc/for-main' into 'main'
inspector: Avoid a crash

See merge request GNOME/gtk!4617
2022-04-03 20:11:29 +00:00
Matthias Clasen 5d979cde82 inspector: Avoid another crash
We need to handle all event types here.
This was tripping over GDK_TOUCHPAD_HOLD events.
2022-04-03 15:55:21 -04:00
Matthias Clasen f48b894468 inspector: Avoid a crash
Attribute lists can be NULL, it turns out.
2022-04-03 15:55:21 -04:00
Matthias Clasen a6e47892be Merge branch 'matthiasc/for-main' into 'main'
gsk: Plug a memory leak

See merge request GNOME/gtk!4616
2022-04-03 14:21:13 +00:00
Matthias Clasen 1e0c25d96a Merge branch 'meson_fixes' into 'main'
meson: Use proper type for bools

See merge request GNOME/gtk!4615
2022-04-03 12:41:14 +00:00
Matthias Clasen f57eec5288 css: Plug a memory leak
We were leaking the terms of calc values. Oops.
2022-04-03 08:04:35 -04:00
illiliti e938befcbc meson: Use proper type for bools
Fix invalid usage of bools which violates official meson specification and thus
breaks muon, an implementation of meson written in C.
2022-04-03 14:55:33 +03:00
Matthias Clasen 2af8ac655b gsk: Plug a memory leak
This was introduced in 9defc7fc64.
2022-04-03 07:34:44 -04:00
Matthias Clasen cc3c0125a8 Merge branch 'matthiasc/for-main' into 'main'
imcontextsimple: Plug a memory leak

See merge request GNOME/gtk!4614
2022-04-02 19:47:03 +00:00
Matthias Clasen 59f9be457f imcontextsimple: Plug a memory leak 2022-04-02 15:30:47 -04:00
Emmanuele Bassi d1ce514260 Merge branch 'selection-model-docs' into 'main'
docs: Fix links in selection models

See merge request GNOME/gtk!4609
2022-04-01 11:20:11 +00:00
Maximiliano Sandoval R ad5e72728f docs: Fix links in selection models 2022-04-01 13:04:14 +02:00
Andika Triwidada 1bf24f7b19 Update Indonesian translation 2022-04-01 03:56:36 +00:00
Matthias Clasen a3cedb0163 Merge branch 'clipboard-seg' into 'main'
x11: Check return of gdk_x11_get_xatom_name_for_display

See merge request GNOME/gtk!4607
2022-04-01 00:56:32 +00:00
Matthias Clasen 97bab27d82 Merge branch 'fix-win32-empty-clipboard' into 'main'
gdkclipboard-win32.c: Fix call to gdk_clipboard_claim_remote() (check GdkContentFormat is not NULL

Closes #4796

See merge request GNOME/gtk!4604
2022-04-01 00:56:02 +00:00
Matthias Clasen 6030da573d Merge branch 'nls' into 'main'
Remove #ifdef ENABLE_NLS

See merge request GNOME/gtk!4606
2022-03-31 17:07:37 +00:00
Matthias Clasen 0128574ca1 Merge branch 'wip/carlosg/immulticontext-display-switch' into 'main'
gtkimmulticontext: Handle switches between displays

Closes #4805

See merge request GNOME/gtk!4605
2022-03-31 16:29:38 +00:00
Christoph Reiter b27a169200 Merge branch 'msys2-ci-cleanup' into 'main'
CI: clean up MSYS2 build dependencies

See merge request GNOME/gtk!4600
2022-03-31 15:46:54 +00:00
Xavier Claessens bcd0704511 Remove #ifdef ENABLE_NLS
libintl API is guaranteed to always be available, glib will fallback to
proxy-libintl in case gettext is not found.
2022-03-31 11:41:34 -04:00
Dr. David Alan Gilbert 506566b6a4 x11: Check return of gdk_x11_get_xatom_name_for_display
When given an invalid atom, gdk_x11_get_xatom_name_for_display can
return NULL and trigger a seg in gdk_x11_clipboard_formats_from_atoms.
Check for NULL.

Why I'm seeing a bad atom there is probably a separate question.
https://bugzilla.redhat.com/show_bug.cgi?id=2037786
2022-03-31 15:56:09 +01:00
Carlos Garnacho b67da38916 gtkimmulticontext: Handle switches between displays
Currently the GtkIMMultiContext may stick to a delegate GtkIMContext
that no longer applies after the multicontext is dissociated from
any widget.

Handle set_client_widget() so that it can handle changes between
widgets from 2 different display, but also so the delegate is made
NULL whenever the context has a NULL widget.

Doing so, any new client widget results in a new delegate IM context
lookup from the right GdkDisplay and GtkSettings, which avoids any
mix up.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4805
2022-03-31 16:35:29 +02:00
Chun-wei Fan 8519ab56f5 gdkclipboard-win32.c: Fix call to gdk_clipboard_claim_remote()
The call to gdk_win32_clipboard_request_contentformats() can return NULL even
without an error condition being hit (such as when the system clipboard is
empty), so check whether the returned GdkContentFormat pointer is not NULL
before calling gdk_clipboard_claim_remote(), which expects it to be not NULL,
otherwise we face a warning from that funtion and the subsequent
g_object_unref().

This at least partially fixes issue #4796.
2022-03-31 10:55:39 +08:00
Chun-wei Fan 89d87e3482 inspector/general.c: Check whether GL context supports WGL
We may well be using an EGL context that does not support Desktop (W)GL on
Windows, such as in the case of using libANGLE.  So, check whether WGL is
supported for this running instance before trying to query WGL extensions.

This will get rid of warning messages from libepoxy.
2022-03-30 16:09:18 +08:00
Carlos Garnacho 04c9c6b428 Merge branch 'wip/exalm/scroll-hold' into 'main'
eventcontrollerscroll: Always propagate hold events

See merge request GNOME/gtk!4599
2022-03-28 14:27:55 +00:00
Alexander Mikhaylenko 9bd8ed0d82 eventcontrollerscroll: Always propagate hold events
Otherwise a stray scroll controller may prevent others from getting hold
events, even if it always propagates scroll events and does absolutely
nothing.
2022-03-28 12:04:15 +00:00
Rūdolfs Mazurs 40386c97eb Update Latvian translation
(cherry picked from commit 3b50f2e8b9)
2022-03-27 20:19:34 +00:00
Rūdolfs Mazurs 6649cc6e5e Update Latvian translation
(cherry picked from commit d4dd7969d6)
2022-03-27 19:54:19 +00:00
Christoph Reiter e69dc04a7f CI: clean up MSYS2 build dependencies
We only need a C compiler and not the whole toolchain,
and gst-plugins-bad was split into libraries and plugins.
pkg-config -> pkgconf.

This should speed the CI setup up a bit.
2022-03-27 20:10:58 +02:00
Emmanuele Bassi c1361f7a5a Merge branch 'antoniof-main-patch-34986' into 'main'
overlaylayout: Set position style class on child

Closes nautilus#2099

See merge request GNOME/gtk!4597
2022-03-27 16:25:50 +00:00
António Fernandes 351ffef704 overlaylayout: Set position style class on child
As documented:
> Overlay children whose alignments cause them to be positioned
> at an edge get the style classes “.left”, “.right”, “.top”, 
> and/or “.bottom” according to their position.

Likely accidental regression in b7ee2cbc28

Fixes https://gitlab.gnome.org/GNOME/nautilus/-/issues/2099
2022-03-27 14:59:10 +00:00
Matthias Clasen a1ddd3fead Merge branch 'inspector-attributes' into 'main'
inspector: Allow viewing PangoAttrList properties

See merge request GNOME/gtk!4596
2022-03-25 13:03:00 +00:00
Matthias Clasen 79f0f4ee8e inspector: Allow viewing PangoAttrList properties
We have pango_attr_list_to/from_string, so this is
easy. The editing UI isn't ideal, but it solves my
immediate need to see attributes.
2022-03-25 08:35:16 -04:00
Matthias Clasen 7b8bfb4c80 Merge branch 'main' into 'main'
Check for 'rst2man' misses installed 'rst2man.py' (#4728)

See merge request GNOME/gtk!4586
2022-03-25 11:48:28 +00:00
Benjamin Otte 7106cf6524 Merge branch 'wip/chergert/fix-gl-rgba' into 'main'
gdk/gl: handle GL_RGBA/GL_UNSIGNED_NORMALIZED

Closes #4783

See merge request GNOME/gtk!4594
2022-03-25 01:34:15 +00:00
Christian Hergert e706e14fd9 gdk/gl: handle GL_RGBA/GL_UNSIGNED_NORMALIZED
WebKit's GTK 4 port can give us textures with an internal format of
GL_RGBA with GL_UNSIGNED_NORMALIZED and a bit-depth of 8. This fixes
warnings for every GdkGLTexture created/delivered to the GskGLRenderer.

The format is essentially the same as GL_RGBA8 since it is normalized
between 0.0..1.0 for 8-bit components.

Fixes #4783
2022-03-24 18:05:11 -07:00
Matthias Clasen 3f1021048f Merge branch 'want_prepare_without_play_for_size' into 'main'
GtkMediaStream with gstreamer backend isn't 'prepared' until media is played

See merge request GNOME/gtk!4560
2022-03-24 19:19:01 +00:00
Matthias Clasen ddba7f8601 Apply 1 suggestion(s) to 1 file(s) 2022-03-24 17:16:11 +00:00
Bruce Cowan 1660a0eaf1 Update British English translation
(cherry picked from commit dd198cfc06)
2022-03-24 13:19:45 +00:00
Kukuh Syafaat ffffb382e2 Update Indonesian translation 2022-03-23 15:39:17 +00:00
Kukuh Syafaat 09453bc60b Update Indonesian translation 2022-03-23 13:46:25 +00:00
Matthias Clasen f76b749e43 Merge branch 'fix-popover-menu-rtl-position' into 'main'
popover-menu: Fix buttons' position in RTL

See merge request GNOME/gtk!4587
2022-03-23 02:16:41 +00:00
Cheng-Chia Tseng 0aca2a03b4 Update Chinese (Taiwan) translation 2022-03-22 14:47:50 +00:00
Matthias Clasen fd358990a2 Merge branch 'wip/chergert/reduce-overlay-overhead' into 'main'
Default: avoid use of opacity for overlay scrollbars

See merge request GNOME/gtk!4590
2022-03-22 13:27:54 +00:00
Matthias Clasen 01b91c1ba3 Merge branch 'fix-high-depth-switch' into 'main'
surface: Use correct display when destroying a surface for depth switch

Closes #4773

See merge request GNOME/gtk!4591
2022-03-22 12:58:07 +00:00
Sebastian Keller cc02076b75 surface: Use correct display when destroying a surface for depth switch
When surface depth switches from non-high-depth to high-depth (or vice
versa) the current surface has to be destroyed before a new one can be
created for this window. eglDestroySurface however was getting passed a
GdkDisplay, rather than the EGLDisplay it expects. As a result the old
surface did not get destroyed and the new surface could not be created
causing rendering to freeze.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4773
2022-03-22 08:18:26 +01:00
Christian Hergert b726a2d902 Default: avoid use of opacity for overlay scrollbars
If using the opacity CSS property the renderer cannot optimize these
handles without the use of offscreens due to the use of both a border
and rgb render node.

Instead, we can apply the alpha to the color values and get the same
effect in a way that the GL renderer can optimize without the use of
offscreen textures for a sizeable reduction in runtime overhead.
2022-03-21 22:10:23 -07:00
Marek Černocký 654ae5928a Updated Czech translation 2022-03-21 14:57:35 +01:00
Marek Černocký 1c24514798 Updated Czech translation 2022-03-21 12:14:36 +01:00
Yosef Or Boczko 33f3ab9991 popover-menu: Fix buttons' position in RTL
The radio/check/previous buttons shows in
the wrong place in RTL. Fix it.

#4641

Signed-off-by: Yosef Or Boczko <yoseforb@gmail.com>
2022-03-20 00:54:26 +02:00
aneejit1 91511a80ac Check for 'rst2man' misses installed 'rst2man.py' (#4728)
By default, 'docutils' installs 'rst2man' as 'rst2man.py'. Amend the
check for 'rst2man' to look for 'rst2man.py' as well if 'rst2man' is
not found.
2022-03-19 13:58:40 +00:00
Philipp Kiemle a585457861 Update German translation
(cherry picked from commit d9c39f6795)
2022-03-19 12:32:43 +00:00
Carlos Garnacho 4a0ddac307 Merge branch 'wip/carlosg/fix-accumulated-velocity' into 'main'
kinetic scroll fixes

See merge request GNOME/gtk!4572
2022-03-19 12:02:56 +00:00
Carlos Garnacho f7d9ede82d gtkkineticscrolling: Do not take distance based shortcuts
The pixel distance could be small enough between tick() calls that
this kind of checks might potentially become a problem. Rely only on
the calculated velocity to trigger the STOPPED phase, and use a lower
threshold to avoid cutting the animation too early.

Related: https://gitlab.gnome.org/GNOME/gtk/-/issues/4725
2022-03-19 12:35:11 +01:00
Carlos Garnacho 65839f67f8 gtkscrolledwindow: Do not trigger kinetic helpers on 0 velocity
Doing this is pointless, so it could be skipped.
2022-03-19 12:35:11 +01:00
Carlos Garnacho df40db137b gtkscrolledwindow: Change lifetime of kinetic scroll helpers
In order to properly accumulate scroll velocities, we need to keep
the kinetic scroll helpers after we have possibly stopped them
in the process of initiating a further scroll flick.

So, instead of stopping (and destroying) those helpers on scroll-begin,
keep them until the next scroll-end if a scroll was initiated before
kinetic scroll finished. This way we can fetch the last velocity when
calculating the extra kick.

In order to ensure the helpers don't live beyond what it is expected,
we now also remove them after a finished hold event.

Fixes the accumulation of scrolling velocity on consecutive scroll
sequences.
2022-03-19 12:35:11 +01:00
Carlos Garnacho 129bc27d53 gtkscrolledwindow: Refactor kinetic scroll animation
Do not depend on the kinetic scroll helpers existing or not before
exiting the animation, as we may want to keep those a little bit
longer after stopped.
2022-03-19 12:35:11 +01:00
Carlos Garnacho 274e2b221f gtkkineticscroll: Do not reset velocity after stop()
We may want to fetch the last velocity obtained, even though we
preemptively called stop() on a kinetic scroll helper. Keep this
velocity so it can be queried later on.
2022-03-19 12:35:11 +01:00
Emmanuele Bassi adc4009354 Merge branch 'search-delay-versions' into 'main'
Fix GtkSearchEntry:search-delay docs

See merge request GNOME/gtk!4585
2022-03-19 10:14:04 +00:00
Sebastian Dröge f058a42bd3 Add version marker to GtkSearchEntry:search-delay property 2022-03-19 11:56:05 +02:00
Sebastian Dröge 3a8cb276e7 Fix typo in gtk_search_entry_set_search_delay() docs causing it to not show up 2022-03-19 11:55:03 +02:00
Matthias Clasen eeaa73c12a Merge branch 'macos-fix-scroll-unit-build' into 'main'
macos: fix scroll-unit build

See merge request GNOME/gtk!4584
2022-03-19 03:57:48 +00:00
panoplie 3873861b27 macos: fix scroll-unit build 2022-03-19 02:55:02 +01:00
Carlos Garnacho 8e455e333b Merge branch 'scroll-unit' into 'main'
GdkScrollEvent: indicate the delta unit with a new GdkScrollUnit enum

See merge request GNOME/gtk!4508
2022-03-19 00:47:08 +00:00
Matthias Clasen 3d10e6c3d1 Merge branch 'wip/carlosg/rewritten-events-from-other-toplevels' into 'main'
gtk/main: Make coords out of surface when rewriting events for grabs

Closes #4760

See merge request GNOME/gtk!4566
2022-03-19 00:34:17 +00:00
Matthias Clasen dcc7cf7114 Merge branch 'wip/chergert/gsk-gl-texture-library' into 'main'
gsk/gl: texture libraries, shader creation

See merge request GNOME/gtk!4583
2022-03-18 23:46:17 +00:00
panoplie f1d0886087 gtkeventcontrollerscroll: Map surface scroll unit in discrete steps 2022-03-19 00:41:26 +01:00
panoplie 951e4ee6b2 recorder: Show scroll events deltas unit 2022-03-19 00:41:26 +01:00
panoplie f9e2c106bc gtkrange: Add scroll unit handling 2022-03-19 00:41:26 +01:00
panoplie 53956e5389 gtkscrolledwindow: Add scroll unit handling
On the "scroll" signal, the widget uses
gtk_event_controller_scroll_get_unit() to get the
scroll unit.

When the unit is GDK_SCROLL_UNIT_WHEEL, the
behavior is unchanged: the widget scrolls a
certain number of pixels at each wheel detent
click. This number of pixels is determined by the
window dimensions in get_wheel_detent_scroll_step().

When the delta unit is GDK_SCROLL_UNIT_SURFACE, the
widget directly adds the delta to the number of
scrolled pixels no matter the window dimensions.
2022-03-19 00:41:26 +01:00
panoplie 3ab63fd03b gtkeventcontrollerscroll: Add scroll unit getter
The scroll unit is accessible through
gtk_event_controller_scroll_get_unit() after the
"scroll" signal reception.
2022-03-19 00:41:26 +01:00
panoplie fb4927827b gdk: Add enum to indicate the unit of scroll deltas
Add a new GdkScrollUnit enum that represent the
unit of scroll deltas provided by GdkScrollEvent.
The unit is accessible through
gdk_scroll_event_get_unit().
2022-03-19 00:41:26 +01:00
Christian Hergert cbbca38d88 gsk/gl: use consistent library naming 2022-03-18 14:59:49 -07:00
Christian Hergert c64836e1c9 gsk/gl: make texture libraries more autonomous
This moves a lot of the texture atlas control out of the driver and into
the various texture libraries through their base GskGLTextureLibrary class.

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

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

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

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

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

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

For example, in the future we might store non-pixel data in the textures
such as Glyphy or even keep glyphs with color content separate from glyphs
which do not and can use alpha channel only.
2022-03-18 12:48:43 -07:00
Christian Hergert 9defc7fc64 gsk/gl: add more control over shader generation
This allows the gskglprograms.defs a bit more control over how a shader
will get generated and if it needs to combine sources. Currently, none of
the built-in shaders do that, but upcoming shaders which come from external
libraries will need the ability to inject additional sources in-between
layers.
2022-03-18 12:34:32 -07:00
Christian Hergert 9d56f44cdf gsk/gl: rename glyphs to glyphs_library
This naming style is less likely to collide with shader naming and makes
it clear where it is consumed what it is.
2022-03-18 12:34:32 -07:00
Christian Hergert 1b9da2bb17 gsk/gl: allow configuring atlas size 2022-03-18 12:34:27 -07:00
Christian Hergert 2efc1729e2 gsk/gl: check for format as well
This could potentially happen if a uniform had never been set.
2022-03-18 12:33:33 -07:00
Christian Hergert a66a0dde81 gsk/gl: only clear glyph cache durign reclaimation
We don't need to clear the front cache on every frame as we can clear it
specifically when we do reclaimation to avoid unnecessary memset() calls.
2022-03-18 12:33:33 -07:00
Christian Hergert 7062411bad gsk/gl: ignore max_entry_size when zero
If the max_entry_size is zero, then assume we can add anything to the
atlas. This allows for situations where we might be uploading an arc list
to the atlas instead of pixel data for GPU font rendering.
2022-03-18 12:33:33 -07:00
Christian Hergert 9dbd137ec8 gsk/gl: make max-frame-age configurable
This is nice for some texture libraries that we might want to keep around
for longer than say 60 frames such as a glyph cache.
2022-03-18 12:33:33 -07:00
Matthias Clasen 79fad9f221 gtk-demo: Don't hardcode a title font
We want a large font size, but we don't have to
hardcode Sans.
2022-03-18 12:33:33 -07:00
Matthias Clasen 8f9ee48aaa Merge branch 'filefilter-suffixes' into 'main'
filefilter: Fix <suffixes> in buildable

See merge request GNOME/gtk!4581
2022-03-17 16:57:09 +00:00
James Westman 8eb9844a45 filefilter: Fix <suffixes> in buildable
A bug in GtkFileFilter's GtkBuildable implementation caused the
<suffixes> tag not to be recognized.
2022-03-17 10:52:20 -05:00
Milo Casagrande b90132c917 Update Italian translation
(cherry picked from commit 3e4bfa2bae)
2022-03-17 08:36:13 +00:00
Milo Casagrande 23806b7788 Update Italian translation
(cherry picked from commit 9bbf09fb0a)
2022-03-17 08:34:32 +00:00
Мирослав Николић d266c0d105 Update Serbian translation
(cherry picked from commit c874f65d95)
2022-03-17 06:04:41 +00:00
Carlos Garnacho 581461c2b5 Merge branch 'wip/carlosg/im-wayland-serials' into 'main'
gtk/imwayland: Use serial to control outbound messages

Closes #3641

See merge request GNOME/gtk!4398
2022-03-16 18:52:24 +00:00
Carlos Garnacho f108f053d4 gtk/imwayland: Use serial to control outbound messages
Following the text-input protocol changes at
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/115,
use the serial number to have the client push changes to the
zwp_text_input_v3 object only after compositor/client states match.

This specifically is more lenient to compositors pushing multiple
.done events ahead of the client replying to them.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3641
2022-03-16 17:38:14 +01:00
Carlos Garnacho e5dc66b10e gtk/main: Fix handling of !owner_events grabs
These are meant to always redirect events to the grabbing surface,
even for other surfaces of the same client. We weren't doing that
(instead letting the event go through unmodified), fix this handling
so GTK sees the events consistenty.
2022-03-15 14:40:49 +01:00
Carlos Garnacho aa43d97a80 gtk/main: Make coords out of surface when rewriting events for grabs
If a grab is held on a toplevel surface tree, and events happen on a
different surface tree from another toplevel/window group, we rewrite
these events so they look like generated on the window group that
holds the grab, but it missed that coordinates would fail to be
translated, so these would stay unchanged and "pointing" to random
parts of the toplevel that is holding the grab and handling the events.

Since off-surface coordinates are not specially meaningful, and in
fact impossible to obtain in some backends, just fake the coordinates
making it sure that all rewritten events point outside the surface.

The grabbing window will still handle the events, but the coordinates
in these will be harmlessly moot.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4760
2022-03-15 14:29:16 +01:00
Caolán McNamara 82f57c6a93 GtkMediaStream with gstreamer backend isn't 'prepared' until media is played
This seems to be a problem since:
https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3565

To demo the problem, the video demo in gtk4-demo is currently set to
autoplay, but it doesn't autoplay on load as expected because the
"prepared" notification doesn't fire until the user explicitly presses
play.

Similarly if the demo is tweaked to disable autoplay then on loading a
video (or an audio-only ogg) the duration is not known or shown until
the user presses play.

In LibreOffice we want to know what the size of the video is to position
it before the user can interact with it to set it to play. We can
workaround this to some degree by listening to "invalidate-size" on the
GtkMediaStream object which updates for videos, but that doesn't wor
for audio-only streams.

So restore listening to media-info-updated but ignore -1 (which I see
for audio-only where I get -1 and then a useful value) and 0 of the
original report.

see also:
https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3550

GNOME/gtk!4513
2022-03-09 16:29:11 +00:00
139 changed files with 15438 additions and 15591 deletions
+3 -3
View File
@@ -15,9 +15,9 @@ pacman --noconfirm -Suy
pacman --noconfirm -S --needed \
base-devel \
git \
mingw-w64-$MSYS2_ARCH-toolchain \
mingw-w64-$MSYS2_ARCH-cc \
mingw-w64-$MSYS2_ARCH-ccache \
mingw-w64-$MSYS2_ARCH-pkg-config \
mingw-w64-$MSYS2_ARCH-pkgconf \
mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \
@@ -30,7 +30,7 @@ pacman --noconfirm -S --needed \
mingw-w64-$MSYS2_ARCH-libepoxy \
mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \
mingw-w64-$MSYS2_ARCH-shared-mime-info \
mingw-w64-$MSYS2_ARCH-python-gobject
+2 -3
View File
@@ -24,6 +24,7 @@ do_cursors (GtkWidget *do_widget)
builder = gtk_builder_new_from_resource ("/cursors/cursors.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
@@ -34,9 +35,7 @@ do_cursors (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
{
gtk_window_destroy (GTK_WINDOW (window));
}
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+1 -1
View File
@@ -512,7 +512,7 @@ load_file (const char *demoname,
info_buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (info_buffer, "title",
"font", "Sans 18",
"size", 18 * 1024,
"pixels-below-lines", 10,
NULL);
+29 -1
View File
@@ -16,6 +16,7 @@ SYNOPSIS
| **gtk4-builder-tool** enumerate <FILE>
| **gtk4-builder-tool** simplify [OPTIONS...] <FILE>
| **gtk4-builder-tool** preview [OPTIONS...] <FILE>
| **gtk4-builder-tool** screenshot [OPTIONS...] <FILE>
DESCRIPTION
-----------
@@ -41,7 +42,7 @@ definition file.
Preview
^^^^^^^
The ``preview`` command displays the UI dfinition file.
The ``preview`` command displays the UI definition file.
This command accepts options to specify the ID of the toplevel object and a CSS
file to use.
@@ -55,6 +56,33 @@ file to use.
Load style information from the given CSS file.
Screenshot
^^^^^^^^^^
The ``screenshot`` command saves a rendering of the UI definition file
as a png image or node file. The name of the file to write can be specified as
a second FILE argument.
This command accepts options to specify the ID of the toplevel object and a CSS
file to use.
``--id=ID``
The ID of the object to preview. If not specified, gtk4-builder-tool will
choose a suitable object on its own.
``--css=FILE``
Load style information from the given CSS file.
``--node``
Write a serialized node file instead of a png image.
``--force``
Overwrite an existing file.
Simplification
^^^^^^^^^^^^^^
+1 -1
View File
@@ -57,7 +57,7 @@ if get_option('gtk_doc')
)
endif
rst2man = find_program('rst2man', required: false)
rst2man = find_program('rst2man', 'rst2man.py', required: false)
if get_option('man-pages') and not rst2man.found()
error('No rst2man found, but man pages were explicitly enabled')
endif
+53 -5
View File
@@ -597,7 +597,8 @@ _gdk_event_unqueue (GdkDisplay *display)
/*
* If the last N events in the event queue are smooth scroll events
* for the same surface and device, combine them into one.
* for the same surface, the same device and the same scroll unit,
* combine them into one.
*
* We give the remaining event a history with N items, and deltas
* that are the sum over the history entries.
@@ -611,6 +612,8 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
GdkEvent *last_event = NULL;
GList *scrolls = NULL;
GArray *history = NULL;
GdkScrollUnit scroll_unit = GDK_SCROLL_UNIT_WHEEL;
gboolean scroll_unit_defined = FALSE;
GdkTimeCoord hist;
l = g_queue_peek_tail_link (&display->queued_events);
@@ -618,6 +621,7 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
while (l)
{
GdkEvent *event = l->data;
GdkScrollEvent *scroll_event = (GdkScrollEvent *) event;
if (event->flags & GDK_EVENT_PENDING)
break;
@@ -634,11 +638,17 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
device != event->device)
break;
if (scroll_unit_defined &&
scroll_unit != scroll_event->unit)
break;
if (!last_event)
last_event = event;
surface = event->surface;
device = event->device;
scroll_unit = scroll_event->unit;
scroll_unit_defined = TRUE;
scrolls = l;
l = l->prev;
@@ -710,7 +720,8 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
gdk_event_get_modifier_state (old_event),
dx,
dy,
gdk_scroll_event_is_stop (old_event));
gdk_scroll_event_is_stop (old_event),
scroll_unit);
((GdkScrollEvent *)event)->history = history;
@@ -746,15 +757,21 @@ gdk_motion_event_push_history (GdkEvent *event,
memset (&hist, 0, sizeof (GdkTimeCoord));
hist.time = gdk_event_get_time (history_event);
if (tool)
{
hist.flags = gdk_device_tool_get_axes (tool);
for (i = GDK_AXIS_X; i < GDK_AXIS_LAST; i++)
gdk_event_get_axis (history_event, i, &hist.axes[i]);
}
else
/* GdkTimeCoord has no dedicated fields to record event position. For plain
* pointer events, and for tools which don't report GDK_AXIS_X/GDK_AXIS_Y
* on their own, we surface the position using the X and Y input axes.
*/
if (!(hist.flags & GDK_AXIS_FLAG_X) || !(hist.flags & GDK_AXIS_FLAG_Y))
{
hist.flags = GDK_AXIS_FLAG_X | GDK_AXIS_FLAG_Y;
hist.flags |= GDK_AXIS_FLAG_X | GDK_AXIS_FLAG_Y;
gdk_event_get_position (history_event, &hist.axes[GDK_AXIS_X], &hist.axes[GDK_AXIS_Y]);
}
@@ -2334,7 +2351,8 @@ gdk_scroll_event_new (GdkSurface *surface,
GdkModifierType state,
double delta_x,
double delta_y,
gboolean is_stop)
gboolean is_stop,
GdkScrollUnit unit)
{
GdkScrollEvent *self = gdk_event_alloc (GDK_SCROLL, surface, device, time);
@@ -2344,6 +2362,7 @@ gdk_scroll_event_new (GdkSurface *surface,
self->delta_x = delta_x;
self->delta_y = delta_y;
self->is_stop = is_stop;
self->unit = unit;
return (GdkEvent *) self;
}
@@ -2363,6 +2382,7 @@ gdk_scroll_event_new_discrete (GdkSurface *surface,
self->state = state;
self->direction = direction;
self->pointer_emulated = emulated;
self->unit = GDK_SCROLL_UNIT_WHEEL;
return (GdkEvent *) self;
}
@@ -2396,6 +2416,9 @@ gdk_scroll_event_get_direction (GdkEvent *event)
*
* The deltas will be zero unless the scroll direction
* is %GDK_SCROLL_SMOOTH.
*
* For the representation unit of these deltas, see
* [method@Gdk.ScrollEvent.get_unit].
*/
void
gdk_scroll_event_get_deltas (GdkEvent *event,
@@ -2438,6 +2461,31 @@ gdk_scroll_event_is_stop (GdkEvent *event)
return self->is_stop;
}
/**
* gdk_scroll_event_get_unit:
* @event: (type GdkScrollEvent): a scroll event.
*
* Extracts the scroll delta unit of a scroll event.
*
* The unit will always be %GDK_SCROLL_UNIT_WHEEL if the scroll direction is not
* %GDK_SCROLL_SMOOTH.
*
* Returns: the scroll unit.
*
* Since: 4.8
*/
GdkScrollUnit
gdk_scroll_event_get_unit (GdkEvent *event)
{
GdkScrollEvent *self = (GdkScrollEvent *) event;
g_return_val_if_fail (GDK_IS_EVENT (event), GDK_SCROLL_UNIT_WHEEL);
g_return_val_if_fail (GDK_IS_EVENT_TYPE (event, GDK_SCROLL),
GDK_SCROLL_UNIT_WHEEL);
return self->unit;
}
/* }}} */
/* {{{ GdkTouchpadEvent */
+33
View File
@@ -265,6 +265,37 @@ typedef enum
GDK_SCROLL_SMOOTH
} GdkScrollDirection;
/**
* GdkScrollUnit:
* @GDK_SCROLL_UNIT_WHEEL: The delta is in number of wheel clicks.
* @GDK_SCROLL_UNIT_SURFACE: The delta is in surface pixels to scroll directly
* on screen.
*
* Specifies the unit of scroll deltas.
*
* When you get %GDK_SCROLL_UNIT_WHEEL, a delta of 1.0 means 1 wheel detent
* click in the south direction, 2.0 means 2 wheel detent clicks in the south
* direction... This is the same logic for negative values but in the north
* direction.
*
* If you get %GDK_SCROLL_UNIT_SURFACE, are managing a scrollable view and get a
* value of 123, you have to scroll 123 surface logical pixels right if it's
* @delta_x or down if it's @delta_y. This is the same logic for negative values
* but you have to scroll left instead of right if it's @delta_x and up instead
* of down if it's @delta_y.
*
* 1 surface logical pixel is equal to 1 real screen pixel multiplied by the
* final scale factor of your graphical interface (the product of the desktop
* scale factor and eventually a custom scale factor in your app).
*
* Since: 4.8
*/
typedef enum
{
GDK_SCROLL_UNIT_WHEEL,
GDK_SCROLL_UNIT_SURFACE
} GdkScrollUnit;
/**
* GdkNotifyType:
* @GDK_NOTIFY_ANCESTOR: the surface is entered from an ancestor or
@@ -395,6 +426,8 @@ GDK_AVAILABLE_IN_ALL
void gdk_scroll_event_get_deltas (GdkEvent *event,
double *delta_x,
double *delta_y);
GDK_AVAILABLE_IN_4_8
GdkScrollUnit gdk_scroll_event_get_unit (GdkEvent *event);
GDK_AVAILABLE_IN_ALL
gboolean gdk_scroll_event_is_stop (GdkEvent *event);
+4 -1
View File
@@ -212,6 +212,7 @@ struct _GdkTouchEvent
* @history: (element-type GdkTimeCoord): array of times and deltas
* for other scroll events that were compressed before delivering the
* current event
* @unit: The scroll unit in which delta_x and delta_y are represented.
*
* Generated from button presses for the buttons 4 to 7. Wheel mice are
* usually configured to generate button press events for buttons 4 and 5
@@ -234,6 +235,7 @@ struct _GdkScrollEvent
gboolean is_stop;
GdkDeviceTool *tool;
GArray *history; /* <GdkTimeCoord> */
GdkScrollUnit unit;
};
/*
@@ -486,7 +488,8 @@ GdkEvent * gdk_scroll_event_new (GdkSurface *surface,
GdkModifierType state,
double delta_x,
double delta_y,
gboolean is_stop);
gboolean is_stop,
GdkScrollUnit unit);
GdkEvent * gdk_scroll_event_new_discrete (GdkSurface *surface,
GdkDevice *device,
+36
View File
@@ -365,6 +365,42 @@ gdk_gl_texture_determine_format (GdkGLTexture *self)
texture->format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
break;
case GL_RGBA:
{
GLint red_size = 0;
GLint green_size = 0;
GLint blue_size = 0;
GLint alpha_size = 0;
GLint red_type = 0;
GLint green_type = 0;
GLint blue_type = 0;
GLint alpha_type = 0;
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_RED_TYPE, &red_type);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_TYPE, &green_type);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_TYPE, &blue_type);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_TYPE, &alpha_type);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &red_size);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &green_size);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &blue_size);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
#define CHECK_RGBA(rt,gt,bt,at,rs,gs,bs,as) \
(red_type == rt && green_type == gt && blue_type == bt && alpha_type == at && \
red_size == rs && green_size == gs && blue_size == bs && alpha_size == as)
if (CHECK_RGBA (GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8))
{
texture->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
break;
}
#undef CHECK_RGBA
}
G_GNUC_FALLTHROUGH;
default:
g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
/* fallback to the dumbest possible format
+2 -6
View File
@@ -19,7 +19,7 @@
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GDKINTL_H__
@@ -27,10 +27,6 @@
#include <glib/gi18n-lib.h>
#ifdef ENABLE_NLS
#define P_(String) dgettext(GETTEXT_PACKAGE "-properties",String)
#else
#define P_(String) (String)
#endif
#define P_(String) dgettext (GETTEXT_PACKAGE "-properties", String)
#endif
+1 -1
View File
@@ -1125,7 +1125,7 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
gdk_display_get_egl_config_high_depth (display) != gdk_display_get_egl_config (display))
{
gdk_gl_context_clear_current_if_surface (self);
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
eglDestroySurface (gdk_display_get_egl_display (display), priv->egl_surface);
priv->egl_surface = NULL;
}
+11
View File
@@ -171,6 +171,11 @@ typedef NSString *CALayerContentsGravity;
return inMove;
}
- (BOOL)inFullscreenTransition;
{
return inFullscreenTransition;
}
-(void)checkSendEnterNotify
{
/* When a new window has been created, and the mouse is in the window
@@ -759,31 +764,37 @@ typedef NSString *CALayerContentsGravity;
-(void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = YES;
lastUnfullscreenFrame = [self frame];
}
-(void)windowDidEnterFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = NO;
initialPositionKnown = NO;
[self checkSendEnterNotify];
}
-(void)windowWillExitFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = YES;
}
-(void)windowDidExitFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = NO;
initialPositionKnown = NO;
[self checkSendEnterNotify];
}
-(void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = NO;
}
-(void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = NO;
}
-(void)windowDidChangeScreen:(NSNotification *)aNotification
+2
View File
@@ -53,6 +53,7 @@
NSRect lastMaximizedFrame;
NSRect lastUnfullscreenFrame;
BOOL inMaximizeTransition;
BOOL inFullscreenTransition;
}
-(void)beginManualMove;
@@ -70,5 +71,6 @@
-(void)setDecorated:(BOOL)decorated;
-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage;
-(BOOL)needsMouseDownQuirk;
-(BOOL)inFullscreenTransition;
@end
+6 -3
View File
@@ -644,7 +644,8 @@ fill_scroll_event (GdkMacosDisplay *self,
NULL,
get_time_from_ns_event (nsevent),
state,
0.0, 0.0, TRUE);
0.0, 0.0, TRUE,
GDK_SCROLL_UNIT_SURFACE);
dx = [nsevent deltaX];
dy = [nsevent deltaY];
@@ -665,7 +666,8 @@ fill_scroll_event (GdkMacosDisplay *self,
state,
-sx,
-sy,
FALSE);
FALSE,
GDK_SCROLL_UNIT_SURFACE);
/* Fall through for scroll emulation */
}
@@ -714,7 +716,8 @@ fill_scroll_event (GdkMacosDisplay *self,
NULL,
get_time_from_ns_event (nsevent),
state,
0.0, 0.0, TRUE);
0.0, 0.0, TRUE,
GDK_SCROLL_UNIT_SURFACE);
}
return g_steal_pointer (&ret);
+2 -1
View File
@@ -434,7 +434,8 @@ select_key_in_idle_cb (gpointer data)
{
GdkMacosSurface *surface = iter->data;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)) &&
([surface->window styleMask] & NSWindowStyleMaskMiniaturizable) == 0)
{
[surface->window showAndMakeKey:YES];
break;
+21 -6
View File
@@ -33,26 +33,26 @@
static void
_gdk_macos_toplevel_surface_fullscreen (GdkMacosToplevelSurface *self)
{
NSWindow *window;
GdkMacosWindow *window;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
window = (GdkMacosWindow *)_gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
if (([window styleMask] & NSWindowStyleMaskFullScreen) == 0)
if (![window inFullscreenTransition] && ([window styleMask] & NSWindowStyleMaskFullScreen) == 0)
[window toggleFullScreen:window];
}
static void
_gdk_macos_toplevel_surface_unfullscreen (GdkMacosToplevelSurface *self)
{
NSWindow *window;
GdkMacosWindow *window;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
window = (GdkMacosWindow *)_gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
if (([window styleMask] & NSWindowStyleMaskFullScreen) != 0)
if (![window inFullscreenTransition] && ([window styleMask] & NSWindowStyleMaskFullScreen) != 0)
[window toggleFullScreen:window];
}
@@ -82,6 +82,19 @@ _gdk_macos_toplevel_surface_unmaximize (GdkMacosToplevelSurface *self)
[window zoom:window];
}
static void
_gdk_macos_toplevel_surface_unminimize (GdkMacosToplevelSurface *self)
{
NSWindow *window;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
if ([window isMiniaturized])
[window deminiaturize:window];
}
static void
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
@@ -202,6 +215,8 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
_gdk_macos_toplevel_surface_unfullscreen (self);
}
_gdk_macos_toplevel_surface_unminimize (self);
if (!GDK_MACOS_SURFACE (self)->did_initial_present)
{
int x = 0, y = 0;
+7 -5
View File
@@ -1416,7 +1416,8 @@ flush_smooth_scroll_event (GdkWaylandSeat *seat,
seat->pointer_info.time,
device_get_modifiers (seat->logical_pointer),
delta_x, delta_y,
is_stop);
is_stop,
GDK_SCROLL_UNIT_SURFACE);
_gdk_wayland_display_deliver_event (seat->display, event);
}
@@ -1755,10 +1756,10 @@ pointer_handle_axis (void *data,
switch (axis)
{
case WL_POINTER_AXIS_VERTICAL_SCROLL:
pointer_frame->delta_y = wl_fixed_to_double (value) / 10.0;
pointer_frame->delta_y = wl_fixed_to_double (value);
break;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
pointer_frame->delta_x = wl_fixed_to_double (value) / 10.0;
pointer_frame->delta_x = wl_fixed_to_double (value);
break;
default:
g_return_if_reached ();
@@ -1768,7 +1769,7 @@ pointer_handle_axis (void *data,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("scroll, axis %s, value %f, seat %p",
get_axis_name (axis), wl_fixed_to_double (value) / 10.0,
get_axis_name (axis), wl_fixed_to_double (value),
seat));
if (display->seat_version < WL_POINTER_HAS_FRAME)
@@ -3994,7 +3995,8 @@ tablet_tool_handle_wheel (void *data,
tablet->pointer_info.time,
device_get_modifiers (tablet->logical_device),
0, clicks,
FALSE);
FALSE,
GDK_SCROLL_UNIT_WHEEL);
_gdk_wayland_display_deliver_event (seat->display, event);
+7 -3
View File
@@ -142,9 +142,13 @@ gdk_win32_clipboard_claim_remote (GdkWin32Clipboard *cb)
cb->sequence_number = -1;
formats = gdk_win32_clipboard_request_contentformats (cb);
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb), formats);
gdk_content_formats_unref (formats);
cb->sequence_number = GetClipboardSequenceNumber ();
if (formats != NULL)
{
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb), formats);
gdk_content_formats_unref (formats);
cb->sequence_number = GetClipboardSequenceNumber ();
}
}
static void
+57 -69
View File
@@ -873,6 +873,7 @@ _gdk_win32_append_event (GdkEvent *event)
{
GdkDisplay *display;
GList *link;
gulong serial;
display = gdk_display_get_default ();
@@ -880,8 +881,9 @@ _gdk_win32_append_event (GdkEvent *event)
#if 1
link = _gdk_event_queue_append (display, event);
GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
serial = _gdk_display_get_next_serial (display);
/* event morphing, the passed in may not be valid afterwards */
_gdk_windowing_got_event (display, link, event, 0);
_gdk_windowing_got_event (display, link, event, serial);
#else
_gdk_event_queue_append (display, event);
GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
@@ -2242,6 +2244,10 @@ gdk_event_translate (MSG *msg,
button = 5;
buttonup0:
{
gboolean release_implicit_grab = FALSE;
GdkSurface *prev_surface = NULL;
GDK_NOTE (EVENTS,
g_print (" (%d,%d)",
GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
@@ -2251,41 +2257,18 @@ gdk_event_translate (MSG *msg,
g_set_object (&window, find_window_for_mouse_event (window, msg));
if (pointer_grab != NULL && pointer_grab->implicit)
{
int state = build_pointer_event_state (msg);
{
int state = build_pointer_event_state (msg);
/* We keep the implicit grab until no buttons at all are held down */
if ((state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (button - 1))) == 0)
{
ReleaseCapture ();
/* We keep the implicit grab until no buttons at all are held down */
if ((state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (button - 1))) == 0)
{
release_implicit_grab = TRUE;
prev_surface = pointer_grab->surface;
}
}
new_window = NULL;
hwnd = WindowFromPoint (msg->pt);
if (hwnd != NULL)
{
POINT client_pt = msg->pt;
ScreenToClient (hwnd, &client_pt);
GetClientRect (hwnd, &rect);
if (PtInRect (&rect, client_pt))
new_window = gdk_win32_handle_table_lookup (hwnd);
}
synthesize_crossing_events (display,
_gdk_device_manager->system_pointer,
pointer_grab->surface, new_window,
GDK_CROSSING_UNGRAB,
&msg->pt,
0, /* TODO: Set right mask */
_gdk_win32_get_next_tick (msg->time),
FALSE);
g_set_object (&mouse_window, new_window);
mouse_window_ignored_leave = NULL;
}
}
generate_button_event (GDK_BUTTON_RELEASE, button,
window, msg);
generate_button_event (GDK_BUTTON_RELEASE, button, window, msg);
impl = GDK_WIN32_SURFACE (window);
@@ -2294,8 +2277,37 @@ gdk_event_translate (MSG *msg,
impl->drag_move_resize_context.button == button)
gdk_win32_surface_end_move_resize_drag (window);
if (release_implicit_grab)
{
ReleaseCapture ();
new_window = NULL;
hwnd = WindowFromPoint (msg->pt);
if (hwnd != NULL)
{
POINT client_pt = msg->pt;
ScreenToClient (hwnd, &client_pt);
GetClientRect (hwnd, &rect);
if (PtInRect (&rect, client_pt))
new_window = gdk_win32_handle_table_lookup (hwnd);
}
synthesize_crossing_events (display,
_gdk_device_manager->system_pointer,
prev_surface, new_window,
GDK_CROSSING_UNGRAB,
&msg->pt,
0, /* TODO: Set right mask */
_gdk_win32_get_next_tick (msg->time),
FALSE);
g_set_object (&mouse_window, new_window);
mouse_window_ignored_leave = NULL;
}
return_val = TRUE;
break;
}
case WM_MOUSEMOVE:
GDK_NOTE (EVENTS,
@@ -2320,60 +2332,35 @@ gdk_event_translate (MSG *msg,
pen_touch_input = FALSE;
new_window = window;
g_set_object (&window, find_window_for_mouse_event (window, msg));
if (pointer_grab != NULL)
{
POINT pt;
pt = msg->pt;
new_window = NULL;
hwnd = WindowFromPoint (pt);
if (hwnd != NULL)
{
POINT client_pt = pt;
ScreenToClient (hwnd, &client_pt);
GetClientRect (hwnd, &rect);
if (PtInRect (&rect, client_pt))
new_window = gdk_win32_handle_table_lookup (hwnd);
}
if (!pointer_grab->owner_events &&
new_window != NULL &&
new_window != pointer_grab->surface)
new_window = NULL;
}
if (mouse_window != new_window)
if (mouse_window != window)
{
GDK_NOTE (EVENTS, g_print (" mouse_window %p -> %p",
mouse_window ? GDK_SURFACE_HWND (mouse_window) : NULL,
new_window ? GDK_SURFACE_HWND (new_window) : NULL));
window ? GDK_SURFACE_HWND (window) : NULL));
synthesize_crossing_events (display,
_gdk_device_manager->system_pointer,
mouse_window, new_window,
mouse_window, window,
GDK_CROSSING_NORMAL,
&msg->pt,
0, /* TODO: Set right mask */
_gdk_win32_get_next_tick (msg->time),
FALSE);
g_set_object (&mouse_window, new_window);
g_set_object (&mouse_window, window);
mouse_window_ignored_leave = NULL;
if (new_window != NULL)
track_mouse_event (TME_LEAVE, GDK_SURFACE_HWND (new_window));
if (window != NULL)
track_mouse_event (TME_LEAVE, GDK_SURFACE_HWND (window));
}
else if (new_window != NULL &&
new_window == mouse_window_ignored_leave)
else if (window != NULL && window == mouse_window_ignored_leave)
{
/* If we ignored a leave event for this window and we're now getting
input again we need to re-arm the mouse tracking, as that was
cancelled by the mouseleave. */
mouse_window_ignored_leave = NULL;
track_mouse_event (TME_LEAVE, GDK_SURFACE_HWND (new_window));
track_mouse_event (TME_LEAVE, GDK_SURFACE_HWND (window));
}
g_set_object (&window, find_window_for_mouse_event (window, msg));
impl = GDK_WIN32_SURFACE (window);
/* If we haven't moved, don't create any GDK event. Windows
@@ -2742,7 +2729,8 @@ gdk_event_translate (MSG *msg,
build_pointer_event_state (msg),
delta_x,
delta_y,
FALSE);
FALSE,
GDK_SCROLL_UNIT_WHEEL);
/* Append the discrete version too */
direction = 0;
+4
View File
@@ -248,6 +248,10 @@ gdk_x11_clipboard_formats_from_atoms (GdkDisplay *display,
const char *name;
name = gdk_x11_get_xatom_name_for_display (display , atoms[i]);
if (!name)
{
continue;
}
if (strchr (name, '/'))
{
gdk_content_formats_builder_add_mime_type (builder, name);
+2 -1
View File
@@ -1778,7 +1778,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
state,
delta_x,
delta_y,
delta_x == 0.0 && delta_y == 0.0);
delta_x == 0.0 && delta_y == 0.0,
GDK_SCROLL_UNIT_WHEEL);
}
break;
}
+1 -1
View File
@@ -282,7 +282,7 @@ snapshot_uniforms (GskGLUniformState *state,
{
const GskGLUniformMapping *mapping = &program->mappings[i];
if (!mapping->info.initial && mapping->location > -1)
if (!mapping->info.initial && mapping->info.format && mapping->location > -1)
{
uniform[count].location = mapping->location;
uniform[count].info = mapping->info;
+87 -111
View File
@@ -44,9 +44,6 @@
#include <gdk/gdkprofilerprivate.h>
#include <gdk/gdktextureprivate.h>
#define ATLAS_SIZE 512
#define MAX_OLD_RATIO 0.5
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
static guint
@@ -156,50 +153,6 @@ gsk_gl_driver_collect_unused_textures (GskGLDriver *self,
return collected;
}
static void
gsk_gl_texture_atlas_free (GskGLTextureAtlas *atlas)
{
if (atlas->texture_id != 0)
{
glDeleteTextures (1, &atlas->texture_id);
atlas->texture_id = 0;
}
g_clear_pointer (&atlas->nodes, g_free);
g_slice_free (GskGLTextureAtlas, atlas);
}
GskGLTextureAtlas *
gsk_gl_driver_create_atlas (GskGLDriver *self)
{
GskGLTextureAtlas *atlas;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), NULL);
atlas = g_slice_new0 (GskGLTextureAtlas);
atlas->width = ATLAS_SIZE;
atlas->height = ATLAS_SIZE;
/* TODO: We might want to change the strategy about the amount of
* nodes here? stb_rect_pack.h says width is optimal. */
atlas->nodes = g_malloc0_n (atlas->width, sizeof (struct stbrp_node));
stbrp_init_target (&atlas->context, atlas->width, atlas->height, atlas->nodes, atlas->width);
atlas->texture_id = gsk_gl_command_queue_create_texture (self->command_queue,
atlas->width,
atlas->height,
GL_RGBA8,
GL_LINEAR,
GL_LINEAR);
gdk_gl_context_label_object_printf (gdk_gl_context_get_current (),
GL_TEXTURE, atlas->texture_id,
"Texture atlas %d",
atlas->texture_id);
g_ptr_array_add (self->atlases, atlas);
return atlas;
}
static void
remove_program (gpointer data)
{
@@ -226,6 +179,29 @@ gsk_gl_driver_shader_weak_cb (gpointer data,
g_hash_table_remove (self->shader_cache, where_object_was);
}
G_GNUC_NULL_TERMINATED static inline GBytes *
join_sources (GBytes *first_bytes,
...)
{
GByteArray *byte_array = g_byte_array_new ();
GBytes *bytes = first_bytes;
va_list args;
va_start (args, first_bytes);
while (bytes != NULL)
{
gsize len;
const guint8 *data = g_bytes_get_data (bytes, &len);
if (len > 0)
g_byte_array_append (byte_array, data, len);
g_bytes_unref (bytes);
bytes = va_arg (args, GBytes *);
}
va_end (args);
return g_byte_array_free_to_bytes (byte_array);
}
static void
gsk_gl_driver_dispose (GObject *object)
{
@@ -235,6 +211,10 @@ gsk_gl_driver_dispose (GObject *object)
g_assert (self->in_frame == FALSE);
#define GSK_GL_NO_UNIFORMS
#define GSK_GL_SHADER_RESOURCE(name)
#define GSK_GL_SHADER_STRING(str)
#define GSK_GL_SHADER_SINGLE(name)
#define GSK_GL_SHADER_JOINED(kind, ...)
#define GSK_GL_ADD_UNIFORM(pos, KEY, name)
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) \
GSK_GL_DELETE_PROGRAM(name); \
@@ -248,6 +228,10 @@ gsk_gl_driver_dispose (GObject *object)
} G_STMT_END;
# include "gskglprograms.defs"
#undef GSK_GL_NO_UNIFORMS
#undef GSK_GL_SHADER_RESOURCE
#undef GSK_GL_SHADER_STRING
#undef GSK_GL_SHADER_SINGLE
#undef GSK_GL_SHADER_JOINED
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_DEFINE_PROGRAM
@@ -289,11 +273,10 @@ gsk_gl_driver_dispose (GObject *object)
g_assert (!self->texture_id_to_key || g_hash_table_size (self->texture_id_to_key) == 0);
g_assert (!self->key_to_texture_id|| g_hash_table_size (self->key_to_texture_id) == 0);
g_clear_object (&self->glyphs);
g_clear_object (&self->icons);
g_clear_object (&self->shadows);
g_clear_object (&self->glyphs_library);
g_clear_object (&self->icons_library);
g_clear_object (&self->shadows_library);
g_clear_pointer (&self->atlases, g_ptr_array_unref);
g_clear_pointer (&self->autorelease_framebuffers, g_array_unref);
g_clear_pointer (&self->key_to_texture_id, g_hash_table_unref);
g_clear_pointer (&self->textures, g_hash_table_unref);
@@ -330,7 +313,6 @@ gsk_gl_driver_init (GskGLDriver *self)
self->shader_cache = g_hash_table_new_full (NULL, NULL, NULL, remove_program);
self->texture_pool = g_array_new (FALSE, FALSE, sizeof (guint));
self->render_targets = g_ptr_array_new ();
self->atlases = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
}
static gboolean
@@ -348,14 +330,14 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
/* Setup preambles that are shared by all shaders */
gsk_gl_compiler_set_preamble_from_resource (compiler,
GSK_GL_COMPILER_ALL,
"/org/gtk/libgsk/gl/preamble.glsl");
GSK_GL_COMPILER_ALL,
"/org/gtk/libgsk/gl/preamble.glsl");
gsk_gl_compiler_set_preamble_from_resource (compiler,
GSK_GL_COMPILER_VERTEX,
"/org/gtk/libgsk/gl/preamble.vs.glsl");
GSK_GL_COMPILER_VERTEX,
"/org/gtk/libgsk/gl/preamble.vs.glsl");
gsk_gl_compiler_set_preamble_from_resource (compiler,
GSK_GL_COMPILER_FRAGMENT,
"/org/gtk/libgsk/gl/preamble.fs.glsl");
GSK_GL_COMPILER_FRAGMENT,
"/org/gtk/libgsk/gl/preamble.fs.glsl");
/* Setup attributes that are provided via VBO */
gsk_gl_compiler_bind_attribute (compiler, "aPosition", 0);
@@ -365,10 +347,28 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
/* Use XMacros to register all of our programs and their uniforms */
#define GSK_GL_NO_UNIFORMS
#define GSK_GL_SHADER_RESOURCE(name) \
g_resources_lookup_data("/org/gtk/libgsk/gl/" name, 0, NULL)
#define GSK_GL_SHADER_STRING(str) \
g_bytes_new_static(str, strlen(str))
#define GSK_GL_SHADER_SINGLE(bytes) \
G_STMT_START { \
GBytes *b = bytes; \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_ALL, b); \
g_bytes_unref (b); \
} G_STMT_END;
#define GSK_GL_SHADER_JOINED(kind, ...) \
G_STMT_START { \
GBytes *bytes = join_sources(__VA_ARGS__); \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_##kind, bytes); \
g_bytes_unref (bytes); \
} G_STMT_END;
#define GSK_GL_ADD_UNIFORM(pos, KEY, name) \
gsk_gl_program_add_uniform (program, #name, UNIFORM_##KEY);
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) \
gsk_gl_compiler_set_source_from_resource (compiler, GSK_GL_COMPILER_ALL, resource); \
#define GSK_GL_DEFINE_PROGRAM(name, sources, uniforms) \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_VERTEX, NULL); \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_FRAGMENT, NULL); \
sources \
GSK_GL_COMPILE_PROGRAM(name ## _no_clip, uniforms, "#define NO_CLIP 1\n"); \
GSK_GL_COMPILE_PROGRAM(name ## _rect_clip, uniforms, "#define RECT_CLIP 1\n"); \
GSK_GL_COMPILE_PROGRAM(name, uniforms, "");
@@ -401,6 +401,11 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
#undef GSK_GL_DEFINE_PROGRAM_CLIP
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_SHADER_SINGLE
#undef GSK_GL_SHADER_JOINED
#undef GSK_GL_SHADER_RESOURCE
#undef GSK_GL_SHADER_STRING
#undef GSK_GL_NO_UNIFORMS
ret = TRUE;
@@ -456,9 +461,9 @@ gsk_gl_driver_new (GskGLCommandQueue *command_queue,
return NULL;
}
self->glyphs = gsk_gl_glyph_library_new (self);
self->icons = gsk_gl_icon_library_new (self);
self->shadows = gsk_gl_shadow_library_new (self);
self->glyphs_library = gsk_gl_glyph_library_new (self);
self->icons_library = gsk_gl_icon_library_new (self);
self->shadows_library = gsk_gl_shadow_library_new (self);
gdk_profiler_end_mark (before, "create GskGLDriver", NULL);
@@ -518,37 +523,6 @@ failure:
return g_steal_pointer (&driver);
}
static GPtrArray *
gsk_gl_driver_compact_atlases (GskGLDriver *self)
{
GPtrArray *removed = NULL;
g_assert (GSK_IS_GL_DRIVER (self));
for (guint i = self->atlases->len; i > 0; i--)
{
GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i - 1);
if (gsk_gl_texture_atlas_get_unused_ratio (atlas) > MAX_OLD_RATIO)
{
GSK_NOTE (GLYPH_CACHE,
g_message ("Dropping atlas %d (%g.2%% old)", i,
100.0 * gsk_gl_texture_atlas_get_unused_ratio (atlas)));
if (removed == NULL)
removed = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
g_ptr_array_add (removed, g_ptr_array_steal_index (self->atlases, i - 1));
}
}
GSK_NOTE (GLYPH_CACHE, {
static guint timestamp;
if (timestamp++ % 60 == 0)
g_message ("%d atlases", self->atlases->len);
});
return removed;
}
/**
* gsk_gl_driver_begin_frame:
* @self: a `GskGLDriver`
@@ -565,7 +539,6 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
GskGLCommandQueue *command_queue)
{
gint64 last_frame_id;
GPtrArray *removed;
g_return_if_fail (GSK_IS_GL_DRIVER (self));
g_return_if_fail (GSK_IS_GL_COMMAND_QUEUE (command_queue));
@@ -580,19 +553,14 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
gsk_gl_command_queue_begin_frame (self->command_queue);
/* Compact atlases with too many freed pixels */
removed = gsk_gl_driver_compact_atlases (self);
/* Mark unused pixel regions of the atlases */
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->icons),
self->current_frame_id,
removed);
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs),
self->current_frame_id,
removed);
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->icons_library),
self->current_frame_id);
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs_library),
self->current_frame_id);
/* Cleanup old shadows */
gsk_gl_shadow_library_begin_frame (self->shadows);
gsk_gl_shadow_library_begin_frame (self->shadows_library);
/* Remove all textures that are from a previous frame or are no
* longer used by linked GdkTexture. We do this at the beginning
@@ -600,9 +568,6 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
* we block on any resources while delivering our frames.
*/
gsk_gl_driver_collect_unused_textures (self, last_frame_id - 1);
/* Now free atlas textures */
g_clear_pointer (&removed, g_ptr_array_unref);
}
/**
@@ -831,7 +796,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
* to upload data, map to a framebuffer, or other uses which may
* modify the texture immediately.
*
* Typical examples for @format are GK_RGBA8, GL_RGBA16F or GL_RGBA32F.
* Typical examples for @format are GL_RGBA8, GL_RGBA16F or GL_RGBA32F.
*
* Use gsk_gl_driver_release_texture() to release this texture back into
* the pool so it may be reused later in the pipeline.
@@ -1182,14 +1147,23 @@ void
gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
const char *directory)
{
GPtrArray *atlases;
g_return_if_fail (GSK_IS_GL_DRIVER (self));
if (directory == NULL)
directory = ".";
for (guint i = 0; i < self->atlases->len; i++)
#define copy_atlases(dst, library) \
g_ptr_array_extend(dst, GSK_GL_TEXTURE_LIBRARY(library)->atlases, NULL, NULL)
atlases = g_ptr_array_new ();
copy_atlases (atlases, self->glyphs_library);
copy_atlases (atlases, self->icons_library);
#undef copy_atlases
for (guint i = 0; i < atlases->len; i++)
{
GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i);
GskGLTextureAtlas *atlas = g_ptr_array_index (atlases, i);
char *filename = g_strdup_printf ("%s%sframe-%d-atlas-%d.png",
directory,
G_DIR_SEPARATOR_S,
@@ -1198,6 +1172,8 @@ gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
write_atlas_to_png (self, atlas, filename);
g_free (filename);
}
g_ptr_array_unref (atlases);
}
#endif
+3 -6
View File
@@ -100,17 +100,15 @@ struct _GskGLDriver
GskGLCommandQueue *shared_command_queue;
GskGLCommandQueue *command_queue;
GskGLGlyphLibrary *glyphs;
GskGLIconLibrary *icons;
GskGLShadowLibrary *shadows;
GskGLGlyphLibrary *glyphs_library;
GskGLIconLibrary *icons_library;
GskGLShadowLibrary *shadows_library;
GArray *texture_pool;
GHashTable *textures;
GHashTable *key_to_texture_id;
GHashTable *texture_id_to_key;
GPtrArray *atlases;
GHashTable *shader_cache;
GArray *autorelease_framebuffers;
@@ -184,7 +182,6 @@ void gsk_gl_driver_add_texture_slices (GskGLDriver *s
GskGLProgram * gsk_gl_driver_lookup_shader (GskGLDriver *self,
GskGLShader *shader,
GError **error);
GskGLTextureAtlas * gsk_gl_driver_create_atlas (GskGLDriver *self);
#ifdef G_ENABLE_DEBUG
void gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
+54 -4
View File
@@ -84,15 +84,64 @@ gsk_gl_glyph_value_free (gpointer data)
}
static void
gsk_gl_glyph_library_begin_frame (GskGLTextureLibrary *library,
gint64 frame_id,
GPtrArray *removed_atlases)
gsk_gl_glyph_library_clear_cache (GskGLTextureLibrary *library)
{
GskGLGlyphLibrary *self = (GskGLGlyphLibrary *)library;
g_assert (GSK_IS_GL_GLYPH_LIBRARY (self));
memset (self->front, 0, sizeof self->front);
}
static void
gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
GskGLTextureAtlas *atlas)
{
gboolean packed G_GNUC_UNUSED;
int x, y;
guint gl_format;
guint gl_type;
guint8 pixel_data[4 * 3 * 3];
g_assert (GSK_IS_GL_GLYPH_LIBRARY (self));
g_assert (atlas != NULL);
/* Insert a single pixel at 0,0 for use in coloring */
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
"Initializing Atlas");
packed = gsk_gl_texture_library_allocate (self, atlas, 3, 3, &x, &y);
g_assert (packed);
g_assert (x == 0 && y == 0);
memset (pixel_data, 255, sizeof pixel_data);
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
gl_format = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
}
else
{
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
glTexSubImage2D (GL_TEXTURE_2D, 0,
0, 0,
3, 3,
gl_format, gl_type,
pixel_data);
gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
self->driver->command_queue->n_uploads++;
}
static void
gsk_gl_glyph_library_finalize (GObject *object)
{
@@ -111,7 +160,8 @@ gsk_gl_glyph_library_class_init (GskGLGlyphLibraryClass *klass)
object_class->finalize = gsk_gl_glyph_library_finalize;
library_class->begin_frame = gsk_gl_glyph_library_begin_frame;
library_class->clear_cache = gsk_gl_glyph_library_clear_cache;
library_class->init_atlas = gsk_gl_glyph_library_init_atlas;
}
static void
+16 -16
View File
@@ -1,71 +1,71 @@
GSK_GL_DEFINE_PROGRAM (blend,
"/org/gtk/libgsk/gl/blend.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("blend.glsl")),
GSK_GL_ADD_UNIFORM (1, BLEND_SOURCE2, u_source2)
GSK_GL_ADD_UNIFORM (2, BLEND_MODE, u_mode))
GSK_GL_DEFINE_PROGRAM (blit,
"/org/gtk/libgsk/gl/blit.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("blit.glsl")),
GSK_GL_NO_UNIFORMS)
GSK_GL_DEFINE_PROGRAM (blur,
"/org/gtk/libgsk/gl/blur.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("blur.glsl")),
GSK_GL_ADD_UNIFORM (1, BLUR_RADIUS, u_blur_radius)
GSK_GL_ADD_UNIFORM (2, BLUR_SIZE, u_blur_size)
GSK_GL_ADD_UNIFORM (3, BLUR_DIR, u_blur_dir))
GSK_GL_DEFINE_PROGRAM (border,
"/org/gtk/libgsk/gl/border.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("border.glsl")),
GSK_GL_ADD_UNIFORM (1, BORDER_WIDTHS, u_widths)
GSK_GL_ADD_UNIFORM (2, BORDER_OUTLINE_RECT, u_outline_rect))
GSK_GL_DEFINE_PROGRAM (color,
"/org/gtk/libgsk/gl/color.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("color.glsl")),
GSK_GL_NO_UNIFORMS)
GSK_GL_DEFINE_PROGRAM (coloring,
"/org/gtk/libgsk/gl/coloring.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("coloring.glsl")),
GSK_GL_NO_UNIFORMS)
GSK_GL_DEFINE_PROGRAM (color_matrix,
"/org/gtk/libgsk/gl/color_matrix.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("color_matrix.glsl")),
GSK_GL_ADD_UNIFORM (1, COLOR_MATRIX_COLOR_MATRIX, u_color_matrix)
GSK_GL_ADD_UNIFORM (2, COLOR_MATRIX_COLOR_OFFSET, u_color_offset))
GSK_GL_DEFINE_PROGRAM (conic_gradient,
"/org/gtk/libgsk/gl/conic_gradient.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("conic_gradient.glsl")),
GSK_GL_ADD_UNIFORM (1, CONIC_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_GL_ADD_UNIFORM (2, CONIC_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_GL_ADD_UNIFORM (3, CONIC_GRADIENT_GEOMETRY, u_geometry))
GSK_GL_DEFINE_PROGRAM (cross_fade,
"/org/gtk/libgsk/gl/cross_fade.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("cross_fade.glsl")),
GSK_GL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress)
GSK_GL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2))
GSK_GL_DEFINE_PROGRAM (filled_border,
"/org/gtk/libgsk/gl/filled_border.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("filled_border.glsl")),
GSK_GL_ADD_UNIFORM (1, FILLED_BORDER_WIDTHS, u_widths)
GSK_GL_ADD_UNIFORM (2, FILLED_BORDER_OUTLINE_RECT, u_outline_rect))
GSK_GL_DEFINE_PROGRAM (inset_shadow,
"/org/gtk/libgsk/gl/inset_shadow.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("inset_shadow.glsl")),
GSK_GL_ADD_UNIFORM (1, INSET_SHADOW_SPREAD, u_spread)
GSK_GL_ADD_UNIFORM (2, INSET_SHADOW_OFFSET, u_offset)
GSK_GL_ADD_UNIFORM (3, INSET_SHADOW_OUTLINE_RECT, u_outline_rect))
GSK_GL_DEFINE_PROGRAM (linear_gradient,
"/org/gtk/libgsk/gl/linear_gradient.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("linear_gradient.glsl")),
GSK_GL_ADD_UNIFORM (1, LINEAR_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_GL_ADD_UNIFORM (2, LINEAR_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_GL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points)
GSK_GL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat))
GSK_GL_DEFINE_PROGRAM (outset_shadow,
"/org/gtk/libgsk/gl/outset_shadow.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("outset_shadow.glsl")),
GSK_GL_ADD_UNIFORM (1, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
GSK_GL_DEFINE_PROGRAM (radial_gradient,
"/org/gtk/libgsk/gl/radial_gradient.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("radial_gradient.glsl")),
GSK_GL_ADD_UNIFORM (1, RADIAL_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_GL_ADD_UNIFORM (2, RADIAL_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_GL_ADD_UNIFORM (3, RADIAL_GRADIENT_REPEAT, u_repeat)
@@ -73,12 +73,12 @@ GSK_GL_DEFINE_PROGRAM (radial_gradient,
GSK_GL_ADD_UNIFORM (5, RADIAL_GRADIENT_GEOMETRY, u_geometry))
GSK_GL_DEFINE_PROGRAM (repeat,
"/org/gtk/libgsk/gl/repeat.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("repeat.glsl")),
GSK_GL_ADD_UNIFORM (1, REPEAT_CHILD_BOUNDS, u_child_bounds)
GSK_GL_ADD_UNIFORM (2, REPEAT_TEXTURE_RECT, u_texture_rect))
GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
"/org/gtk/libgsk/gl/unblurred_outset_shadow.glsl",
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("unblurred_outset_shadow.glsl")),
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
+97 -113
View File
@@ -2512,7 +2512,9 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
scaled_outline.corner[i].height *= scale_y;
}
cached_tid = gsk_gl_shadow_library_lookup (job->driver->shadows, &scaled_outline, blur_radius);
cached_tid = gsk_gl_shadow_library_lookup (job->driver->shadows_library,
&scaled_outline,
blur_radius);
if (cached_tid == 0)
{
@@ -2574,7 +2576,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
blur_radius * scale_x,
blur_radius * scale_y);
gsk_gl_shadow_library_insert (job->driver->shadows,
gsk_gl_shadow_library_insert (job->driver->shadows_library,
&scaled_outline,
blur_radius,
blurred_texture_id);
@@ -2858,58 +2860,6 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
gsk_gl_render_job_end_draw (job);
}
static gboolean
is_non_branching (const GskRenderNode *node)
{
switch ((int)gsk_render_node_get_node_type (node))
{
case GSK_COLOR_NODE:
case GSK_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_CONIC_GRADIENT_NODE:
case GSK_BORDER_NODE:
case GSK_TEXTURE_NODE:
case GSK_INSET_SHADOW_NODE:
case GSK_OUTSET_SHADOW_NODE:
case GSK_TEXT_NODE:
case GSK_CAIRO_NODE:
return TRUE;
case GSK_TRANSFORM_NODE:
return is_non_branching (gsk_transform_node_get_child (node));
case GSK_OPACITY_NODE:
return is_non_branching (gsk_opacity_node_get_child (node));
case GSK_COLOR_MATRIX_NODE:
return is_non_branching (gsk_color_matrix_node_get_child (node));
case GSK_CLIP_NODE:
return is_non_branching (gsk_clip_node_get_child (node));
case GSK_ROUNDED_CLIP_NODE:
return is_non_branching (gsk_rounded_clip_node_get_child (node));
case GSK_SHADOW_NODE:
return is_non_branching (gsk_shadow_node_get_child (node));
case GSK_BLUR_NODE:
return is_non_branching (gsk_shadow_node_get_child (node));
case GSK_DEBUG_NODE:
return is_non_branching (gsk_debug_node_get_child (node));
case GSK_CONTAINER_NODE:
return gsk_container_node_get_n_children (node) == 1 &&
is_non_branching (gsk_container_node_get_child (node, 0));
default:
return FALSE;
}
}
static inline void
gsk_gl_render_job_visit_opacity_node (GskGLRenderJob *job,
const GskRenderNode *node)
@@ -2922,11 +2872,7 @@ gsk_gl_render_job_visit_opacity_node (GskGLRenderJob *job,
{
float prev_alpha = gsk_gl_render_job_set_alpha (job, new_alpha);
/* Handle a few easy cases without offscreen. We bail out
* as soon as we see nodes with multiple children - in theory,
* we would only need offscreens for overlapping children.
*/
if (is_non_branching (child))
if (!gsk_render_node_use_offscreen_for_opacity (child))
{
gsk_gl_render_job_visit_node (job, child);
gsk_gl_render_job_set_alpha (job, prev_alpha);
@@ -2996,7 +2942,7 @@ gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
float x = offset->x + job->offset_x;
float y = offset->y + job->offset_y;
GskGLGlyphLibrary *library = job->driver->glyphs;
GskGLGlyphLibrary *library = job->driver->glyphs_library;
GskGLCommandBatch *batch;
int x_position = 0;
GskGLGlyphKey lookup;
@@ -3499,14 +3445,14 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
GdkTexture *texture,
GskGLRenderOffscreen *offscreen)
{
if (gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons,
if (gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
texture->width,
texture->height) &&
!GDK_IS_GL_TEXTURE (texture))
{
const GskGLIconData *icon_data;
gsk_gl_icon_library_lookup_or_add (job->driver->icons, texture, &icon_data);
gsk_gl_icon_library_lookup_or_add (job->driver->icons_library, texture, &icon_data);
offscreen->texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
memcpy (&offscreen->area, &icon_data->entry.area, sizeof offscreen->area);
}
@@ -3869,7 +3815,6 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
filter = offscreen->linear_filter ? GL_LINEAR : GL_NEAREST;
/* Check if we've already cached the drawn texture. */
key.pointer = node;
key.pointer_is_child = TRUE; /* Don't conflict with the child using the cache too */
key.parent_rect = *offscreen->bounds;
@@ -3877,61 +3822,111 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
key.scale_y = job->scale_y;
key.filter = filter;
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key);
float offset_x = job->offset_x;
float offset_y = job->offset_y;
gboolean flipped_x = job->scale_x < 0;
gboolean flipped_y = job->scale_y < 0;
graphene_rect_t viewport;
if (cached_id != 0)
if (flipped_x || flipped_y)
{
offscreen->texture_id = cached_id;
init_full_texture_region (offscreen);
/* We didn't render it offscreen, but hand out an offscreen texture id */
offscreen->was_offscreen = TRUE;
return TRUE;
GskTransform *transform = gsk_transform_scale (NULL,
flipped_x ? -1 : 1,
flipped_y ? -1 : 1);
gsk_gl_render_job_push_modelview (job, transform);
}
float scaled_width;
float scaled_height;
float downscale_x = 1;
float downscale_y = 1;
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
g_assert (job->command_queue->max_texture_size > 0);
float aligned_x = floorf (viewport.origin.x);
float padding_left = viewport.origin.x - aligned_x;
float aligned_width = ceilf (viewport.size.width + padding_left);
float padding_right = aligned_width - viewport.size.width - padding_left;
float aligned_y = floorf (viewport.origin.y);
float padding_top = viewport.origin.y - aligned_y;
float aligned_height = ceilf (viewport.size.height + padding_top);
float padding_bottom = aligned_height - viewport.size.height - padding_top;
/* Tweak the scale factor so that the required texture doesn't
* exceed the max texture limit. This will render with a lower
* resolution, but this is better than clipping.
*/
{
int max_texture_size = job->command_queue->max_texture_size;
scaled_width = ceilf (offscreen->bounds->size.width * fabs (job->scale_x));
if (scaled_width > max_texture_size)
{
downscale_x = (float)max_texture_size / scaled_width;
scaled_width = max_texture_size;
}
if (job->scale_x < 0)
downscale_x = -downscale_x;
g_assert (job->command_queue->max_texture_size > 0);
scaled_height = ceilf (offscreen->bounds->size.height * fabs (job->scale_y));
if (scaled_height > max_texture_size)
{
downscale_y = (float)max_texture_size / scaled_height;
scaled_height = max_texture_size;
}
if (job->scale_y < 0)
downscale_y = -downscale_y;
}
float downscale_x = 1;
float downscale_y = 1;
int texture_width;
int texture_height;
int max_texture_size = job->command_queue->max_texture_size;
if (aligned_width > max_texture_size)
downscale_x = (float)max_texture_size / viewport.size.width;
if (aligned_height > max_texture_size)
downscale_y = (float)max_texture_size / viewport.size.height;
if (downscale_x != 1 || downscale_y != 1)
{
GskTransform *transform = gsk_transform_scale (NULL, downscale_x, downscale_y);
gsk_gl_render_job_push_modelview (job, transform);
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
}
if (downscale_x == 1)
{
viewport.origin.x = aligned_x;
viewport.size.width = aligned_width;
offscreen->area.x = padding_left / aligned_width;
offscreen->area.x2 = 1.0f - (padding_right / aligned_width);
texture_width = aligned_width;
}
else
{
offscreen->area.x = 0;
offscreen->area.x2 = 1;
texture_width = max_texture_size;
}
if (downscale_y == 1)
{
viewport.origin.y = aligned_y;
viewport.size.height = aligned_height;
offscreen->area.y = padding_bottom / aligned_height;
offscreen->area.y2 = 1.0f - padding_top / aligned_height;
texture_height = aligned_height;
}
else
{
offscreen->area.y = 0;
offscreen->area.y2 = 1;
texture_height = max_texture_size;
}
/* Check if we've already cached the drawn texture. */
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key);
if (cached_id != 0)
{
if (downscale_x != 1 || downscale_y != 1)
gsk_gl_render_job_pop_modelview (job);
if (flipped_x || flipped_y)
gsk_gl_render_job_pop_modelview (job);
offscreen->texture_id = cached_id;
/* We didn't render it offscreen, but hand out an offscreen texture id */
offscreen->was_offscreen = TRUE;
return TRUE;
}
GskGLRenderTarget *render_target;
graphene_matrix_t prev_projection;
graphene_rect_t prev_viewport;
graphene_rect_t viewport;
float offset_x = job->offset_x;
float offset_y = job->offset_y;
float prev_alpha;
guint prev_fbo;
if (!gsk_gl_driver_create_render_target (job->driver,
scaled_width, scaled_height,
texture_width, texture_height,
get_target_format (job, node),
filter, filter,
&render_target))
@@ -3953,19 +3948,6 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
render_target->framebuffer_id);
}
if (downscale_x != 1 || downscale_y != 1)
{
GskTransform *transform = gsk_transform_scale (NULL, downscale_x, downscale_y);
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
}
gsk_gl_render_job_transform_bounds (job, offscreen->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;
gsk_gl_render_job_set_viewport (job, &viewport, &prev_viewport);
gsk_gl_render_job_set_projection_from_rect (job, &job->viewport, &prev_projection);
prev_alpha = gsk_gl_render_job_set_alpha (job, 1.0f);
@@ -3983,6 +3965,10 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
if (downscale_x != 1 || downscale_y != 1)
gsk_gl_render_job_pop_modelview (job);
if (flipped_x || flipped_y)
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL);
gsk_gl_render_job_set_projection (job, &prev_projection);
gsk_gl_render_job_set_alpha (job, prev_alpha);
@@ -3996,8 +3982,6 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
render_target,
FALSE);
init_full_texture_region (offscreen);
if (!offscreen->do_not_cache)
gsk_gl_driver_cache_texture (job->driver, &key, offscreen->texture_id);
+2 -2
View File
@@ -29,9 +29,9 @@
struct _GskGLShadowLibrary
{
GObject parent_instance;
GObject parent_instance;
GskGLDriver *driver;
GArray *shadows;
GArray *shadows;
};
typedef struct _Shadow
+318 -158
View File
@@ -27,7 +27,10 @@
#include "gskgldriverprivate.h"
#include "gskgltexturelibraryprivate.h"
#define MAX_FRAME_AGE 60
#define DEFAULT_MAX_FRAME_AGE 60
#define DEFAULT_ATLAS_WIDTH 512
#define DEFAULT_ATLAS_HEIGHT 512
#define MAX_OLD_RATIO 0.5
G_DEFINE_ABSTRACT_TYPE (GskGLTextureLibrary, gsk_gl_texture_library, G_TYPE_OBJECT)
@@ -39,6 +42,149 @@ enum {
static GParamSpec *properties [N_PROPS];
static void
gsk_gl_texture_atlas_free (GskGLTextureAtlas *atlas)
{
if (atlas->texture_id != 0)
{
glDeleteTextures (1, &atlas->texture_id);
atlas->texture_id = 0;
}
g_clear_pointer (&atlas->nodes, g_free);
g_slice_free (GskGLTextureAtlas, atlas);
}
static gboolean
gsk_gl_texture_library_real_compact (GskGLTextureLibrary *self,
gint64 frame_id)
{
GPtrArray *removed = NULL;
gboolean ret = FALSE;
gboolean periodic_scan;
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
periodic_scan = (self->max_frame_age > 0 &&
(frame_id % self->max_frame_age) == 0);
for (guint i = self->atlases->len; i > 0; i--)
{
GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i - 1);
if (gsk_gl_texture_atlas_get_unused_ratio (atlas) > MAX_OLD_RATIO)
{
GSK_NOTE (GLYPH_CACHE,
g_message ("Dropping atlas %d (%g.2%% old)", i,
100.0 * gsk_gl_texture_atlas_get_unused_ratio (atlas)));
if (removed == NULL)
removed = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
g_ptr_array_add (removed, g_ptr_array_steal_index (self->atlases, i - 1));
}
}
if (periodic_scan || removed != NULL)
{
GskGLTextureAtlasEntry *entry;
GHashTableIter iter;
guint dropped = 0;
guint atlased = 0;
g_hash_table_iter_init (&iter, self->hash_table);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&entry))
{
if (entry->is_atlased)
{
if (removed && g_ptr_array_find (removed, entry->atlas, NULL))
{
g_hash_table_iter_remove (&iter);
dropped++;
}
else if (periodic_scan)
{
gsk_gl_texture_atlas_entry_mark_unused (entry);
entry->accessed = FALSE;
if (entry->is_atlased)
atlased++;
}
}
else
{
if (!entry->accessed)
{
gsk_gl_driver_release_texture (self->driver, entry->texture);
g_hash_table_iter_remove (&iter);
dropped++;
}
if (periodic_scan)
entry->accessed = FALSE;
}
}
GSK_NOTE (GLYPH_CACHE, g_message ("%s: Dropped %d individual items",
G_OBJECT_TYPE_NAME (self),
dropped);
g_message ("%s: %d items cached (%d atlased, %d individually)",
G_OBJECT_TYPE_NAME (self),
g_hash_table_size (self->hash_table),
atlased,
g_hash_table_size (self->hash_table) - atlased));
if (dropped > 0)
gsk_gl_texture_library_clear_cache (self);
ret = TRUE;
g_clear_pointer (&removed, g_ptr_array_unref);
}
GSK_NOTE (GLYPH_CACHE, {
static gint64 last_message;
gint64 now = g_get_monotonic_time ();
if (now - last_message > G_USEC_PER_SEC)
{
last_message = now;
g_message ("%s contains %d atlases",
G_OBJECT_TYPE_NAME (self),
self->atlases->len);
}
});
return ret;
}
static gboolean
gsk_gl_texture_library_real_allocate (GskGLTextureLibrary *self,
GskGLTextureAtlas *atlas,
int width,
int height,
int *out_x,
int *out_y)
{
stbrp_rect rect;
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
g_assert (atlas != NULL);
g_assert (width > 0);
g_assert (height > 0);
g_assert (out_x != NULL);
g_assert (out_y != NULL);
rect.w = width;
rect.h = height;
stbrp_pack_rects (&atlas->context, &rect, 1);
if (rect.was_packed)
{
*out_x = rect.x;
*out_y = rect.y;
}
return rect.was_packed;
}
static void
gsk_gl_texture_library_constructed (GObject *object)
{
@@ -52,6 +198,7 @@ gsk_gl_texture_library_dispose (GObject *object)
{
GskGLTextureLibrary *self = (GskGLTextureLibrary *)object;
g_clear_pointer (&self->atlases, g_ptr_array_unref);
g_clear_object (&self->driver);
G_OBJECT_CLASS (gsk_gl_texture_library_parent_class)->dispose (object);
@@ -105,6 +252,9 @@ gsk_gl_texture_library_class_init (GskGLTextureLibraryClass *klass)
object_class->get_property = gsk_gl_texture_library_get_property;
object_class->set_property = gsk_gl_texture_library_set_property;
klass->compact = gsk_gl_texture_library_real_compact;
klass->allocate = gsk_gl_texture_library_real_allocate;
properties [PROP_DRIVER] =
g_param_spec_object ("driver",
"Driver",
@@ -118,6 +268,10 @@ gsk_gl_texture_library_class_init (GskGLTextureLibraryClass *klass)
static void
gsk_gl_texture_library_init (GskGLTextureLibrary *self)
{
self->max_frame_age = DEFAULT_MAX_FRAME_AGE;
self->atlas_width = DEFAULT_ATLAS_WIDTH;
self->atlas_height = DEFAULT_ATLAS_HEIGHT;
self->atlases = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
}
void
@@ -136,78 +290,14 @@ gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self,
void
gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
gint64 frame_id,
GPtrArray *removed_atlases)
gint64 frame_id)
{
GHashTableIter iter;
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
gsk_gl_texture_library_compact (self, frame_id);
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->begin_frame)
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->begin_frame (self, frame_id, removed_atlases);
if (removed_atlases != NULL)
{
GskGLTextureAtlasEntry *entry;
guint dropped = 0;
g_hash_table_iter_init (&iter, self->hash_table);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&entry))
{
if (entry->is_atlased)
{
for (guint i = 0; i < removed_atlases->len; i++)
{
GskGLTextureAtlas *atlas = g_ptr_array_index (removed_atlases, i);
if (atlas == entry->atlas)
{
g_hash_table_iter_remove (&iter);
dropped++;
break;
}
}
}
}
GSK_NOTE (GLYPH_CACHE,
if (dropped > 0)
g_message ("%s: Dropped %d items",
G_OBJECT_TYPE_NAME (self), dropped));
}
if (frame_id % MAX_FRAME_AGE == 0)
{
GskGLTextureAtlasEntry *entry;
int atlased = 0;
int dropped = 0;
g_hash_table_iter_init (&iter, self->hash_table);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&entry))
{
if (!entry->is_atlased && !entry->accessed)
{
gsk_gl_driver_release_texture (self->driver, entry->texture);
g_hash_table_iter_remove (&iter);
dropped++;
continue;
}
gsk_gl_texture_atlas_entry_mark_unused (entry);
entry->accessed = FALSE;
if (entry->is_atlased)
atlased++;
}
GSK_NOTE (GLYPH_CACHE, g_message ("%s: Dropped %d individual items",
G_OBJECT_TYPE_NAME (self),
dropped);
g_message ("%s: %d items cached (%d atlased, %d individually)",
G_OBJECT_TYPE_NAME (self),
g_hash_table_size (self->hash_table),
atlased,
g_hash_table_size (self->hash_table) - atlased));
}
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->begin_frame (self, frame_id);
}
static GskGLTexture *
@@ -234,90 +324,29 @@ gsk_gl_texture_library_pack_one (GskGLTextureLibrary *self,
return texture;
}
static inline gboolean
gsk_gl_texture_atlas_pack (GskGLTextureAtlas *self,
int width,
int height,
int *out_x,
int *out_y)
{
stbrp_rect rect;
rect.w = width;
rect.h = height;
stbrp_pack_rects (&self->context, &rect, 1);
if (rect.was_packed)
{
*out_x = rect.x;
*out_y = rect.y;
}
return rect.was_packed;
}
static void
gsk_gl_texture_atlas_initialize (GskGLDriver *driver,
GskGLTextureAtlas *atlas)
{
/* Insert a single pixel at 0,0 for use in coloring */
gboolean packed G_GNUC_UNUSED;
int x, y;
guint gl_format;
guint gl_type;
guint8 pixel_data[4 * 3 * 3];
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
"Initializing Atlas");
packed = gsk_gl_texture_atlas_pack (atlas, 3, 3, &x, &y);
g_assert (packed);
g_assert (x == 0 && y == 0);
memset (pixel_data, 255, sizeof pixel_data);
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
gl_format = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
}
else
{
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
glTexSubImage2D (GL_TEXTURE_2D, 0,
0, 0,
3, 3,
gl_format, gl_type,
pixel_data);
gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
driver->command_queue->n_uploads++;
}
static void
gsk_gl_texture_atlases_pack (GskGLDriver *driver,
int width,
int height,
GskGLTextureAtlas **out_atlas,
int *out_x,
int *out_y)
gsk_gl_texture_library_pack_any_atlas (GskGLTextureLibrary *self,
int width,
int height,
GskGLTextureAtlas **out_atlas,
int *out_x,
int *out_y)
{
GskGLTextureAtlas *atlas = NULL;
int x, y;
for (guint i = 0; i < driver->atlases->len; i++)
{
atlas = g_ptr_array_index (driver->atlases, i);
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
g_assert (width > 0);
g_assert (height > 0);
g_assert (out_atlas != NULL);
g_assert (out_x != NULL);
g_assert (out_y != NULL);
if (gsk_gl_texture_atlas_pack (atlas, width, height, &x, &y))
for (guint i = 0; i < self->atlases->len; i++)
{
atlas = g_ptr_array_index (self->atlases, i);
if (gsk_gl_texture_library_allocate (self, atlas, width, height, &x, &y))
break;
atlas = NULL;
@@ -326,12 +355,10 @@ gsk_gl_texture_atlases_pack (GskGLDriver *driver,
if (atlas == NULL)
{
/* No atlas has enough space, so create a new one... */
atlas = gsk_gl_driver_create_atlas (driver);
gsk_gl_texture_atlas_initialize (driver, atlas);
atlas = gsk_gl_texture_library_acquire_atlas (self);
/* Pack it onto that one, which surely has enough space... */
if (!gsk_gl_texture_atlas_pack (atlas, width, height, &x, &y))
if (!gsk_gl_texture_library_allocate (self, atlas, width, height, &x, &y))
g_assert_not_reached ();
}
@@ -380,17 +407,19 @@ gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
*out_packed_x = 0;
*out_packed_y = 0;
}
else if (width <= self->max_entry_size && height <= self->max_entry_size)
else if (self->max_entry_size == 0 ||
(width <= self->max_entry_size &&
height <= self->max_entry_size))
{
int packed_x;
int packed_y;
gsk_gl_texture_atlases_pack (self->driver,
padding + width + padding,
padding + height + padding,
&atlas,
&packed_x,
&packed_y);
gsk_gl_texture_library_pack_any_atlas (self,
padding + width + padding,
padding + height + padding,
&atlas,
&packed_x,
&packed_y);
entry->atlas = atlas;
entry->is_atlased = TRUE;
@@ -424,3 +453,134 @@ gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
return entry;
}
/*
* gsk_gl_texture_library_clear_cache:
*
* Clear the front cache if the texture library is using one. For
* example the glyph cache would drop it's front cache to force
* next lookups to fall through to the GHashTable key lookup.
*/
void
gsk_gl_texture_library_clear_cache (GskGLTextureLibrary *self)
{
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->clear_cache)
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->clear_cache (self);
}
/*
* gsk_gl_texture_library_compact:
*
* Requests that the texture library compact it's altases. That
* generally means to traverse them to look for unused pixels over
* a certain threshold and release them if necessary.
*
* Returns: %TRUE if any compaction occurred.
*/
gboolean
gsk_gl_texture_library_compact (GskGLTextureLibrary *self,
gint64 frame_id)
{
g_return_val_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self), FALSE);
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->compact)
return GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->compact (self, frame_id);
return FALSE;
}
void
gsk_gl_texture_library_reset (GskGLTextureLibrary *self)
{
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
gsk_gl_texture_library_clear_cache (self);
g_hash_table_remove_all (self->hash_table);
if (self->atlases->len)
g_ptr_array_remove_range (self->atlases, 0, self->atlases->len);
}
void
gsk_gl_texture_library_set_atlas_size (GskGLTextureLibrary *self,
int width,
int height)
{
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
if (width <= 0)
width = DEFAULT_ATLAS_WIDTH;
if (height <= 0)
height = DEFAULT_ATLAS_HEIGHT;
self->atlas_height = height;
self->atlas_width = width;
gsk_gl_texture_library_reset (self);
}
/*
* gsk_gl_texture_library_acquire_atlas:
*
* Allocates a new texture atlas based on the current size
* and format requirements.
*/
GskGLTextureAtlas *
gsk_gl_texture_library_acquire_atlas (GskGLTextureLibrary *self)
{
GskGLTextureAtlas *atlas;
g_return_val_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self), NULL);
g_return_val_if_fail (GSK_IS_GL_DRIVER (self->driver), NULL);
g_return_val_if_fail (GSK_IS_GL_COMMAND_QUEUE (self->driver->command_queue), NULL);
g_return_val_if_fail (self->atlas_width > 0, NULL);
g_return_val_if_fail (self->atlas_height > 0, NULL);
atlas = g_slice_new0 (GskGLTextureAtlas);
atlas->width = self->atlas_width;
atlas->height = self->atlas_height;
/* TODO: We might want to change the strategy about the amount of
* nodes here? stb_rect_pack.h says width is optimal. */
atlas->nodes = g_malloc0_n (atlas->width, sizeof (struct stbrp_node));
stbrp_init_target (&atlas->context, atlas->width, atlas->height, atlas->nodes, atlas->width);
atlas->texture_id = gsk_gl_command_queue_create_texture (self->driver->command_queue,
atlas->width,
atlas->height,
GL_RGBA8,
GL_LINEAR,
GL_LINEAR);
gdk_gl_context_label_object_printf (gdk_gl_context_get_current (),
GL_TEXTURE, atlas->texture_id,
"Texture atlas %d",
atlas->texture_id);
g_ptr_array_add (self->atlases, atlas);
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->init_atlas)
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->init_atlas (self, atlas);
return atlas;
}
gboolean
gsk_gl_texture_library_allocate (GskGLTextureLibrary *self,
GskGLTextureAtlas *atlas,
int width,
int height,
int *out_x,
int *out_y)
{
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
g_assert (atlas != NULL);
g_assert (width > 0);
g_assert (height > 0);
g_assert (out_x != NULL);
g_assert (out_y != NULL);
return GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->allocate (self, atlas, width, height, out_x, out_y);
}
+50 -24
View File
@@ -50,7 +50,6 @@ typedef struct _GskGLTextureAtlas
*/
int unused_pixels;
void *user_data;
} GskGLTextureAtlas;
typedef struct _GskGLTextureAtlasEntry
@@ -89,40 +88,67 @@ typedef struct _GskGLTextureAtlasEntry
typedef struct _GskGLTextureLibrary
{
GObject parent_instance;
GObject parent_instance;
GskGLDriver *driver;
GHashTable *hash_table;
guint max_entry_size;
GPtrArray *atlases;
GHashTable *hash_table;
guint max_entry_size;
guint max_frame_age;
guint atlas_width;
guint atlas_height;
} GskGLTextureLibrary;
typedef struct _GskGLTextureLibraryClass
{
GObjectClass parent_class;
void (*begin_frame) (GskGLTextureLibrary *library,
gint64 frame_id,
GPtrArray *removed_atlases);
void (*begin_frame) (GskGLTextureLibrary *library,
gint64 frame_id);
gboolean (*compact) (GskGLTextureLibrary *library,
gint64 frame_id);
void (*clear_cache) (GskGLTextureLibrary *library);
void (*init_atlas) (GskGLTextureLibrary *library,
GskGLTextureAtlas *atlas);
gboolean (*allocate) (GskGLTextureLibrary *library,
GskGLTextureAtlas *atlas,
int width,
int height,
int *out_x,
int *out_y);
} GskGLTextureLibraryClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GskGLTextureLibrary, g_object_unref)
GType gsk_gl_texture_library_get_type (void) G_GNUC_CONST;
void gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self,
GHashFunc hash_func,
GEqualFunc equal_func,
GDestroyNotify key_destroy,
GDestroyNotify value_destroy);
void gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
gint64 frame_id,
GPtrArray *removed_atlases);
gpointer gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
gpointer key,
gsize valuelen,
guint width,
guint height,
int padding,
guint *out_packed_x,
guint *out_packed_y);
GType gsk_gl_texture_library_get_type (void) G_GNUC_CONST;
gboolean gsk_gl_texture_library_compact (GskGLTextureLibrary *self,
gint64 frame_id);
void gsk_gl_texture_library_clear_cache (GskGLTextureLibrary *self);
void gsk_gl_texture_library_reset (GskGLTextureLibrary *self);
void gsk_gl_texture_library_set_atlas_size (GskGLTextureLibrary *self,
int width,
int height);
GskGLTextureAtlas *gsk_gl_texture_library_acquire_atlas (GskGLTextureLibrary *self);
void gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self,
GHashFunc hash_func,
GEqualFunc equal_func,
GDestroyNotify key_destroy,
GDestroyNotify value_destroy);
void gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
gint64 frame_id);
gboolean gsk_gl_texture_library_allocate (GskGLTextureLibrary *self,
GskGLTextureAtlas *atlas,
int width,
int height,
int *out_x,
int *out_y);
gpointer gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
gpointer key,
gsize valuelen,
guint width,
guint height,
int padding,
guint *out_packed_x,
guint *out_packed_y);
static inline void
gsk_gl_texture_atlas_mark_unused (GskGLTextureAtlas *self,
+16 -3
View File
@@ -58,14 +58,14 @@ value_render_node_init (GValue *value)
{
value->data[0].v_pointer = NULL;
}
static void
value_render_node_free_value (GValue *value)
{
if (value->data[0].v_pointer != NULL)
gsk_render_node_unref (value->data[0].v_pointer);
}
static void
value_render_node_copy_value (const GValue *src,
GValue *dst)
@@ -75,7 +75,7 @@ value_render_node_copy_value (const GValue *src,
else
dst->data[0].v_pointer = NULL;
}
static gpointer
value_render_node_peek_pointer (const GValue *value)
{
@@ -738,3 +738,16 @@ gsk_render_node_prefers_high_depth (const GskRenderNode *node)
{
return node->prefers_high_depth;
}
/* Whether we need an offscreen to handle opacity correctly for this node.
* We don't if there is only one drawing node inside (could be child
* node, or grandchild, or...).
*
* For containers with multiple children, we can avoid the offscreen if
* the children are known not to overlap.
*/
gboolean
gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node)
{
return node->offscreen_for_opacity;
}
+47
View File
@@ -139,6 +139,7 @@ gsk_color_node_new (const GdkRGBA *rgba,
self = gsk_render_node_alloc (GSK_COLOR_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
self->color = *rgba;
graphene_rect_init_from_rect (&node->bounds, bounds);
@@ -284,6 +285,7 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
self = gsk_render_node_alloc (GSK_LINEAR_GRADIENT_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->start, start);
@@ -336,6 +338,7 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
self = gsk_render_node_alloc (GSK_REPEATING_LINEAR_GRADIENT_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->start, start);
@@ -584,6 +587,7 @@ gsk_radial_gradient_node_new (const graphene_rect_t *bounds,
self = gsk_render_node_alloc (GSK_RADIAL_GRADIENT_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->center, center);
@@ -652,6 +656,7 @@ gsk_repeating_radial_gradient_node_new (const graphene_rect_t *bounds,
self = gsk_render_node_alloc (GSK_REPEATING_RADIAL_GRADIENT_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->center, center);
@@ -1030,6 +1035,7 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
self = gsk_render_node_alloc (GSK_CONIC_GRADIENT_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->center, center);
@@ -1413,6 +1419,7 @@ gsk_border_node_new (const GskRoundedRect *outline,
self = gsk_render_node_alloc (GSK_BORDER_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
gsk_rounded_rect_init_copy (&self->outline, outline);
memcpy (self->border_width, border_width, sizeof (self->border_width));
@@ -1559,6 +1566,7 @@ gsk_texture_node_new (GdkTexture *texture,
self = gsk_render_node_alloc (GSK_TEXTURE_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
self->texture = g_object_ref (texture);
graphene_rect_init_from_rect (&node->bounds, bounds);
@@ -2014,6 +2022,7 @@ gsk_inset_shadow_node_new (const GskRoundedRect *outline,
self = gsk_render_node_alloc (GSK_INSET_SHADOW_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
gsk_rounded_rect_init_copy (&self->outline, outline);
self->color = *color;
@@ -2313,6 +2322,7 @@ gsk_outset_shadow_node_new (const GskRoundedRect *outline,
self = gsk_render_node_alloc (GSK_OUTSET_SHADOW_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
gsk_rounded_rect_init_copy (&self->outline, outline);
self->color = *color;
@@ -2506,6 +2516,7 @@ gsk_cairo_node_new (const graphene_rect_t *bounds)
self = gsk_render_node_alloc (GSK_CAIRO_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
graphene_rect_init_from_rect (&node->bounds, bounds);
@@ -2576,6 +2587,7 @@ struct _GskContainerNode
{
GskRenderNode render_node;
gboolean disjoint;
guint n_children;
GskRenderNode **children;
};
@@ -2724,6 +2736,7 @@ gsk_container_node_new (GskRenderNode **children,
self = gsk_render_node_alloc (GSK_CONTAINER_NODE);
node = (GskRenderNode *) self;
self->disjoint = TRUE;
self->n_children = n_children;
if (n_children == 0)
@@ -2743,11 +2756,14 @@ gsk_container_node_new (GskRenderNode **children,
for (guint i = 1; i < n_children; i++)
{
self->children[i] = gsk_render_node_ref (children[i]);
self->disjoint &= !graphene_rect_intersection (&bounds, &(children[i]->bounds), NULL);
graphene_rect_union (&bounds, &(children[i]->bounds), &bounds);
node->prefers_high_depth |= gsk_render_node_prefers_high_depth (children[i]);
node->offscreen_for_opacity |= children[i]->offscreen_for_opacity;
}
graphene_rect_init_from_rect (&node->bounds, &bounds);
node->offscreen_for_opacity |= !self->disjoint;
}
return node;
@@ -2801,6 +2817,24 @@ gsk_container_node_get_children (const GskRenderNode *node,
return self->children;
}
/*< private>
* gsk_container_node_is_disjoint:
* @node: a container `GskRenderNode`
*
* Returns `TRUE` if it is known that the child nodes are not
* overlapping. There is no guarantee that they do overlap
* if this function return FALSE.
*
* Returns: `TRUE` if children don't overlap
*/
gboolean
gsk_container_node_is_disjoint (const GskRenderNode *node)
{
const GskContainerNode *self = (const GskContainerNode *) node;
return self->disjoint;
}
/*** GSK_TRANSFORM_NODE ***/
/**
@@ -2962,6 +2996,7 @@ gsk_transform_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_TRANSFORM_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
self->transform = gsk_transform_ref (transform);
@@ -3106,6 +3141,7 @@ gsk_opacity_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_OPACITY_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
self->opacity = CLAMP (opacity, 0.0, 1.0);
@@ -3309,6 +3345,7 @@ gsk_color_matrix_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_COLOR_MATRIX_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
graphene_matrix_init_from_matrix (&self->color_matrix, color_matrix);
@@ -3457,6 +3494,7 @@ gsk_repeat_node_new (const graphene_rect_t *bounds,
self = gsk_render_node_alloc (GSK_REPEAT_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = TRUE;
graphene_rect_init_from_rect (&node->bounds, bounds);
@@ -3594,6 +3632,7 @@ gsk_clip_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_CLIP_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
graphene_rect_normalize_r (clip, &self->clip);
@@ -3727,6 +3766,7 @@ gsk_rounded_clip_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_ROUNDED_CLIP_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
gsk_rounded_rect_init_copy (&self->clip, clip);
@@ -3946,6 +3986,7 @@ gsk_shadow_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_SHADOW_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
self->n_shadows = n_shadows;
@@ -4142,6 +4183,7 @@ gsk_blend_node_new (GskRenderNode *bottom,
self = gsk_render_node_alloc (GSK_BLEND_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = TRUE;
self->bottom = gsk_render_node_ref (bottom);
self->top = gsk_render_node_ref (top);
@@ -4292,6 +4334,7 @@ gsk_cross_fade_node_new (GskRenderNode *start,
self = gsk_render_node_alloc (GSK_CROSS_FADE_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = TRUE;
self->start = gsk_render_node_ref (start);
self->end = gsk_render_node_ref (end);
@@ -4478,6 +4521,7 @@ gsk_text_node_new (PangoFont *font,
self = gsk_render_node_alloc (GSK_TEXT_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
self->font = g_object_ref (font);
self->color = *color;
@@ -4884,6 +4928,7 @@ gsk_blur_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_BLUR_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
self->radius = radius;
@@ -5013,6 +5058,7 @@ gsk_debug_node_new (GskRenderNode *child,
self = gsk_render_node_alloc (GSK_DEBUG_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
self->child = gsk_render_node_ref (child);
self->message = message;
@@ -5174,6 +5220,7 @@ gsk_gl_shader_node_new (GskGLShader *shader,
self = gsk_render_node_alloc (GSK_GL_SHADER_NODE);
node = (GskRenderNode *) self;
node->offscreen_for_opacity = TRUE;
graphene_rect_init_from_rect (&node->bounds, bounds);
self->shader = g_object_ref (shader);
+5
View File
@@ -29,6 +29,7 @@ struct _GskRenderNode
graphene_rect_t bounds;
guint prefers_high_depth : 1;
guint offscreen_for_opacity : 1;
};
struct _GskRenderNodeClass
@@ -113,6 +114,10 @@ void gsk_transform_node_get_translate (const GskRenderNode *no
float *dy);
gboolean gsk_render_node_prefers_high_depth (const GskRenderNode *node);
gboolean gsk_container_node_is_disjoint (const GskRenderNode *node);
gboolean gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node);
G_END_DECLS
+3 -3
View File
@@ -68,7 +68,7 @@
*
* `GtkApplication` will automatically load menus from the `GtkBuilder`
* resource located at "gtk/menus.ui", relative to the application's
* resource base path (see `g_application_set_resource_base_path()`).
* resource base path (see [method@Gio.Application.set_resource_base_path]).
* The menu with the ID "menubar" is taken as the application's
* menubar. Additional menus (most interesting submenus) can be named
* and accessed via [method@Gtk.Application.get_menu_by_id] which allows for
@@ -83,8 +83,8 @@
* resources. See [method@Gtk.IconTheme.add_resource_path] for more
* information.
*
* If there is a resource located at "gtk/help-overlay.ui" which
* defines a [class@Gtk.ShortcutsWindow] with ID "help_overlay" then
* If there is a resource located at `gtk/help-overlay.ui` which
* defines a [class@Gtk.ShortcutsWindow] with ID `help_overlay` then
* `GtkApplication` associates an instance of this shortcuts window with
* each [class@Gtk.ApplicationWindow] and sets up the keyboard accelerator
* <kbd>Control</kbd>+<kbd>?</kbd> to open it. To create a menu item that
+1 -1
View File
@@ -38,7 +38,7 @@ struct _GtkBinLayout
GtkLayoutManager parent_instance;
};
G_DEFINE_FINAL_TYPE (GtkBinLayout, gtk_bin_layout, GTK_TYPE_LAYOUT_MANAGER)
G_DEFINE_TYPE (GtkBinLayout, gtk_bin_layout, GTK_TYPE_LAYOUT_MANAGER)
static void
gtk_bin_layout_measure (GtkLayoutManager *layout_manager,
+2 -2
View File
@@ -117,8 +117,8 @@ static void bookmark_file_changed (GFileMonitor *monitor,
static void gtk_bookmark_list_set_filename (GtkBookmarkList *self,
const char *filename);
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkBookmarkList, gtk_bookmark_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_bookmark_list_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkBookmarkList, gtk_bookmark_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_bookmark_list_model_init))
static void
gtk_bookmark_list_set_property (GObject *object,
+2 -2
View File
@@ -46,7 +46,7 @@ enum {
NUM_PROPERTIES
};
G_DEFINE_FINAL_TYPE (GtkBoolFilter, gtk_bool_filter, GTK_TYPE_FILTER)
G_DEFINE_TYPE (GtkBoolFilter, gtk_bool_filter, GTK_TYPE_FILTER)
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
@@ -106,7 +106,7 @@ gtk_bool_filter_set_property (GObject *object,
}
}
static void
static void
gtk_bool_filter_get_property (GObject *object,
guint prop_id,
GValue *value,
+3 -3
View File
@@ -58,8 +58,8 @@ struct _GtkBoxLayout
GtkBaselinePosition baseline_position;
};
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkBoxLayout, gtk_box_layout, GTK_TYPE_LAYOUT_MANAGER,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
G_DEFINE_TYPE_WITH_CODE (GtkBoxLayout, gtk_box_layout, GTK_TYPE_LAYOUT_MANAGER,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
enum {
PROP_HOMOGENEOUS = 1,
@@ -342,7 +342,7 @@ distribute_remaining_size (GtkRequestedSize *sizes,
else
max = test;
}
return available - total_size;
}
+1 -1
View File
@@ -54,7 +54,7 @@ struct _GtkCenterLayout
};
};
G_DEFINE_FINAL_TYPE (GtkCenterLayout, gtk_center_layout, GTK_TYPE_LAYOUT_MANAGER)
G_DEFINE_TYPE (GtkCenterLayout, gtk_center_layout, GTK_TYPE_LAYOUT_MANAGER)
static int
get_spacing (GtkCenterLayout *self,
+2 -3
View File
@@ -1703,9 +1703,8 @@ gtk_column_view_sort_by_column (GtkColumnView *self,
g_return_if_fail (column == NULL || GTK_IS_COLUMN_VIEW_COLUMN (column));
g_return_if_fail (column == NULL || gtk_column_view_column_get_column_view (column) == self);
if (column == NULL)
gtk_column_view_sorter_clear (GTK_COLUMN_VIEW_SORTER (self->sorter));
else
gtk_column_view_sorter_clear (GTK_COLUMN_VIEW_SORTER (self->sorter));
if (column != NULL)
gtk_column_view_sorter_set_column (GTK_COLUMN_VIEW_SORTER (self->sorter),
column,
direction == GTK_SORT_DESCENDING);
+1 -1
View File
@@ -60,7 +60,7 @@ enum {
static GParamSpec *obj_props[N_PROPERTIES];
G_DEFINE_FINAL_TYPE (GtkConstraint, gtk_constraint, G_TYPE_OBJECT)
G_DEFINE_TYPE (GtkConstraint, gtk_constraint, G_TYPE_OBJECT)
static void
gtk_constraint_set_property (GObject *gobject,
+4 -4
View File
@@ -59,7 +59,7 @@ typedef enum {
} GuideValue;
struct _GtkConstraintGuide
{
{
GObject parent_instance;
char *name;
@@ -104,9 +104,9 @@ gtk_constraint_guide_constraint_target_iface_init (GtkConstraintTargetInterface
{
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkConstraintGuide, gtk_constraint_guide, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_CONSTRAINT_TARGET,
gtk_constraint_guide_constraint_target_iface_init))
G_DEFINE_TYPE_WITH_CODE (GtkConstraintGuide, gtk_constraint_guide, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_CONSTRAINT_TARGET,
gtk_constraint_guide_constraint_target_iface_init))
static void
gtk_constraint_guide_init (GtkConstraintGuide *guide)
+3 -3
View File
@@ -266,7 +266,7 @@ struct _GtkConstraintLayout
GListStore *guides_observer;
};
G_DEFINE_FINAL_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK_TYPE_LAYOUT_CHILD)
G_DEFINE_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK_TYPE_LAYOUT_CHILD)
GtkConstraintSolver *
gtk_constraint_layout_get_solver (GtkConstraintLayout *self)
@@ -537,8 +537,8 @@ gtk_constraint_layout_child_init (GtkConstraintLayoutChild *self)
static void gtk_buildable_interface_init (GtkBuildableIface *iface);
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkConstraintLayout, gtk_constraint_layout, GTK_TYPE_LAYOUT_MANAGER,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_buildable_interface_init))
G_DEFINE_TYPE_WITH_CODE (GtkConstraintLayout, gtk_constraint_layout, GTK_TYPE_LAYOUT_MANAGER,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_buildable_interface_init))
static void
gtk_constraint_layout_finalize (GObject *gobject)
+10 -3
View File
@@ -69,11 +69,18 @@ gtk_css_calc_value_new_from_array (GtkCssValue **values,
return result;
}
static void
gtk_css_value_number_free (GtkCssValue *value)
gtk_css_value_number_free (GtkCssValue *number)
{
g_slice_free (GtkCssValue, value);
if (number->type == TYPE_CALC)
{
const guint n_terms = number->calc.n_terms;
for (guint i = 0; i < n_terms; i++)
_gtk_css_value_unref (number->calc.terms[i]);
}
g_slice_free (GtkCssValue, number);
}
static double
+1 -1
View File
@@ -38,7 +38,7 @@ struct _GtkCustomFilter
GDestroyNotify user_destroy;
};
G_DEFINE_FINAL_TYPE (GtkCustomFilter, gtk_custom_filter, GTK_TYPE_FILTER)
G_DEFINE_TYPE (GtkCustomFilter, gtk_custom_filter, GTK_TYPE_FILTER)
static gboolean
gtk_custom_filter_match (GtkFilter *filter,
+1 -1
View File
@@ -22,7 +22,7 @@ struct _GtkCustomLayout
GtkCustomAllocateFunc allocate_func;
};
G_DEFINE_FINAL_TYPE (GtkCustomLayout, gtk_custom_layout, GTK_TYPE_LAYOUT_MANAGER)
G_DEFINE_TYPE (GtkCustomLayout, gtk_custom_layout, GTK_TYPE_LAYOUT_MANAGER)
static GtkSizeRequestMode
gtk_custom_layout_get_request_mode (GtkLayoutManager *manager,
+1 -1
View File
@@ -39,7 +39,7 @@ struct _GtkCustomSorter
GDestroyNotify user_destroy;
};
G_DEFINE_FINAL_TYPE (GtkCustomSorter, gtk_custom_sorter, GTK_TYPE_SORTER)
G_DEFINE_TYPE (GtkCustomSorter, gtk_custom_sorter, GTK_TYPE_SORTER)
static GtkOrdering
gtk_custom_sorter_compare (GtkSorter *sorter,
+2 -2
View File
@@ -144,8 +144,8 @@ gtk_directory_list_model_init (GListModelInterface *iface)
iface->get_item = gtk_directory_list_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkDirectoryList, gtk_directory_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_directory_list_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkDirectoryList, gtk_directory_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_directory_list_model_init))
static void
gtk_directory_list_set_property (GObject *object,
+5 -5
View File
@@ -79,11 +79,11 @@ static GParamSpec *properties[LAST_ARG] = { NULL, };
static void gtk_drag_icon_root_init (GtkRootInterface *iface);
static void gtk_drag_icon_native_init (GtkNativeInterface *iface);
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkDragIcon, gtk_drag_icon, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
gtk_drag_icon_native_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
gtk_drag_icon_root_init))
G_DEFINE_TYPE_WITH_CODE (GtkDragIcon, gtk_drag_icon, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
gtk_drag_icon_native_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
gtk_drag_icon_root_init))
static GdkDisplay *
gtk_drag_icon_root_get_display (GtkRoot *self)
+1 -1
View File
@@ -132,7 +132,7 @@ enum
LAST_SIGNAL
};
G_DEFINE_FINAL_TYPE (GtkDropDown, gtk_drop_down, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (GtkDropDown, gtk_drop_down, GTK_TYPE_WIDGET)
static GParamSpec *properties[N_PROPS] = { NULL, };
static guint signals[LAST_SIGNAL] = { 0 };
+3 -3
View File
@@ -103,9 +103,9 @@ gtk_editable_label_editable_init (GtkEditableInterface *iface)
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkEditableLabel, gtk_editable_label, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
gtk_editable_label_editable_init))
G_DEFINE_TYPE_WITH_CODE (GtkEditableLabel, gtk_editable_label, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
gtk_editable_label_editable_init))
static void
start_editing (GtkWidget *widget,
+66 -24
View File
@@ -67,6 +67,7 @@
#define SCROLL_CAPTURE_THRESHOLD_MS 150
#define HOLD_TIMEOUT_MS 50
#define SURFACE_UNIT_DISCRETE_MAPPING 10
typedef struct
{
@@ -85,6 +86,8 @@ struct _GtkEventControllerScroll
double cur_dx;
double cur_dy;
GdkScrollUnit cur_unit;
guint hold_timeout_id;
guint active : 1;
};
@@ -238,28 +241,26 @@ gtk_event_controller_scroll_get_property (GObject *object,
}
}
static gboolean
static void
gtk_event_controller_scroll_begin (GtkEventController *controller)
{
GtkEventControllerScroll *scroll = GTK_EVENT_CONTROLLER_SCROLL (controller);
if (scroll->active)
return FALSE;
return;
g_signal_emit (controller, signals[SCROLL_BEGIN], 0);
scroll_history_reset (scroll);
scroll->active = TRUE;
return TRUE;
}
static gboolean
static void
gtk_event_controller_scroll_end (GtkEventController *controller)
{
GtkEventControllerScroll *scroll = GTK_EVENT_CONTROLLER_SCROLL (controller);
if (!scroll->active)
return FALSE;
return;
g_signal_emit (controller, signals[SCROLL_END], 0);
scroll->active = FALSE;
@@ -271,8 +272,6 @@ gtk_event_controller_scroll_end (GtkEventController *controller)
scroll_history_finish (scroll, &vel_x, &vel_y);
g_signal_emit (controller, signals[DECELERATE], 0, vel_x, vel_y);
}
return TRUE;
}
static gboolean
@@ -295,30 +294,29 @@ gtk_event_controller_scroll_handle_hold_event (GtkEventController *controller,
GdkEvent *event)
{
GtkEventControllerScroll *scroll = GTK_EVENT_CONTROLLER_SCROLL (controller);
gboolean handled = GDK_EVENT_PROPAGATE;
GdkTouchpadGesturePhase phase;
guint n_fingers = 0;
if (gdk_event_get_event_type (event) != GDK_TOUCHPAD_HOLD)
return handled;
return GDK_EVENT_PROPAGATE;
n_fingers = gdk_touchpad_event_get_n_fingers (event);
if (n_fingers != 1 && n_fingers != 2)
return handled;
return GDK_EVENT_PROPAGATE;
if (scroll->hold_timeout_id != 0)
return handled;
return GDK_EVENT_PROPAGATE;
phase = gdk_touchpad_event_get_gesture_phase (event);
switch (phase)
{
case GDK_TOUCHPAD_GESTURE_PHASE_BEGIN:
handled = gtk_event_controller_scroll_begin (controller);
gtk_event_controller_scroll_begin (controller);
break;
case GDK_TOUCHPAD_GESTURE_PHASE_END:
handled = gtk_event_controller_scroll_end (controller);
gtk_event_controller_scroll_end (controller);
break;
case GDK_TOUCHPAD_GESTURE_PHASE_CANCEL:
@@ -336,7 +334,7 @@ gtk_event_controller_scroll_handle_hold_event (GtkEventController *controller,
break;
}
return handled;
return GDK_EVENT_PROPAGATE;
}
static gboolean
@@ -350,6 +348,7 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
double dx = 0, dy = 0;
gboolean handled = GDK_EVENT_PROPAGATE;
GdkEventType event_type;
GdkScrollUnit scroll_unit;
event_type = gdk_event_get_event_type (event);
@@ -365,6 +364,8 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
g_clear_handle_id (&scroll->hold_timeout_id, g_source_remove);
scroll_unit = gdk_scroll_event_get_unit (event);
/* FIXME: Handle device changes */
direction = gdk_scroll_event_get_direction (event);
if (direction == GDK_SCROLL_SMOOTH)
@@ -385,18 +386,31 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
scroll->cur_dy += dy;
dx = dy = 0;
if (ABS (scroll->cur_dx) >= 1)
if (scroll_unit == GDK_SCROLL_UNIT_SURFACE)
{
steps = trunc (scroll->cur_dx);
scroll->cur_dx -= steps;
dx = steps;
}
dx = (int) scroll->cur_dx / SURFACE_UNIT_DISCRETE_MAPPING;
scroll->cur_dx -= dx * SURFACE_UNIT_DISCRETE_MAPPING;
if (ABS (scroll->cur_dy) >= 1)
dy = (int) scroll->cur_dy / SURFACE_UNIT_DISCRETE_MAPPING;
scroll->cur_dy -= dy * SURFACE_UNIT_DISCRETE_MAPPING;
scroll_unit = GDK_SCROLL_UNIT_WHEEL;
}
else
{
steps = trunc (scroll->cur_dy);
scroll->cur_dy -= steps;
dy = steps;
if (ABS (scroll->cur_dx) >= 1)
{
steps = trunc (scroll->cur_dx);
scroll->cur_dx -= steps;
dx = steps;
}
if (ABS (scroll->cur_dy) >= 1)
{
steps = trunc (scroll->cur_dy);
scroll->cur_dy -= steps;
dy = steps;
}
}
}
}
@@ -428,6 +442,8 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
dx = 0;
}
scroll->cur_unit = scroll_unit;
if (dx != 0 || dy != 0)
g_signal_emit (controller, signals[SCROLL], 0, dx, dy, &handled);
else if (direction == GDK_SCROLL_SMOOTH &&
@@ -497,6 +513,9 @@ gtk_event_controller_scroll_class_init (GtkEventControllerScrollClass *klass)
* Signals that the widget should scroll by the
* amount specified by @dx and @dy.
*
* For the representation unit of the deltas, see
* [method@Gtk.EventControllerScroll.get_unit].
*
* Returns: %TRUE if the scroll event was handled,
* %FALSE otherwise.
*/
@@ -614,3 +633,26 @@ gtk_event_controller_scroll_get_flags (GtkEventControllerScroll *scroll)
return scroll->flags;
}
/**
* gtk_event_controller_scroll_get_unit:
* @scroll: a `GtkEventControllerScroll`.
*
* Gets the scroll unit of the last
* [signal@Gtk.EventControllerScroll::scroll] signal received.
*
* Always returns %GDK_SCROLL_UNIT_WHEEL if the
* %GTK_EVENT_CONTROLLER_SCROLL_DISCRETE flag is set.
*
* Returns: the scroll unit.
*
* Since: 4.8
*/
GdkScrollUnit
gtk_event_controller_scroll_get_unit (GtkEventControllerScroll *scroll)
{
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_SCROLL (scroll),
GDK_SCROLL_UNIT_WHEEL);
return scroll->cur_unit;
}
+3
View File
@@ -71,6 +71,9 @@ GDK_AVAILABLE_IN_ALL
GtkEventControllerScrollFlags
gtk_event_controller_scroll_get_flags (GtkEventControllerScroll *scroll);
GDK_AVAILABLE_IN_4_8
GdkScrollUnit gtk_event_controller_scroll_get_unit (GtkEventControllerScroll *scroll);
G_END_DECLS
#endif /* __GTK_EVENT_CONTROLLER_SCROLL_H__ */
+1 -1
View File
@@ -125,7 +125,7 @@
* a `GtkExpression` object is needed like in a `<property>` tag for an expression
* property, or in a `<binding name="property">` tag to bind a property to an expression.
*
* To create an property expression, use the `<lookup>` element. It can have a `type`
* To create a property expression, use the `<lookup>` element. It can have a `type`
* attribute to specify the object type, and a `name` attribute to specify the property
* to look up. The content of `<lookup>` can either be an element specfiying the expression
* to use the object, or a string that specifies the name of the object to use.
+3 -3
View File
@@ -206,9 +206,9 @@ static GParamSpec *native_props[LAST_ARG] = { NULL, };
static void _gtk_file_chooser_native_iface_init (GtkFileChooserIface *iface);
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkFileChooserNative, gtk_file_chooser_native, GTK_TYPE_NATIVE_DIALOG,
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
_gtk_file_chooser_native_iface_init))
G_DEFINE_TYPE_WITH_CODE (GtkFileChooserNative, gtk_file_chooser_native, GTK_TYPE_NATIVE_DIALOG,
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
_gtk_file_chooser_native_iface_init))
/**
+7 -1
View File
@@ -2193,7 +2193,7 @@ update_default (GtkFileChooserWidget *impl)
return;
files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (impl));
sensitive = (g_list_model_get_n_items (files) > 0);
sensitive = (g_list_model_get_n_items (files) > 0 || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE);
gtk_widget_set_sensitive (button, sensitive);
g_object_unref (files);
@@ -4748,9 +4748,15 @@ update_chooser_entry (GtkFileChooserWidget *impl)
if (change_entry && !impl->auto_selecting_first_row)
{
GtkEntryCompletion *completion = gtk_entry_get_completion (GTK_ENTRY (impl->location_entry));
if (completion)
gtk_entry_completion_set_popup_completion (completion, FALSE);
g_signal_handlers_block_by_func (impl->location_entry, G_CALLBACK (location_entry_changed_cb), impl);
gtk_editable_set_text (GTK_EDITABLE (impl->location_entry), impl->browse_files_last_selected_name);
g_signal_handlers_unblock_by_func (impl->location_entry, G_CALLBACK (location_entry_changed_cb), impl);
if (completion)
gtk_entry_completion_set_popup_completion (completion, TRUE);
if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
_gtk_file_chooser_entry_select_filename (GTK_FILE_CHOOSER_ENTRY (impl->location_entry));
+4 -2
View File
@@ -283,7 +283,8 @@ parser_start_element (GtkBuildableParseContext *context,
}
if (strcmp (element_name, "mime-types") == 0 ||
strcmp (element_name, "patterns") == 0)
strcmp (element_name, "patterns") == 0 ||
strcmp (element_name, "suffixes") == 0)
{
if (!_gtk_builder_check_parent (data->builder, context, "object", error))
return;
@@ -422,7 +423,8 @@ gtk_file_filter_buildable_custom_tag_end (GtkBuildable *buildable,
gpointer user_data)
{
if (strcmp (tagname, "mime-types") == 0 ||
strcmp (tagname, "patterns") == 0)
strcmp (tagname, "patterns") == 0 ||
strcmp (tagname, "suffixes") == 0)
{
SubParserData *data = (SubParserData*)user_data;
+1 -1
View File
@@ -28,7 +28,7 @@
* GtkFilter:
*
* A `GtkFilter` object describes the filtering to be performed by a
* `GtkFilterListModel`.
* [class@Gtk.FilterListModel].
*
* The model will use the filter to determine if it should include items
* or not by calling [method@Gtk.Filter.match] for each item and only
+5 -5
View File
@@ -134,8 +134,8 @@ gtk_filter_list_model_model_init (GListModelInterface *iface)
iface->get_item = gtk_filter_list_model_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkFilterListModel, gtk_filter_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_filter_list_model_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkFilterListModel, gtk_filter_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_filter_list_model_model_init))
static gboolean
gtk_filter_list_model_run_filter_on_item (GtkFilterListModel *self,
@@ -163,7 +163,7 @@ gtk_filter_list_model_run_filter (GtkFilterListModel *self,
gboolean more;
g_return_if_fail (GTK_IS_FILTER_LIST_MODEL (self));
if (self->pending == NULL)
return;
@@ -346,7 +346,7 @@ gtk_filter_list_model_set_property (GObject *object,
}
}
static void
static void
gtk_filter_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -473,7 +473,7 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self,
case GTK_FILTER_MATCH_SOME:
{
GtkBitset *old, *pending;
if (self->matches == NULL)
{
if (self->strictness == GTK_FILTER_MATCH_ALL)
+2 -2
View File
@@ -92,7 +92,7 @@ enum
static GParamSpec *child_props[N_CHILD_PROPERTIES];
G_DEFINE_FINAL_TYPE (GtkFixedLayoutChild, gtk_fixed_layout_child, GTK_TYPE_LAYOUT_CHILD)
G_DEFINE_TYPE (GtkFixedLayoutChild, gtk_fixed_layout_child, GTK_TYPE_LAYOUT_CHILD)
static void
gtk_fixed_layout_child_set_property (GObject *gobject,
@@ -215,7 +215,7 @@ gtk_fixed_layout_child_get_transform (GtkFixedLayoutChild *child)
return child->transform;
}
G_DEFINE_FINAL_TYPE (GtkFixedLayout, gtk_fixed_layout, GTK_TYPE_LAYOUT_MANAGER)
G_DEFINE_TYPE (GtkFixedLayout, gtk_fixed_layout, GTK_TYPE_LAYOUT_MANAGER)
static GtkSizeRequestMode
gtk_fixed_layout_get_request_mode (GtkLayoutManager *layout_manager,
+4 -4
View File
@@ -198,8 +198,8 @@ gtk_flatten_list_model_model_init (GListModelInterface *iface)
iface->get_item = gtk_flatten_list_model_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkFlattenListModel, gtk_flatten_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_flatten_list_model_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkFlattenListModel, gtk_flatten_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_flatten_list_model_model_init))
static void
gtk_flatten_list_model_items_changed_cb (GListModel *model,
@@ -322,7 +322,7 @@ gtk_flatten_list_model_set_property (GObject *object,
}
}
static void
static void
gtk_flatten_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -463,7 +463,7 @@ gtk_flatten_list_model_set_model (GtkFlattenListModel *self,
if (self->model == model)
return;
removed = g_list_model_get_n_items (G_LIST_MODEL (self));
removed = g_list_model_get_n_items (G_LIST_MODEL (self));
gtk_flatten_list_clear_model (self);
self->model = model;
+2 -2
View File
@@ -84,7 +84,7 @@ enum {
static GParamSpec *child_props[N_CHILD_PROPERTIES];
G_DEFINE_FINAL_TYPE (GtkGridLayoutChild, gtk_grid_layout_child, GTK_TYPE_LAYOUT_CHILD)
G_DEFINE_TYPE (GtkGridLayoutChild, gtk_grid_layout_child, GTK_TYPE_LAYOUT_CHILD)
static void
gtk_grid_layout_child_set_property (GObject *gobject,
@@ -454,7 +454,7 @@ enum {
static GParamSpec *layout_props[N_PROPERTIES];
G_DEFINE_FINAL_TYPE (GtkGridLayout, gtk_grid_layout, GTK_TYPE_LAYOUT_MANAGER)
G_DEFINE_TYPE (GtkGridLayout, gtk_grid_layout, GTK_TYPE_LAYOUT_MANAGER)
static inline GtkGridLayoutChild *
get_grid_child (GtkGridLayout *self,
+14 -14
View File
@@ -274,7 +274,6 @@ gtk_im_context_simple_init_compose_table (void)
char **lang = NULL;
const char * const sys_langs[] = { "el_gr", "fi_fi", "pt_br", NULL };
const char * const *sys_lang = NULL;
char *x11_compose_file_dir = get_x11_compose_file_dir ();
path = g_build_filename (g_get_user_config_dir (), "gtk-4.0", "Compose", NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS))
@@ -323,7 +322,9 @@ gtk_im_context_simple_init_compose_table (void)
{
if (g_ascii_strncasecmp (*lang, *sys_lang, strlen (*sys_lang)) == 0)
{
char *x11_compose_file_dir = get_x11_compose_file_dir ();
path = g_build_filename (x11_compose_file_dir, *lang, "Compose", NULL);
g_free (x11_compose_file_dir);
break;
}
}
@@ -336,7 +337,6 @@ gtk_im_context_simple_init_compose_table (void)
g_clear_pointer (&path, g_free);
}
g_free (x11_compose_file_dir);
g_strfreev (langs);
if (path != NULL &&
@@ -406,7 +406,7 @@ gtk_im_context_simple_finalize (GObject *obj)
/**
* gtk_im_context_simple_new:
*
*
* Creates a new `GtkIMContextSimple`.
*
* Returns: a new `GtkIMContextSimple`
@@ -483,14 +483,14 @@ check_hex (GtkIMContextSimple *context_simple,
priv->tentative_match_len = 0;
str = g_string_new (NULL);
i = 0;
while (i < n_compose)
{
gunichar ch;
ch = gdk_keyval_to_unicode (priv->compose_buffer[i]);
if (ch == 0)
return FALSE;
@@ -500,7 +500,7 @@ check_hex (GtkIMContextSimple *context_simple,
buf[g_unichar_to_utf8 (ch, buf)] = '\0';
g_string_append (str, buf);
++i;
}
@@ -523,7 +523,7 @@ check_hex (GtkIMContextSimple *context_simple,
g_string_append_unichar (priv->tentative_match, n);
priv->tentative_match_len = n_compose;
}
return TRUE;
}
@@ -665,7 +665,7 @@ no_sequence_matches (GtkIMContextSimple *context_simple,
FALSE,
&translated,
&translated);
gtk_im_context_filter_keypress (context, tmp_event);
gdk_event_unref (tmp_event);
}
@@ -725,7 +725,7 @@ no_sequence_matches (GtkIMContextSimple *context_simple,
g_signal_emit_by_name (context, "preedit-end");
return TRUE;
}
keyval = gdk_key_event_get_keyval (event);
ch = gdk_keyval_to_unicode (keyval);
if (ch != 0 && !g_unichar_iscntrl (ch))
@@ -783,7 +783,7 @@ canonical_hex_keyval (GdkEvent *event)
}
g_free (keyvals);
if (keyval)
return keyval;
else
@@ -954,7 +954,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
if (!priv->in_hex_sequence)
g_signal_emit_by_name (context_simple, "preedit-end");
return TRUE;
}
@@ -991,7 +991,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
priv->compose_buffer[0] = 0;
}
}
/* Check for hex sequence start */
if (!priv->in_hex_sequence && have_hex_mods && is_hex_start)
{
@@ -1002,7 +1002,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
g_signal_emit_by_name (context_simple, "preedit-start");
g_signal_emit_by_name (context_simple, "preedit-changed");
return TRUE;
}
+45 -19
View File
@@ -48,6 +48,7 @@ struct _GtkIMContextWaylandGlobal
gboolean focused;
guint serial;
guint done_serial;
};
struct _GtkIMContextWaylandClass
@@ -70,6 +71,7 @@ struct _GtkIMContextWayland
{
GtkIMContextSimple parent_instance;
GtkWidget *widget;
GtkWidget *controller_widget;
GtkGesture *gesture;
double press_x;
@@ -207,11 +209,11 @@ text_input_commit (void *data,
}
static void
text_input_commit_apply (GtkIMContextWaylandGlobal *global, gboolean valid)
text_input_commit_apply (GtkIMContextWaylandGlobal *global)
{
GtkIMContextWayland *context;
context = GTK_IM_CONTEXT_WAYLAND (global->current);
if (context->pending_commit && valid)
if (context->pending_commit)
g_signal_emit_by_name (global->current, "commit", context->pending_commit);
g_free (context->pending_commit);
context->pending_commit = NULL;
@@ -236,8 +238,7 @@ text_input_delete_surrounding_text (void *data,
}
static void
text_input_delete_surrounding_text_apply (GtkIMContextWaylandGlobal *global,
gboolean valid)
text_input_delete_surrounding_text_apply (GtkIMContextWaylandGlobal *global)
{
GtkIMContextWayland *context;
gboolean retval;
@@ -248,7 +249,7 @@ text_input_delete_surrounding_text_apply (GtkIMContextWaylandGlobal *global,
len = context->pending_surrounding_delete.after_length
+ context->pending_surrounding_delete.before_length;
if (len > 0 && valid)
if (len > 0)
g_signal_emit_by_name (global->current, "delete-surrounding",
-context->pending_surrounding_delete.before_length,
len, &retval);
@@ -262,16 +263,16 @@ text_input_done (void *data,
{
GtkIMContextWaylandGlobal *global = data;
gboolean result;
gboolean valid;
global->done_serial = serial;
if (!global->current)
return;
valid = serial == global->serial;
text_input_delete_surrounding_text_apply(global, valid);
text_input_commit_apply(global, valid);
text_input_delete_surrounding_text_apply (global);
text_input_commit_apply (global);
g_signal_emit_by_name (global->current, "retrieve-surrounding", &result);
text_input_preedit_apply(global);
text_input_preedit_apply (global);
}
static void
@@ -288,6 +289,8 @@ notify_surrounding_text (GtkIMContextWayland *context)
global = gtk_im_context_wayland_get_global (context);
if (global == NULL)
return;
if (global->done_serial != global->serial)
return;
len = strlen (context->surrounding.text);
cursor = context->surrounding.cursor_idx;
@@ -362,6 +365,8 @@ notify_cursor_location (GtkIMContextWayland *context)
global = gtk_im_context_wayland_get_global (context);
if (global == NULL)
return;
if (global->done_serial != global->serial)
return;
rect = context->cursor_rect;
gtk_widget_translate_coordinates (context->widget,
@@ -452,6 +457,8 @@ notify_content_type (GtkIMContextWayland *context)
global = gtk_im_context_wayland_get_global (context);
if (global == NULL)
return;
if (global->done_serial != global->serial)
return;
g_object_get (context,
"input-hints", &hints,
@@ -549,16 +556,21 @@ gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
return;
if (context_wayland->widget)
gtk_im_context_wayland_focus_out (context);
if (context_wayland->controller_widget)
{
gtk_im_context_wayland_focus_out (context);
gtk_widget_remove_controller (context_wayland->widget, GTK_EVENT_CONTROLLER (context_wayland->gesture));
gtk_widget_remove_controller (context_wayland->controller_widget,
GTK_EVENT_CONTROLLER (context_wayland->gesture));
context_wayland->gesture = NULL;
g_clear_object (&context_wayland->controller_widget);
}
g_set_object (&context_wayland->widget, widget);
if (widget)
{
GtkWidget *parent;
GtkGesture *gesture;
gesture = gtk_gesture_click_new ();
@@ -569,7 +581,18 @@ gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
G_CALLBACK (pressed_cb), context);
g_signal_connect (gesture, "released",
G_CALLBACK (released_cb), context);
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
parent = gtk_widget_get_parent (widget);
if (parent &&
GTK_IS_EDITABLE (widget) &&
GTK_IS_EDITABLE (parent))
g_set_object (&context_wayland->controller_widget, parent);
else
g_set_object (&context_wayland->controller_widget, widget);
gtk_widget_add_controller (context_wayland->controller_widget,
GTK_EVENT_CONTROLLER (gesture));
context_wayland->gesture = gesture;
}
}
@@ -887,17 +910,20 @@ gtk_im_context_wayland_set_surrounding (GtkIMContext *context,
context_wayland = GTK_IM_CONTEXT_WAYLAND (context);
if (context_wayland->surrounding.text && text &&
(len < 0 || len == strlen (context_wayland->surrounding.text)) &&
strncmp (context_wayland->surrounding.text, text, len) == 0 &&
context_wayland->surrounding.cursor_idx == cursor_index &&
context_wayland->surrounding.anchor_idx == selection_bound)
return;
g_free (context_wayland->surrounding.text);
context_wayland->surrounding.text = g_strndup (text, len);
context_wayland->surrounding.cursor_idx = cursor_index;
context_wayland->surrounding.anchor_idx = selection_bound;
notify_surrounding_text (context_wayland);
/* State changes coming from reset don't have any other opportunity to get
* committed. */
if (context_wayland->surrounding_change !=
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD)
commit_state (context_wayland);
commit_state (context_wayland);
}
static gboolean
+9 -4
View File
@@ -314,6 +314,11 @@ gtk_im_multicontext_set_client_widget (GtkIMContext *context,
GtkIMContext *delegate;
GtkSettings *settings;
if (priv->client_widget == widget)
return;
gtk_im_multicontext_set_delegate (self, NULL, TRUE);
if (priv->client_widget != NULL)
{
settings = gtk_widget_get_settings (priv->client_widget);
@@ -332,11 +337,11 @@ gtk_im_multicontext_set_client_widget (GtkIMContext *context,
g_signal_connect (settings, "notify::gtk-im-module",
G_CALLBACK (im_module_setting_changed),
self);
}
delegate = gtk_im_multicontext_get_delegate (self);
if (delegate)
gtk_im_context_set_client_widget (delegate, widget);
delegate = gtk_im_multicontext_get_delegate (self);
if (delegate)
gtk_im_context_set_client_widget (delegate, widget);
}
}
static void
+1 -5
View File
@@ -3,11 +3,7 @@
#include <glib/gi18n-lib.h>
#ifdef ENABLE_NLS
#define P_(String) g_dgettext(GETTEXT_PACKAGE "-properties",String)
#else
#define P_(String) (String)
#endif
#define P_(String) g_dgettext (GETTEXT_PACKAGE "-properties", String)
/* not really I18N-related, but also a string marker macro */
#define I_(string) g_intern_static_string (string)
+1 -5
View File
@@ -181,8 +181,6 @@ gtk_kinetic_scrolling_tick (GtkKineticScrolling *data,
{
case GTK_KINETIC_SCROLLING_PHASE_DECELERATING:
{
double last_position = data->position;
double last_time = data->t;
double exp_part;
data->t += time_delta;
@@ -199,8 +197,7 @@ gtk_kinetic_scrolling_tick (GtkKineticScrolling *data,
{
gtk_kinetic_scrolling_init_overshoot(data, data->upper, data->position, data->velocity);
}
else if (fabs(data->velocity) < 1 ||
(last_time != 0.0 && fabs(data->position - last_position) < 1))
else if (fabs(data->velocity) < 0.1)
{
gtk_kinetic_scrolling_stop (data);
}
@@ -254,6 +251,5 @@ gtk_kinetic_scrolling_stop (GtkKineticScrolling *data)
{
data->phase = GTK_KINETIC_SCROLLING_PHASE_FINISHED;
data->position = round (data->position);
data->velocity = 0;
}
}
+23 -9
View File
@@ -1793,6 +1793,7 @@ gtk_label_focus (GtkWidget *widget,
{
info->selection_anchor = focus_link->start;
info->selection_end = focus_link->start;
break;
}
}
}
@@ -1856,7 +1857,6 @@ gtk_label_focus (GtkWidget *widget,
{
int focus_link_index;
int new_index = -1;
int i;
if (info->n_links == 0)
goto out;
@@ -1870,29 +1870,39 @@ gtk_label_focus (GtkWidget *widget,
{
case GTK_DIR_TAB_FORWARD:
if (focus_link)
new_index = (focus_link_index + 1) % info->n_links;
new_index = focus_link_index + 1;
else
new_index = 0;
for (i = new_index; i < info->n_links; i++)
if (new_index >= info->n_links)
goto out;
while (new_index < info->n_links)
{
const GtkLabelLink *link = &info->links[i];
const GtkLabelLink *link = &info->links[new_index];
if (!range_is_in_ellipsis (self, link->start, link->end))
break;
new_index++;
}
break;
case GTK_DIR_TAB_BACKWARD:
if (focus_link)
new_index = focus_link_index == 0 ? info->n_links - 1 : focus_link_index - 1;
new_index = focus_link_index - 1;
else
new_index = info->n_links - 1;
for (i = new_index; i >= 0; i--)
if (new_index < 0)
goto out;
while (new_index >= 0)
{
const GtkLabelLink *link = &info->links[i];
const GtkLabelLink *link = &info->links[new_index];
if (!range_is_in_ellipsis (self, link->start, link->end))
break;
new_index--;
}
break;
@@ -1904,7 +1914,7 @@ gtk_label_focus (GtkWidget *widget,
goto out;
}
if (new_index != -1)
if (new_index != -1 && new_index < info->n_links)
{
focus_link = &info->links[new_index];
info->selection_anchor = focus_link->start;
@@ -3615,7 +3625,11 @@ static void
gtk_label_ensure_has_tooltip (GtkLabel *self)
{
guint i;
gboolean has_tooltip = FALSE;
gboolean has_tooltip = gtk_widget_get_has_tooltip(GTK_WIDGET(self));
if (has_tooltip) {
return;
}
for (i = 0; i < self->select_info->n_links; i++)
{
+20 -30
View File
@@ -505,13 +505,11 @@ gettext_initialization (void)
{
setlocale_initialization ();
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, _gtk_get_localedir ());
bindtextdomain (GETTEXT_PACKAGE "-properties", _gtk_get_localedir ());
# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
# endif
#endif
}
@@ -899,31 +897,11 @@ rewrite_event_for_surface (GdkEvent *event,
GdkSurface *new_surface)
{
GdkEventType type;
double x, y;
double x = -G_MAXDOUBLE, y = -G_MAXDOUBLE;
double dx, dy;
type = gdk_event_get_event_type (event);
switch ((guint) type)
{
case GDK_BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
case GDK_MOTION_NOTIFY:
case GDK_TOUCH_BEGIN:
case GDK_TOUCH_UPDATE:
case GDK_TOUCH_END:
case GDK_TOUCH_CANCEL:
case GDK_TOUCHPAD_SWIPE:
case GDK_TOUCHPAD_PINCH:
case GDK_TOUCHPAD_HOLD:
gdk_event_get_position (event, &x, &y);
gdk_surface_translate_coordinates (gdk_event_get_surface (event), new_surface, &x, &y);
break;
default:
x = y = 0;
break;
}
switch ((guint) type)
{
case GDK_BUTTON_PRESS:
@@ -1033,8 +1011,7 @@ rewrite_event_for_grabs (GdkEvent *event)
display = gdk_event_get_display (event);
device = gdk_event_get_device (event);
if (!gdk_device_grab_info (display, device, &grab_surface, &owner_events) ||
!owner_events)
if (!gdk_device_grab_info (display, device, &grab_surface, &owner_events))
return NULL;
break;
default:
@@ -1044,11 +1021,24 @@ rewrite_event_for_grabs (GdkEvent *event)
event_widget = gtk_get_event_widget (event);
grab_widget = GTK_WIDGET (gtk_native_get_for_surface (grab_surface));
if (grab_widget &&
gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
return rewrite_event_for_surface (event, grab_surface);
else
if (!grab_widget)
return NULL;
/* If owner_events was set, events in client surfaces get forwarded
* as normal, but we consider other window groups foreign surfaces.
*/
if (owner_events &&
gtk_main_get_window_group (grab_widget) == gtk_main_get_window_group (event_widget))
return NULL;
/* If owner_events was not set, events only get sent to the grabbing
* surface.
*/
if (!owner_events &&
grab_surface == gtk_native_get_surface (gtk_widget_get_native (event_widget)))
return NULL;
return rewrite_event_for_surface (event, grab_surface);
}
static GdkEvent *
+6 -6
View File
@@ -147,7 +147,7 @@ static guint
gtk_map_list_model_get_n_items (GListModel *list)
{
GtkMapListModel *self = GTK_MAP_LIST_MODEL (list);
if (self->model == NULL)
return 0;
@@ -205,8 +205,8 @@ gtk_map_list_model_model_init (GListModelInterface *iface)
iface->get_item = gtk_map_list_model_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkMapListModel, gtk_map_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_map_list_model_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkMapListModel, gtk_map_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_map_list_model_model_init))
static void
gtk_map_list_model_items_changed_cb (GListModel *model,
@@ -291,7 +291,7 @@ gtk_map_list_model_set_property (GObject *object,
}
}
static void
static void
gtk_map_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -527,7 +527,7 @@ gtk_map_list_model_set_map_func (GtkMapListModel *self,
self->map_func = map_func;
self->user_data = user_data;
self->user_destroy = user_destroy;
gtk_map_list_model_init_items (self);
if (self->model)
@@ -579,7 +579,7 @@ gtk_map_list_model_set_model (GtkMapListModel *self,
}
gtk_map_list_model_init_items (self);
if (removed > 0 || added > 0)
g_list_model_items_changed (G_LIST_MODEL (self), 0, removed, added);
+2 -2
View File
@@ -62,7 +62,7 @@ enum
N_PROPS
};
G_DEFINE_FINAL_TYPE (GtkMediaControls, gtk_media_controls, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (GtkMediaControls, gtk_media_controls, GTK_TYPE_WIDGET)
static GParamSpec *properties[N_PROPS] = { NULL, };
@@ -138,7 +138,7 @@ time_adjustment_changed (GtkAdjustment *adjustment,
if (gtk_adjustment_get_value (adjustment) == (double) gtk_media_stream_get_timestamp (controls->stream) / G_USEC_PER_SEC)
return;
gtk_media_stream_seek (controls->stream,
gtk_media_stream_seek (controls->stream,
gtk_adjustment_get_value (adjustment) * G_USEC_PER_SEC + 0.5);
}
+2 -2
View File
@@ -379,8 +379,8 @@ update_node_ordering (GtkModelButton *button)
gtk_widget_insert_before (button->end_indicator, GTK_WIDGET (button), child);
child = gtk_widget_get_last_child (GTK_WIDGET (button));
if (child != button->start_box)
gtk_widget_insert_after (button->start_box, GTK_WIDGET (button), child);
if (button->end_indicator && child != button->end_indicator)
gtk_widget_insert_after (button->end_indicator, GTK_WIDGET (button), child);
}
}
+5 -5
View File
@@ -201,11 +201,11 @@ gtk_multi_selection_selection_model_init (GtkSelectionModelInterface *iface)
iface->set_selection = gtk_multi_selection_set_selection;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkMultiSelection, gtk_multi_selection, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_multi_selection_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
gtk_multi_selection_selection_model_init))
G_DEFINE_TYPE_EXTENDED (GtkMultiSelection, gtk_multi_selection, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_multi_selection_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
gtk_multi_selection_selection_model_init))
static void
gtk_multi_selection_items_changed_cb (GListModel *model,
+3 -3
View File
@@ -240,9 +240,9 @@ gtk_multi_sorter_buildable_init (GtkBuildableIface *iface)
iface->add_child = gtk_multi_sorter_buildable_add_child;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkMultiSorter, gtk_multi_sorter, GTK_TYPE_SORTER,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_multi_sorter_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_multi_sorter_buildable_init))
G_DEFINE_TYPE_WITH_CODE (GtkMultiSorter, gtk_multi_sorter, GTK_TYPE_SORTER,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_multi_sorter_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_multi_sorter_buildable_init))
static GtkOrdering
gtk_multi_sorter_compare (GtkSorter *sorter,
+6 -6
View File
@@ -113,11 +113,11 @@ gtk_no_selection_selection_model_init (GtkSelectionModelInterface *iface)
iface->get_selection_in_range = gtk_no_selection_get_selection_in_range;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkNoSelection, gtk_no_selection, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_no_selection_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
gtk_no_selection_selection_model_init))
G_DEFINE_TYPE_EXTENDED (GtkNoSelection, gtk_no_selection, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_no_selection_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
gtk_no_selection_selection_model_init))
static void
gtk_no_selection_clear_model (GtkNoSelection *self)
@@ -125,7 +125,7 @@ gtk_no_selection_clear_model (GtkNoSelection *self)
if (self->model == NULL)
return;
g_signal_handlers_disconnect_by_func (self->model,
g_signal_handlers_disconnect_by_func (self->model,
g_list_model_items_changed,
self);
g_clear_object (&self->model);
+2 -2
View File
@@ -52,7 +52,7 @@ enum {
NUM_PROPERTIES
};
G_DEFINE_FINAL_TYPE (GtkNumericSorter, gtk_numeric_sorter, GTK_TYPE_SORTER)
G_DEFINE_TYPE (GtkNumericSorter, gtk_numeric_sorter, GTK_TYPE_SORTER)
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
@@ -491,7 +491,7 @@ gtk_numeric_sorter_set_property (GObject *object,
}
}
static void
static void
gtk_numeric_sorter_get_property (GObject *object,
guint prop_id,
GValue *value,
+14 -14
View File
@@ -72,7 +72,7 @@ enum
static GParamSpec *child_props[N_CHILD_PROPERTIES];
G_DEFINE_FINAL_TYPE (GtkOverlayLayoutChild, gtk_overlay_layout_child, GTK_TYPE_LAYOUT_CHILD)
G_DEFINE_TYPE (GtkOverlayLayoutChild, gtk_overlay_layout_child, GTK_TYPE_LAYOUT_CHILD)
static void
gtk_overlay_layout_child_set_property (GObject *gobject,
@@ -247,7 +247,7 @@ gtk_overlay_layout_child_get_clip_overlay (GtkOverlayLayoutChild *child)
return child->clip_overlay;
}
G_DEFINE_FINAL_TYPE (GtkOverlayLayout, gtk_overlay_layout, GTK_TYPE_LAYOUT_MANAGER)
G_DEFINE_TYPE (GtkOverlayLayout, gtk_overlay_layout, GTK_TYPE_LAYOUT_MANAGER)
static void
gtk_overlay_layout_measure (GtkLayoutManager *layout_manager,
@@ -346,10 +346,10 @@ gtk_overlay_child_update_style_classes (GtkOverlay *overlay,
gboolean is_left, is_right, is_top, is_bottom;
gboolean has_left, has_right, has_top, has_bottom;
has_left = gtk_widget_has_css_class (widget, "left");
has_right = gtk_widget_has_css_class (widget, "right");
has_top = gtk_widget_has_css_class (widget, "top");
has_bottom = gtk_widget_has_css_class (widget, "bottom");
has_left = gtk_widget_has_css_class (child, "left");
has_right = gtk_widget_has_css_class (child, "right");
has_top = gtk_widget_has_css_class (child, "top");
has_bottom = gtk_widget_has_css_class (child, "bottom");
is_left = is_right = is_top = is_bottom = FALSE;
@@ -372,24 +372,24 @@ gtk_overlay_child_update_style_classes (GtkOverlay *overlay,
is_bottom = (child_allocation->y + child_allocation->height == height);
if (has_left && !is_left)
gtk_widget_remove_css_class (widget, "left");
gtk_widget_remove_css_class (child, "left");
else if (!has_left && is_left)
gtk_widget_add_css_class (widget, "left");
gtk_widget_add_css_class (child, "left");
if (has_right && !is_right)
gtk_widget_remove_css_class (widget, "right");
gtk_widget_remove_css_class (child, "right");
else if (!has_right && is_right)
gtk_widget_add_css_class (widget, "right");
gtk_widget_add_css_class (child, "right");
if (has_top && !is_top)
gtk_widget_remove_css_class (widget, "top");
gtk_widget_remove_css_class (child, "top");
else if (!has_top && is_top)
gtk_widget_add_css_class (widget, "top");
gtk_widget_add_css_class (child, "top");
if (has_bottom && !is_bottom)
gtk_widget_remove_css_class (widget, "bottom");
gtk_widget_remove_css_class (child, "bottom");
else if (!has_bottom && is_bottom)
gtk_widget_add_css_class (widget, "bottom");
gtk_widget_add_css_class (child, "bottom");
}
static void
+43 -40
View File
@@ -44,7 +44,7 @@
/**
* GtkPaned:
*
* `GtkPaned` has two panes, arranged either horizontally or vertically.
* A widget with two panes, arranged either horizontally or vertically.
*
* ![An example GtkPaned](panes.png)
*
@@ -63,13 +63,13 @@
* each child inside a [class@Gtk.Frame] so that the gutter appears as a
* ridge. No separator is drawn if one of the children is missing.
*
* Each child has two options that can be set, @resize and @shrink. If
* @resize is true, then when the `GtkPaned` is resized, that child will
* expand or shrink along with the paned widget. If @shrink is true, then
* Each child has two options that can be set, "resize" and "shrink". If
* "resize" is true then, when the `GtkPaned` is resized, that child will
* expand or shrink along with the paned widget. If "shrink" is true, then
* that child can be made smaller than its requisition by the user.
* Setting @shrink to %FALSE allows the application to set a minimum size.
* If @resize is false for both children, then this is treated as if
* @resize is true for both children.
* Setting "shrink" to false allows the application to set a minimum size.
* If "resize" is false for both children, then this is treated as if
* "resize" is true for both children.
*
* The application can set the position of the slider as if it were set
* by the user, by calling [method@Gtk.Paned.set_position].
@@ -431,7 +431,7 @@ gtk_paned_class_init (GtkPanedClass *class)
/**
* GtkPaned:position-set:
*
* %TRUE if the `position` property has been set.
* Whether the [property@Gtk.Paned:position] property has been set.
*/
paned_props[PROP_POSITION_SET] =
g_param_spec_boolean ("position-set",
@@ -443,7 +443,8 @@ gtk_paned_class_init (GtkPanedClass *class)
/**
* GtkPaned:min-position:
*
* The smallest possible value for the position property.
* The smallest possible value for the [property@Gtk.Paned:position]
* property.
*
* This property is derived from the size and shrinkability
* of the widget's children.
@@ -458,7 +459,8 @@ gtk_paned_class_init (GtkPanedClass *class)
/**
* GtkPaned:max-position:
*
* The largest possible value for the position property.
* The largest possible value for the [property@Gtk.Paned:position]
* property.
*
* This property is derived from the size and shrinkability
* of the widget's children.
@@ -573,7 +575,7 @@ gtk_paned_class_init (GtkPanedClass *class)
*
* This is a [keybinding signal](class.SignalAction.html).
*
* The default binding is F6.
* The default binding is <kbd>F6</kbd>.
*/
signals [CYCLE_CHILD_FOCUS] =
g_signal_new (I_("cycle-child-focus"),
@@ -594,7 +596,7 @@ gtk_paned_class_init (GtkPanedClass *class)
*
* This is a [keybinding signal](class.SignalAction.html).
*
* The default binding is Tab.
* The default binding is <kbd>Tab</kbd>.
*/
signals [TOGGLE_HANDLE_FOCUS] =
g_signal_new (I_("toggle-handle-focus"),
@@ -634,7 +636,7 @@ gtk_paned_class_init (GtkPanedClass *class)
*
* This is a [keybinding signal](class.SignalAction.html).
*
* The default binding for this signal is F8.
* The default binding for this signal is <kbd>F8</kbd>.
*/
signals [CYCLE_HANDLE_FOCUS] =
g_signal_new (I_("cycle-handle-focus"),
@@ -655,7 +657,8 @@ gtk_paned_class_init (GtkPanedClass *class)
*
* This is a [keybinding signal](class.SignalAction.html).
*
* The default binding for this signal is Return or Space.
* The default binding for this signal is <kbd>Return</kbd> or
* <kbd>Space</kbd>.
*/
signals [ACCEPT_POSITION] =
g_signal_new (I_("accept-position"),
@@ -678,7 +681,7 @@ gtk_paned_class_init (GtkPanedClass *class)
*
* This is a [keybinding signal](class.SignalAction.html).
*
* The default binding for this signal is Escape.
* The default binding for this signal is <kbd>Escape</kbd>.
*/
signals [CANCEL_POSITION] =
g_signal_new (I_("cancel-position"),
@@ -1555,7 +1558,7 @@ gtk_paned_css_changed (GtkWidget *widget,
*
* Creates a new `GtkPaned` widget.
*
* Returns: a new `GtkPaned`.
* Returns: the newly created paned widget
*/
GtkWidget *
gtk_paned_new (GtkOrientation orientation)
@@ -1568,9 +1571,11 @@ gtk_paned_new (GtkOrientation orientation)
/**
* gtk_paned_set_start_child: (attributes org.gtk.Method.set_property=start-child)
* @paned: a `GtkPaned`
* @child: the widget to add
* @child: (nullable): the widget to add
*
* Sets the start child of @paned to @child.
*
* If @child is `NULL`, the existing child will be removed.
*/
void
gtk_paned_set_start_child (GtkPaned *paned,
@@ -1596,8 +1601,6 @@ gtk_paned_set_start_child (GtkPaned *paned,
*
* Retrieves the start child of the given `GtkPaned`.
*
* See also: `GtkPaned`:start-child
*
* Returns: (transfer none) (nullable): the start child widget
*/
GtkWidget *
@@ -1611,9 +1614,9 @@ gtk_paned_get_start_child (GtkPaned *paned)
/**
* gtk_paned_set_resize_start_child: (attributes org.gtk.Method.set_property=resize-start-child)
* @paned: a `GtkPaned`
* @resize: %TRUE to let the start child be resized
* @resize: true to let the start child be resized
*
* Sets the `GtkPaned`:resize-start-child property
* Sets whether the [property@Gtk.Paned:start-child] can be resized.
*/
void
gtk_paned_set_resize_start_child (GtkPaned *paned,
@@ -1633,9 +1636,9 @@ gtk_paned_set_resize_start_child (GtkPaned *paned,
* gtk_paned_get_resize_start_child: (attributes org.gtk.Method.get_property=resize-start-child)
* @paned: a `GtkPaned`
*
* Returns whether the start child can be resized.
* Returns whether the [property@Gtk.Paned:start-child] can be resized.
*
* Returns: %TRUE if the start child is resizable
* Returns: true if the start child is resizable
*/
gboolean
gtk_paned_get_resize_start_child (GtkPaned *paned)
@@ -1648,9 +1651,9 @@ gtk_paned_get_resize_start_child (GtkPaned *paned)
/**
* gtk_paned_set_shrink_start_child: (attributes org.gtk.Method.set_property=shrink-start-child)
* @paned: a `GtkPaned`
* @resize: %TRUE to let the start child be shrunk
* @resize: true to let the start child be shrunk
*
* Sets the `GtkPaned`:shrink-start-child property
* Sets whether the [property@Gtk.Paned:start-child] can shrink.
*/
void
gtk_paned_set_shrink_start_child (GtkPaned *paned,
@@ -1670,9 +1673,9 @@ gtk_paned_set_shrink_start_child (GtkPaned *paned,
* gtk_paned_get_shrink_start_child: (attributes org.gtk.Method.get_property=shrink-start-child)
* @paned: a `GtkPaned`
*
* Returns whether the start child can be shrunk.
* Returns whether the [property@Gtk.Paned:start-child] can shrink.
*
* Returns: %TRUE if the start child is shrinkable
* Returns: true if the start child is shrinkable
*/
gboolean
gtk_paned_get_shrink_start_child (GtkPaned *paned)
@@ -1685,9 +1688,11 @@ gtk_paned_get_shrink_start_child (GtkPaned *paned)
/**
* gtk_paned_set_end_child: (attributes org.gtk.Method.set_property=end-child)
* @paned: a `GtkPaned`
* @child: the widget to add
* @child: (nullable): the widget to add
*
* Sets the end child of @paned to @child.
*
* If @child is `NULL`, the existing child will be removed.
*/
void
gtk_paned_set_end_child (GtkPaned *paned,
@@ -1713,8 +1718,6 @@ gtk_paned_set_end_child (GtkPaned *paned,
*
* Retrieves the end child of the given `GtkPaned`.
*
* See also: `GtkPaned`:end-child
*
* Returns: (transfer none) (nullable): the end child widget
*/
GtkWidget *
@@ -1728,9 +1731,9 @@ gtk_paned_get_end_child (GtkPaned *paned)
/**
* gtk_paned_set_resize_end_child: (attributes org.gtk.Method.set_property=resize-end-child)
* @paned: a `GtkPaned`
* @resize: %TRUE to let the end child be resized
* @resize: true to let the end child be resized
*
* Sets the `GtkPaned`:resize-end-child property
* Sets whether the [property@Gtk.Paned:end-child] can be resized.
*/
void
gtk_paned_set_resize_end_child (GtkPaned *paned,
@@ -1750,9 +1753,9 @@ gtk_paned_set_resize_end_child (GtkPaned *paned,
* gtk_paned_get_resize_end_child: (attributes org.gtk.Method.get_property=resize-end-child)
* @paned: a `GtkPaned`
*
* Returns whether the end child can be resized.
* Returns whether the [property@Gtk.Paned:end-child] can be resized.
*
* Returns: %TRUE if the end child is resizable
* Returns: true if the end child is resizable
*/
gboolean
gtk_paned_get_resize_end_child (GtkPaned *paned)
@@ -1765,9 +1768,9 @@ gtk_paned_get_resize_end_child (GtkPaned *paned)
/**
* gtk_paned_set_shrink_end_child: (attributes org.gtk.Method.set_property=shrink-end-child)
* @paned: a `GtkPaned`
* @resize: %TRUE to let the end child be shrunk
* @resize: true to let the end child be shrunk
*
* Sets the `GtkPaned`:shrink-end-child property
* Sets whether the [property@Gtk.Paned:end-child] can shrink.
*/
void
gtk_paned_set_shrink_end_child (GtkPaned *paned,
@@ -1787,9 +1790,9 @@ gtk_paned_set_shrink_end_child (GtkPaned *paned,
* gtk_paned_get_shrink_end_child: (attributes org.gtk.Method.get_property=shrink-end-child)
* @paned: a `GtkPaned`
*
* Returns whether the end child can be shrunk.
* Returns whether the [property@Gtk.Paned:end-child] can shrink.
*
* Returns: %TRUE if the end child is shrinkable
* Returns: true if the end child is shrinkable
*/
gboolean
gtk_paned_get_shrink_end_child (GtkPaned *paned)
@@ -1805,7 +1808,7 @@ gtk_paned_get_shrink_end_child (GtkPaned *paned)
*
* Obtains the position of the divider between the two panes.
*
* Returns: position of the divider
* Returns: the position of the divider, in pixels
**/
int
gtk_paned_get_position (GtkPaned *paned)
@@ -1822,7 +1825,7 @@ gtk_paned_get_position (GtkPaned *paned)
* is unset
*
* Sets the position of the divider between the two panes.
**/
*/
void
gtk_paned_set_position (GtkPaned *paned,
int position)
+4 -4
View File
@@ -104,7 +104,7 @@ enum {
PROP_ACTIVATES_DEFAULT,
PROP_SHOW_PEEK_ICON,
PROP_EXTRA_MENU,
NUM_PROPERTIES
NUM_PROPERTIES
};
static GParamSpec *props[NUM_PROPERTIES] = { NULL, };
@@ -112,9 +112,9 @@ static GParamSpec *props[NUM_PROPERTIES] = { NULL, };
static void gtk_password_entry_editable_init (GtkEditableInterface *iface);
static void gtk_password_entry_accessible_init (GtkAccessibleInterface *iface);
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkPasswordEntry, gtk_password_entry, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE, gtk_password_entry_accessible_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_password_entry_editable_init))
G_DEFINE_TYPE_WITH_CODE (GtkPasswordEntry, gtk_password_entry, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE, gtk_password_entry_accessible_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_password_entry_editable_init))
static void
caps_lock_state_changed (GdkDevice *device,
+7 -2
View File
@@ -29,10 +29,15 @@
G_BEGIN_DECLS
#define GTK_TYPE_PASSWORD_ENTRY (gtk_password_entry_get_type ())
#define GTK_TYPE_PASSWORD_ENTRY (gtk_password_entry_get_type ())
#define GTK_PASSWORD_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PASSWORD_ENTRY, GtkPasswordEntry))
#define GTK_IS_PASSWORD_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PASSWORD_ENTRY))
typedef struct _GtkPasswordEntry GtkPasswordEntry;
typedef struct _GtkPasswordEntryClass GtkPasswordEntryClass;
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkPasswordEntry, gtk_password_entry, GTK, PASSWORD_ENTRY, GtkWidget)
GType gtk_password_entry_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_password_entry_new (void);
+2 -2
View File
@@ -1,4 +1,4 @@
/* gtkpasswordentrybuffer.c: Entry buffer with secure allocation
/* gtkpasswordentrybuffer.c: Entry buffer with secure allocation
*
Copyright 2009 Stefan Walter
* Copyright 2020 GNOME Foundation
@@ -50,7 +50,7 @@ struct _GtkPasswordEntryBuffer
guint text_chars;
};
G_DEFINE_FINAL_TYPE (GtkPasswordEntryBuffer, gtk_password_entry_buffer, GTK_TYPE_ENTRY_BUFFER)
G_DEFINE_TYPE (GtkPasswordEntryBuffer, gtk_password_entry_buffer, GTK_TYPE_ENTRY_BUFFER)
static const char *
gtk_password_entry_buffer_real_get_text (GtkEntryBuffer *buffer,
+1 -1
View File
@@ -111,7 +111,7 @@ struct _GtkPictureClass
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
G_DEFINE_FINAL_TYPE (GtkPicture, gtk_picture, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (GtkPicture, gtk_picture, GTK_TYPE_WIDGET)
static void
gtk_picture_snapshot (GtkWidget *widget,
+11 -9
View File
@@ -2202,25 +2202,27 @@ gtk_range_scroll_controller_scroll (GtkEventControllerScroll *scroll,
GtkRange *range)
{
GtkRangePrivate *priv = gtk_range_get_instance_private (range);
double scroll_unit, delta;
double delta;
gboolean handled;
GtkOrientation move_orientation;
#ifdef GDK_WINDOWING_MACOS
scroll_unit = 1;
#else
scroll_unit = gtk_adjustment_get_page_increment (priv->adjustment);
#endif
GdkScrollUnit scroll_unit;
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL && dx != 0)
{
move_orientation = GTK_ORIENTATION_HORIZONTAL;
delta = dx * scroll_unit;
delta = dx;
}
else
{
move_orientation = GTK_ORIENTATION_VERTICAL;
delta = dy * scroll_unit;
delta = dy;
}
scroll_unit = gtk_event_controller_scroll_get_unit (scroll);
if (scroll_unit == GDK_SCROLL_UNIT_WHEEL)
{
delta *= gtk_adjustment_get_page_increment (priv->adjustment);
}
if (delta != 0 && should_invert_move (range, move_orientation))
+7 -8
View File
@@ -29,13 +29,11 @@
* All scrollable widgets should do the following.
*
* - When a parent widget sets the scrollable child widgets adjustments,
* the widget should populate the adjustments
* [property@Gtk.Adjustment:lower],
* [property@Gtk.Adjustment:upper],
* [property@Gtk.Adjustment:step-increment],
* [property@Gtk.Adjustment:page-increment] and
* [property@Gtk.Adjustment:page-size] properties and connect to the
* [signal@Gtk.Adjustment::value-changed] signal.
* the widget should connect to the [signal@Gtk.Adjustment::value-changed]
* signal. The child widget should then populate the adjustments properties
* as soon as possible, which usually means queueing an allocation right away
* and populating the properties in the [vfunc@Gtk.Widget.size_allocate]
* implementation.
*
* - Because its preferred size is the size for a fully expanded widget,
* the scrollable widget must be able to cope with underallocations.
@@ -43,7 +41,8 @@
* [vfunc@Gtk.Widget.size_allocate] implementation.
*
* - When the parent allocates space to the scrollable child widget,
* the widget should update the adjustments properties with new values.
* the widget must ensure the adjustments property values are correct and up
* to date, for example using [method@Gtk.Adjustment.configure].
*
* - When any of the adjustments emits the [signal@Gtk.Adjustment::value-changed]
* signal, the scrollable widget should scroll its contents.
+106 -72
View File
@@ -379,6 +379,7 @@ static void gtk_scrolled_window_measure (GtkWidget *widget,
static void gtk_scrolled_window_map (GtkWidget *widget);
static void gtk_scrolled_window_unmap (GtkWidget *widget);
static void gtk_scrolled_window_realize (GtkWidget *widget);
static void gtk_scrolled_window_unrealize (GtkWidget *widget);
static void _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window,
GtkAdjustment *adjustment,
double value);
@@ -587,6 +588,7 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
widget_class->map = gtk_scrolled_window_map;
widget_class->unmap = gtk_scrolled_window_unmap;
widget_class->realize = gtk_scrolled_window_realize;
widget_class->unrealize = gtk_scrolled_window_unrealize;
widget_class->direction_changed = gtk_scrolled_window_direction_changed;
widget_class->compute_expand = gtk_scrolled_window_compute_expand;
widget_class->get_request_mode = gtk_scrolled_window_get_request_mode;
@@ -700,7 +702,7 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkScrolledWindow:kinetic-scrolling: (attributes org.gtk.Property.get=gtk_scrolled_window_get_kinetic_scrolling org.gtk.Property.set=gtk_scrolled_window_set_overlay_scrolling)
* GtkScrolledWindow:kinetic-scrolling: (attributes org.gtk.Property.get=gtk_scrolled_window_get_kinetic_scrolling org.gtk.Property.set=gtk_scrolled_window_set_kinetic_scrolling)
*
* Whether kinetic scrolling is enabled or not.
*
@@ -1056,6 +1058,11 @@ gtk_scrolled_window_decelerate (GtkScrolledWindow *scrolled_window,
gtk_scrolled_window_start_deceleration (scrolled_window);
priv->x_velocity = priv->y_velocity = 0;
}
else
{
g_clear_pointer (&priv->hscrolling, gtk_kinetic_scrolling_free);
g_clear_pointer (&priv->vscrolling, gtk_kinetic_scrolling_free);
}
}
static void
@@ -1226,15 +1233,14 @@ check_update_scrollbar_proximity (GtkScrolledWindow *sw,
}
static double
get_scroll_unit (GtkScrolledWindow *sw,
GtkOrientation orientation,
GtkEventControllerScroll *scroll)
get_wheel_detent_scroll_step (GtkScrolledWindow *sw,
GtkOrientation orientation)
{
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (sw);
GtkScrollbar *scrollbar;
GtkAdjustment *adj;
double page_size;
double scroll_unit;
double scroll_step;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
scrollbar = GTK_SCROLLBAR (priv->hscrollbar);
@@ -1246,20 +1252,9 @@ get_scroll_unit (GtkScrolledWindow *sw,
adj = gtk_scrollbar_get_adjustment (scrollbar);
page_size = gtk_adjustment_get_page_size (adj);
scroll_unit = pow (page_size, 2.0 / 3.0);
scroll_step = pow (page_size, 2.0 / 3.0);
#ifdef GDK_WINDOWING_MACOS
{
GdkEvent *event = gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (scroll));
if (event != NULL &&
gdk_event_get_event_type (event) == GDK_SCROLL &&
gdk_scroll_event_get_direction (event) == GDK_SCROLL_SMOOTH)
scroll_unit = 1;
}
#endif
return scroll_unit;
return scroll_step;
}
static gboolean
@@ -1401,12 +1396,18 @@ scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
{
GtkAdjustment *adj;
double new_value;
double scroll_unit;
GdkScrollUnit scroll_unit;
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->hscrollbar));
scroll_unit = get_scroll_unit (scrolled_window, GTK_ORIENTATION_HORIZONTAL, scroll);
scroll_unit = gtk_event_controller_scroll_get_unit (scroll);
new_value = priv->unclamped_hadj_value + delta_x * scroll_unit;
if (scroll_unit == GDK_SCROLL_UNIT_WHEEL)
{
delta_x *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_HORIZONTAL);
}
new_value = priv->unclamped_hadj_value + delta_x;
_gtk_scrolled_window_set_adjustment_value (scrolled_window, adj,
new_value);
}
@@ -1416,12 +1417,18 @@ scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
{
GtkAdjustment *adj;
double new_value;
double scroll_unit;
GdkScrollUnit scroll_unit;
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->vscrollbar));
scroll_unit = get_scroll_unit (scrolled_window, GTK_ORIENTATION_VERTICAL, scroll);
scroll_unit = gtk_event_controller_scroll_get_unit (scroll);
new_value = priv->unclamped_vadj_value + delta_y * scroll_unit;
if (scroll_unit == GDK_SCROLL_UNIT_WHEEL)
{
delta_y *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_VERTICAL);
}
new_value = priv->unclamped_vadj_value + delta_y;
_gtk_scrolled_window_set_adjustment_value (scrolled_window, adj,
new_value);
}
@@ -1468,30 +1475,36 @@ scroll_controller_decelerate (GtkEventControllerScroll *scroll,
double initial_vel_y,
GtkScrolledWindow *scrolled_window)
{
double unit_x, unit_y;
GdkScrollUnit scroll_unit;
gboolean shifted;
GdkModifierType state;
scroll_unit = gtk_event_controller_scroll_get_unit (scroll);
state = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (scroll));
shifted = (state & GDK_SHIFT_MASK) != 0;
unit_x = get_scroll_unit (scrolled_window, GTK_ORIENTATION_HORIZONTAL, scroll);
unit_y = get_scroll_unit (scrolled_window, GTK_ORIENTATION_VERTICAL, scroll);
if (shifted)
{
gtk_scrolled_window_decelerate (scrolled_window,
initial_vel_y * unit_x,
initial_vel_x * unit_y);
double tmp;
tmp = initial_vel_x;
initial_vel_x = initial_vel_y;
initial_vel_y = tmp;
}
else
if (scroll_unit == GDK_SCROLL_UNIT_WHEEL)
{
gtk_scrolled_window_decelerate (scrolled_window,
initial_vel_x * unit_x,
initial_vel_y * unit_y);
initial_vel_x *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_HORIZONTAL);
initial_vel_y *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_VERTICAL);
}
gtk_scrolled_window_decelerate (scrolled_window,
initial_vel_x,
initial_vel_y);
}
static void
@@ -3262,6 +3275,7 @@ scrolled_window_deceleration_cb (GtkWidget *widget,
GtkAdjustment *hadjustment, *vadjustment;
gint64 current_time;
double position, elapsed;
gboolean retval = G_SOURCE_REMOVE;
current_time = gdk_frame_clock_get_frame_time (frame_clock);
elapsed = (current_time - priv->last_deceleration_time) / (double)G_TIME_SPAN_SECOND;
@@ -3277,28 +3291,23 @@ scrolled_window_deceleration_cb (GtkWidget *widget,
{
priv->unclamped_hadj_value = position;
gtk_adjustment_set_value (hadjustment, position);
retval = G_SOURCE_CONTINUE;
}
else if (priv->hscrolling)
g_clear_pointer (&priv->hscrolling, gtk_kinetic_scrolling_free);
if (priv->vscrolling &&
gtk_kinetic_scrolling_tick (priv->vscrolling, elapsed, &position, NULL))
{
priv->unclamped_vadj_value = position;
gtk_adjustment_set_value (vadjustment, position);
}
else if (priv->vscrolling)
g_clear_pointer (&priv->vscrolling, gtk_kinetic_scrolling_free);
if (!priv->hscrolling && !priv->vscrolling)
{
gtk_scrolled_window_cancel_deceleration (scrolled_window);
return G_SOURCE_REMOVE;
retval = G_SOURCE_CONTINUE;
}
gtk_scrolled_window_invalidate_overshoot (scrolled_window);
if (retval == G_SOURCE_REMOVE)
gtk_scrolled_window_cancel_deceleration (scrolled_window);
else
gtk_scrolled_window_invalidate_overshoot (scrolled_window);
return G_SOURCE_CONTINUE;
return retval;
}
static void
@@ -3362,19 +3371,23 @@ gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
GtkAdjustment *hadjustment;
gtk_scrolled_window_accumulate_velocity (&priv->hscrolling, elapsed, &priv->x_velocity);
g_clear_pointer (&priv->hscrolling, gtk_kinetic_scrolling_free);
hadjustment = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->hscrollbar));
lower = gtk_adjustment_get_lower (hadjustment);
upper = gtk_adjustment_get_upper (hadjustment);
upper -= gtk_adjustment_get_page_size (hadjustment);
priv->hscrolling =
gtk_kinetic_scrolling_new (lower,
upper,
MAX_OVERSHOOT_DISTANCE,
DECELERATION_FRICTION,
OVERSHOOT_FRICTION,
priv->unclamped_hadj_value,
priv->x_velocity);
if (priv->x_velocity != 0)
{
hadjustment = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->hscrollbar));
lower = gtk_adjustment_get_lower (hadjustment);
upper = gtk_adjustment_get_upper (hadjustment);
upper -= gtk_adjustment_get_page_size (hadjustment);
priv->hscrolling =
gtk_kinetic_scrolling_new (lower,
upper,
MAX_OVERSHOOT_DISTANCE,
DECELERATION_FRICTION,
OVERSHOOT_FRICTION,
priv->unclamped_hadj_value,
priv->x_velocity);
}
}
else
g_clear_pointer (&priv->hscrolling, gtk_kinetic_scrolling_free);
@@ -3385,19 +3398,23 @@ gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
GtkAdjustment *vadjustment;
gtk_scrolled_window_accumulate_velocity (&priv->vscrolling, elapsed, &priv->y_velocity);
g_clear_pointer (&priv->vscrolling, gtk_kinetic_scrolling_free);
vadjustment = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->vscrollbar));
lower = gtk_adjustment_get_lower(vadjustment);
upper = gtk_adjustment_get_upper(vadjustment);
upper -= gtk_adjustment_get_page_size(vadjustment);
priv->vscrolling =
gtk_kinetic_scrolling_new (lower,
upper,
MAX_OVERSHOOT_DISTANCE,
DECELERATION_FRICTION,
OVERSHOOT_FRICTION,
priv->unclamped_vadj_value,
priv->y_velocity);
if (priv->y_velocity != 0)
{
vadjustment = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->vscrollbar));
lower = gtk_adjustment_get_lower(vadjustment);
upper = gtk_adjustment_get_upper(vadjustment);
upper -= gtk_adjustment_get_page_size(vadjustment);
priv->vscrolling =
gtk_kinetic_scrolling_new (lower,
upper,
MAX_OVERSHOOT_DISTANCE,
DECELERATION_FRICTION,
OVERSHOOT_FRICTION,
priv->unclamped_vadj_value,
priv->y_velocity);
}
}
else
g_clear_pointer (&priv->vscrolling, gtk_kinetic_scrolling_free);
@@ -3849,15 +3866,32 @@ gtk_scrolled_window_realize (GtkWidget *widget)
{
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window);
GtkSettings *settings;
priv->hindicator.scrollbar = priv->hscrollbar;
priv->vindicator.scrollbar = priv->vscrollbar;
gtk_scrolled_window_sync_use_indicators (scrolled_window);
settings = gtk_widget_get_settings (widget);
g_signal_connect_swapped (settings, "notify::gtk-overlay-scrolling",
G_CALLBACK (gtk_scrolled_window_update_use_indicators), widget);
GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->realize (widget);
}
static void
gtk_scrolled_window_unrealize (GtkWidget *widget)
{
GtkSettings *settings;
settings = gtk_widget_get_settings (widget);
g_signal_handlers_disconnect_by_func (settings, gtk_scrolled_window_sync_use_indicators, widget);
GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->unrealize (widget);
}
/**
* gtk_scrolled_window_get_min_content_width: (attributes org.gtk.Method.get_property=min-content-width)
* @scrolled_window: a `GtkScrolledWindow`
+3 -1
View File
@@ -328,6 +328,8 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
*
* The delay in milliseconds from last keypress to the search
* changed signal.
*
* Since: 4.8
*/
props[PROP_SEARCH_DELAY] =
g_param_spec_uint ("search-delay",
@@ -798,7 +800,7 @@ gtk_search_entry_get_key_capture_widget (GtkSearchEntry *entry)
}
/**
* gtk_search_entry_set_searcH-delay:
* gtk_search_entry_set_search_delay:
* @entry: a `GtkSearchEntry`
* @delay: a delay in milliseconds
*
+2 -2
View File
@@ -95,8 +95,8 @@ gtk_selection_filter_model_list_model_init (GListModelInterface *iface)
iface->get_item = gtk_selection_filter_model_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkSelectionFilterModel, gtk_selection_filter_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_selection_filter_model_list_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkSelectionFilterModel, gtk_selection_filter_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_selection_filter_model_list_model_init))
static void
selection_filter_model_items_changed (GtkSelectionFilterModel *self,
+7 -5
View File
@@ -43,12 +43,14 @@
* [signal@Gtk.SelectionModel::selection-changed] signal by calling the
* [method@Gtk.SelectionModel.selection_changed] function. The positions given
* in that signal may have their selection state changed, though that is not a
* requirement. If new items added to the model via the ::items-changed signal
* are selected or not is up to the implementation.
* requirement. If new items added to the model via the
* [signal@Gio.ListModel::items-changed] signal are selected or not is up to the
* implementation.
*
* Note that items added via ::items-changed may already be selected and no
* [Gtk.SelectionModel::selection-changed] will be emitted for them. So to
* track which items are selected, it is necessary to listen to both signals.
* Note that items added via [signal@Gio.ListModel::items-changed] may already
* be selected and no [signal@Gtk.SelectionModel::selection-changed] will be
* emitted for them. So to track which items are selected, it is necessary to
* listen to both signals.
*
* Additionally, the interface can expose functionality to select and unselect
* items. If these functions are implemented, GTK's list widgets will allow users
+2 -2
View File
@@ -65,7 +65,7 @@ enum
N_PROPS
};
G_DEFINE_FINAL_TYPE (GtkShortcut, gtk_shortcut, G_TYPE_OBJECT)
G_DEFINE_TYPE (GtkShortcut, gtk_shortcut, G_TYPE_OBJECT)
static GParamSpec *properties[N_PROPS] = { NULL, };
@@ -387,7 +387,7 @@ gtk_shortcut_set_arguments (GtkShortcut *self,
if (self->args == args)
return;
g_clear_pointer (&self->args, g_variant_unref);
if (args)
self->args = g_variant_ref_sink (args);
+15 -15
View File
@@ -32,9 +32,9 @@
* item.
*
* Note that the selection is *persistent* -- if the selected item is removed
* and re-added in the same ::items-changed emission, it stays selected.
* In particular, this means that changing the sort order of an underlying sort
* model will preserve the selection.
* and re-added in the same [signal@Gio.ListModel::items-changed] emission, it
* stays selected. In particular, this means that changing the sort order of an
* underlying sort model will preserve the selection.
*/
struct _GtkSingleSelection
{
@@ -157,17 +157,17 @@ gtk_single_selection_unselect_item (GtkSelectionModel *model,
static void
gtk_single_selection_selection_model_init (GtkSelectionModelInterface *iface)
{
iface->is_selected = gtk_single_selection_is_selected;
iface->get_selection_in_range = gtk_single_selection_get_selection_in_range;
iface->select_item = gtk_single_selection_select_item;
iface->unselect_item = gtk_single_selection_unselect_item;
iface->is_selected = gtk_single_selection_is_selected;
iface->get_selection_in_range = gtk_single_selection_get_selection_in_range;
iface->select_item = gtk_single_selection_select_item;
iface->unselect_item = gtk_single_selection_unselect_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkSingleSelection, gtk_single_selection, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_single_selection_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
gtk_single_selection_selection_model_init))
G_DEFINE_TYPE_EXTENDED (GtkSingleSelection, gtk_single_selection, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_single_selection_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
gtk_single_selection_selection_model_init))
static void
gtk_single_selection_items_changed_cb (GListModel *model,
@@ -281,7 +281,7 @@ gtk_single_selection_clear_model (GtkSingleSelection *self)
if (self->model == NULL)
return;
g_signal_handlers_disconnect_by_func (self->model,
g_signal_handlers_disconnect_by_func (self->model,
gtk_single_selection_items_changed_cb,
self);
g_clear_object (&self->model);
@@ -510,7 +510,7 @@ gtk_single_selection_set_model (GtkSingleSelection *self,
return;
g_object_freeze_notify (G_OBJECT (self));
n_items_before = self->model ? g_list_model_get_n_items (self->model) : 0;
gtk_single_selection_clear_model (self);
@@ -674,7 +674,7 @@ gtk_single_selection_set_autoselect (GtkSingleSelection *self,
self->autoselect = autoselect;
g_object_freeze_notify (G_OBJECT (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_AUTOSELECT]);
if (self->autoselect && !self->selected_item)
+4 -4
View File
@@ -73,7 +73,7 @@ gtk_slice_list_model_get_n_items (GListModel *list)
{
GtkSliceListModel *self = GTK_SLICE_LIST_MODEL (list);
guint n_items;
if (self->model == NULL)
return 0;
@@ -110,8 +110,8 @@ gtk_slice_list_model_model_init (GListModelInterface *iface)
iface->get_item = gtk_slice_list_model_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkSliceListModel, gtk_slice_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_slice_list_model_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkSliceListModel, gtk_slice_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_slice_list_model_model_init))
static void
gtk_slice_list_model_items_changed_cb (GListModel *model,
@@ -193,7 +193,7 @@ gtk_slice_list_model_set_property (GObject *object,
}
}
static void
static void
gtk_slice_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
+8 -8
View File
@@ -173,8 +173,8 @@ gtk_sort_list_model_model_init (GListModelInterface *iface)
iface->get_item = gtk_sort_list_model_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkSortListModel, gtk_sort_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_sort_list_model_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkSortListModel, gtk_sort_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_sort_list_model_model_init))
static gboolean
gtk_sort_list_model_is_sorting (GtkSortListModel *self)
@@ -253,7 +253,7 @@ gtk_sort_list_model_sort_step (GtkSortListModel *self,
start_change = MIN (start_change, (gpointer *) change.base);
end_change = MAX (end_change, ((gpointer *) change.base) + change.len);
}
if (g_get_monotonic_time () >= end_time && !finish)
break;
}
@@ -419,7 +419,7 @@ gtk_sort_list_model_clear_items (GtkSortListModel *self,
g_clear_pointer (&self->positions, g_free);
gtk_sort_list_model_clear_keys (self);
}
}
static gboolean
gtk_sort_list_model_should_sort (GtkSortListModel *self)
@@ -478,7 +478,7 @@ gtk_sort_list_model_update_items (GtkSortListModel *self,
n_items = self->n_items;
start = n_items;
end = n_items;
/* first, move the keys over */
old_keys = self->keys;
gtk_sort_list_model_clear_sort_keys (self, position, removed);
@@ -523,7 +523,7 @@ gtk_sort_list_model_update_items (GtkSortListModel *self,
if (pos >= position + removed)
pos = pos - removed + added;
else if (pos >= position)
{
{
start = MIN (start, valid);
end = n_items - i - 1;
continue;
@@ -650,7 +650,7 @@ gtk_sort_list_model_set_property (GObject *object,
}
}
static void
static void
gtk_sort_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -903,7 +903,7 @@ gtk_sort_list_model_set_model (GtkSortListModel *self,
gtk_sort_list_model_finish_sorting (self, &ignore1, &ignore2);
}
}
if (removed > 0 || self->n_items > 0)
g_list_model_items_changed (G_LIST_MODEL (self), 0, removed, self->n_items);
+2 -2
View File
@@ -64,7 +64,7 @@ enum {
NUM_PROPERTIES
};
G_DEFINE_FINAL_TYPE (GtkStringFilter, gtk_string_filter, GTK_TYPE_FILTER)
G_DEFINE_TYPE (GtkStringFilter, gtk_string_filter, GTK_TYPE_FILTER)
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
@@ -190,7 +190,7 @@ gtk_string_filter_set_property (GObject *object,
}
}
static void
static void
gtk_string_filter_get_property (GObject *object,
guint prop_id,
GValue *value,
+6 -6
View File
@@ -83,7 +83,7 @@ enum {
PROP_NUM_PROPERTIES
};
G_DEFINE_FINAL_TYPE (GtkStringObject, gtk_string_object, G_TYPE_OBJECT)
G_DEFINE_TYPE (GtkStringObject, gtk_string_object, G_TYPE_OBJECT);
static void
gtk_string_object_init (GtkStringObject *object)
@@ -395,11 +395,11 @@ gtk_string_list_buildable_init (GtkBuildableIface *iface)
iface->custom_finished = gtk_string_list_buildable_custom_finished;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkStringList, gtk_string_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_string_list_buildable_init)
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_string_list_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkStringList, gtk_string_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_string_list_buildable_init)
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_string_list_model_init))
static void
gtk_string_list_dispose (GObject *object)
+2 -2
View File
@@ -54,7 +54,7 @@ enum {
NUM_PROPERTIES
};
G_DEFINE_FINAL_TYPE (GtkStringSorter, gtk_string_sorter, GTK_TYPE_SORTER)
G_DEFINE_TYPE (GtkStringSorter, gtk_string_sorter, GTK_TYPE_SORTER)
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
@@ -238,7 +238,7 @@ gtk_string_sorter_set_property (GObject *object,
}
}
static void
static void
gtk_string_sorter_get_property (GObject *object,
guint prop_id,
GValue *value,
+1 -1
View File
@@ -605,7 +605,7 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
GTK_PARAM_READWRITE));
/**
* GtkTexTag:line-height:
* GtkTextTag:line-height:
*
* Factor to scale line height by.
*
-3
View File
@@ -388,8 +388,6 @@ gtk_tooltip_window_class_init (GtkTooltipWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, box);
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, image);
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, label);
gtk_widget_class_set_css_name (widget_class, "tooltip");
}
static void
@@ -420,7 +418,6 @@ update_label_width (GtkLabel *label)
len = g_utf8_strlen (text, -1);
gtk_label_set_width_chars (label, MIN (len, 50));
gtk_label_set_max_width_chars (label, MIN (len, 50));
gtk_label_set_wrap (label, TRUE);
}
+1 -1
View File
@@ -101,7 +101,7 @@ enum
N_PROPS
};
G_DEFINE_FINAL_TYPE (GtkTreeExpander, gtk_tree_expander, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (GtkTreeExpander, gtk_tree_expander, GTK_TYPE_WIDGET)
static GParamSpec *properties[N_PROPS] = { NULL, };
+11 -11
View File
@@ -165,7 +165,7 @@ tree_node_get_local_position (GtkRbTree *tree,
TreeNode *left, *parent;
TreeAugment *left_aug;
guint n;
left = gtk_rb_tree_node_get_left (node);
if (left)
{
@@ -209,7 +209,7 @@ tree_node_get_position (TreeNode *node)
TreeNode *left, *parent;
TreeAugment *left_aug;
guint n;
for (n = 0;
!node->is_root;
node = node->parent, n++)
@@ -520,7 +520,7 @@ gtk_tree_list_model_expand_node (GtkTreeListModel *self,
if (node->empty)
return 0;
if (node->model != NULL)
return 0;
@@ -528,18 +528,18 @@ gtk_tree_list_model_expand_node (GtkTreeListModel *self,
if (model == NULL)
return 0;
gtk_tree_list_model_init_node (self, node, model);
tree_node_mark_dirty (node);
return tree_node_get_n_children (node);
}
static guint
gtk_tree_list_model_collapse_node (GtkTreeListModel *self,
TreeNode *node)
{
{
guint n_items;
if (node->model == NULL)
@@ -604,8 +604,8 @@ gtk_tree_list_model_model_init (GListModelInterface *iface)
iface->get_item = gtk_tree_list_model_get_item;
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GtkTreeListModel, gtk_tree_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_tree_list_model_model_init))
G_DEFINE_TYPE_WITH_CODE (GtkTreeListModel, gtk_tree_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_tree_list_model_model_init))
static void
gtk_tree_list_model_set_property (GObject *object,
@@ -631,7 +631,7 @@ gtk_tree_list_model_set_property (GObject *object,
}
}
static void
static void
gtk_tree_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -956,7 +956,7 @@ enum {
static GParamSpec *row_properties[NUM_ROW_PROPERTIES] = { NULL, };
G_DEFINE_FINAL_TYPE (GtkTreeListRow, gtk_tree_list_row, G_TYPE_OBJECT)
G_DEFINE_TYPE (GtkTreeListRow, gtk_tree_list_row, G_TYPE_OBJECT)
static void
gtk_tree_list_row_destroy (GtkTreeListRow *self)
@@ -993,7 +993,7 @@ gtk_tree_list_row_set_property (GObject *object,
}
}
static void
static void
gtk_tree_list_row_get_property (GObject *object,
guint prop_id,
GValue *value,
+3 -3
View File
@@ -60,7 +60,7 @@ enum {
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
G_DEFINE_FINAL_TYPE (GtkTreeListRowSorter, gtk_tree_list_row_sorter, GTK_TYPE_SORTER)
G_DEFINE_TYPE (GtkTreeListRowSorter, gtk_tree_list_row_sorter, GTK_TYPE_SORTER)
#define MAX_KEY_DEPTH (8)
@@ -155,7 +155,7 @@ gtk_tree_list_row_sort_keys_compare (gconstpointer a,
resa = unpack (keysa, &keysa, &sizea);
resb = unpack (keysb, &keysb, &sizeb);
if (!resa)
return resb ? GTK_ORDERING_LARGER : (keysa[2] < keysb[2] ? GTK_ORDERING_SMALLER :
return resb ? GTK_ORDERING_LARGER : (keysa[2] < keysb[2] ? GTK_ORDERING_SMALLER :
(keysb[2] > keysa[2] ? GTK_ORDERING_LARGER : GTK_ORDERING_EQUAL));
else if (!resb)
return GTK_ORDERING_SMALLER;
@@ -329,7 +329,7 @@ gtk_tree_list_row_sort_keys_clear_key (GtkSortKeys *keys,
for (i = 0; i < max && key[i] != NULL; i++)
gtk_tree_list_row_sort_keys_unref_key (self, key[i]);
if (key[0] == NULL)
g_free (key[1]);
}

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