Compare commits

...

264 Commits

Author SHA1 Message Date
Matthias Clasen c96113e6d8 Fix ui files to work for translations
We need to keep using translatable="yes", since
that is what the installed its file is looking
for.

Fixes: #4957
2022-06-01 14:47:08 -04:00
Matthias Clasen 3e766a4fe2 4.6.5 2022-05-30 16:26:00 -04:00
Matthias Clasen 60a8367594 Merge branch 'gtk-4-6-backports' into 'gtk-4-6'
Drop the quit-mnemonic reftest

See merge request GNOME/gtk!4775
2022-05-30 11:22:32 +00:00
Aurimas Černius 22b9cf1644 Updated Lithuanian translation 2022-05-29 22:39:41 +03:00
Benjamin Otte 224a8390eb testsuite: Add tests for label overdraw
This brings back a subset of what quit-mnemonic.ui tested for, but
trying a lot harder to trigger the label overdrawing its allocation,
which will cause the text to be cut off when clipping is happening.

It should not be an issue at all with GTK4, but keeping that test around
is a good idea.
2022-05-29 08:13:09 -04:00
Matthias Clasen 5fee68f80d Drop the quit-mnemonic reftest
I can't quite figure out what this test was meant
to test, and how to make it do so in a way that
does not fall afoul of rendering issues in the GL
renderer and rounding differences in pango.

Can't win with reftests.
2022-05-29 08:13:09 -04:00
Matthias Clasen 41086f0756 Merge branch 'backports-for-4-6' into 'gtk-4-6'
Avoid g_log_set_writer_func in tests

See merge request GNOME/gtk!4773
2022-05-28 15:59:03 +00:00
Matthias Clasen 78c153ae14 Avoid g_log_set_writer_func in tests
It is not usable anymore since GLib 2.72.
2022-05-28 11:34:42 -04:00
Benjamin Otte 53c02a1e84 broadway: Fix gcc 12 complaining 2022-05-28 08:12:37 -04:00
Matthias Clasen 1523fecfe1 Merge branch 'wayland-cursor-scale2-for-4-6' into 'gtk-4-6'
wayland: scale cursors to the right size

See merge request GNOME/gtk!4767
2022-05-27 17:37:53 +00:00
Matthias Clasen 75821de2d7 wayland: scale cursors to the right size
When loading cursors at scale, we expect the
cursor images to have a size of scale * size.
If we don't find such images, load them at their
unscaled size and scale them up ourselves.

Without this, cursors will appear in unexpected
sizes depending on scales and themes.

Related: #4746
2022-05-27 13:05:18 -04:00
Matthias Clasen 91d2e1bc7f Merge branch 'stackpage-fix-for-4-6' into 'gtk-4-6'
realize stackpage accessible parent when needed

See merge request GNOME/gtk!4763
2022-05-27 12:01:18 +00:00
Matthias Clasen 986fd9959d Merge branch 'blink-assertion-for-4-6' into 'gtk-4-6'
Remove an assertion that we hit

See merge request GNOME/gtk!4764
2022-05-27 11:48:41 +00:00
Matthias Clasen 92b6c59f80 Merge branch 'wayland-cursor-scale-for-4-6' into 'gtk-4-6'
wayland: Sanity check cursor image size

See merge request GNOME/gtk!4762
2022-05-27 11:48:21 +00:00
Sebastian Keller 1860da7a1a a11y: Realize GtkStackPage parent context before trying to get a ref
If a context is not realized, calling gtk_at_spi_context_to_ref() will
return a null ref, because its path has not been initialized yet. This
was already done for all other cases in get_parent_context_ref(), but
was missing for the GtkStackPage case.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4944
2022-05-27 07:21:49 -04:00
Matthias Clasen 09a0151233 Remove an assertion that we hit
It appears that we mess up accounting for blinking
cursors sometimes, and can hit blink_cb when there
is a nonempty selection.

Instead of asserting, warn and stop blinking.

Related: #4767
2022-05-27 07:06:23 -04:00
Matthias Clasen c47759bd3d wayland: Make cursors have the right size
The Wayland protocol requires that width and height
of cursor surfaces is an integer multiple of the
surface scale. Make it so.

Fixes: #4746
2022-05-27 06:59:17 -04:00
Matthias Clasen c543206d79 wayland: Sanity check cursor image size
On Wayland it is a protocol violation to upload buffers with
dimensions that are not an integer multiple of the buffer scale.

Until recently, Mutter did not enforce this. When it started
doing so, some users started seeing crashes in GTK apps because the
cursor theme ended up with e.g. a 15x16 pixel image at scale of 2.

Add a small sanity check for this case.
2022-05-27 06:59:10 -04:00
Christian Kirbach 3523b02a35 Update German translation 2022-05-26 20:16:33 +00:00
Manuel Zabelt f936d7a883 Update docs/reference/gdk/gdk4-x11.toml.in 2022-05-26 08:25:13 -04:00
Manuel Zabelt 804caae32a GDK is LGPL-2.1-or-later not GPL-2.1-or-later, right? 2022-05-26 08:25:04 -04:00
Christian Hergert bc09956d79 build: fix sysprof default options
Sysprof just recently cleaned up it's meson_options.txt and this makes
the tracking of the master branch match the new values.
2022-05-26 08:24:52 -04:00
Benjamin Otte 7104861614 Merge branch 'cherry-pick-21349009' into 'gtk-4-6'
x11: Always update shadow size

See merge request GNOME/gtk!4760
2022-05-26 12:17:50 +00:00
Benjamin Otte 22288d9854 x11: Always update shadow size
Not updating shadow size unconditionally would lead to shadow size not
being set on map, which would lead mutter to think that we are a Window
without extents and then become confused when we suddenly set some.

Make sure that doesn't happen by always having shadows set on map, just
like GTK3.

Fixes #4136


(cherry picked from commit 213490099b)
2022-05-26 11:19:04 +00:00
Christian Kirbach 7703aa5cd3 Update German translation 2022-05-22 10:41:16 +00:00
Rafael Fontenelle 17896f9841 Update Brazilian Portuguese translation 2022-05-17 07:54:22 +00:00
Aleksandr Melman a67f82975e Update Russian translation 2022-05-15 14:18:48 +00:00
Piotr Drąg 9bc9116d24 Update Polish translation 2022-05-15 13:48:01 +02:00
Emin Tufan Çetin 1ff47f246b Update Turkish translation 2022-05-15 11:04:01 +00:00
Danial Behzadi 2b1c09dd42 Update Persian translation 2022-05-15 06:30:26 +00:00
Hugo Carvalho 4559bbbb9a Update Portuguese translation 2022-05-14 17:18:42 +00:00
Yuri Chornoivan 700c30d465 Update Ukrainian translation 2022-05-14 12:19:15 +00:00
Anders Jonsson 2d8a8e3575 Update Swedish translation 2022-05-14 10:03:33 +00:00
Matthias Clasen 9ea6bcb7b3 Merge branch 'cherry-pick-4f2b1b3c' into 'gtk-4-6'
egl: Fix invalid format string

See merge request GNOME/gtk!4727
2022-05-14 00:41:32 +00:00
Loïc Minier 394e0ab3be egl: Fix invalid format string
(cherry picked from commit 4f2b1b3cfc)
2022-05-13 21:05:58 +00:00
Luca Bacci fc533c6598 Merge branch 'backport-mr-4723-to-gtk-4-6' into 'gtk-4-6'
GtkFileChooserWidget: Propagate keys from external entry to fcwidget at the BUBBLE phase

See merge request GNOME/gtk!4726
2022-05-13 20:35:49 +00:00
Luca Bacci 40709245ad GtkFileChooserWidget: Propagate keys from external entry to fcwidget at the BUBBLE phase
Now that we use event controllers we can forward keybindings from the
external entry to the filechooserwidget at the bubble phase.

Fixes #4905

References:
 * commit 1fb075dbca
 * commit 686116ba61
2022-05-13 21:47:34 +02:00
Matthias Clasen 1e6bad6c4f 4.6.4 2022-05-13 13:58:42 -04:00
Christian Hergert 6d95ac9299 actionmuxer: check for observer before unregistering
This can happen if the group can be resolved even when doing the initial
registration of an action as observer will not yet be in the GSList of
watchers (and therefore has no weak references).

Fixes a warning like the following:

 g_object_weak_unref: couldn't find weak ref
2022-05-11 21:54:33 -04:00
Christian Hergert ce003f4eec actionmuxer: set handler ids initially to zero
These were getting created with possible non-zero values and then inserted
into a hashtable where the readers may not know the state of the group.

Ensure those values are set to zero until we assign them below.
2022-05-11 21:54:28 -04:00
Christian Hergert f737131d27 gdk/wayland: freeze popups when hidden
Previously, there was an issue with glitching after showing/hiding a
popover that was not also destroyed. This was due to the popover having
an update_freeze_count of zero after hiding the surface.

That resulted in it's toplevel continuously dropping frames such as during
high-frame-rate scrolling in textviews. This problem is much more visible
on high-frame-rate displays such as 120hz/144hz.

With this commit, we freeze the frame clock of the popup until it is
mapped again.
2022-05-11 16:32:17 -04:00
Matthias Clasen f54c153775 printdialog: Handle nonexisting files better
When a non-existing file is selected in the file chooser
for print-to-file, we weren't updating the button label
to show the new filename. Fix that.

Also, use newer file chooser api.
2022-05-11 16:32:17 -04:00
Matthias Clasen f2436eaf7b gsk: Check for half float support
The GL renderer currently relies on half float support
in vertex buffers, so check that we have it.

Related: #4894
2022-05-11 16:32:17 -04:00
Matthias Clasen 2f9387630f Merge branch 'wip/carlosg/ignore-null-preedit-4.6' into 'gtk-4-6'
imcontextwayland: Ignore preedit updates from NULL to NULL

See merge request GNOME/gtk!4711
2022-05-09 19:57:44 +00:00
Carlos Garnacho c1895ad823 imcontextwayland: Ignore preedit updates from NULL to NULL
If we get consecutive preedit string updates that announce a NULL
string, we still do end up issuing ::preedit-changed with those.
Ignore changes from NULL to NULL, it is the other combinations which
must issue this signal.

(cherry-picked from commit d6fe6f495a)
2022-05-09 17:41:08 +02:00
Pawan Chitrakar f60e5950dc Update Nepali translation 2022-05-09 10:44:41 +00:00
Pawan Chitrakar 5ae37c6d99 Update Nepali translation 2022-05-08 08:44:53 +00:00
Matthias Clasen d91c612eab listitemwidget: Avoid some unnecessary work
Only update widget and accessible state if the
selected property actually changed.
2022-05-07 10:31:37 -04:00
Ivan Molodetskikh 3894f04d0e list-item: Use notify_by_pspec instead of by name
This is a hot path when scrolling a ColumnView, and
g_param_spec_pool_lookup () was taking a measurable part in this hot
path. Instead, notify using pspecs to avoid the name lookup.

Related: https://gitlab.gnome.org/GNOME/gtk/-/issues/3334
2022-05-07 10:31:22 -04:00
Ivan Molodetskikh a39d55e5b0 listitemfactory: Track notify manually instead of freeze/thaw
freeze/thaw_notify () showed up on the perf trace for rapid ColumnView
scrolling. Track the three properties manually to make it a little
faster.

Related: https://gitlab.gnome.org/GNOME/gtk/-/issues/3334
2022-05-07 10:31:15 -04:00
Benjamin Otte fc5966a347 Don't invalidate parent if it didn't change
This looks like a leftover excess invalidation from when the surrounding
code was refactored to not just be called on parent changes but also
when repositioning inside the same parent in commit
507016cafc

Ivan Molodetskikh found this problem in
https://gitlab.gnome.org/GNOME/gtk/-/issues/3334#note_1445873 which
contains a longer analysis of this problem and the performance
reductions it causes.

Related: #3334
2022-05-07 10:31:00 -04:00
Matthias Clasen 55a4b4a174 gdk: Check OES_vertex_half_float GLES extension
This will be checked in the GL renderer.
2022-05-07 10:30:38 -04:00
Luca Bacci 045446c3da Merge branch 'backport-mr-4678-gtk-4-6' into 'gtk-4-6'
GtkFileChooserWidget: fixes for NULL vs empty GListModel

See merge request GNOME/gtk!4684
2022-05-03 08:52:02 +00:00
Luca Bacci f0120700dc GtkFileChooserWidget: return empty GListModel in get_files () instead of NULL 2022-05-03 12:38:22 +02:00
Luca Bacci 6b740c86f9 GtkFileChooserWidget: check for empty instead of NULL GListModel
While porting GtkFileChooserWidget from GList to GListModel we did not
change some checks for NULL to checks for empty list.

Fixes #4851, #4858
2022-05-03 12:38:03 +02:00
Emmanuele Bassi fb6de419f6 Merge branch 'wip/sophie-h/cherry-pick-filechooser' into 'gtk-4-6'
filechooser: cherry-pick small fix for select folder mode

See merge request GNOME/gtk!4676
2022-04-29 18:33:55 +00:00
Sophie Herold 1e561035e2 filechooser: Small fix for select folder mode
When changing folders, we were making the select
button insensitive when there is no folder selected.
However, the select button should be usable to
select the current folder.

Fixes #4020
2022-04-29 20:11:44 +02:00
Yosef Or Boczko 0a23c4678f Update Hebrew translation 2022-04-27 14:19:20 +00:00
Yaron Shahrabani edc21ef202 Update Hebrew translation 2022-04-27 12:00:13 +00:00
Benjamin Otte 2441409b34 Merge branch 'cherry-pick-515b1f52' into 'gtk-4-6'
boxlayout: Do not infloop

See merge request GNOME/gtk!4670
2022-04-26 23:51:10 +00:00
Benjamin Otte ae01669737 boxlayout: Do not infloop
if the loop for determining max width grows too big, print an error and
abort assuming that a satisfactory value was reached.

This will cause wrong layout and might cause widgets to overlap, but it
will not infloop.

It actually works around and doesn't really fix the primary cause of the
following bugs, but good enough to close them:

Fixes: #4252
Fixes: #4517


(cherry picked from commit 515b1f5292)
2022-04-26 21:11:32 +00:00
Matthias Clasen 21103ad811 4.6.3 2022-04-21 20:58:13 -04:00
Matthias Clasen 6e5573f5bb theme: Fix vertical spin button selection
The selection should be black-on-blue as it is
everywhere else now. This was just a leftover.

Fixes: #4788
2022-04-21 19:28:14 -04:00
Emmanuele Bassi e17d51df66 Quench the anger of GCC
Direct access of the fields of the union trips compiler warnings with
GCC 12, such as:

  ../gtk/gtkimagedefinition.c:135:13: error: array subscript
  ‘GtkImageDefinition {aka union _GtkImageDefinition}[0]’ is partly
  outside array bounds of ‘GtkImageDefinitionEmpty[1]’ {aka
  ‘struct _GtkImageDefinitionEmpty[1]’} [-Werror=array-bounds]
2022-04-21 19:27:48 -04:00
Matthias Clasen 01f63c87b2 Fix file filter buildable support
File filters creates from ui files had some
extraneous gunk in them. Fix that. Test included.

Fixes: #4787
2022-04-21 19:27:37 -04:00
Marcel Tiede e449bd8459 docs: Fix typo in description of GtkExpression 2022-04-21 19:27:26 -04:00
Alexander Mikhaylenko edb69f0bb3 scrolledwindow: Pick up gtk-overlay-scrolling changes on the fly 2022-04-21 19:26:25 -04:00
Alexander Mikhaylenko cf48d15c2c scrolledwindow: Fix :kinetic-scrolling setter 2022-04-21 19:26:17 -04:00
Alexander Mikhaylenko 7cc49ba288 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-21 19:26:03 -04:00
Alexander Mikhaylenko 6809a78321 tooltipwindow: Remove a duplicate gtk_widget_class_set_css_name() call 2022-04-21 19:25:52 -04:00
Emmanuele Bassi c1002b20ee 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-21 19:25:42 -04:00
Emmanuele Bassi fdf3ae31c6 docs: Fix the GtkPaned style
Use proper links to properties and methods, and drop gtk-doc'isms.
2022-04-21 19:25:36 -04:00
Julian Sparber f915c6bb5c 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-21 19:25:09 -04:00
Julian Sparber 659c1c41de 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-21 19:24:59 -04:00
Ivan Molodetskikh 8f2be7e840 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-21 19:24:52 -04:00
Matthias Clasen 14772602a0 gsk/gl: Typo fix 2022-04-21 19:24:41 -04:00
Matthias Clasen 93921f32bd gtk-demo: Small fixup to the cursors demo 2022-04-21 19:24:24 -04:00
Carlos Garnacho 812c8926ec 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-21 19:24:00 -04:00
Carlos Garnacho b14bc4749e 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-21 19:23:48 -04:00
Sebastian Keller d56276f6d6 testsuite: Add unaligned-offscreen test
Tests whether text rendered to an offscreen node unaligned with the
pixel grid introduces blurriness.
2022-04-21 19:23:13 -04:00
Sebastian Keller f1d44635bd 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-21 19:23:06 -04:00
Maximiliano Sandoval R de8cb17ee8 application: Add link and inline code blocks 2022-04-21 19:22:38 -04:00
Maximiliano Sandoval R e69eb24b32 filter: Add link to FilterListmodel 2022-04-21 19:22:33 -04:00
Maximiliano Sandoval R 4a388b5540 texttag: Correct typo
Does not generate a gir docstring without it.
2022-04-21 19:22:27 -04:00
Matthias Clasen 25bedcd85d inspector: Avoid another crash
We need to handle all event types here.
This was tripping over GDK_TOUCHPAD_HOLD events.
2022-04-21 19:20:10 -04:00
Matthias Clasen feb3d3b274 inspector: Avoid a crash
Attribute lists can be NULL, it turns out.
2022-04-21 19:19:45 -04:00
Matthias Clasen e191519d30 css: Plug a memory leak
We were leaking the terms of calc values. Oops.
2022-04-21 19:19:33 -04:00
illiliti aa1921cbef 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-21 19:18:55 -04:00
Matthias Clasen e2abb0211c imcontextsimple: Plug a memory leak 2022-04-21 19:18:34 -04:00
Maximiliano Sandoval R b024c9a743 docs: Fix links in selection models 2022-04-21 19:18:25 -04:00
Xavier Claessens 91c60dcac0 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-04-21 19:18:00 -04:00
Dr. David Alan Gilbert 66117d1017 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-04-21 19:17:54 -04:00
Chun-wei Fan 177302cf4d 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-04-21 19:16:13 -04:00
Alexander Mikhaylenko d1fc90e8a2 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-04-21 19:15:58 -04:00
Christoph Reiter da152ac37e 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-04-21 19:15:52 -04:00
Matthias Clasen 29d4821e3d 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-04-21 19:15:20 -04:00
Christian Hergert cbd03cda56 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-04-21 19:15:05 -04:00
Sebastian Keller 018bbd6774 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-04-21 19:14:32 -04:00
Christian Hergert e50e2136d2 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-04-21 19:14:14 -04:00
Yosef Or Boczko a5eeb99f37 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-04-21 19:14:03 -04:00
aneejit1 52cb3b2ec4 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-04-21 19:13:54 -04:00
Matthias Clasen 9ca55cb5bf Merge branch 'cherry-pick-b67da389' into 'gtk-4-6'
Backport: gtkimmulticontext: Handle switches between displays

See merge request GNOME/gtk!4660
2022-04-20 15:35:21 +00:00
Carlos Garnacho bc4b2c142f 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


(cherry picked from commit b67da38916)
2022-04-20 14:54:04 +00:00
Matthias Clasen b65d7c86d7 Merge branch 'filechooser-fixes-4-6' into 'gtk-4-6'
filechooser: cherry-pick fixes from main for 4.6

See merge request GNOME/gtk!4654
2022-04-20 01:34:51 +00:00
Matthias Clasen cc37c9c86c Merge branch 'ebassi/issue-4825-backport' into 'gtk-4-6'
a11y: Defer object registration after root registration

See merge request GNOME/gtk!4658
2022-04-20 01:30:51 +00:00
Emmanuele Bassi e41a4ced8b a11y: Defer object registration after root registration
The root accessible object is registered asynchronously, as it needs to
call a method on the AT-SPI registry daemon. This means we need to defer
registering the GtkAtSpiContext on the accessibility bus and in the
cache until after the registration is complete.

Fixes: #4825
2022-04-19 22:05:46 +01:00
Matthias Clasen eb2699aa9f 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-19 13:51:44 +02:00
Matthias Clasen fcab393c3b 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-19 13:49:31 +02:00
Luca Bacci 8a6de521e7 Merge branch 'gdk-win32-fix-mouse-move-crossing-events-gtk-4-6' into 'gtk-4-6'
GdkWin32: Mouse events fixes

See merge request GNOME/gtk!4627
2022-04-08 13:58:29 +00:00
Luca Bacci 88db5509a3 GdkWin32: Generate crossing event after button release
Fixes #4813
2022-04-08 15:26:48 +02:00
Luca Bacci 7538ff9798 GdkWin32: Correct generation of crossing events when holding an implicit grab
Fixes #4722
2022-04-08 15:26:37 +02:00
Luca Bacci c0a60ece97 GdkWin32: Report serial for events 2022-04-08 15:26:26 +02:00
Luca Bacci c799b05f2a Merge branch 'backport-4406-4.6' into 'gtk-4-6'
gdkclipboard-win32.c: Fix call to gdk_clipboard_claim_remote() (backport MR !4604 to gtk-4-6)

See merge request GNOME/gtk!4608
2022-04-08 08:30:48 +00:00
Christian Hergert d468dd2f3b 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

(cherry picked from commit d75147db0a)

d3cf7088 macos: Skip running `showAndMakeKey` when a window is minimized by user action
2022-04-04 18:53:35 +00:00
Christian Hergert 029fc0fdef 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

(cherry picked from commit 15b7a4572b)

69a0a5cf macos: Prohibit changing the full-screen state of a window during a full-screen transition
229e4b58 macos: Corrected code style
2022-04-03 22:15:16 +00:00
Andika Triwidada c43737324a Update Indonesian translation 2022-04-01 04:10:57 +00:00
Andika Triwidada 270e643c7b Update Indonesian translation 2022-04-01 04:04:49 +00:00
Chun-wei Fan edd8d55b42 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-04-01 10:28:37 +08:00
Rūdolfs Mazurs 3b50f2e8b9 Update Latvian translation 2022-03-27 20:19:10 +00:00
Rūdolfs Mazurs d4dd7969d6 Update Latvian translation 2022-03-27 19:53:51 +00:00
Emmanuele Bassi a0bebefef8 Merge branch 'cherry-pick-351ffef7' into 'gtk-4-6'
overlaylayout: Set position style class on child

See merge request GNOME/gtk!4598
2022-03-27 18:24:38 +00:00
António Fernandes 42a4c62025 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

(cherry picked from commit 351ffef704)
2022-03-27 17:50:16 +00:00
Bruce Cowan dd198cfc06 Update British English translation 2022-03-24 13:19:20 +00:00
Marek Černocký 3ef96c445f Updated Czech translation 2022-03-21 12:16:07 +01:00
Philipp Kiemle d9c39f6795 Update German translation 2022-03-19 12:32:20 +00:00
Matthias Clasen aec7ca8200 4.6.2 2022-03-18 20:38:15 -04:00
Matthias Clasen f567bf62e1 Merge branch 'alatiera/stable-wraps-4-6' into 'gtk-4-6'
meson: use proper handling of wayland-protocols dependency

See merge request GNOME/gtk!4580
2022-03-19 00:37:58 +00:00
James Westman 1f00cdc7a6 filefilter: Fix <suffixes> in buildable
A bug in GtkFileFilter's GtkBuildable implementation caused the
<suffixes> tag not to be recognized.
2022-03-17 16:18:28 -04:00
Jordan Petridis dc875b6af9 meson: switch some .wrap files to stable branches
To avoid random failures if one of the projects starts
depending on new things or has incompatible changes.
2022-03-17 12:54:58 +02:00
Eli Schwartz e2873bc614 meson: use proper handling of wayland-protocols dependency
Ensure that resolution of the subproject occurs via the dependency
interface, not the "poke at subprojects manually" interface, and make
that actually work via --wrap-mode=forcefallback.

There's no need to mark it as not-required and then manually invoke
subproject(), since fallback should work correctly and it is always
needed.

However, if fallback was performed (or forced) it would error out since
get_variable() was instructed to only use pkg-config while the relevant
variable was exported by the subproject as an internal fallback
dependency.
2022-03-17 12:54:58 +02:00
Milo Casagrande 3e4bfa2bae Update Italian translation 2022-03-17 08:35:42 +00:00
Milo Casagrande 9bbf09fb0a Update Italian translation 2022-03-17 08:34:04 +00:00
Мирослав Николић c874f65d95 Update Serbian translation 2022-03-17 06:04:15 +00:00
Matthias Clasen 8a12628af9 Merge branch 'wip/carlosg/backports-4-6' into 'gtk-4-6'
Backport fixes to 4.6

See merge request GNOME/gtk!4577
2022-03-17 01:50:18 +00:00
Matthias Clasen 17e0618ff6 Merge branch 'wip/chergert/for-4-6' into 'gtk-4-6'
backport macOS fixes to gtk-4-6

See merge request GNOME/gtk!4578
2022-03-16 20:03:38 +00:00
Christian Hergert 73d5f7061b macos: exclude popups from window list
This probably only matters if you do window list integration for the global
menu on macOS.
2022-03-16 12:25:10 -07:00
Christian Hergert ccbaa020ff macos: pass events to foreign windows 2022-03-16 12:25:10 -07:00
Christian Hergert a9c89fa23e macos: dont steal key window from NSPanel
Or we risk making it really difficult to use native file choosers.
2022-03-16 12:25:10 -07:00
Christian Hergert 36730537cc macos: fix window level for popups
This comment isn't really accurate anymore it seems, so we can start
setting the proper stacking order for popups now.
2022-03-16 12:25:10 -07:00
Christian Hergert 9456f6eea1 macos: fix attachment of popups to parents
We had code to do it and it never actually got used correctly. This ensures
that the popup services are attached to the parents so that they get proper
stacking orders when displayed. Additionally, it fixes popups from being
shown as their own windows in Exposé.
2022-03-16 12:25:10 -07:00
Christian Hergert 2c630a74cd macos: fix window activation during shadow click-through
If we are clicking through the shadow of a window, we need to take special
care to not raise the old window on mouseUp. This is normally done by the
display server for us, so we need to use the proper API that is public to
handle this (rather than CGSSetWindowTags()). Doing so requires us to
dispatch the event to the NSView and then cancel the activcation from
the mouseDown: event there.
2022-03-16 12:25:10 -07:00
Christian Hergert 9462b3fea2 macos: select new key window after processing events
If we closed a key window in response to events, we need to denote another
window as the new key window. This is easiest to do from an idle so that
we don't clobber notification pairs of "did resign"/"did become" key
window.

We have a sorted set of surfaces by display server stacking, so we can
take the first one we come across that is already mapped and re-show it
to become key/main.
2022-03-16 12:25:10 -07:00
Christian Hergert d62313e75c macos: request layout with server-side decoration
If we have server-side decorations we might need to request a layout in
response to the resize notification. We don't need to do this in other
cases because we already handle that in the process of doing the resize
(and that code is that way because of delayed delivery of NSNotification).
2022-03-16 12:25:10 -07:00
Christian Hergert 023bf9aea7 macos: fix resize when using server-side decorations
If we are using NSWindow titled windows, we don't end up waking up the
frame clock when the window is resized on the display server. This ensures
that we do that after getting a notification of resize.
2022-03-16 12:25:10 -07:00
Christian Hergert 4bc593c761 macos: set main window in addition to key
If we are showing the window, we might also want to make it the main
window for the application when shown.
2022-03-16 12:25:10 -07:00
Christian Hergert f47e6dda78 macos: make transient-for key window when hiding surface
This only handled the popover case before and not the transient-for case.
2022-03-16 12:25:10 -07:00
Christian Hergert 5c2d9d6f19 macos: actually drop unnecessary momentum events
These would get passed along to the NSApplication which we don't really
need to have happen. Denote it as such.
2022-03-16 12:25:10 -07:00
Christian Hergert 5efa8071d6 macos: queue all pending events
Rather than process these a single event at a time, queue all of the
outstanding events from the NSEvent queue.
2022-03-16 12:25:10 -07:00
Christian Hergert 659832ccab macos: drop enter/exit when in manual drag/resize
If we are in a manual resize/drag then we don't want to generate crossing
events as they can just confuse things.
2022-03-16 12:25:10 -07:00
Christian Hergert 913f6d4a4f macos: allow dropping NSEvent without propagation
There are cases we might want to consume a NSEvent without creating a
GdkEvent or passing it along to the NSApplication for processing. This
creates a new value we can use and check against to propagate that without
having to do out parameters at the slightly odd invalid pointer value for
a GdkEvent (similar to how MMAP_FAILED is done).
2022-03-16 12:25:10 -07:00
Christian Hergert cb386ec2a2 macos: do not focus new window when resigning main
This can get in the way of how we track changes while events are actively
processing. Instead, we may want to delay this until the next main loop
idle and then check to see if we have a main window as the NSNotification
may have come in right after this.
2022-03-16 12:25:10 -07:00
Christian Hergert 2f873052f9 macos: fix cursor blink time
The value from settings is for the duration of the blink period, not the
timeout. This fixes the blink lasting longer than 10 seconds.
2022-03-16 12:25:10 -07:00
Christian Hergert 60aceb984f macos: require input region to become key
Some things cannot become key windows (like tooltips). We can use the
input_region existence to determine if we should allow it as a key window.
2022-03-16 12:25:10 -07:00
Christian Hergert 9dbd79f2d8 macos: clear window stack before requesting motion
We want to ensure that we recalculate the sort order of windows before
processing the motion. Generally this would be done in response from the
display server in GdkMacosWindow, but I've seen it possible to race there.
2022-03-16 12:25:10 -07:00
Christian Hergert 0aabf47f09 macos: invalidate surface contents when mapping 2022-03-16 12:25:10 -07:00
Christian Hergert 2961cc44c5 macos: move children when monitor changes
We can rely on other code to move monitors, but specifically with children
we want to try harder to move them as a group and keep positioning in tact.
2022-03-16 12:25:09 -07:00
Christian Hergert 46da364289 macos: make move_resize possibly idempotent
We need to handle the case where we might be racing against an incoming
configure event due to how notifications are queued from the display
server. Rather than calling configure (and possibly causing other things
to move around) this just queries the display server directly for the
coordinates that we care about.

Additionally, we can display:NO as we are in control of all the display
process now using CALayer.
2022-03-16 12:25:09 -07:00
Christian Hergert cb99370ce4 macos: handle transient-for from configure
We failed to handle the toplevel with transient-for case here which could
cause our X/Y calculations to be off in other areas such as best monitor
detection.
2022-03-16 12:25:09 -07:00
Christian Hergert c2d1a21f9c macos: use parent frame clock again
We do actually need the parent frame clock here because it is the way we
ensure that we get layout called for our popup surfaces at the same time
as the parent surface.
2022-03-16 12:25:09 -07:00
Christian Hergert edc6790fbb macos: reduce chances for layout cycles
We need to be more careful about when we request a layout because it can
cause us to get into a layout cycle at maximum frame rate.
2022-03-16 12:25:09 -07:00
Christian Hergert b0d7889b20 macos: improve initial placement of toplevels with parent
This doesn't appear to happen much, but if it does it is nice to setup
the window placement initially. Generally, transient-for is set after
the creation of the toplevel rather than here.
2022-03-16 12:25:09 -07:00
Christian Hergert 867f2de194 macos: leave a note about monitor configuration
It can be helpful to see what the range of monitor values is when emulating
the GDK coordinate system.
2022-03-16 12:25:09 -07:00
Christian Hergert 50e2a8239b macos: use GdkMacosBuffer for storing damage region
The GdkMacosBuffer object already has storage for tracking the damage
region as it is used in GdkMacosCairoContext to manually copy regions from
the front buffer to the back buffer. This makes the GdkMacosGLContext also
use that field so that we can easily drop old damage regions when the
buffer is lost. This happens during resizes, monitor changes, etc.
2022-03-16 12:25:09 -07:00
Christian Hergert 42f9ea07e2 macos: add clamp helper to keep rectangle in workarea
This helper is useful to ensure we are consistent with how we keep a
window clamped to the workarea of a monitor when placing windows on
screen. (This does not affect snap-to-edges).
2022-03-16 12:25:09 -07:00
Christian Hergert 9b28153571 macos: style cleanup 2022-03-16 12:24:12 -07:00
Christian Hergert 2e1e7e7265 macos: add re-entrancy check when monitors change 2022-03-16 12:24:12 -07:00
Christian Hergert 7369ce58da macos: check for best_monitor before using
Make sure we have a monitor to enqueue/dequeue from before using it. That
also allows us to use this from destroy and what-not.
2022-03-16 12:24:11 -07:00
Christian Hergert c7a6d1e8bf macos: avoid size/origin changes when possible
If _gdk_macos_surface_move_resize() was called with various -1 parameters
we really want to avoid changing anything even if we think we know what
the value might be. Otherwise, we risk messing up in-flight operations that
we have not yet been notified of yet.

This improves the chances we place windows in an appropriate location as
they don't et screwed up before window-manager placement.
2022-03-16 12:24:11 -07:00
Christian Hergert 17b40ca148 macos: start application in foreground
We need to bring the application to the foreground in multiple ways, and
this call to [NSApp activateIgnoringOtherApps:YES] ensures that we become
foreground before the first window is opened. Otherwise we end up starting
applications in the background.

Fixes #4736
2022-03-16 12:24:11 -07:00
Christian Hergert 29d424ef91 macos: add GDK_NOTE when surface changes monitor 2022-03-16 12:24:11 -07:00
Christian Hergert 27e9b87fbd macos: add GDK_NOTE for surface sizing and placement
This can be useful to debug sizing issues with the surface as well as the
"window manager" placement code.
2022-03-16 12:24:11 -07:00
Christian Hergert f2ac5576c2 macos: leave note about monitor discovery 2022-03-16 12:24:11 -07:00
Christian Hergert 590a1c2f3a macos: external access to display name helpers
These can be handy to print debug information when we don't have a
GdkMacosMonitor to work with.
2022-03-16 12:24:11 -07:00
Christian Hergert 75b186eb62 macos: fix redisplay of GdkPopup
This broke recently during the configure cleanups and also needed to have
the tail directions fixed again.
2022-03-16 12:24:11 -07:00
Christian Hergert 998c787638 macos: fix cairo renderer with double buffering
If we are double buffering surfaces with IOSurface then we need to copy
the area that was damaged in the previous frame to the back buffer. This
can be done with IOSurface but we need to hold the read-only lock so that
we don't cause the underlying IOSurface contents to be invalidated.

Additionally, since this is only used in the context of rendering to a
GdkMacosSurface, we know the life-time of the cairo_surface_t and can
simply lock/unlock the IOSurface buffer from begin_frame/end_frame to have
the buffer flushing semantics we want.

To ensure that we don't over damage, we store the damage in begin_frame
(and copy it) and then subtract it from the next frames damage to determine
the smallest amount we need to copy (taking scale factor into account).

We don't care to modify the damage region to swapBuffers because they
already have the right contents and could potentially fall into another
tile anyway and we'd like to avoid damaging that.

Fixes #4735
2022-03-16 12:24:11 -07:00
Christian Hergert b2ab0b1fcb macos: add readonly IOSurfaceLock helper
This can be used to lock a surface for reading to avoid causing the
surface contents to be invalidated. This is needed when reading back from
a front-buffer to the back-buffer as is needed when using Cairo surfaces
to implement something similar to BufferAge.
2022-03-16 12:24:11 -07:00
Christian Hergert b19526489e macos: short-circuit on NSEventPhaseMayBegin
We only need to send a single event in this case, so just short-circuit
instead of trying to return an additional event.
2022-03-16 12:24:11 -07:00
Christian Hergert 856728ea10 macos: support mix-rate monitors
Previously, a single CVDisplayLink was used to drive updates for all
surfaces across all monitors. It used a 'best guess' rate which would
allow for updates across monitors of mixed rates. This is undesirable for
situations where you might have a 144hz monitor as it does not allow for
reaching up to that frame rate.

Instead, we want to use a per-monitor CVDisplayLink which will fire at the
rate of the monitor down to the level of updates we require. This commit
does just that.

When a surface crosses onto a new monitor, that monitor is used to drive
the GdkFrameClock.

Fixes #4732
2022-03-16 12:24:11 -07:00
Christian Hergert df2fb3b520 macos: use video mode for refresh rate and interval
Using the mode allows better detection of refresh rate and refresh
interval for the CVDisplayLink bridge to GdkFrameClock. Using it can help
ensure that our 144hz displays can actually reach that rather than falling
back to just 60hz.

This will also need future commits to rework the displaylink source to be
per-monitor.
2022-03-16 12:24:11 -07:00
Christian Hergert 48c650c102 macos: send stop event when fingers touch
When the fingers are placed on the touchpad, we get a scroll event with
the phase NSEventPhaseMayBegin. We can use this to synthesize an is_stop
event. This results in the scrolledwindow stopping scroll with stop
gestures.

This can cause another warning as well, however, which should be addressed
from #4730.

Fixes #4733
2022-03-16 12:24:11 -07:00
Christian Hergert ccf18c239d macos: remove emulated scroll events
We don't appear to actually need the emulated scroll events and they get
in the way of proper scrolling with the touchpad.

Fixes #4734
2022-03-16 12:24:11 -07:00
Christian Hergert 48b408e2c3 macos: do not inherit parents frame clock
Windows can end up on different monitors despite having a parent or
transient-for ancestor. We want them to be driven by the CVDisplayLink
for the best-monitor, and so this needs to be unshared.
2022-03-16 12:24:11 -07:00
Christian Hergert 433de2849d macos: calculate best monitor when changing screens
When we change screens, we can keep track of the best monitor so that we
can use it to register CVDisplayLink callbacks.
2022-03-16 12:24:11 -07:00
Christian Hergert 94deb551aa macos: remove duplicated opaque_region field
This can be relied upon from GdkSurface and we do not need to keep a copy
of it. Just remove it and use the GdkSurface.opaque_region field.
2022-03-16 12:24:11 -07:00
Christian Hergert 9767b3a97e macos: use display id when creating CVDisplayLink
Currently we're using a display link that is for all active displays which
is just the display server trying to find some timings that try to overlap
as many as possible.

That was fine for a prototype, but we really need to do better for
situations with mixed frame rate (such as 60hz and 120hz promotion
displays). Additionally, the 144hz external monitor I have will never
reach 144hz using the current design.

This is just the first step in changing this, but the goal is to have
one of these attached to each GdkMacosMonitor which we can then use to
thaw surfaces specific to that monitor.
2022-03-16 12:24:11 -07:00
Christian Hergert 676e9ab127 macos: move feedback mechanisms into separate file
We will eventually be needing additional feedback from the display server
which would be nice to keep away from the rest of GdkMacosDisplay for
cleanliness sake. Particularly for feedback from mission control and other
environment factors that requires private API for proper integration.
2022-03-16 12:23:34 -07:00
Christian Hergert 5b15bc86a3 macos: fix origin during live resize of titled window
When using server-side-decorations, we need to avoid potential cycles with
compute-size as it may not have the new sizing information yet. We can
just short circuit during "live resize" to get that effect.

Fixes poor window resizing from top-left on titled windows.
2022-03-16 12:23:04 -07:00
Christian Hergert bad392eb2a macos: restore unfullscreen frame with style mask
This doesn't give us appropriate results if we use the window delegate.
Instead, we need to adjust the frame at the same time we change the
style mask so that we end up in the same location.
2022-03-16 12:23:04 -07:00
Christian Hergert 278f976add macos: fix kinetic scrolling with overshoot
Previously we had issues on macos where the overshoot would keep showing.
To fix this we need to actually use discrete events instead of the
generated deltas from macOS in the scroll wheel case. Additionally, we need
to drop the kinetic momentum events from macOS and rely on the gtk kinetic
events which are already happening anyway. We also need to submit the
is_stop event for the GDK_SCROLL_SMOOTH case when we detect it.

To keep the discrete scroll events correct, we need to alter the hack in
gtkscrolledwindow.c to use the same path as other platforms except for
when a smooth scroll event is in place. In the future, I would imagine that
this falls into the boundary of high-precision scrolling and would share
the same code paths as other platforms.

With all of these in place, kinetic scrolling with overshoot appears the
same on macOS as other platforms.
2022-03-16 12:23:04 -07:00
Christian Hergert f58ece72cf macos: remove unused code 2022-03-16 12:23:04 -07:00
Christian Hergert af3f34ca94 macos: create new windows with slight origin offset
When creating new windows, it is better if we create them with a slight
offset to where they were created before so that they are visible to the
user separately from what they might be overshadowing.
2022-03-16 12:22:52 -07:00
Carlos Garnacho 07a5cf4996 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 19:50:21 +01:00
Carlos Garnacho d808298b68 gtkimcontextwayland: Add native surface offset to input coordinates
We were missing the surface offset (e.g. shadows) at the time of expressing
the text caret location in surface coordinates. Add this offset so the
coordinates are as expected by the compositor.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4668
2022-03-16 19:50:21 +01:00
Guido Günther 108b7025dc wayland: xdg-activation: Don't assume there's a focus surface
Tools like gtk4-launch can't set surface on the activation token so
don't require it. If the compositor requires it we can't do anything
about it anyway. This avoids a critical:

   (gtk4-launch:23497): Gdk-CRITICAL **: 17:07:24.704: gdk_wayland_surface_get_wl_surface: assertion 'GDK_IS_WAYLAND_SURFACE (surface)' failed

Fixes: be4216e051 ("gdk/wayland: Support the xdg-activation wayland protocol")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2022-03-16 19:50:21 +01:00
Carlos Garnacho 9822d2b6b2 wayland: Use xdg-activation for non-startup initiated focus requests
Currently, we have all the plumbing in place so that GTK consumes the
startup notification ID when focusing a window through the xdg-activation
protocol.

This however misses the case that a window might be requested to be
focused with no startup ID (i.e. via interaction with the application,
not through GApplication or other application launching logic).

In this case, we let the application create a token that will be
consumed by itself. The serial used is that from the last
interaction, so the compositor will still be able to do focus prevention
logic if it applies.

Since we already do have a last serial at hand, prefer xdg-activation
all the way over the now stale gtk-shell focusing support. The timestamp
argument becomes unused, but that is a weak argument to prefer the
private protocol over the standard one. The gtk-shell protocol support
is so far left for interaction with older Mutter.
2022-03-16 19:50:21 +01:00
Guido Günther a36594e754 print-editor: Use gtk_window_present()
This lets xdg-activation work as otherwise gdk_wayland_surface_focus is
never invoked.
2022-03-16 19:50:21 +01:00
Guido Günther c331e22f3a demo: Use gtk_window_present()
This lets xdg-activation work as otherwise gdk_wayland_surface_focus is
never invoked.
2022-03-16 19:50:21 +01:00
Guido Günther d077f113b2 widget-factory: Use gtk_window_present()
This lets xdg-activation work as otherwise gdk_wayland_surface_focus is
never invoked.
2022-03-16 19:50:21 +01:00
Guido Günther 1ab89b3908 wayland: Keep startup_notification_id around long enough
When using xdg_activation we need to keep the id around until we send
the first activate to signal succesful startup.
2022-03-16 19:50:21 +01:00
Guido Günther c5da579cda window: Make sure we call gdk_wayland_surface_focus
When using xdg_activation this is responsible for submitting
the activation token / startup id to the compositor.
2022-03-16 19:50:21 +01:00
Matthias Clasen 38bbcb7411 gtk-builder-tool: Operate without display
The simplify and validate commands can function
without a display connection, only preview absolutely
needs one. Allow this, by using gtk_init_check().
2022-03-15 22:08:01 -04:00
Matthias Clasen 3223f3e3b8 build: Avoid objcopy on arm
The trickery we do with objcopy and ld to speed up
resource inclusion does not seem to work right on
32bit Arm, so just skip it there.

Fixes: #4757, #4748, #4752
2022-03-15 22:07:52 -04:00
Matthias Clasen ba885e2ace Apply 1 suggestion(s) to 1 file(s) 2022-03-15 22:07:35 -04:00
Fina Wilke 9cc051ffa5 gtkplacessidebar: Prevent calling g_object_unref on null
g_object_unref would be called on a null end_icon when provider_account_status
is CLOUD_PROVIDERS_ACCOUNT_STATUS_IDLE
2022-03-15 22:07:20 -04:00
Ting-Wei Lan e8dd40ccca build: Don't use ld and objcopy when cross-compiling
These commands don't work when compiling Windows binaries on Linux.
2022-03-15 22:06:30 -04:00
Caolán McNamara 53263d3d27 fix docs for gtk_accessible_update_relation example 2022-03-15 22:06:04 -04:00
Sebastien Bacher 71c935d1f4 Use the correct name for installed gdk tests 2022-03-15 22:05:31 -04:00
Matthias Clasen 5e07e216d3 Fix a documentation typo
It is XDG_DATA_HOME.

Fixes: #4747
2022-03-15 22:05:22 -04:00
Matthias Clasen 88894b705b Fix up preconditions of gsk_gl_shader_node_new
These were not quite right, and implied that args
may be NULL, when it really can't.

Fixes: #4739
2022-03-15 22:05:14 -04:00
Emmanuel Gil Peyrot b8d01bf041 gdk: Add a rgb8 → rgba8 conversion macro
This one can be used for both premultiplied and non-premultiplied alpha
formats, since alpha is always 255.  It is useful for opaque PNG upload
on both cairo and GL renderers.
2022-03-15 22:05:00 -04:00
Emmanuel Gil Peyrot c636ea036a gdk: Make the optimized premultiply function a macro
That way, all permutations are possible.  Previously it was only useful
in the cairo renderer, which required rgba8 → premultiplied bgra8, while
the GL renderer required rgba8 → premultiplied rgba8.  Now both are
available.
2022-03-15 22:04:52 -04:00
Emmanuel Gil Peyrot 08099ed17d gdk: Remove pixel format conversion ARM intrinsics
This was only useful when building for AArch32 without -mfpu=neon, on
AArch64 or with -mfpu=neon gcc is smart enough to do the auto-
vectorisation, leading to code almost as good as what I wrote in
1fdf5b7cf8.
2022-03-15 22:04:44 -04:00
Christian Hergert f0e8ee3c29 gdk: use EGL_KHR_swap_buffers_with_damage
It appears that NVIDIA does not implement EGL_EXT_swap_buffers_with_damage
on their EGL implementation, but does implement the KHR variant of it.
This checks for a suitable implementation and stores a pointer to the
compatible implementation within the GdkGLContextPrivate struct.
2022-03-15 22:04:30 -04:00
Bilal Elmoussaoui 33a1cf203e headerbar: Fix docs 2022-03-15 22:04:23 -04:00
Matthias Clasen 5adce748cb text: Stop blinking when we lose focus
We were looking at GtkWidget:has-focus from
event controller signal handlers here, but
the widget property is only changed after
the event controllers.
2022-03-15 22:03:50 -04:00
Matthias Clasen 21d39b6054 focus controller: Update for active window
When the window gains or looses active status,
update the focus controllers status.
2022-03-15 22:03:42 -04:00
Matthias Clasen a2f30ac1ab window: Update has-focus property
Update the :has-focus property of the focus
widget when the active status of the window
changes.

We change the property after generating the
GDK_CROSSING_ACTIVE crossing events.
2022-03-15 22:03:34 -04:00
Carlos Garnacho 3764b27bab gtkscrolledwindow: Do not try to doubly trigger deceleration
This may come from different sources at around the same time, e.g.
a hold gesture while on overshoot. Avoid doing that if an
animation is already set.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4730
2022-03-15 22:02:45 -04:00
Rico Tzschichholz 8fb610915c gdk: Add missing out annotation on gdk_content_deserialize_finish 2022-03-15 22:01:19 -04:00
Benjamin Otte 16a7e3e3d8 listview: Fix return_if_fail()s 2022-03-15 22:00:58 -04:00
Benjamin Otte 47ea51efab flattenlistmodel: Fix indentation 2022-03-15 22:00:47 -04:00
Benjamin Otte 50554bb92b renderers: Handle large viewports
When large viewports are passed to gsk_renderer_render_texture(), don't
fail (or even return NULL).

Instead, draw multiple tiles and assemble them into a memory texture.

Tests added to the testsuite for this.
2022-03-15 22:00:39 -04:00
Christoph Reiter 0ea0fc9c7b CI: disable debug for MSVC
CI currently fails with "fatal error LNK1318: Unexpected PDB error; OK (0) ''"
Google tells me it might be related to hitting a memory limit. Let's try
disabling debug for now.
2022-03-15 22:00:30 -04:00
Luca Bacci 206e837dde Fix last error reporting when calling GetClipboardOwner
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/1402
2022-03-15 22:00:10 -04:00
Matej Urbančič f43d0365dd Update Slovenian translation 2022-03-15 21:27:06 +00:00
Kjartan Maraas 72a557087c Update Norwegian Bokmål translation 2022-03-15 15:26:33 +00:00
Мирослав Николић b59f9b97f3 Update Serbian translation 2022-03-15 06:33:22 +00:00
Christian Kirbach a1f4735652 Update German translation 2022-03-13 22:08:50 +00:00
Balázs Úr c5e372490d Update Hungarian translation 2022-03-13 00:25:05 +00:00
Baurzhan Muftakhidinov 78e083b014 Update Kazakh translation 2022-03-12 16:34:02 +00:00
Baurzhan Muftakhidinov 6ac723321f Update Kazakh translation 2022-03-12 13:23:19 +00:00
Anders Jonsson 343b08f3e6 Update Swedish translation 2022-03-12 11:39:05 +00:00
Dušan Kazik c8d1f23ff5 Update Slovak translation 2022-03-11 07:43:53 +00:00
Balázs Úr 8a7fd71697 Update Hungarian translation 2022-03-11 01:08:54 +00:00
Yosef Or Boczko 39fcfa4473 Update Hebrew translation 2022-03-10 18:42:34 +00:00
Jiri Grönroos d188c6dbaf Update Finnish translation 2022-03-09 19:03:37 +00:00
Marek Černocký 8aec0dc200 Fixed Czech translation 2022-03-09 19:07:33 +01:00
Anders Jonsson 9053fd8335 Update Swedish translation 2022-03-09 10:49:50 +00:00
Danial Behzadi a9720259f0 Update Persian translation 2022-03-08 15:00:39 +00:00
Ask Hjorth Larsen b012886294 Updated Danish translation of gtk-properties 2022-03-08 01:21:58 +01:00
Ask Hjorth Larsen 5de26c684b Updated Danish translation 2022-03-08 01:21:58 +01:00
Aurimas Černius b1d9259e7d Updated Lithuanian translation 2022-03-07 18:29:36 +02:00
Luna Jernberg 89bba41fd7 Update Swedish translation 2022-03-07 08:09:32 +00:00
Luming Zh 248d7ec93c Update Chinese (China) translation 2022-03-05 23:45:12 +00:00
Jordi Mas i Hernandez 2be2912e43 Update Catalan translation 2022-03-04 21:40:27 +00:00
Changwoo Ryu 2755ad19be Update Korean translation 2022-03-04 14:20:21 +00:00
Changwoo Ryu 156f99560d Update Korean translation 2022-03-03 12:46:34 +00:00
Daniel Mustieles 159e9de034 Updated Spanish translation 2022-03-03 11:45:15 +01:00
Luca Bacci f679b0648b Merge branch 'backport-mr-4506-to-gtk-4-6' into 'gtk-4-6'
GdkWin32: Configure as needed when going fullscreen

See merge request GNOME/gtk!4547
2022-03-03 10:09:38 +00:00
Luca Bacci f1ffa6eae9 Merge branch 'backport-mr-4531-to-gtk-4-6' into 'gtk-4-6'
gdkkeys-win32: Only perform substitution as last-resort

See merge request GNOME/gtk!4546
2022-03-03 09:33:27 +00:00
Luca Bacci ec1b61494f GdkWin32: Configure as needed when going fullscreen
Apply the fixes made by Chun-Wei Fan in [1] also for fullscreening /
unfullscreen. Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/4631

Also set the SWP_FRAMECHANGED flag as written by Raymond Chen in "How
do I switch a window between normal and fullscreen?" [2]

> An important flag to pass here is SWP_FRAME­CHANGED, which tells
> the window manager to recalculate the window decorations (which we
> need it to do because we just changed them).

References:
[1] - https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3712
[2] - https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353
2022-03-03 10:01:41 +01:00
Philip Zander cc561915b7 gdkkeys-win32: Only perform substitution as last-resort
Instead of performing keyboard layout substitution whenever we find a matching
entry in the registry, first try to load the original layout and only attempt
substitution when that fails.

See #4724
2022-03-03 09:59:53 +01:00
Aleksandr Melman 15707acb82 Update Russian translation 2022-03-02 19:29:31 +00:00
Emin Tufan Çetin a8ce293bfc Update Turkish translation 2022-03-02 13:05:48 +00:00
Goran Vidović 4eee322654 Update Croatian translation 2022-03-01 13:04:47 +00:00
Goran Vidović 67ae05d855 Update Croatian translation 2022-03-01 12:53:52 +00:00
Marek Černocký 5c535517b5 Updated Czech translation 2022-03-01 12:07:36 +01:00
Rafael Fontenelle ded6bc04ff Update Brazilian Portuguese translation 2022-02-28 14:46:55 +00:00
Fran Dieguez 3e8179c66e Update Galician translation 2022-02-27 22:45:33 +00:00
Asier Sarasua Garmendia 3c21d6bf92 Update Basque translation 2022-02-27 08:05:18 +00:00
Hugo Carvalho 4c7af43eb3 Update Portuguese translation 2022-02-26 18:09:30 +00:00
Yuri Chornoivan 5ce96d5f3b Update Ukrainian translation 2022-02-26 13:05:23 +00:00
Piotr Drąg 6b61cd1869 Update Polish translation 2022-02-26 13:29:19 +01:00
Christian Hergert 9bbf5966d3 macos: fix positioning of popover tails
This broke with the previous fixes for initial window positioning. We need
the initial positioning so that tails will be displayed correctly when the
popover surface is displayed.
2022-02-25 10:51:19 -05:00
209 changed files with 57299 additions and 63748 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson==0.59 || goto :error
meson -Dmedia-gstreamer=disabled _build || goto :error
meson -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
ninja -C _build || goto :error
goto :EOF
+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
+199
View File
@@ -1,3 +1,202 @@
Overview of Changes in 4.6.5, 27-05-2022
========================================
* GtkFileChooser:
- Fix pasting text into the name field
* GtkText:
- Remove an assertion that is sometimes hit
* Wayland:
- Ensure that our cursor surfaces don't violate
protocol constraints
* Accssibility:
- Fix a problem in the accessibility tree
* Translation updates:
Brazilian Portuguese
German
Persian
Polish
Portuguese
Russian
Swedish
Turkish
Ukrainian
Overview of Changes in 4.6.4, 13-05-2022
========================================
* GtkFileChooser:
- Fix select button sensitivity in select_folder mode
- Fix some fallout from list model porting
* GtkListView, GtkColumnView:
- Optimize scrolling
* print-to-file:
- Handle nonexisting files better in the dialog
* Avoid infinite loops in size allocation
* CSS:
- Optimize a case of reparenting that is important in GtkListView
* GSK:
- Check for half-float support before using it
* Wayland:
- Ignore empty preedit updates This fixes a problem with
textview scrolling
- Freeze popups when hidden. This addresses a frame rate drop
* Translation updates
Hebrew
Nepali
Overview of Changes in 4.6.3, 21-04-2022
========================================
* GtkOverlay:
- Bring back positional style classes
* GtkFileChooser:
- Prevent unwanted completion popups
- Fix small problems in save mode
- Fix buildable suport of GtkFileFilter
* GtkPopover:
- Fix button positions in right-to-left locales
* GtkLabel:
- Fix small issues with link handling
* Tooltips:
- Don't restrict the minimum tooltip length
* Theme:
- Don't use opacity for overlay scrollbars
- Fix selection text color in vertical spin buttons
* GSK:
- Accept textures that are generated by webkit
- Align offscreen rendering to the pixel grid
* Accessibility
- Fix a crash in startup when orca is running
* Input:
- Fix display changes in GtkIMMultiContext
- Fix activating on-screen keyboards
- Always propagate hold events in GtkEventControllerScroll
* Windows:
- Fix a critical warning in clipboard handling
- Report serial numbers for events
* MacOS:
- Prevent fullscreen transition reentrancy
* Translation updates
British English
Czech
German
Indonesian
Latvian
Overview of Changes in 4.6.2, 18-03-2022
========================================
* GtkScrolledWindow:
- Set scroll-to-focus on viewports
- Avoid doubly triggering deceleration
* GtkEntry:
- Stop cursor blinking on focus-out
* Emoji:
- Update Emoji data to CLDR 40 and Unicode 14
- Add more locales for Emoji data (da, de, en, es,
fr hu, it, ko, lt, ms, nl, pl, pt, ru, s, uk zh)
* GDK
- Optimize texture conversions on x86 and ARM
- Use EGK_KHR_swap_buffers_with_damage if available
* GSK
- Avoid clearing opaque regions
- Support using a non-default framebuffer
- Handle large viewports by tiling
* Wayland:
- Prefer xdg-activation over gtk-shell
- text protocol: Fix text caret location
- text protocol: Use serials to control outbound messages
* Inspector:
- Show app ID and resource path
* Demos:
- widget-factory: Handle F11 to toggle fullscreen
* Tools:
- gtk-builder-tool: Allow use without display
* Windows:
- Fix preedit window placement on HiDPI
- Build improvements
- Fix fullscreen handling
* MacOS:
- Fix scrolling with an external mouse
- Fix kinetic scrolling with overshoot
- Improve monitor detection
- Many input handling fixes
- Support OpenGL accelerated video playback
- Support fullscreen
- Improve interactive window resizing and moving
- Fix backdrop state handling
- Fix GtkFileChooserNative filtering
- Use CALayer and IOSurface for rendering
- Use per monitor CVDisplayLink to support mixed-rate monitors
- Start applications in foreground
- Fix cursor blink time
* Translation updates
Basque
Brazilian Portuguese
Catalan
Chinese (China)
Croatian
Czech
Danish
Finnish
Galician
German
Hebrew
Hungarian
Italian
Kazakh
Korean
Lithuanian
Norwegian Bokmål
Persian
Poliah
Portuguese
Russian
Slovak
Slovenian
Spanish
Swedish
Turkish
Ukrainian
Overview of Changes in 4.6.1, 11-02-2022
========================================
+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
@@ -1040,7 +1040,7 @@ out:
g_signal_connect_swapped (G_OBJECT (demo), "destroy", G_CALLBACK (g_application_quit), app);
}
else
gtk_widget_show (GTK_WIDGET (window));
gtk_window_present (GTK_WINDOW (window));
if (autoquit)
g_timeout_add_seconds (1, auto_quit, app);
+1 -1
View File
@@ -160,7 +160,7 @@ endif
ld = find_program('ld', required : false)
if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_add_symbol and ld.found()
if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_add_symbol and ld.found()
glib_compile_resources = find_program('glib-compile-resources')
# Create the resource blob
+1 -1
View File
@@ -871,7 +871,7 @@ activate (GApplication *app)
update_ui ();
gtk_widget_show (main_window);
gtk_window_present (GTK_WINDOW (main_window));
}
static void
+1 -1
View File
@@ -8,7 +8,7 @@ endif
ld = find_program('ld', required : false)
if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_add_symbol and ld.found()
if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_add_symbol and ld.found()
glib_compile_resources = find_program('glib-compile-resources')
# Create the resource blob
+1 -1
View File
@@ -2360,7 +2360,7 @@ activate (GApplication *app)
model = (GMenuModel *)gtk_builder_get_object (builder, "new_style_context_menu_model");
set_up_context_popover (widget, model);
gtk_widget_show (GTK_WIDGET (window));
gtk_window_present (window);
g_object_unref (builder);
}
+102 -102
View File
@@ -479,7 +479,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<child>
<object class="GtkStackPage">
<property name="name">page1</property>
<property name="title" translatable="1">Page _1</property>
<property name="title" translatable="yes">Page _1</property>
<property name="use-underline">1</property>
<property name="child">
<object class="GtkBox" id="page1">
@@ -497,7 +497,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<property name="has-entry">1</property>
<child internal-child="entry">
<object class="GtkEntry" id="comboboxtext-entry">
<property name="text" translatable="1">comboboxentry</property>
<property name="text" translatable="yes">comboboxentry</property>
</object>
</child>
<items>
@@ -514,7 +514,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<child internal-child="entry">
<object class="GtkEntry" id="comboboxtext-entry2">
<property name="invisible-char">•</property>
<property name="text" translatable="1">comboboxentry</property>
<property name="text" translatable="yes">comboboxentry</property>
</object>
</child>
</object>
@@ -523,7 +523,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<object class="GtkEntry" id="entry1">
<property name="enable-emoji-completion">1</property>
<property name="invisible_char">•</property>
<property name="placeholder-text" translatable="1">Click icon to change mode</property>
<property name="placeholder-text" translatable="yes">Click icon to change mode</property>
<property name="secondary-icon-name">view-refresh-symbolic</property>
<property name="secondary-icon-tooltip-text">Change mode</property>
<signal name="icon-release" handler="on_entry_icon_release" swapped="no"/>
@@ -532,7 +532,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<child>
<object class="GtkEntry" id="entry2">
<property name="sensitive">0</property>
<property name="text" translatable="1">entry</property>
<property name="text" translatable="yes">entry</property>
</object>
</child>
<child>
@@ -543,7 +543,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<child>
<object class="GtkEntry" id="entry24">
<property name="enable-emoji-completion">1</property>
<property name="text" translatable="1">entry</property>
<property name="text" translatable="yes">entry</property>
<property name="hexpand">1</property>
</object>
</child>
@@ -557,7 +557,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<child>
<object class="GtkPasswordEntry">
<property name="show-peek-icon">1</property>
<property name="placeholder-text" translatable="1">Password…</property>
<property name="placeholder-text" translatable="yes">Password…</property>
</object>
</child>
<child>
@@ -612,13 +612,13 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<property name="spacing">20</property>
<child>
<object class="GtkLabel" id="label3">
<property name="label" translatable="1">label</property>
<property name="label" translatable="yes">label</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="sensitive">0</property>
<property name="label" translatable="1">label</property>
<property name="label" translatable="yes">label</property>
</object>
</child>
<child>
@@ -644,13 +644,13 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<property name="row-spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkbutton1">
<property name="label" translatable="1">checkbutton</property>
<property name="label" translatable="yes">checkbutton</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkCheckButton" id="checkbutton2">
<property name="label" translatable="1">checkbutton</property>
<property name="label" translatable="yes">checkbutton</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
@@ -659,7 +659,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="checkbutton3">
<property name="label" translatable="1">checkbutton</property>
<property name="label" translatable="yes">checkbutton</property>
<property name="inconsistent">1</property>
<layout>
<property name="column">0</property>
@@ -669,7 +669,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="checkbutton4">
<property name="label" translatable="1">checkbutton</property>
<property name="label" translatable="yes">checkbutton</property>
<property name="sensitive">0</property>
<property name="active">1</property>
<layout>
@@ -680,7 +680,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="checkbutton5">
<property name="label" translatable="1">checkbutton</property>
<property name="label" translatable="yes">checkbutton</property>
<property name="sensitive">0</property>
<layout>
<property name="column">0</property>
@@ -690,7 +690,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="checkbutton6">
<property name="label" translatable="1">checkbutton</property>
<property name="label" translatable="yes">checkbutton</property>
<property name="sensitive">0</property>
<property name="inconsistent">1</property>
<layout>
@@ -701,7 +701,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="radiobutton1">
<property name="label" translatable="1">radiobutton</property>
<property name="label" translatable="yes">radiobutton</property>
<property name="active">1</property>
<layout>
<property name="column">1</property>
@@ -711,7 +711,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton">
<property name="label" translatable="1">radiobutton</property>
<property name="label" translatable="yes">radiobutton</property>
<property name="group">radiobutton1</property>
<layout>
<property name="column">1</property>
@@ -721,7 +721,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="radiobutton3">
<property name="label" translatable="1">radiobutton</property>
<property name="label" translatable="yes">radiobutton</property>
<property name="inconsistent">1</property>
<property name="group">radiobutton1</property>
<layout>
@@ -732,7 +732,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="radiobutton4">
<property name="label" translatable="1">radiobutton</property>
<property name="label" translatable="yes">radiobutton</property>
<property name="sensitive">0</property>
<property name="active">1</property>
<layout>
@@ -743,7 +743,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="radiobutton5">
<property name="label" translatable="1">radiobutton</property>
<property name="label" translatable="yes">radiobutton</property>
<property name="sensitive">0</property>
<property name="group">radiobutton4</property>
<layout>
@@ -754,7 +754,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkCheckButton" id="radiobutton6">
<property name="label" translatable="1">radiobutton</property>
<property name="label" translatable="yes">radiobutton</property>
<property name="sensitive">0</property>
<property name="inconsistent">1</property>
<property name="group">radiobutton4</property>
@@ -809,27 +809,27 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<property name="spacing">10</property>
<child>
<object class="GtkToggleButton" id="togglebutton1">
<property name="label" translatable="1">togglebutton</property>
<property name="label" translatable="yes">togglebutton</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkToggleButton" id="togglebutton2">
<property name="label" translatable="1">togglebutton</property>
<property name="label" translatable="yes">togglebutton</property>
<property name="sensitive">0</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkToggleButton" id="togglebutton3">
<property name="label" translatable="1">togglebutton</property>
<property name="label" translatable="yes">togglebutton</property>
<property name="receives-default">1</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleButton" id="togglebutton4">
<property name="label" translatable="1">togglebutton</property>
<property name="label" translatable="yes">togglebutton</property>
<property name="sensitive">0</property>
<property name="receives-default">1</property>
<property name="active">1</property>
@@ -874,7 +874,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkLinkButton" id="linkbutton1">
<property name="label" translatable="1">link button</property>
<property name="label" translatable="yes">link button</property>
<property name="receives-default">1</property>
<property name="has-tooltip">1</property>
<property name="has-frame">0</property>
@@ -1061,7 +1061,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<object class="GtkFrame">
<child type="label">
<object class="GtkLabel" id="label1">
<property name="label" translatable="1">&lt;b&gt;Text Styles&lt;/b&gt;</property>
<property name="label" translatable="yes">&lt;b&gt;Text Styles&lt;/b&gt;</property>
<property name="use-markup">1</property>
</object>
</child>
@@ -1176,7 +1176,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn3">
<property name="title" translatable="1">Cool</property>
<property name="title" translatable="yes">Cool</property>
<child>
<object class="GtkCellRendererToggle" id="cellrenderertoggle1"/>
<attributes>
@@ -1188,7 +1188,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn4">
<property name="title" translatable="1">Icon</property>
<property name="title" translatable="yes">Icon</property>
<property name="reorderable">1</property>
<child>
<object class="GtkCellRendererPixbuf" id="cellrendererpixbuf1"/>
@@ -1200,7 +1200,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<property name="title" translatable="1">Name</property>
<property name="title" translatable="yes">Name</property>
<property name="resizable">1</property>
<property name="reorderable">1</property>
<property name="sort-indicator">1</property>
@@ -1217,7 +1217,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn2">
<property name="title" translatable="1">Nick</property>
<property name="title" translatable="yes">Nick</property>
<property name="resizable">1</property>
<property name="reorderable">1</property>
<property name="sort-indicator">1</property>
@@ -1281,7 +1281,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label5">
<property name="label" translatable="1">Sunset</property>
<property name="label" translatable="yes">Sunset</property>
</object>
</property>
</object>
@@ -1307,7 +1307,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label6">
<property name="label" translatable="1">NYC</property>
<property name="label" translatable="yes">NYC</property>
</object>
</property>
</object>
@@ -1333,7 +1333,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label7">
<property name="label" translatable="1">Beach</property>
<property name="label" translatable="yes">Beach</property>
</object>
</property>
</object>
@@ -1352,7 +1352,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label8">
<property name="label" translatable="1">page 1</property>
<property name="label" translatable="yes">page 1</property>
</object>
</property>
</object>
@@ -1367,7 +1367,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label9">
<property name="label" translatable="1">page 2</property>
<property name="label" translatable="yes">page 2</property>
</object>
</property>
</object>
@@ -1382,7 +1382,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label10">
<property name="label" translatable="1">page 3</property>
<property name="label" translatable="yes">page 3</property>
</object>
</property>
</object>
@@ -1401,7 +1401,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label11">
<property name="label" translatable="1">page 1</property>
<property name="label" translatable="yes">page 1</property>
</object>
</property>
</object>
@@ -1416,7 +1416,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label12">
<property name="label" translatable="1">page 2</property>
<property name="label" translatable="yes">page 2</property>
</object>
</property>
</object>
@@ -1431,7 +1431,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label13">
<property name="label" translatable="1">page 3</property>
<property name="label" translatable="yes">page 3</property>
</object>
</property>
</object>
@@ -1450,7 +1450,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label14">
<property name="label" translatable="1">page 1</property>
<property name="label" translatable="yes">page 1</property>
</object>
</property>
</object>
@@ -1465,7 +1465,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label15">
<property name="label" translatable="1">page 2</property>
<property name="label" translatable="yes">page 2</property>
</object>
</property>
</object>
@@ -1480,7 +1480,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</property>
<property name="tab">
<object class="GtkLabel" id="label16">
<property name="label" translatable="1">page 3</property>
<property name="label" translatable="yes">page 3</property>
</object>
</property>
</object>
@@ -1496,7 +1496,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<child>
<object class="GtkStackPage">
<property name="name">page2</property>
<property name="title" translatable="1">Page _2</property>
<property name="title" translatable="yes">Page _2</property>
<property name="use-underline">1</property>
<property name="child">
<object class="GtkOverlay" id="page2">
@@ -1527,7 +1527,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<child>
<object class="GtkButton" id="page2reset">
<property name="valign">3</property>
<property name="label" translatable="1">Reset</property>
<property name="label" translatable="yes">Reset</property>
</object>
</child>
<child>
@@ -1700,7 +1700,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 1</property>
<property name="label" translatable="yes">Row 1</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1723,7 +1723,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 2</property>
<property name="label" translatable="yes">Row 2</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1747,7 +1747,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 3</property>
<property name="label" translatable="yes">Row 3</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1772,7 +1772,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 4</property>
<property name="label" translatable="yes">Row 4</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1797,7 +1797,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 5</property>
<property name="label" translatable="yes">Row 5</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1821,7 +1821,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 6</property>
<property name="label" translatable="yes">Row 6</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1843,7 +1843,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 7</property>
<property name="label" translatable="yes">Row 7</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1859,7 +1859,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Row 8</property>
<property name="label" translatable="yes">Row 8</property>
<property name="halign">1</property>
<property name="valign">3</property>
<property name="hexpand">1</property>
@@ -1896,16 +1896,16 @@ microphone-sensitivity-medium-symbolic</property>
</style>
<child>
<object class="GtkButton">
<property name="label" translatable="1">New</property>
<property name="label" translatable="yes">New</property>
<property name="icon-name">document-new</property>
<property name="tooltip-text" translatable="1">Create a new document</property>
<property name="tooltip-text" translatable="yes">Create a new document</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="1">Save</property>
<property name="label" translatable="yes">Save</property>
<property name="icon-name">document-save</property>
<property name="tooltip-text" translatable="1">Save the current document</property>
<property name="tooltip-text" translatable="yes">Save the current document</property>
</object>
</child>
<child>
@@ -1913,24 +1913,24 @@ microphone-sensitivity-medium-symbolic</property>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="1">Search</property>
<property name="label" translatable="yes">Search</property>
<property name="icon-name">edit-find</property>
<property name="action-name">win.search</property>
<property name="tooltip-text" translatable="1">Search for it</property>
<property name="tooltip-text" translatable="yes">Search for it</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="sensitive">0</property>
<property name="label" translatable="1">Insert</property>
<property name="label" translatable="yes">Insert</property>
<property name="icon-name">insert-image</property>
<property name="tooltip-text" translatable="1">Insert something</property>
<property name="tooltip-text" translatable="yes">Insert something</property>
</object>
</child>
<child>
<object class="GtkColorButton">
<property name="rgba">#9141AC</property>
<property name="tooltip-text" translatable="1">Select a color</property>
<property name="tooltip-text" translatable="yes">Select a color</property>
</object>
</child>
</object>
@@ -2107,32 +2107,32 @@ microphone-sensitivity-medium-symbolic</property>
</child>
<child type="label">
<object class="GtkLabel" id="label19">
<property name="label" translatable="1">Expander</property>
<property name="label" translatable="yes">Expander</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="info_dialog_button">
<property name="label" translatable="1">_Inform</property>
<property name="label" translatable="yes">_Inform</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="action_dialog_button">
<property name="label" translatable="1">_Act</property>
<property name="label" translatable="yes">_Act</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="preference_dialog_button">
<property name="label" translatable="1">_Configure</property>
<property name="label" translatable="yes">_Configure</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="selection_dialog_button">
<property name="label" translatable="1">S_elect</property>
<property name="label" translatable="yes">S_elect</property>
<property name="use-underline">1</property>
</object>
</child>
@@ -2147,7 +2147,7 @@ microphone-sensitivity-medium-symbolic</property>
<child>
<object class="GtkStackPage">
<property name="name">page3</property>
<property name="title" translatable="1">Page _3</property>
<property name="title" translatable="yes">Page _3</property>
<property name="use-underline">1</property>
<property name="child">
<object class="GtkBox">
@@ -2179,7 +2179,7 @@ microphone-sensitivity-medium-symbolic</property>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="1">Name</property>
<property name="title" translatable="yes">Name</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
@@ -2190,7 +2190,7 @@ microphone-sensitivity-medium-symbolic</property>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="1">Birth</property>
<property name="title" translatable="yes">Birth</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
@@ -2201,7 +2201,7 @@ microphone-sensitivity-medium-symbolic</property>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="1">Death</property>
<property name="title" translatable="yes">Death</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
@@ -2219,7 +2219,7 @@ microphone-sensitivity-medium-symbolic</property>
<property name="selectable">1</property>
<property name="halign">1</property>
<property name="use-markup">1</property>
<property name="label" translatable="1">&lt;small&gt;Data source: &lt;a href=&quot;http://en.wikipedia.org/wiki/Charlemagne#Ancestry&quot;&gt;Wikipedia&lt;/a&gt;&lt;/small&gt;</property>
<property name="label" translatable="yes">&lt;small&gt;Data source: &lt;a href=&quot;http://en.wikipedia.org/wiki/Charlemagne#Ancestry&quot;&gt;Wikipedia&lt;/a&gt;&lt;/small&gt;</property>
</object>
</child>
</object>
@@ -2553,28 +2553,28 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkButton" id="toolbutton1">
<property name="icon-name">document-open-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Insert ⌘</property>
<property name="tooltip-text" translatable="yes">Insert ⌘</property>
</object>
</child>
<child>
<object class="GtkButton" id="toolbutton2">
<property name="icon-name">send-to-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Insert ⚽</property>
<property name="tooltip-text" translatable="yes">Insert ⚽</property>
</object>
</child>
<child>
<object class="GtkButton" id="toolbutton3">
<property name="icon-name">view-fullscreen-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Insert ⤢</property>
<property name="tooltip-text" translatable="yes">Insert ⤢</property>
</object>
</child>
<child>
<object class="GtkButton" id="toolbutton4">
<property name="icon-name">star-new-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Insert ☆</property>
<property name="tooltip-text" translatable="yes">Insert ☆</property>
</object>
</child>
</object>
@@ -2602,7 +2602,7 @@ microphone-sensitivity-medium-symbolic</property>
<property name="sensitive">0</property>
<property name="icon-name">edit-cut-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Cut</property>
<property name="tooltip-text" translatable="yes">Cut</property>
</object>
</child>
<child>
@@ -2610,7 +2610,7 @@ microphone-sensitivity-medium-symbolic</property>
<property name="sensitive">0</property>
<property name="icon-name">edit-copy-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Copy</property>
<property name="tooltip-text" translatable="yes">Copy</property>
</object>
</child>
<child>
@@ -2618,7 +2618,7 @@ microphone-sensitivity-medium-symbolic</property>
<property name="sensitive">0</property>
<property name="icon-name">edit-paste-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Paste</property>
<property name="tooltip-text" translatable="yes">Paste</property>
</object>
</child>
</object>
@@ -2629,7 +2629,7 @@ microphone-sensitivity-medium-symbolic</property>
<property name="valign">2</property>
<property name="icon-name">edit-delete-symbolic</property>
<property name="focus-on-click">0</property>
<property name="tooltip-text" translatable="1">Delete</property>
<property name="tooltip-text" translatable="yes">Delete</property>
</object>
</child>
</object>
@@ -2715,7 +2715,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Page 1</property>
<property name="label" translatable="yes">Page 1</property>
<property name="halign">3</property>
<property name="hexpand">1</property>
</object>
@@ -2747,7 +2747,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Page 2</property>
<property name="label" translatable="yes">Page 2</property>
<property name="halign">3</property>
<property name="hexpand">1</property>
</object>
@@ -2781,7 +2781,7 @@ microphone-sensitivity-medium-symbolic</property>
</property>
<property name="tab">
<object class="GtkLabel">
<property name="label" translatable="1">Page 3</property>
<property name="label" translatable="yes">Page 3</property>
</object>
</property>
</object>
@@ -2810,7 +2810,7 @@ microphone-sensitivity-medium-symbolic</property>
<child>
<object class="GtkEntry">
<property name="hexpand">1</property>
<property name="placeholder-text" translatable="1">Name…</property>
<property name="placeholder-text" translatable="yes">Name…</property>
<property name="completion">name_completion</property>
</object>
</child>
@@ -2818,7 +2818,7 @@ microphone-sensitivity-medium-symbolic</property>
<object class="GtkEntry">
<property name="hexpand">1</property>
<property name="show-emoji-icon">1</property>
<property name="placeholder-text" translatable="1">Age…</property>
<property name="placeholder-text" translatable="yes">Age…</property>
<signal name="notify::text" handler="age_entry_changed"/>
</object>
</child>
@@ -2851,7 +2851,7 @@ microphone-sensitivity-medium-symbolic</property>
</property>
<property name="tab">
<object class="GtkLabel">
<property name="label" translatable="1">Page 1</property>
<property name="label" translatable="yes">Page 1</property>
</object>
</property>
</object>
@@ -2866,7 +2866,7 @@ microphone-sensitivity-medium-symbolic</property>
</property>
<property name="tab">
<object class="GtkLabel">
<property name="label" translatable="1">Page 2</property>
<property name="label" translatable="yes">Page 2</property>
</object>
</property>
</object>
@@ -2879,7 +2879,7 @@ microphone-sensitivity-medium-symbolic</property>
</property>
<property name="tab">
<object class="GtkLabel">
<property name="label" translatable="1">Page 3</property>
<property name="label" translatable="yes">Page 3</property>
</object>
</property>
</object>
@@ -2892,7 +2892,7 @@ microphone-sensitivity-medium-symbolic</property>
</property>
<property name="tab">
<object class="GtkLabel">
<property name="label" translatable="1">Page 4</property>
<property name="label" translatable="yes">Page 4</property>
</object>
</property>
</object>
@@ -2905,7 +2905,7 @@ microphone-sensitivity-medium-symbolic</property>
</property>
<property name="tab">
<object class="GtkLabel">
<property name="label" translatable="1">Page 5</property>
<property name="label" translatable="yes">Page 5</property>
</object>
</property>
</object>
@@ -2932,19 +2932,19 @@ microphone-sensitivity-medium-symbolic</property>
<property name="transient-for">window</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<property name="text" translatable="1">Do something?</property>
<property name="secondary-text" translatable="1">If you don't do something,
<property name="text" translatable="yes">Do something?</property>
<property name="secondary-text" translatable="yes">If you don't do something,
bad things might happen.</property>
<property name="hide-on-close">1</property>
<child type="action">
<object class="GtkButton" id="cancel_info_dialog">
<property name="label" translatable="1">_Cancel</property>
<property name="label" translatable="yes">_Cancel</property>
<property name="use-underline">1</property>
</object>
</child>
<child type="action">
<object class="GtkButton" id="doit_info_dialog">
<property name="label" translatable="1">_Do It</property>
<property name="label" translatable="yes">_Do It</property>
<property name="use-underline">1</property>
</object>
</child>
@@ -2958,7 +2958,7 @@ bad things might happen.</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<property name="use-header-bar">1</property>
<property name="title" translatable="1">Zelda</property>
<property name="title" translatable="yes">Zelda</property>
<property name="hide-on-close">1</property>
<property name="default-widget">act_action_dialog</property>
<child internal-child="content_area">
@@ -2969,20 +2969,20 @@ bad things might happen.</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="label" translatable="1">To free the princess, you have to slay the dragon.</property>
<property name="label" translatable="yes">To free the princess, you have to slay the dragon.</property>
</object>
</child>
</object>
</child>
<child type="action">
<object class="GtkButton" id="cancel_action_dialog">
<property name="label" translatable="1">_Run</property>
<property name="label" translatable="yes">_Run</property>
<property name="use-underline">1</property>
</object>
</child>
<child type="action">
<object class="GtkButton" id="act_action_dialog">
<property name="label" translatable="1">_Act</property>
<property name="label" translatable="yes">_Act</property>
<property name="use-underline">1</property>
</object>
</child>
@@ -2996,7 +2996,7 @@ bad things might happen.</property>
<property name="modal">1</property>
<property name="resizable">0</property>
<property name="use-header-bar">1</property>
<property name="title" translatable="1">Settings</property>
<property name="title" translatable="yes">Settings</property>
<property name="hide-on-close">1</property>
<child internal-child="content_area">
<object class="GtkBox">
@@ -3141,7 +3141,7 @@ bad things might happen.</property>
<property name="transient-for">window</property>
<property name="modal">1</property>
<property name="use-header-bar">1</property>
<property name="title" translatable="1">Choose one</property>
<property name="title" translatable="yes">Choose one</property>
<property name="hide-on-close">1</property>
<property name="default-widget">select_selection_dialog</property>
<child internal-child="content_area">
@@ -3162,13 +3162,13 @@ bad things might happen.</property>
</child>
<child type="action">
<object class="GtkButton" id="cancel_selection_dialog">
<property name="label" translatable="1">_Cancel</property>
<property name="label" translatable="yes">_Cancel</property>
<property name="use-underline">1</property>
</object>
</child>
<child type="action">
<object class="GtkButton" id="select_selection_dialog">
<property name="label" translatable="1">_Select</property>
<property name="label" translatable="yes">_Select</property>
<property name="use-underline">1</property>
</object>
</child>
+1 -1
View File
@@ -5,7 +5,7 @@ repository_url = "https://gitlab.gnome.org/GNOME/gtk.git"
website_url = "https://www.gtk.org"
authors = "GTK Development Team"
logo_url = "gtk-logo.svg"
license = "GPL-2.1-or-later"
license = "LGPL-2.1-or-later"
description = "The GTK toolkit"
devhelp = true
+1 -1
View File
@@ -5,7 +5,7 @@ repository_url = "https://gitlab.gnome.org/GNOME/gtk.git"
website_url = "https://www.gtk.org"
authors = "GTK Development Team"
logo_url = "gtk-logo.svg"
license = "GPL-2.1-or-later"
license = "LGPL-2.1-or-later"
description = "The GTK toolkit"
dependencies = ["Gdk-4.0"]
devhelp = true
+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
+1 -1
View File
@@ -372,7 +372,7 @@ library you are using:
The `test` accessibility backend is recommended for test suites and remote
continuous integration pipelines.
### `XDG_DTA_HOME`, `XDG_DATA_DIRS`
### `XDG_DATA_HOME`, `XDG_DATA_DIRS`
GTK uses these environment variables to locate icon themes
and MIME information. For more information, see the
+1
View File
@@ -354,6 +354,7 @@ typedef struct {
typedef union {
BroadwayReplyBase base;
BroadwayReplySync sync;
BroadwayReplyEvent event;
BroadwayReplyQueryMouse query_mouse;
BroadwayReplyNewSurface new_surface;
+14 -18
View File
@@ -219,11 +219,7 @@ static void
client_handle_request (BroadwayClient *client,
BroadwayRequest *request)
{
BroadwayReplyNewSurface reply_new_surface;
BroadwayReplySync reply_sync;
BroadwayReplyQueryMouse reply_query_mouse;
BroadwayReplyGrabPointer reply_grab_pointer;
BroadwayReplyUngrabPointer reply_ungrab_pointer;
BroadwayReply reply;
guint32 before_serial, now_serial;
guint32 global_id;
int fd;
@@ -233,7 +229,7 @@ client_handle_request (BroadwayClient *client,
switch (request->base.type)
{
case BROADWAY_REQUEST_NEW_SURFACE:
reply_new_surface.id =
reply.new_surface.id =
broadway_server_new_surface (server, client->id,
request->new_surface.x,
request->new_surface.y,
@@ -241,9 +237,9 @@ client_handle_request (BroadwayClient *client,
request->new_surface.height);
client->surfaces =
g_list_prepend (client->surfaces,
GUINT_TO_POINTER (reply_new_surface.id));
GUINT_TO_POINTER (reply.new_surface.id));
send_reply (client, request, (BroadwayReply *)&reply_new_surface, sizeof (reply_new_surface),
send_reply (client, request, &reply, sizeof (reply.new_surface),
BROADWAY_REPLY_NEW_SURFACE);
break;
case BROADWAY_REQUEST_FLUSH:
@@ -251,7 +247,7 @@ client_handle_request (BroadwayClient *client,
break;
case BROADWAY_REQUEST_SYNC:
broadway_server_flush (server);
send_reply (client, request, (BroadwayReply *)&reply_sync, sizeof (reply_sync),
send_reply (client, request, &reply, sizeof (reply.sync),
BROADWAY_REPLY_SYNC);
break;
case BROADWAY_REQUEST_ROUNDTRIP:
@@ -261,11 +257,11 @@ client_handle_request (BroadwayClient *client,
break;
case BROADWAY_REQUEST_QUERY_MOUSE:
broadway_server_query_mouse (server,
&reply_query_mouse.surface,
&reply_query_mouse.root_x,
&reply_query_mouse.root_y,
&reply_query_mouse.mask);
send_reply (client, request, (BroadwayReply *)&reply_query_mouse, sizeof (reply_query_mouse),
&reply.query_mouse.surface,
&reply.query_mouse.root_x,
&reply.query_mouse.root_y,
&reply.query_mouse.mask);
send_reply (client, request, &reply, sizeof (reply.query_mouse),
BROADWAY_REPLY_QUERY_MOUSE);
break;
case BROADWAY_REQUEST_DESTROY_SURFACE:
@@ -361,21 +357,21 @@ client_handle_request (BroadwayClient *client,
request->move_resize.height);
break;
case BROADWAY_REQUEST_GRAB_POINTER:
reply_grab_pointer.status =
reply.grab_pointer.status =
broadway_server_grab_pointer (server,
client->id,
request->grab_pointer.id,
request->grab_pointer.owner_events,
request->grab_pointer.event_mask,
request->grab_pointer.time_);
send_reply (client, request, (BroadwayReply *)&reply_grab_pointer, sizeof (reply_grab_pointer),
send_reply (client, request, &reply, sizeof (reply.grab_pointer),
BROADWAY_REPLY_GRAB_POINTER);
break;
case BROADWAY_REQUEST_UNGRAB_POINTER:
reply_ungrab_pointer.status =
reply.ungrab_pointer.status =
broadway_server_ungrab_pointer (server,
request->ungrab_pointer.time_);
send_reply (client, request, (BroadwayReply *)&reply_ungrab_pointer, sizeof (reply_ungrab_pointer),
send_reply (client, request, &reply, sizeof (reply.ungrab_pointer),
BROADWAY_REPLY_UNGRAB_POINTER);
break;
case BROADWAY_REQUEST_FOCUS_SURFACE:
+1 -1
View File
@@ -576,7 +576,7 @@ gdk_content_deserialize_async (GInputStream *stream,
/**
* gdk_content_deserialize_finish:
* @result: the `GAsyncResult`
* @value: return location for the result of the operation
* @value: (out): return location for the result of the operation
* @error: return location for an error
*
* Finishes a content deserialization operation.
+3 -5
View File
@@ -1628,10 +1628,10 @@ gdk_display_check_egl_extensions (EGLDisplay egl_display,
/* translators: Arguments are the number of missing extensions
* followed by a comma-separated list of their names */
g_dngettext (GETTEXT_PACKAGE,
"EGL implementation is missing extension %2$s",
"EGL implementation is missing %d extensions: %s",
"EGL implementation is missing extension %s",
"EGL implementation is missing %2$d extensions: %1$s",
n_missing),
(int) n_missing, missing->str);
missing->str, (int) n_missing);
g_string_free (missing, TRUE);
return FALSE;
@@ -1721,8 +1721,6 @@ gdk_display_init_egl (GdkDisplay *self,
self->have_egl_buffer_age =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_buffer_age");
self->have_egl_swap_buffers_with_damage =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_swap_buffers_with_damage");
self->have_egl_no_config_context =
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_no_config_context");
self->have_egl_pixel_format_float =
-1
View File
@@ -107,7 +107,6 @@ struct _GdkDisplay
/* egl info */
guint have_egl_buffer_age : 1;
guint have_egl_swap_buffers_with_damage : 1;
guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
guint have_egl_win32_libangle : 1;
+26 -6
View File
@@ -1,7 +1,7 @@
/* GDK - The GIMP Drawing Kit
*
* gdkglcontext.c: GL context abstraction
*
*
* Copyright © 2014 Emmanuele Bassi
*
* This library is free software; you can redistribute it and/or
@@ -103,6 +103,7 @@ typedef struct {
guint has_khr_debug : 1;
guint use_khr_debug : 1;
guint has_half_float : 1;
guint has_unpack_subimage : 1;
guint has_debug_output : 1;
guint extensions_checked : 1;
@@ -117,6 +118,7 @@ typedef struct {
#ifdef HAVE_EGL
EGLContext egl_context;
EGLBoolean (*eglSwapBuffersWithDamage) (EGLDisplay, EGLSurface, const EGLint *, EGLint);
#endif
} GdkGLContextPrivate;
@@ -420,6 +422,11 @@ gdk_gl_context_real_realize (GdkGLContext *context,
gdk_gl_context_set_is_legacy (context, legacy_bit);
if (epoxy_has_egl_extension (egl_display, "EGL_KHR_swap_buffers_with_damage"))
priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageKHR");
else if (epoxy_has_egl_extension (egl_display, "EGL_EXT_swap_buffers_with_damage"))
priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageEXT");
gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL);
return api;
@@ -608,7 +615,7 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "EGL", "swap buffers");
if (display->have_egl_swap_buffers_with_damage)
if (priv->eglSwapBuffersWithDamage)
{
EGLint stack_rects[4 * 4]; /* 4 rects */
EGLint *heap_rects = NULL;
@@ -632,7 +639,7 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
rects[j++] = rect.width * scale;
rects[j++] = rect.height * scale;
}
eglSwapBuffersWithDamageEXT (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
priv->eglSwapBuffersWithDamage (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
g_free (heap_rects);
}
else
@@ -1536,18 +1543,23 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
glGetIntegerv (GL_MAX_LABEL_LENGTH, &priv->max_debug_label_length);
}
priv->has_half_float = gdk_gl_context_check_version (context, 3, 0, 3, 0) ||
epoxy_has_gl_extension ("OES_vertex_half_float");
GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), OPENGL,
g_message ("%s version: %d.%d (%s)\n"
"* GLSL version: %s\n"
"* Extensions checked:\n"
" - GL_KHR_debug: %s\n"
" - GL_EXT_unpack_subimage: %s",
" - GL_EXT_unpack_subimage: %s\n"
" - OES_vertex_half_float: %s",
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
priv->gl_version / 10, priv->gl_version % 10,
priv->is_legacy ? "legacy" : "core",
glGetString (GL_SHADING_LANGUAGE_VERSION),
priv->has_khr_debug ? "yes" : "no",
priv->has_unpack_subimage ? "yes" : "no"));
priv->has_unpack_subimage ? "yes" : "no",
priv->has_half_float ? "yes" : "no"));
priv->extensions_checked = TRUE;
}
@@ -1751,6 +1763,14 @@ gdk_gl_context_has_debug (GdkGLContext *self)
return priv->debug_enabled || priv->use_khr_debug;
}
gboolean
gdk_gl_context_has_vertex_half_float (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_half_float;
}
/* This is currently private! */
/* When using GL/ES, don't flip the 'R' and 'B' bits on Windows/ANGLE for glReadPixels() */
gboolean
@@ -1793,7 +1813,7 @@ gboolean
gdk_gl_backend_can_be_used (GdkGLBackend backend_type,
GError **error)
{
if (the_gl_backend_type == GDK_GL_NONE ||
if (the_gl_backend_type == GDK_GL_NONE ||
the_gl_backend_type == backend_type)
return TRUE;
+2
View File
@@ -139,6 +139,8 @@ gboolean gdk_gl_context_has_debug (GdkGLContext
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
gboolean gdk_gl_context_has_vertex_half_float (GdkGLContext *self) G_GNUC_PURE;
G_END_DECLS
#endif /* __GDK_GL_CONTEXT_PRIVATE_H__ */
+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
+86 -73
View File
@@ -25,10 +25,6 @@
#include <epoxy/gl.h>
#ifdef __ARM_NEON
#include <arm_neon.h>
#endif
typedef struct _GdkMemoryFormatDescription GdkMemoryFormatDescription;
#define TYPED_FUNCS(name, T, R, G, B, A, bpp, scale) \
@@ -170,75 +166,54 @@ r32g32b32a32_float_from_float (guchar *dest,
memcpy (dest, src, sizeof (float) * n * 4);
}
// This one conversion is quite important, it converts from RGBA with straight
// alpha (as found in PNG for instance) to BGRA with premultiplied alpha (the
// sole cairo format available).
static void
r8g8b8a8_to_b8g8r8a8_premultiplied (guchar *dest,
const guchar *src,
gsize n)
{
#ifdef __ARM_NEON
uint16x8_t one = vdupq_n_u16 (1);
uint16x8_t half = vdupq_n_u16 (127);
for (gsize i = n / 8; i > 0; i--)
{
// Work on “just” 8 pixels at once, since we need the full 16-bytes of
// the q registers for the multiplication.
uint8x8x4_t rgba = vld4_u8 (src);
uint8x8_t r8 = rgba.val[0];
uint8x8_t g8 = rgba.val[1];
uint8x8_t b8 = rgba.val[2];
uint8x8_t a8 = rgba.val[3];
// This is the same algorithm as premultiply(), but on packed 16-bit
// instead of float.
uint16x8_t r16 = vmull_u8 (r8, a8);
uint16x8_t g16 = vmull_u8 (g8, a8);
uint16x8_t b16 = vmull_u8 (b8, a8);
r16 = vaddq_u16 (r16, half);
g16 = vaddq_u16 (g16, half);
b16 = vaddq_u16 (b16, half);
r16 = vsraq_n_u16 (r16, r16, 8);
g16 = vsraq_n_u16 (g16, g16, 8);
b16 = vsraq_n_u16 (b16, b16, 8);
r16 = vaddq_u16 (r16, one);
g16 = vaddq_u16 (g16, one);
b16 = vaddq_u16 (b16, one);
// Just like the other one, here we use BGRA instead of RGBA!
rgba.val[0] = vshrn_n_u16 (b16, 8);
rgba.val[1] = vshrn_n_u16 (g16, 8);
rgba.val[2] = vshrn_n_u16 (r16, 8);
vst4_u8 (dest, rgba);
src += 32;
dest += 32;
}
// We want the fallthrough here for the last (up to) seven bytes of the row.
n = n % 8;
#endif // __ARM_NEON
for (; n > 0; n--)
{
guchar a = src[3];
guint16 r = (guint16)src[0] * a + 127;
guint16 g = (guint16)src[1] * a + 127;
guint16 b = (guint16)src[2] * a + 127;
dest[0] = (b + (b >> 8) + 1) >> 8;
dest[1] = (g + (g >> 8) + 1) >> 8;
dest[2] = (r + (r >> 8) + 1) >> 8;
dest[3] = a;
dest += 4;
src += 4;
}
#define PREMULTIPLY_FUNC(name, R1, G1, B1, A1, R2, G2, B2, A2) \
static void \
name (guchar *dest, \
const guchar *src, \
gsize n) \
{ \
for (; n > 0; n--) \
{ \
guchar a = src[A1]; \
guint16 r = (guint16)src[R1] * a + 127; \
guint16 g = (guint16)src[G1] * a + 127; \
guint16 b = (guint16)src[B1] * a + 127; \
dest[R2] = (r + (r >> 8) + 1) >> 8; \
dest[G2] = (g + (g >> 8) + 1) >> 8; \
dest[B2] = (b + (b >> 8) + 1) >> 8; \
dest[A2] = a; \
dest += 4; \
src += 4; \
} \
}
PREMULTIPLY_FUNC(r8g8b8a8_to_r8g8b8a8_premultiplied, 0, 1, 2, 3, 0, 1, 2, 3)
PREMULTIPLY_FUNC(r8g8b8a8_to_b8g8r8a8_premultiplied, 0, 1, 2, 3, 2, 1, 0, 3)
PREMULTIPLY_FUNC(r8g8b8a8_to_a8r8g8b8_premultiplied, 0, 1, 2, 3, 1, 2, 3, 0)
PREMULTIPLY_FUNC(r8g8b8a8_to_a8b8g8r8_premultiplied, 0, 1, 2, 3, 3, 2, 1, 0)
#define ADD_ALPHA_FUNC(name, R1, G1, B1, R2, G2, B2, A2) \
static void \
name (guchar *dest, \
const guchar *src, \
gsize n) \
{ \
for (; n > 0; n--) \
{ \
dest[R2] = src[R1]; \
dest[G2] = src[G1]; \
dest[B2] = src[B1]; \
dest[A2] = 255; \
dest += 4; \
src += 3; \
} \
}
ADD_ALPHA_FUNC(r8g8b8_to_r8g8b8a8, 0, 1, 2, 0, 1, 2, 3)
ADD_ALPHA_FUNC(r8g8b8_to_b8g8r8a8, 0, 1, 2, 2, 1, 0, 3)
ADD_ALPHA_FUNC(r8g8b8_to_a8r8g8b8, 0, 1, 2, 1, 2, 3, 0)
ADD_ALPHA_FUNC(r8g8b8_to_a8b8g8r8, 0, 1, 2, 3, 2, 1, 0)
struct _GdkMemoryFormatDescription
{
GdkMemoryAlpha alpha;
@@ -548,15 +523,53 @@ gdk_memory_convert (guchar *dest_data,
const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
float *tmp;
gsize y;
void (*func) (guchar *, const guchar *, gsize) = NULL;
g_assert (dest_format < GDK_MEMORY_N_FORMATS);
g_assert (src_format < GDK_MEMORY_N_FORMATS);
if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED)
if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
func = r8g8b8a8_to_r8g8b8a8_premultiplied;
else if (src_format == GDK_MEMORY_B8G8R8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
func = r8g8b8a8_to_b8g8r8a8_premultiplied;
else if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED)
func = r8g8b8a8_to_b8g8r8a8_premultiplied;
else if (src_format == GDK_MEMORY_B8G8R8A8 && dest_format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED)
func = r8g8b8a8_to_r8g8b8a8_premultiplied;
else if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_A8R8G8B8_PREMULTIPLIED)
func = r8g8b8a8_to_a8r8g8b8_premultiplied;
else if (src_format == GDK_MEMORY_B8G8R8A8 && dest_format == GDK_MEMORY_A8R8G8B8_PREMULTIPLIED)
func = r8g8b8a8_to_a8b8g8r8_premultiplied;
else if (src_format == GDK_MEMORY_R8G8B8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
func = r8g8b8_to_r8g8b8a8;
else if (src_format == GDK_MEMORY_B8G8R8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
func = r8g8b8_to_b8g8r8a8;
else if (src_format == GDK_MEMORY_R8G8B8 && dest_format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED)
func = r8g8b8_to_b8g8r8a8;
else if (src_format == GDK_MEMORY_B8G8R8 && dest_format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED)
func = r8g8b8_to_r8g8b8a8;
else if (src_format == GDK_MEMORY_R8G8B8 && dest_format == GDK_MEMORY_A8R8G8B8_PREMULTIPLIED)
func = r8g8b8_to_a8r8g8b8;
else if (src_format == GDK_MEMORY_B8G8R8 && dest_format == GDK_MEMORY_A8R8G8B8_PREMULTIPLIED)
func = r8g8b8_to_a8b8g8r8;
else if (src_format == GDK_MEMORY_R8G8B8 && dest_format == GDK_MEMORY_R8G8B8A8)
func = r8g8b8_to_r8g8b8a8;
else if (src_format == GDK_MEMORY_B8G8R8 && dest_format == GDK_MEMORY_R8G8B8A8)
func = r8g8b8_to_b8g8r8a8;
else if (src_format == GDK_MEMORY_R8G8B8 && dest_format == GDK_MEMORY_B8G8R8A8)
func = r8g8b8_to_b8g8r8a8;
else if (src_format == GDK_MEMORY_B8G8R8 && dest_format == GDK_MEMORY_B8G8R8A8)
func = r8g8b8_to_r8g8b8a8;
else if (src_format == GDK_MEMORY_R8G8B8 && dest_format == GDK_MEMORY_A8R8G8B8)
func = r8g8b8_to_a8r8g8b8;
else if (src_format == GDK_MEMORY_B8G8R8 && dest_format == GDK_MEMORY_A8R8G8B8)
func = r8g8b8_to_a8b8g8r8;
if (func != NULL)
{
for (y = 0; y < height; y++)
{
r8g8b8a8_to_b8g8r8a8_premultiplied (dest_data, src_data, width);
func (dest_data, src_data, width);
src_data += src_stride;
dest_data += dest_stride;
}
+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;
}
+14
View File
@@ -24,6 +24,7 @@
#import "GdkMacosLayer.h"
#import "GdkMacosView.h"
#import "GdkMacosWindow.h"
@implementation GdkMacosView
@@ -56,6 +57,19 @@
return NO;
}
-(void)mouseDown:(NSEvent *)nsevent
{
if ([(GdkMacosWindow *)[self window] needsMouseDownQuirk])
/* We should only hit this when we are trying to click through
* the shadow of a window into another window. Just request
* that the application not activate this window on mouseUp.
* See gdkmacosdisplay-translate.c for the other half of this.
*/
[NSApp preventWindowOrdering];
else
[super mouseDown:nsevent];
}
-(void)setFrame:(NSRect)rect
{
[super setFrame:rect];
+40 -7
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
@@ -253,7 +258,8 @@ typedef NSString *CALayerContentsGravity;
-(BOOL)canBecomeKeyWindow
{
return GDK_IS_TOPLEVEL (gdk_surface) || GDK_IS_POPUP (gdk_surface);
return GDK_IS_TOPLEVEL (gdk_surface) ||
(GDK_IS_POPUP (gdk_surface) && GDK_SURFACE (gdk_surface)->input_region != NULL);
}
-(void)showAndMakeKey:(BOOL)makeKey
@@ -261,9 +267,12 @@ typedef NSString *CALayerContentsGravity;
inShowOrHide = YES;
if (makeKey && [self canBecomeKeyWindow])
[self makeKeyAndOrderFront:nil];
[self makeKeyAndOrderFront:self];
else
[self orderFront:nil];
[self orderFront:self];
if (makeKey && [self canBecomeMainWindow])
[self makeMainWindow];
inShowOrHide = NO;
@@ -373,9 +382,17 @@ typedef NSString *CALayerContentsGravity;
_gdk_macos_surface_configure ([self gdkSurface]);
}
- (void)windowDidResize:(NSNotification *)notification
-(void)windowDidResize:(NSNotification *)notification
{
_gdk_macos_surface_configure ([self gdkSurface]);
_gdk_macos_surface_configure (gdk_surface);
/* If we're using server-side decorations, this notification is coming
* in from a display-side change. We need to request a layout in
* addition to the configure event.
*/
if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface) &&
GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface)->decorated)
gdk_surface_request_layout (GDK_SURFACE (gdk_surface));
}
/* Used by gdkmacosdisplay-translate.c to decide if our sendEvent() handler
@@ -668,7 +685,12 @@ typedef NSString *CALayerContentsGravity;
is_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
if (was_fullscreen != is_fullscreen)
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
{
if (was_fullscreen)
[self setFrame:lastUnfullscreenFrame display:NO];
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
}
if (was_opaque != is_opaque)
{
@@ -742,32 +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
{
[self setFrame:lastUnfullscreenFrame display:NO];
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
@@ -814,4 +841,10 @@ typedef NSString *CALayerContentsGravity;
[(GdkMacosView *)[self contentView] swapBuffer:buffer withDamage:damage];
}
-(BOOL)needsMouseDownQuirk
{
return GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface) &&
!GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface)->decorated;
}
@end
+3
View File
@@ -53,6 +53,7 @@
NSRect lastMaximizedFrame;
NSRect lastUnfullscreenFrame;
BOOL inMaximizeTransition;
BOOL inFullscreenTransition;
}
-(void)beginManualMove;
@@ -69,5 +70,7 @@
-(BOOL)trackManualResize;
-(void)setDecorated:(BOOL)decorated;
-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage;
-(BOOL)needsMouseDownQuirk;
-(BOOL)inFullscreenTransition;
@end
+59 -24
View File
@@ -26,7 +26,9 @@
#include "gdkdisplaylinksource.h"
#include "gdkdebug.h"
#include "gdkmacoseventsource-private.h"
#include "gdkmacosmonitor-private.h"
#include "gdk-private.h"
static gint64 host_to_frame_clock_time (gint64 val);
@@ -65,7 +67,7 @@ gdk_display_link_source_dispatch (GSource *source,
impl->needs_dispatch = FALSE;
if (callback != NULL)
if (!impl->paused && callback != NULL)
ret = callback (user_data);
return ret;
@@ -76,7 +78,9 @@ gdk_display_link_source_finalize (GSource *source)
{
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
CVDisplayLinkStop (impl->display_link);
if (!impl->paused)
CVDisplayLinkStop (impl->display_link);
CVDisplayLinkRelease (impl->display_link);
}
@@ -90,12 +94,18 @@ static GSourceFuncs gdk_display_link_source_funcs = {
void
gdk_display_link_source_pause (GdkDisplayLinkSource *source)
{
g_return_if_fail (source->paused == FALSE);
source->paused = TRUE;
CVDisplayLinkStop (source->display_link);
}
void
gdk_display_link_source_unpause (GdkDisplayLinkSource *source)
{
g_return_if_fail (source->paused == TRUE);
source->paused = FALSE;
CVDisplayLinkStart (source->display_link);
}
@@ -147,6 +157,7 @@ gdk_display_link_source_frame_cb (CVDisplayLinkRef display_link,
/**
* gdk_display_link_source_new:
* @display_id: the identifier of the monitor
*
* Creates a new `GSource` that will activate the dispatch function upon
* notification from a CVDisplayLink that a new frame should be drawn.
@@ -159,41 +170,61 @@ gdk_display_link_source_frame_cb (CVDisplayLinkRef display_link,
* Returns: (transfer full): A newly created `GSource`
*/
GSource *
gdk_display_link_source_new (void)
gdk_display_link_source_new (CGDirectDisplayID display_id,
CGDisplayModeRef mode)
{
GdkDisplayLinkSource *impl;
GSource *source;
CVReturn ret;
double period;
char *name;
source = g_source_new (&gdk_display_link_source_funcs, sizeof *impl);
impl = (GdkDisplayLinkSource *)source;
impl->display_id = display_id;
impl->paused = TRUE;
/*
* Create our link based on currently connected displays.
* If there are multiple displays, this will be something that tries
* to work for all of them. In the future, we may want to explore multiple
* links based on the connected displays.
/* Create DisplayLink for timing information for the display in
* question so that we can produce graphics for that display at whatever
* rate it can provide.
*/
ret = CVDisplayLinkCreateWithActiveCGDisplays (&impl->display_link);
if (ret != kCVReturnSuccess)
if (CVDisplayLinkCreateWithCGDisplay (display_id, &impl->display_link) != kCVReturnSuccess)
{
g_warning ("Failed to initialize CVDisplayLink!");
return source;
goto failure;
}
/*
* Determine our nominal period between frames.
*/
period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
if (period == 0.0)
period = 1.0 / 60.0;
impl->refresh_interval = period * 1000000L;
impl->refresh_rate = 1.0 / period * 1000L;
impl->refresh_rate = CGDisplayModeGetRefreshRate (mode) * 1000.0;
/*
* Wire up our callback to be executed within the high-priority thread.
*/
if (impl->refresh_rate == 0)
{
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod (impl->display_link);
if (!(time.flags & kCVTimeIsIndefinite))
impl->refresh_rate = (double)time.timeScale / (double)time.timeValue * 1000.0;
}
if (impl->refresh_rate != 0)
{
impl->refresh_interval = 1000000.0 / (double)impl->refresh_rate * 1000.0;
}
else
{
double period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
if (period == 0.0)
period = 1.0 / 60.0;
impl->refresh_rate = 1.0 / period * 1000L;
impl->refresh_interval = period * 1000000L;
}
name = _gdk_macos_monitor_get_connector_name (display_id);
GDK_NOTE (MISC,
g_message ("Monitor \"%s\" discovered with Refresh Rate %d and Interval %"G_GINT64_FORMAT,
name ? name : "unknown",
impl->refresh_rate,
impl->refresh_interval));
g_free (name);
/* Wire up our callback to be executed within the high-priority thread. */
CVDisplayLinkSetOutputCallback (impl->display_link,
gdk_display_link_source_frame_cb,
source);
@@ -201,6 +232,10 @@ gdk_display_link_source_new (void)
g_source_set_static_name (source, "[gdk] quartz frame clock");
return source;
failure:
g_source_unref (source);
return NULL;
}
static gint64
+10 -7
View File
@@ -30,17 +30,20 @@ G_BEGIN_DECLS
typedef struct
{
GSource source;
GSource source;
CVDisplayLinkRef display_link;
gint64 refresh_interval;
guint refresh_rate;
CGDirectDisplayID display_id;
CVDisplayLinkRef display_link;
gint64 refresh_interval;
guint refresh_rate;
guint paused : 1;
volatile gint64 presentation_time;
volatile guint needs_dispatch;
volatile gint64 presentation_time;
volatile guint needs_dispatch;
} GdkDisplayLinkSource;
GSource *gdk_display_link_source_new (void);
GSource *gdk_display_link_source_new (CGDirectDisplayID display_id,
CGDisplayModeRef mode);
void gdk_display_link_source_pause (GdkDisplayLinkSource *source);
void gdk_display_link_source_unpause (GdkDisplayLinkSource *source);
+2
View File
@@ -41,6 +41,8 @@ GdkMacosBuffer *_gdk_macos_buffer_new (int width
IOSurfaceRef _gdk_macos_buffer_get_native (GdkMacosBuffer *self);
void _gdk_macos_buffer_lock (GdkMacosBuffer *self);
void _gdk_macos_buffer_unlock (GdkMacosBuffer *self);
void _gdk_macos_buffer_read_lock (GdkMacosBuffer *self);
void _gdk_macos_buffer_read_unlock (GdkMacosBuffer *self);
guint _gdk_macos_buffer_get_width (GdkMacosBuffer *self);
guint _gdk_macos_buffer_get_height (GdkMacosBuffer *self);
guint _gdk_macos_buffer_get_stride (GdkMacosBuffer *self);
+40 -1
View File
@@ -192,6 +192,45 @@ _gdk_macos_buffer_unlock (GdkMacosBuffer *self)
IOSurfaceUnlock (self->surface, 0, NULL);
}
/**
* _gdk_macos_buffer_lock_readonly:
*
* Like _gdk_macos_buffer_lock() but uses the read-only flag to
* indicate we are not interested in retrieving the updates from
* the GPU before modifying the CPU-side cache.
*
* Must be used with _gdk_macos_buffer_unlock_readonly().
*/
void
_gdk_macos_buffer_read_lock (GdkMacosBuffer *self)
{
kern_return_t ret;
g_return_if_fail (GDK_IS_MACOS_BUFFER (self));
g_return_if_fail (self->lock_count == 0);
self->lock_count++;
ret = IOSurfaceLock (self->surface, kIOSurfaceLockReadOnly, NULL);
g_return_if_fail (ret == KERN_SUCCESS);
}
void
_gdk_macos_buffer_read_unlock (GdkMacosBuffer *self)
{
kern_return_t ret;
g_return_if_fail (GDK_IS_MACOS_BUFFER (self));
g_return_if_fail (self->lock_count == 1);
self->lock_count--;
ret = IOSurfaceUnlock (self->surface, kIOSurfaceLockReadOnly, NULL);
g_return_if_fail (ret == KERN_SUCCESS);
}
guint
_gdk_macos_buffer_get_width (GdkMacosBuffer *self)
{
@@ -242,7 +281,7 @@ _gdk_macos_buffer_set_damage (GdkMacosBuffer *self,
return;
g_clear_pointer (&self->damage, cairo_region_destroy);
self->damage = cairo_region_reference (damage);
self->damage = cairo_region_copy (damage);
}
gpointer
+92 -28
View File
@@ -42,19 +42,6 @@ struct _GdkMacosCairoContextClass
G_DEFINE_TYPE (GdkMacosCairoContext, _gdk_macos_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
static const cairo_user_data_key_t buffer_key;
static void
unlock_buffer (gpointer data)
{
GdkMacosBuffer *buffer = data;
g_assert (GDK_IS_MACOS_BUFFER (buffer));
_gdk_macos_buffer_unlock (buffer);
g_clear_object (&buffer);
}
static cairo_t *
_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
{
@@ -106,12 +93,9 @@ _gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
stride);
cairo_surface_set_device_scale (image_surface, scale, scale);
/* Lock the buffer so we can modify it safely */
_gdk_macos_buffer_lock (buffer);
cairo_surface_set_user_data (image_surface,
&buffer_key,
g_object_ref (buffer),
unlock_buffer);
/* The buffer should already be locked at this point, and will
* be unlocked as part of end_frame.
*/
if (!(cr = cairo_create (image_surface)))
goto failure;
@@ -158,6 +142,52 @@ failure:
return cr;
}
static void
copy_surface_data (GdkMacosBuffer *from,
GdkMacosBuffer *to,
const cairo_region_t *region,
int scale)
{
const guint8 *from_base;
guint8 *to_base;
guint from_stride;
guint to_stride;
guint n_rects;
g_assert (GDK_IS_MACOS_BUFFER (from));
g_assert (GDK_IS_MACOS_BUFFER (to));
g_assert (region != NULL);
g_assert (!cairo_region_is_empty (region));
from_base = _gdk_macos_buffer_get_data (from);
from_stride = _gdk_macos_buffer_get_stride (from);
to_base = _gdk_macos_buffer_get_data (to);
to_stride = _gdk_macos_buffer_get_stride (to);
n_rects = cairo_region_num_rectangles (region);
for (guint i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
int y2;
cairo_region_get_rectangle (region, i, &rect);
rect.y *= scale;
rect.height *= scale;
rect.x *= scale;
rect.width *= scale;
y2 = rect.y + rect.height;
for (int y = rect.y; y < y2; y++)
memcpy (&to_base[y * to_stride + rect.x * 4],
&from_base[y * from_stride + rect.x * 4],
rect.width * 4);
}
}
static void
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
gboolean prefers_high_depth,
@@ -165,34 +195,68 @@ _gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
GdkMacosBuffer *buffer;
GdkSurface *surface;
GdkMacosSurface *surface;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
[CATransaction begin];
[CATransaction setDisableActions:YES];
surface = gdk_draw_context_get_surface (draw_context);
buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (draw_context));
buffer = _gdk_macos_surface_get_buffer (surface);
_gdk_macos_buffer_set_damage (buffer, region);
_gdk_macos_buffer_set_flipped (buffer, FALSE);
_gdk_macos_buffer_lock (buffer);
/* If there is damage that was on the previous frame that is not on
* this frame, we need to copy that rendered region over to the back
* buffer so that when swapping buffers, we still have that content.
* This is done with a read-only lock on the IOSurface to avoid
* invalidating the buffer contents.
*/
if (surface->front != NULL)
{
const cairo_region_t *previous = _gdk_macos_buffer_get_damage (surface->front);
if (previous != NULL)
{
cairo_region_t *copy;
copy = cairo_region_copy (previous);
cairo_region_subtract (copy, region);
if (!cairo_region_is_empty (copy))
{
int scale = gdk_surface_get_scale_factor (GDK_SURFACE (surface));
_gdk_macos_buffer_read_lock (surface->front);
copy_surface_data (surface->front, buffer, copy, scale);
_gdk_macos_buffer_read_unlock (surface->front);
}
cairo_region_destroy (copy);
}
}
}
static void
_gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
GdkMacosSurface *surface;
GdkMacosBuffer *buffer;
GdkSurface *surface;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (draw_context));
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
surface = gdk_draw_context_get_surface (draw_context);
buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (draw_context));
buffer = _gdk_macos_surface_get_buffer (surface);
_gdk_macos_surface_swap_buffers (GDK_MACOS_SURFACE (surface), painted);
_gdk_macos_buffer_set_damage (buffer, NULL);
_gdk_macos_buffer_unlock (buffer);
_gdk_macos_surface_swap_buffers (surface, painted);
[CATransaction commit];
}
+105
View File
@@ -0,0 +1,105 @@
/*
* Copyright © 2022 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <AppKit/AppKit.h>
#include "gdkmacosdisplay-private.h"
#include "gdkmacossurface-private.h"
static void
gdk_macos_display_user_defaults_changed_cb (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
GdkMacosDisplay *self = observer;
g_assert (GDK_IS_MACOS_DISPLAY (self));
_gdk_macos_display_reload_settings (self);
}
static void
gdk_macos_display_monitors_changed_cb (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
GdkMacosDisplay *self = observer;
g_assert (GDK_IS_MACOS_DISPLAY (self));
_gdk_macos_display_reload_monitors (self);
/* Now we need to update all our surface positions since they
* probably just changed origins.
*/
for (const GList *iter = _gdk_macos_display_get_surfaces (self);
iter != NULL;
iter = iter->next)
{
GdkMacosSurface *surface = iter->data;
g_assert (GDK_IS_MACOS_SURFACE (surface));
_gdk_macos_surface_monitor_changed (surface);
}
}
void
_gdk_macos_display_feedback_init (GdkMacosDisplay *self)
{
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
CFNotificationCenterAddObserver (CFNotificationCenterGetLocalCenter (),
self,
gdk_macos_display_monitors_changed_cb,
CFSTR ("NSApplicationDidChangeScreenParametersNotification"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
self,
gdk_macos_display_user_defaults_changed_cb,
CFSTR ("NSUserDefaultsDidChangeNotification"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
}
void
_gdk_macos_display_feedback_destroy (GdkMacosDisplay *self)
{
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
self,
CFSTR ("NSApplicationDidChangeScreenParametersNotification"),
NULL);
CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
self,
CFSTR ("NSUserDefaultsDidChangeNotification"),
NULL);
}
+12 -15
View File
@@ -43,6 +43,8 @@ G_BEGIN_DECLS
#define GIC_FILTER_PASSTHRU 0
#define GIC_FILTER_FILTERED 1
#define GDK_MACOS_EVENT_DROP (GdkEvent *)GSIZE_TO_POINTER(1)
struct _GdkMacosDisplay
{
GdkDisplay parent_instance;
@@ -68,16 +70,6 @@ struct _GdkMacosDisplay
*/
GQueue sorted_surfaces;
/* Our CVDisplayLink based GSource which we use to freeze/thaw the
* GdkFrameClock for the surface.
*/
GSource *frame_source;
/* A queue of surfaces which we know are awaiting frames to be drawn. This
* uses the GdkMacosSurface.frame link.
*/
GQueue awaiting_frames;
/* The surface that is receiving keyboard events */
GdkMacosSurface *keyboard_surface;
@@ -92,6 +84,14 @@ struct _GdkMacosDisplay
int min_y;
int max_x;
int max_y;
/* A GSource to select a new main/key window */
guint select_key_in_idle;
/* Note if we have a key window that is not a GdkMacosWindow
* such as a NSPanel used for native dialogs.
*/
guint key_window_is_foregin : 1;
};
struct _GdkMacosDisplayClass
@@ -124,6 +124,8 @@ GdkMonitor *_gdk_macos_display_get_monitor_at_display_coords (GdkMacosDisp
int y);
GdkEvent *_gdk_macos_display_translate (GdkMacosDisplay *self,
NSEvent *event);
void _gdk_macos_display_feedback_init (GdkMacosDisplay *self);
void _gdk_macos_display_feedback_destroy (GdkMacosDisplay *self);
void _gdk_macos_display_break_all_grabs (GdkMacosDisplay *self,
guint32 time);
GdkModifierType _gdk_macos_display_get_current_keyboard_modifiers (GdkMacosDisplay *self);
@@ -136,10 +138,6 @@ GdkMacosSurface *_gdk_macos_display_get_surface_at_display_coords (GdkMacosDisp
void _gdk_macos_display_reload_monitors (GdkMacosDisplay *self);
void _gdk_macos_display_surface_removed (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_remove_frame_callback (GdkMacosDisplay *self,
GdkMacosSurface *surface);
NSWindow *_gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
int *x,
int *y);
@@ -155,7 +153,6 @@ void _gdk_macos_display_surface_resigned_key (GdkMacosDisp
GdkMacosSurface *surface);
void _gdk_macos_display_surface_became_key (GdkMacosDisplay *self,
GdkMacosSurface *surface);
int _gdk_macos_display_get_nominal_refresh_rate (GdkMacosDisplay *self);
void _gdk_macos_display_clear_sorting (GdkMacosDisplay *self);
const GList *_gdk_macos_display_get_surfaces (GdkMacosDisplay *self);
void _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
+5 -5
View File
@@ -34,7 +34,7 @@ typedef struct
const char *font_name;
int xft_dpi;
int double_click_time;
int cursor_blink_timeout;
int cursor_blink_time;
guint enable_animations : 1;
guint shell_shows_desktop : 1;
guint shell_shows_menubar : 1;
@@ -65,9 +65,9 @@ _gdk_macos_settings_load (GdkMacosSettings *settings)
ival = [defaults integerForKey:@"NSTextInsertionPointBlinkPeriod"];
if (ival > 0)
settings->cursor_blink_timeout = ival;
settings->cursor_blink_time = ival;
else
settings->cursor_blink_timeout = 1000;
settings->cursor_blink_time = 1000;
settings->primary_button_warps_slider =
[[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"] == YES;
@@ -124,9 +124,9 @@ _gdk_macos_display_get_setting (GdkMacosDisplay *self,
g_value_set_int (value, current_settings.xft_dpi);
ret = TRUE;
}
else if (strcmp (setting, "gtk-cursor-blink-timeout") == 0)
else if (strcmp (setting, "gtk-cursor-blink-time") == 0)
{
g_value_set_int (value, current_settings.cursor_blink_timeout);
g_value_set_int (value, current_settings.cursor_blink_time);
ret = TRUE;
}
else if (strcmp (setting, "gtk-double-click-time") == 0)
+80 -30
View File
@@ -612,6 +612,8 @@ fill_scroll_event (GdkMacosDisplay *self,
GdkModifierType state;
GdkDevice *pointer;
GdkEvent *ret = NULL;
NSEventPhase phase;
NSEventPhase momentumPhase;
GdkSeat *seat;
double dx;
double dy;
@@ -619,11 +621,31 @@ fill_scroll_event (GdkMacosDisplay *self,
g_assert (GDK_IS_MACOS_SURFACE (surface));
g_assert (nsevent != NULL);
phase = [nsevent phase];
momentumPhase = [nsevent momentumPhase];
/* Ignore kinetic scroll events from the display server as we already
* handle those internally.
*/
if (phase == 0 && momentumPhase != 0)
return GDK_MACOS_EVENT_DROP;
seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
pointer = gdk_seat_get_pointer (seat);
state = _gdk_macos_display_get_current_mouse_modifiers (self) |
_gdk_macos_display_get_current_keyboard_modifiers (self);
/* If we are starting a new phase, send a stop so any previous
* scrolling immediately stops.
*/
if (phase == NSEventPhaseMayBegin)
return gdk_scroll_event_new (GDK_SURFACE (surface),
pointer,
NULL,
get_time_from_ns_event (nsevent),
state,
0.0, 0.0, TRUE);
dx = [nsevent deltaX];
dy = [nsevent deltaY];
@@ -667,34 +689,32 @@ fill_scroll_event (GdkMacosDisplay *self,
dy = 0.0;
}
if (dx != 0.0 || dy != 0.0)
if ((dx != 0.0 || dy != 0.0) && ![nsevent hasPreciseScrollingDeltas])
{
if ([nsevent hasPreciseScrollingDeltas])
{
GdkEvent *emulated;
g_assert (ret == NULL);
emulated = gdk_scroll_event_new_discrete (GDK_SURFACE (surface),
pointer,
NULL,
get_time_from_ns_event (nsevent),
state,
direction,
TRUE);
_gdk_event_queue_append (GDK_DISPLAY (self), emulated);
}
else
{
g_assert (ret == NULL);
ret = gdk_scroll_event_new_discrete (GDK_SURFACE (surface),
pointer,
NULL,
get_time_from_ns_event (nsevent),
state,
direction,
FALSE);
}
ret = gdk_scroll_event_new (GDK_SURFACE (surface),
pointer,
NULL,
get_time_from_ns_event (nsevent),
state,
-dx * 32,
-dy * 32,
FALSE);
}
if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled)
{
/* The user must have released their fingers in a touchpad
* scroll, so try to send a scroll is_stop event.
*/
if (ret != NULL)
_gdk_event_queue_append (GDK_DISPLAY (self), g_steal_pointer (&ret));
ret = gdk_scroll_event_new (GDK_SURFACE (surface),
pointer,
NULL,
get_time_from_ns_event (nsevent),
state,
0.0, 0.0, TRUE);
}
return g_steal_pointer (&ret);
@@ -1066,6 +1086,7 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
GdkMacosSurface *surface;
GdkMacosWindow *window;
NSEventType event_type;
NSWindow *event_window;
GdkEvent *ret = NULL;
int x;
int y;
@@ -1108,6 +1129,15 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
return NULL;
}
/* If the event was delivered to NSWindow that is foreign (or rather,
* Cocoa native), then we should pass the event along to that window.
*/
if ((event_window = [nsevent window]) && !GDK_IS_MACOS_WINDOW (event_window))
return NULL;
/* If we can't find a GdkSurface to deliver the event to, then we
* should pass it along to the NSApp.
*/
if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
return NULL;
@@ -1139,15 +1169,31 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
if (test_resize (nsevent, surface, x, y))
return NULL;
if ((event_type == NSEventTypeRightMouseDown ||
event_type == NSEventTypeOtherMouseDown ||
event_type == NSEventTypeLeftMouseDown))
if (event_type == NSEventTypeRightMouseDown ||
event_type == NSEventTypeOtherMouseDown ||
event_type == NSEventTypeLeftMouseDown)
{
if (![NSApp isActive])
[NSApp activateIgnoringOtherApps:YES];
if (![window isKeyWindow])
[window makeKeyWindow];
{
NSWindow *orig_window = [nsevent window];
/* To get NSApp to supress activating the window we might
* have clicked through the shadow of, we need to dispatch
* the event and handle it in GdkMacosView:mouseDown to call
* [NSApp preventWindowOrdering]. Calling it here will not
* do anything as the event is not registered.
*/
if (orig_window &&
GDK_IS_MACOS_WINDOW (orig_window) &&
[(GdkMacosWindow *)orig_window needsMouseDownQuirk])
[NSApp sendEvent:nsevent];
[window showAndMakeKey:YES];
_gdk_macos_display_clear_sorting (self);
}
}
switch ((int)event_type)
@@ -1180,7 +1226,11 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
GdkDevice *pointer = gdk_seat_get_pointer (seat);
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
if (grab == NULL)
if ([(GdkMacosWindow *)window isInManualResizeOrMove])
{
ret = GDK_MACOS_EVENT_DROP;
}
else if (grab == NULL)
{
if (event_type == NSEventTypeMouseExited)
[[NSCursor arrowCursor] set];
+48 -34
View File
@@ -20,10 +20,13 @@
#include "config.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosmonitor.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacossurface-private.h"
#include "gdkmacostoplevelsurface-private.h"
#define WARP_OFFSET_X 15
#define WARP_OFFSET_Y 15
static void
_gdk_macos_display_position_toplevel_with_parent (GdkMacosDisplay *self,
GdkMacosSurface *surface,
@@ -33,52 +36,49 @@ _gdk_macos_display_position_toplevel_with_parent (GdkMacosDisplay *self,
{
GdkRectangle surface_rect;
GdkRectangle parent_rect;
GdkRectangle workarea;
GdkMonitor *monitor;
g_assert (GDK_IS_MACOS_DISPLAY (self));
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (surface));
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (parent));
/* If x/y is set, we should place relative to parent */
if (GDK_SURFACE (surface)->x != 0 || GDK_SURFACE (surface)->y != 0)
{
*x = parent->root_x + GDK_SURFACE (surface)->x;
*y = parent->root_y + GDK_SURFACE (surface)->y;
return;
}
monitor = _gdk_macos_surface_get_best_monitor (parent);
/* Try to center on top of the parent but also try to make the whole thing
* visible in case that lands us under the topbar/panel/etc.
*/
surface_rect.x = surface->root_x + surface->shadow_left;
surface_rect.y = surface->root_y + surface->shadow_top;
parent_rect.x = parent->root_x + parent->shadow_left;
parent_rect.y = parent->root_y + parent->shadow_top;
parent_rect.width = GDK_SURFACE (parent)->width - parent->shadow_left - parent->shadow_right;
parent_rect.height = GDK_SURFACE (parent)->height - parent->shadow_top - parent->shadow_bottom;
surface_rect.width = GDK_SURFACE (surface)->width - surface->shadow_left - surface->shadow_right;
surface_rect.height = GDK_SURFACE (surface)->height - surface->shadow_top - surface->shadow_bottom;
parent_rect.x = parent->root_x + surface->shadow_left;
parent_rect.y = parent->root_y + surface->shadow_top;
parent_rect.width = GDK_SURFACE (parent)->width - surface->shadow_left - surface->shadow_right;
parent_rect.height = GDK_SURFACE (parent)->height - surface->shadow_top - surface->shadow_bottom;
/* Try to place centered atop parent */
surface_rect.x = parent_rect.x + ((parent_rect.width - surface_rect.width) / 2);
surface_rect.y = parent_rect.y + ((parent_rect.height - surface_rect.height) / 2);
/* Now make sure that we don't overlap the top-bar */
monitor = _gdk_macos_surface_get_best_monitor (parent);
gdk_macos_monitor_get_workarea (monitor, &workarea);
if (surface_rect.x < workarea.x)
surface_rect.x = workarea.x;
if (surface_rect.y < workarea.y)
surface_rect.y = workarea.y;
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (monitor), &surface_rect);
*x = surface_rect.x - surface->shadow_left;
*y = surface_rect.y - surface->shadow_top;
}
static inline gboolean
has_surface_at_origin (const GList *surfaces,
int x,
int y)
{
for (const GList *iter = surfaces; iter; iter = iter->next)
{
GdkMacosSurface *surface = iter->data;
if (surface->root_x == x && surface->root_y == y)
return TRUE;
}
return FALSE;
}
static void
_gdk_macos_display_position_toplevel (GdkMacosDisplay *self,
GdkMacosSurface *surface,
@@ -87,6 +87,7 @@ _gdk_macos_display_position_toplevel (GdkMacosDisplay *self,
{
cairo_rectangle_int_t surface_rect;
GdkRectangle workarea;
const GList *surfaces;
GdkMonitor *monitor;
CGPoint mouse;
@@ -103,16 +104,29 @@ _gdk_macos_display_position_toplevel (GdkMacosDisplay *self,
surface_rect.x = workarea.x + ((workarea.width - surface_rect.width) / 2);
surface_rect.y = workarea.y + ((workarea.height - surface_rect.height) / 2);
if (surface_rect.x < workarea.x)
surface_rect.x = workarea.x;
if (surface_rect.y < workarea.y)
surface_rect.y = workarea.y;
/* TODO: If there is another window at this same position, perhaps we should move it */
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (surface->best_monitor), &surface_rect);
*x = surface_rect.x - surface->shadow_left;
*y = surface_rect.y - surface->shadow_top;
/* Try to see if there are any other surfaces at this origin and if so,
* adjust until we get something better.
*/
surfaces = _gdk_macos_display_get_surfaces (self);
while (has_surface_at_origin (surfaces, *x, *y))
{
*x += WARP_OFFSET_X;
*y += WARP_OFFSET_Y;
/* If we reached the bottom right, just bail and try the workspace origin */
if (*x + surface->shadow_left + WARP_OFFSET_X > workarea.x + workarea.width ||
*y + surface->shadow_top + WARP_OFFSET_Y > workarea.y + workarea.height)
{
*x = workarea.x - surface->shadow_left;
*y = workarea.y - surface->shadow_top;
return;
}
}
}
/*<private>
+57 -207
View File
@@ -156,51 +156,13 @@ gdk_macos_display_update_bounds (GdkMacosDisplay *self)
self->width = self->max_x - self->min_x;
self->height = self->max_y - self->min_y;
GDK_NOTE (MISC,
g_message ("Displays reconfigured to bounds %d,%d %dx%d",
self->min_x, self->min_y, self->width, self->height));
GDK_END_MACOS_ALLOC_POOL;
}
static void
gdk_macos_display_monitors_changed_cb (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
GdkMacosDisplay *self = observer;
g_assert (GDK_IS_MACOS_DISPLAY (self));
_gdk_macos_display_reload_monitors (self);
/* Now we need to update all our surface positions since they
* probably just changed origins.
*/
for (const GList *iter = _gdk_macos_display_get_surfaces (self);
iter != NULL;
iter = iter->next)
{
GdkMacosSurface *surface = iter->data;
g_assert (GDK_IS_MACOS_SURFACE (surface));
_gdk_macos_surface_monitor_changed (surface);
}
}
static void
gdk_macos_display_user_defaults_changed_cb (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
GdkMacosDisplay *self = observer;
g_assert (GDK_IS_MACOS_DISPLAY (self));
_gdk_macos_display_reload_settings (self);
}
void
_gdk_macos_display_reload_monitors (GdkMacosDisplay *self)
{
@@ -273,56 +235,6 @@ gdk_macos_display_load_seat (GdkMacosDisplay *self)
g_object_unref (seat);
}
static gboolean
gdk_macos_display_frame_cb (gpointer data)
{
GdkMacosDisplay *self = data;
GdkDisplayLinkSource *source;
gint64 presentation_time;
gint64 now;
GList *iter;
g_assert (GDK_IS_MACOS_DISPLAY (self));
source = (GdkDisplayLinkSource *)self->frame_source;
presentation_time = source->presentation_time;
now = g_source_get_time ((GSource *)source);
iter = self->awaiting_frames.head;
while (iter != NULL)
{
GdkMacosSurface *surface = iter->data;
g_assert (GDK_IS_MACOS_SURFACE (surface));
iter = iter->next;
_gdk_macos_surface_publish_timings (surface,
source->presentation_time,
source->refresh_interval);
_gdk_macos_display_remove_frame_callback (self, surface);
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
gdk_surface_thaw_updates (GDK_SURFACE (surface));
}
return G_SOURCE_CONTINUE;
}
static void
gdk_macos_display_load_display_link (GdkMacosDisplay *self)
{
self->frame_source = gdk_display_link_source_new ();
g_source_set_callback (self->frame_source,
gdk_macos_display_frame_cb,
self,
NULL);
g_source_attach (self->frame_source, NULL);
}
static const char *
gdk_macos_display_get_name (GdkDisplay *display)
{
@@ -398,11 +310,15 @@ gdk_macos_display_queue_events (GdkDisplay *display)
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
if ((nsevent = _gdk_macos_event_source_get_pending ()))
while ((nsevent = _gdk_macos_event_source_get_pending ()))
{
GdkEvent *event = _gdk_macos_display_translate (self, nsevent);
if (event != NULL)
if (event == GDK_MACOS_EVENT_DROP)
{
[nsevent release];
}
else if (event != NULL)
{
push_nsevent (event, nsevent);
_gdk_windowing_got_event (GDK_DISPLAY (self),
@@ -426,7 +342,6 @@ _gdk_macos_display_surface_added (GdkMacosDisplay *self,
g_assert (GDK_IS_MACOS_SURFACE (surface));
g_assert (!queue_contains (&self->sorted_surfaces, &surface->sorted));
g_assert (!queue_contains (&self->main_surfaces, &surface->main));
g_assert (!queue_contains (&self->awaiting_frames, &surface->frame));
g_assert (surface->sorted.data == surface);
g_assert (surface->main.data == surface);
g_assert (surface->frame.data == surface);
@@ -453,9 +368,6 @@ _gdk_macos_display_surface_removed (GdkMacosDisplay *self,
if (queue_contains (&self->main_surfaces, &surface->main))
_gdk_macos_display_surface_resigned_main (self, surface);
if (queue_contains (&self->awaiting_frames, &surface->frame))
g_queue_unlink (&self->awaiting_frames, &surface->frame);
g_return_if_fail (self->keyboard_surface != surface);
}
@@ -501,6 +413,39 @@ _gdk_macos_display_surface_became_key (GdkMacosDisplay *self,
gdk_surface_request_motion (GDK_SURFACE (surface));
}
static gboolean
select_key_in_idle_cb (gpointer data)
{
GdkMacosDisplay *self = data;
g_assert (GDK_IS_MACOS_DISPLAY (self));
self->select_key_in_idle = 0;
/* Don't steal focus from NSPanel, etc */
if (self->key_window_is_foregin)
return G_SOURCE_REMOVE;
if (self->keyboard_surface == NULL)
{
const GList *surfaces = _gdk_macos_display_get_surfaces (self);
for (const GList *iter = surfaces; iter; iter = iter->next)
{
GdkMacosSurface *surface = iter->data;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)) &&
([surface->window styleMask] & NSWindowStyleMaskMiniaturizable) == 0)
{
[surface->window showAndMakeKey:YES];
break;
}
}
}
return G_SOURCE_REMOVE;
}
void
_gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
GdkMacosSurface *surface)
@@ -545,6 +490,9 @@ _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
}
_gdk_macos_display_clear_sorting (self);
if (self->select_key_in_idle == 0)
self->select_key_in_idle = g_idle_add (select_key_in_idle_cb, self);
}
/* Raises a transient window.
@@ -583,8 +531,6 @@ void
_gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self,
GdkMacosSurface *surface)
{
GdkMacosSurface *new_surface = NULL;
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
@@ -592,40 +538,6 @@ _gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self,
g_queue_unlink (&self->main_surfaces, &surface->main);
_gdk_macos_display_clear_sorting (self);
if (GDK_SURFACE (surface)->transient_for &&
gdk_surface_get_mapped (GDK_SURFACE (surface)->transient_for))
{
new_surface = GDK_MACOS_SURFACE (GDK_SURFACE (surface)->transient_for);
}
else
{
const GList *surfaces = _gdk_macos_display_get_surfaces (self);
for (const GList *iter = surfaces; iter; iter = iter->next)
{
GdkMacosSurface *item = iter->data;
g_assert (GDK_IS_MACOS_SURFACE (item));
if (item == surface)
continue;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (item)))
{
new_surface = item;
break;
}
}
}
if (new_surface != NULL)
{
NSWindow *nswindow = _gdk_macos_surface_get_native (new_surface);
[nswindow makeKeyAndOrderFront:nswindow];
}
_gdk_macos_display_clear_sorting (self);
}
static GdkSurface *
@@ -686,20 +598,12 @@ gdk_macos_display_finalize (GObject *object)
{
GdkMacosDisplay *self = (GdkMacosDisplay *)object;
CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
self,
CFSTR ("NSApplicationDidChangeScreenParametersNotification"),
NULL);
CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
self,
CFSTR ("NSUserDefaultsDidChangeNotification"),
NULL);
_gdk_macos_display_feedback_destroy (self);
g_clear_handle_id (&self->select_key_in_idle, g_source_remove);
g_clear_pointer (&self->active_drags, g_hash_table_unref);
g_clear_pointer (&self->active_drops, g_hash_table_unref);
g_clear_object (&GDK_DISPLAY (self)->clipboard);
g_clear_pointer (&self->frame_source, g_source_unref);
g_clear_object (&self->monitors);
g_clear_pointer (&self->name, g_free);
@@ -774,24 +678,10 @@ _gdk_macos_display_open (const char *display_name)
gdk_macos_display_load_seat (self);
gdk_macos_display_load_clipboard (self);
/* Load CVDisplayLink before monitors to access refresh rates */
gdk_macos_display_load_display_link (self);
_gdk_macos_display_reload_monitors (self);
CFNotificationCenterAddObserver (CFNotificationCenterGetLocalCenter (),
self,
gdk_macos_display_monitors_changed_cb,
CFSTR ("NSApplicationDidChangeScreenParametersNotification"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
self,
gdk_macos_display_user_defaults_changed_cb,
CFSTR ("NSUserDefaultsDidChangeNotification"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
/* Initialize feedback from display server */
_gdk_macos_display_feedback_init (self);
if (event_source == NULL)
{
@@ -803,6 +693,8 @@ _gdk_macos_display_open (const char *display_name)
gdk_display_emit_opened (GDK_DISPLAY (self));
[NSApp activateIgnoringOtherApps:YES];
return GDK_DISPLAY (self);
}
@@ -1033,42 +925,6 @@ _gdk_macos_display_get_surface_at_display_coords (GdkMacosDisplay *self,
return _gdk_macos_display_get_surface_at_coords (self, x_gdk, y_gdk, surface_x, surface_y);
}
void
_gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
GdkMacosSurface *surface)
{
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
if (!queue_contains (&self->awaiting_frames, &surface->frame))
{
/* Processing frames is always head to tail, so push to the
* head so that we don't possibly re-enter this right after
* adding to the queue.
*/
g_queue_push_head_link (&self->awaiting_frames, &surface->frame);
if (self->awaiting_frames.length == 1)
gdk_display_link_source_unpause ((GdkDisplayLinkSource *)self->frame_source);
}
}
void
_gdk_macos_display_remove_frame_callback (GdkMacosDisplay *self,
GdkMacosSurface *surface)
{
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
if (queue_contains (&self->awaiting_frames, &surface->frame))
{
g_queue_unlink (&self->awaiting_frames, &surface->frame);
if (self->awaiting_frames.length == 0)
gdk_display_link_source_pause ((GdkDisplayLinkSource *)self->frame_source);
}
}
NSWindow *
_gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
int *x,
@@ -1088,17 +944,6 @@ _gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
return NULL;
}
int
_gdk_macos_display_get_nominal_refresh_rate (GdkMacosDisplay *self)
{
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), 60 * 1000);
if (self->frame_source == NULL)
return 60 * 1000;
return ((GdkDisplayLinkSource *)self->frame_source)->refresh_rate;
}
void
_gdk_macos_display_clear_sorting (GdkMacosDisplay *self)
{
@@ -1120,11 +965,16 @@ _gdk_macos_display_get_surfaces (GdkMacosDisplay *self)
NSArray *array = [NSApp orderedWindows];
GQueue sorted = G_QUEUE_INIT;
self->key_window_is_foregin = FALSE;
for (id obj in array)
{
NSWindow *nswindow = (NSWindow *)obj;
GdkMacosSurface *surface;
if ([nswindow isKeyWindow])
self->key_window_is_foregin = !GDK_IS_MACOS_WINDOW (nswindow);
if (!GDK_IS_MACOS_WINDOW (nswindow))
continue;
-2
View File
@@ -38,8 +38,6 @@ struct _GdkMacosGLContext
{
GdkGLContext parent_instance;
cairo_region_t *damage;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
CGLContextObj cgl_context;
G_GNUC_END_IGNORE_DEPRECATIONS
+10 -9
View File
@@ -469,6 +469,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
_gdk_macos_buffer_set_flipped (buffer, TRUE);
_gdk_macos_buffer_set_damage (buffer, region);
/* Create our render target and bind it */
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
@@ -476,9 +477,6 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, prefers_high_depth, region);
g_clear_pointer (&self->damage, cairo_region_destroy);
self->damage = g_steal_pointer (&copy);
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
CHECK_GL (NULL, glBindFramebuffer (GL_FRAMEBUFFER, self->fbo));
}
@@ -531,8 +529,6 @@ gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
g_clear_pointer (&self->damage, cairo_region_destroy);
if (self->cgl_context != NULL)
CGLUpdateContext (self->cgl_context);
}
@@ -587,9 +583,16 @@ static cairo_region_t *
gdk_macos_gl_context_get_damage (GdkGLContext *context)
{
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
const cairo_region_t *damage;
GdkMacosBuffer *buffer;
GdkSurface *surface;
if (self->damage)
return cairo_region_copy (self->damage);
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
if ((surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context))) &&
(buffer = GDK_MACOS_SURFACE (surface)->front) &&
(damage = _gdk_macos_buffer_get_damage (buffer)))
return cairo_region_copy (damage);
return GDK_GL_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->get_damage (context);
}
@@ -619,8 +622,6 @@ gdk_macos_gl_context_dispose (GObject *gobject)
CGLDestroyContext (cgl_context);
}
g_clear_pointer (&self->damage, cairo_region_destroy);
G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
}
+14 -5
View File
@@ -24,16 +24,25 @@
#include "gdkmacosdisplay.h"
#include "gdkmacosmonitor.h"
#include "gdkmacossurface.h"
#include "gdkmonitorprivate.h"
G_BEGIN_DECLS
GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay *display,
CGDirectDisplayID screen_id);
CGDirectDisplayID _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self);
gboolean _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self);
CGColorSpaceRef _gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self);
char *_gdk_macos_monitor_get_localized_name (NSScreen *screen);
char *_gdk_macos_monitor_get_connector_name (CGDirectDisplayID screen_id);
GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay *display,
CGDirectDisplayID screen_id);
CGDirectDisplayID _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self);
gboolean _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self);
CGColorSpaceRef _gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self);
void _gdk_macos_monitor_add_frame_callback (GdkMacosMonitor *self,
GdkMacosSurface *surface);
void _gdk_macos_monitor_remove_frame_callback (GdkMacosMonitor *self,
GdkMacosSurface *surface);
void _gdk_macos_monitor_clamp (GdkMacosMonitor *self,
GdkRectangle *area);
G_END_DECLS
+166 -11
View File
@@ -22,16 +22,21 @@
#include <gdk/gdk.h>
#include <math.h>
#include "gdkdisplaylinksource.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacossurface-private.h"
#include "gdkmacosutils-private.h"
struct _GdkMacosMonitor
{
GdkMonitor parent_instance;
CGDirectDisplayID screen_id;
NSRect workarea;
guint has_opengl : 1;
GdkMonitor parent_instance;
CGDirectDisplayID screen_id;
GdkDisplayLinkSource *display_link;
NSRect workarea;
GQueue awaiting_frames;
guint has_opengl : 1;
guint in_frame : 1;
};
struct _GdkMacosMonitorClass
@@ -75,9 +80,26 @@ gdk_macos_monitor_get_workarea (GdkMonitor *monitor,
geometry->height = self->workarea.size.height;
}
static void
gdk_macos_monitor_dispose (GObject *object)
{
GdkMacosMonitor *self = (GdkMacosMonitor *)object;
if (self->display_link)
{
g_source_destroy ((GSource *)self->display_link);
g_clear_pointer ((GSource **)&self->display_link, g_source_unref);
}
G_OBJECT_CLASS (gdk_macos_monitor_parent_class)->dispose (object);
}
static void
gdk_macos_monitor_class_init (GdkMacosMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gdk_macos_monitor_dispose;
}
static void
@@ -138,8 +160,8 @@ GetSubpixelLayout (CGDirectDisplayID screen_id)
return GDK_SUBPIXEL_LAYOUT_UNKNOWN;
}
static char *
GetLocalizedName (NSScreen *screen)
char *
_gdk_macos_monitor_get_localized_name (NSScreen *screen)
{
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_15_AND_LATER
GDK_BEGIN_MACOS_ALLOC_POOL;
@@ -160,8 +182,8 @@ GetLocalizedName (NSScreen *screen)
#endif
}
static char *
GetConnectorName (CGDirectDisplayID screen_id)
char *
_gdk_macos_monitor_get_connector_name (CGDirectDisplayID screen_id)
{
guint unit = CGDisplayUnitNumber (screen_id);
return g_strdup_printf ("unit-%u", unit);
@@ -188,6 +210,68 @@ find_screen (CGDirectDisplayID screen_id)
return screen;
}
static gboolean
gdk_macos_monitor_display_link_cb (GdkMacosMonitor *self)
{
gint64 presentation_time;
gint64 refresh_interval;
gint64 now;
GList *iter;
g_assert (GDK_IS_MACOS_MONITOR (self));
g_assert (!self->display_link->paused);
self->in_frame = TRUE;
presentation_time = self->display_link->presentation_time;
refresh_interval = self->display_link->refresh_interval;
now = g_source_get_time ((GSource *)self->display_link);
iter = self->awaiting_frames.head;
while (iter != NULL)
{
GdkMacosSurface *surface = iter->data;
g_assert (GDK_IS_MACOS_SURFACE (surface));
iter = iter->next;
g_queue_unlink (&self->awaiting_frames, &surface->frame);
_gdk_macos_surface_frame_presented (surface, presentation_time, refresh_interval);
}
if (self->awaiting_frames.length == 0 && !self->display_link->paused)
gdk_display_link_source_pause (self->display_link);
self->in_frame = FALSE;
return G_SOURCE_CONTINUE;
}
static void
_gdk_macos_monitor_reset_display_link (GdkMacosMonitor *self,
CGDisplayModeRef mode)
{
GSource *source;
g_assert (GDK_IS_MACOS_MONITOR (self));
if (self->display_link)
{
g_source_destroy ((GSource *)self->display_link);
g_clear_pointer ((GSource **)&self->display_link, g_source_unref);
}
source = gdk_display_link_source_new (self->screen_id, mode);
self->display_link = (GdkDisplayLinkSource *)source;
g_source_set_callback (source,
(GSourceFunc) gdk_macos_monitor_display_link_cb,
self,
NULL);
g_source_attach (source, NULL);
}
gboolean
_gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
{
@@ -222,8 +306,8 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
pixel_width = CGDisplayModeGetPixelWidth (mode);
has_opengl = CGDisplayUsesOpenGLAcceleration (self->screen_id);
subpixel_layout = GetSubpixelLayout (self->screen_id);
name = GetLocalizedName (screen);
connector = GetConnectorName (self->screen_id);
name = _gdk_macos_monitor_get_localized_name (screen);
connector = _gdk_macos_monitor_get_connector_name (self->screen_id);
if (width != 0 && pixel_width != 0)
scale_factor = MAX (1, pixel_width / width);
@@ -241,7 +325,7 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
* setting (which is also used by the frame clock).
*/
if (!(refresh_rate = CGDisplayModeGetRefreshRate (mode)))
refresh_rate = _gdk_macos_display_get_nominal_refresh_rate (display);
refresh_rate = 60 * 1000;
gdk_monitor_set_connector (GDK_MONITOR (self), connector);
gdk_monitor_set_model (GDK_MONITOR (self), name);
@@ -261,6 +345,9 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
*/
self->has_opengl = !!has_opengl;
/* Create a new display link to receive feedback about when to render */
_gdk_macos_monitor_reset_display_link (self, mode);
CGDisplayModeRelease (mode);
g_free (name);
g_free (connector);
@@ -302,3 +389,71 @@ _gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self)
return CGDisplayCopyColorSpace (self->screen_id);
}
void
_gdk_macos_monitor_add_frame_callback (GdkMacosMonitor *self,
GdkMacosSurface *surface)
{
g_return_if_fail (GDK_IS_MACOS_MONITOR (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
g_return_if_fail (surface->frame.data == (gpointer)surface);
g_return_if_fail (surface->frame.prev == NULL);
g_return_if_fail (surface->frame.next == NULL);
g_return_if_fail (self->awaiting_frames.head != &surface->frame);
g_return_if_fail (self->awaiting_frames.tail != &surface->frame);
/* Processing frames is always head to tail, so push to the
* head so that we don't possibly re-enter this right after
* adding to the queue.
*/
if (!queue_contains (&self->awaiting_frames, &surface->frame))
{
g_queue_push_head_link (&self->awaiting_frames, &surface->frame);
if (!self->in_frame && self->awaiting_frames.length == 1)
gdk_display_link_source_unpause (self->display_link);
}
}
void
_gdk_macos_monitor_remove_frame_callback (GdkMacosMonitor *self,
GdkMacosSurface *surface)
{
g_return_if_fail (GDK_IS_MACOS_MONITOR (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
g_return_if_fail (surface->frame.data == (gpointer)surface);
if (queue_contains (&self->awaiting_frames, &surface->frame))
{
g_queue_unlink (&self->awaiting_frames, &surface->frame);
if (!self->in_frame && self->awaiting_frames.length == 0)
gdk_display_link_source_pause (self->display_link);
}
}
void
_gdk_macos_monitor_clamp (GdkMacosMonitor *self,
GdkRectangle *area)
{
GdkRectangle workarea;
GdkRectangle geom;
g_return_if_fail (GDK_IS_MACOS_MONITOR (self));
g_return_if_fail (area != NULL);
gdk_macos_monitor_get_workarea (GDK_MONITOR (self), &workarea);
gdk_monitor_get_geometry (GDK_MONITOR (self), &geom);
if (area->x + area->width > workarea.x + workarea.width)
area->x = workarea.x + workarea.width - area->width;
if (area->x < workarea.x)
area->x = workarea.x;
if (area->y + area->height > workarea.y + workarea.height)
area->y = workarea.y + workarea.height - area->height;
if (area->y < workarea.y)
area->y = workarea.y;
}
+30 -11
View File
@@ -34,6 +34,7 @@ struct _GdkMacosPopupSurface
{
GdkMacosSurface parent_instance;
GdkPopupLayout *layout;
guint attached : 1;
};
struct _GdkMacosPopupSurfaceClass
@@ -87,6 +88,9 @@ gdk_macos_popup_surface_layout (GdkMacosPopupSurface *self,
gdk_surface_get_origin (GDK_SURFACE (self)->parent, &x, &y);
GDK_SURFACE (self)->x = final_rect.x;
GDK_SURFACE (self)->y = final_rect.y;
x += final_rect.x;
y += final_rect.y;
@@ -135,6 +139,9 @@ gdk_macos_popup_surface_present (GdkPopup *popup,
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
return TRUE;
if (!self->attached && GDK_SURFACE (self)->parent != NULL)
_gdk_macos_popup_surface_attach_to_parent (self);
if (GDK_SURFACE (self)->autohide)
{
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (popup));
@@ -200,6 +207,19 @@ enum {
LAST_PROP,
};
static void
_gdk_macos_popup_surface_hide (GdkSurface *surface)
{
GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)surface;
g_assert (GDK_IS_MACOS_POPUP_SURFACE (self));
if (self->attached)
_gdk_macos_popup_surface_detach_from_parent (self);
GDK_SURFACE_CLASS (_gdk_macos_popup_surface_parent_class)->hide (surface);
}
static void
_gdk_macos_popup_surface_finalize (GObject *object)
{
@@ -267,12 +287,15 @@ static void
_gdk_macos_popup_surface_class_init (GdkMacosPopupSurfaceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkSurfaceClass *surface_class = GDK_SURFACE_CLASS (klass);
object_class->finalize = _gdk_macos_popup_surface_finalize;
object_class->get_property = _gdk_macos_popup_surface_get_property;
object_class->set_property = _gdk_macos_popup_surface_set_property;
gdk_popup_install_properties (object_class, 1);
surface_class->hide = _gdk_macos_popup_surface_hide;
gdk_popup_install_properties (object_class, LAST_PROP);
}
static void
@@ -323,14 +346,8 @@ _gdk_macos_popup_surface_new (GdkMacosDisplay *display,
[window setOpaque:NO];
[window setBackgroundColor:[NSColor clearColor]];
[window setDecorated:NO];
#if 0
/* NOTE: We could set these to be popup level, but then
* [NSApp orderedWindows] would not give us the windows
* back with the stacking order applied.
*/
[window setExcludedFromWindowsMenu:YES];
[window setLevel:NSPopUpMenuWindowLevel];
#endif
self = g_object_new (GDK_TYPE_MACOS_POPUP_SURFACE,
"display", display,
@@ -361,6 +378,8 @@ _gdk_macos_popup_surface_attach_to_parent (GdkMacosPopupSurface *self)
[parent addChildWindow:window ordered:NSWindowAbove];
self->attached = TRUE;
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
}
}
@@ -382,6 +401,8 @@ _gdk_macos_popup_surface_detach_from_parent (GdkMacosPopupSurface *self)
[parent removeChildWindow:window];
self->attached = FALSE;
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
}
}
@@ -391,9 +412,7 @@ _gdk_macos_popup_surface_reposition (GdkMacosPopupSurface *self)
{
g_return_if_fail (GDK_IS_MACOS_POPUP_SURFACE (self));
if (self->layout == NULL ||
!gdk_surface_get_mapped (GDK_SURFACE (self)) ||
GDK_SURFACE (self)->parent == NULL)
if (self->layout == NULL || GDK_SURFACE (self)->parent == NULL)
return;
gdk_macos_popup_surface_layout (self,
+7 -4
View File
@@ -49,7 +49,7 @@ struct _GdkMacosSurface
GdkMacosBuffer *buffer;
GdkMacosBuffer *front;
GPtrArray *monitors;
cairo_region_t *opaque_region;
GdkMonitor *best_monitor;
char *title;
int root_x;
@@ -75,6 +75,9 @@ struct _GdkMacosSurface
guint geometry_dirty : 1;
guint next_frame_set : 1;
guint show_on_next_swap : 1;
guint in_change_monitor : 1;
guint in_frame : 1;
guint awaiting_frame : 1;
};
struct _GdkMacosSurfaceClass
@@ -116,11 +119,11 @@ void _gdk_macos_surface_resize (GdkMacosSurface
int width,
int height);
void _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self);
void _gdk_macos_surface_update_position (GdkMacosSurface *self);
void _gdk_macos_surface_show (GdkMacosSurface *self);
void _gdk_macos_surface_publish_timings (GdkMacosSurface *self,
void _gdk_macos_surface_request_frame (GdkMacosSurface *self);
void _gdk_macos_surface_frame_presented (GdkMacosSurface *self,
gint64 predicted_presentation_time,
gint64 refresh_interval);
void _gdk_macos_surface_show (GdkMacosSurface *self);
void _gdk_macos_surface_synthesize_null_key (GdkMacosSurface *self);
void _gdk_macos_surface_move (GdkMacosSurface *self,
int x,
+224 -123
View File
@@ -27,6 +27,7 @@
#include "gdkmacossurface-private.h"
#include "gdkdebug.h"
#include "gdkdeviceprivate.h"
#include "gdkdisplay.h"
#include "gdkeventsprivate.h"
@@ -63,16 +64,87 @@ window_is_fullscreen (GdkMacosSurface *self)
return ([self->window styleMask] & NSWindowStyleMaskFullScreen) != 0;
}
void
_gdk_macos_surface_request_frame (GdkMacosSurface *self)
{
g_assert (GDK_IS_MACOS_SURFACE (self));
if (self->awaiting_frame)
return;
if (self->best_monitor != NULL)
{
self->awaiting_frame = TRUE;
_gdk_macos_monitor_add_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
gdk_surface_freeze_updates (GDK_SURFACE (self));
}
}
static void
_gdk_macos_surface_cancel_frame (GdkMacosSurface *self)
{
g_assert (GDK_IS_MACOS_SURFACE (self));
if (!self->awaiting_frame)
return;
if (self->best_monitor != NULL)
{
self->awaiting_frame = FALSE;
_gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
gdk_surface_thaw_updates (GDK_SURFACE (self));
}
}
void
_gdk_macos_surface_frame_presented (GdkMacosSurface *self,
gint64 presentation_time,
gint64 refresh_interval)
{
GdkFrameTimings *timings;
GdkFrameClock *frame_clock;
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
self->awaiting_frame = FALSE;
if (GDK_SURFACE_DESTROYED (self))
return;
frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
if (self->pending_frame_counter)
{
timings = gdk_frame_clock_get_timings (frame_clock, self->pending_frame_counter);
if (timings != NULL)
{
timings->presentation_time = presentation_time - refresh_interval;
timings->complete = TRUE;
}
self->pending_frame_counter = 0;
}
timings = gdk_frame_clock_get_current_timings (frame_clock);
if (timings != NULL)
{
timings->refresh_interval = refresh_interval;
timings->predicted_presentation_time = presentation_time;
}
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
gdk_surface_thaw_updates (GDK_SURFACE (self));
}
void
_gdk_macos_surface_reposition_children (GdkMacosSurface *self)
{
g_assert (GDK_IS_MACOS_SURFACE (self));
if (GDK_SURFACE_DESTROYED (self))
return;
if (!gdk_surface_get_mapped (GDK_SURFACE (self)))
if (GDK_SURFACE_DESTROYED (self))
return;
for (const GList *iter = GDK_SURFACE (self)->children;
@@ -86,9 +158,6 @@ _gdk_macos_surface_reposition_children (GdkMacosSurface *self)
if (GDK_IS_MACOS_POPUP_SURFACE (child))
_gdk_macos_popup_surface_reposition (GDK_MACOS_POPUP_SURFACE (child));
}
if (GDK_IS_POPUP (self) && self->did_initial_present)
gdk_surface_request_layout (GDK_SURFACE (self));
}
static void
@@ -117,12 +186,6 @@ gdk_macos_surface_set_opaque_region (GdkSurface *surface,
g_assert (GDK_IS_MACOS_SURFACE (self));
if (region != self->opaque_region)
{
g_clear_pointer (&self->opaque_region, cairo_region_destroy);
self->opaque_region = cairo_region_copy (region);
}
if ((nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface))))
[(GdkMacosView *)nsview setOpaqueRegion:region];
}
@@ -139,9 +202,9 @@ gdk_macos_surface_hide (GdkSurface *surface)
self->show_on_next_swap = FALSE;
_gdk_macos_display_remove_frame_callback (GDK_MACOS_DISPLAY (surface->display), self);
_gdk_macos_surface_cancel_frame (self);
was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
was_key = [self->window isKeyWindow];
seat = gdk_display_get_default_seat (surface->display);
@@ -156,17 +219,21 @@ gdk_macos_surface_hide (GdkSurface *surface)
if (was_key)
{
GdkSurface *parent;
if (GDK_IS_TOPLEVEL (surface))
parent = surface->transient_for;
else
parent = surface->parent;
/* Return key input to the parent window if necessary */
if (surface->parent != NULL && GDK_SURFACE_IS_MAPPED (surface->parent))
if (parent != NULL && GDK_SURFACE_IS_MAPPED (parent))
{
GdkMacosWindow *parentWindow = GDK_MACOS_SURFACE (surface->parent)->window;
GdkMacosWindow *parentWindow = GDK_MACOS_SURFACE (parent)->window;
[parentWindow showAndMakeKey:YES];
}
}
if (was_mapped)
gdk_surface_freeze_updates (GDK_SURFACE (self));
}
static int
@@ -210,6 +277,7 @@ gdk_macos_surface_begin_frame (GdkMacosSurface *self)
{
g_assert (GDK_IS_MACOS_SURFACE (self));
self->in_frame = TRUE;
}
static void
@@ -230,11 +298,9 @@ gdk_macos_surface_end_frame (GdkMacosSurface *self)
if ((timings = gdk_frame_clock_get_current_timings (frame_clock)))
self->pending_frame_counter = timings->frame_counter;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
{
_gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
gdk_surface_freeze_updates (GDK_SURFACE (self));
}
self->in_frame = FALSE;
_gdk_macos_surface_request_frame (self);
}
static void
@@ -408,6 +474,9 @@ gdk_macos_surface_destroy (GdkSurface *surface,
GdkMacosWindow *window = g_steal_pointer (&self->window);
GdkFrameClock *frame_clock;
_gdk_macos_surface_cancel_frame (self);
g_clear_object (&self->best_monitor);
if ((frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
{
g_signal_handlers_disconnect_by_func (frame_clock,
@@ -419,7 +488,6 @@ gdk_macos_surface_destroy (GdkSurface *surface,
}
g_clear_pointer (&self->title, g_free);
g_clear_pointer (&self->opaque_region, cairo_region_destroy);
if (window != NULL)
[window close];
@@ -561,7 +629,7 @@ _gdk_macos_surface_new (GdkMacosDisplay *display,
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
if (parent != NULL)
frame_clock = g_object_ref (gdk_surface_get_frame_clock (parent));
frame_clock = g_object_ref (parent->frame_clock);
else
frame_clock = _gdk_frame_clock_idle_new ();
@@ -621,14 +689,16 @@ _gdk_macos_surface_get_shadow (GdkMacosSurface *self,
gboolean
_gdk_macos_surface_is_opaque (GdkMacosSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), FALSE);
if (self->opaque_region != NULL &&
cairo_region_num_rectangles (self->opaque_region) == 1)
if (surface->opaque_region != NULL &&
cairo_region_num_rectangles (surface->opaque_region) == 1)
{
cairo_rectangle_int_t extents;
cairo_region_get_extents (self->opaque_region, &extents);
cairo_region_get_extents (surface->opaque_region, &extents);
return (extents.x == 0 &&
extents.y == 0 &&
@@ -748,8 +818,9 @@ _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self)
void
_gdk_macos_surface_configure (GdkMacosSurface *self)
{
GdkMacosDisplay *display;
GdkSurface *surface = (GdkSurface *)self;
GdkMacosDisplay *display;
GdkMacosSurface *parent;
NSRect frame_rect;
NSRect content_rect;
@@ -758,6 +829,13 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
if (GDK_SURFACE_DESTROYED (self))
return;
if (surface->parent != NULL)
parent = GDK_MACOS_SURFACE (surface->parent);
else if (surface->transient_for != NULL)
parent = GDK_MACOS_SURFACE (surface->transient_for);
else
parent = NULL;
display = GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display);
frame_rect = [self->window frame];
content_rect = [self->window contentRectForFrameRect:frame_rect];
@@ -767,18 +845,15 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
content_rect.origin.y + content_rect.size.height,
&self->root_x, &self->root_y);
if (self->did_initial_present)
if (parent != NULL)
{
if (surface->parent != NULL)
{
surface->x = self->root_x - GDK_MACOS_SURFACE (surface->parent)->root_x;
surface->y = self->root_y - GDK_MACOS_SURFACE (surface->parent)->root_y;
}
else
{
surface->x = self->root_x;
surface->y = self->root_y;
}
surface->x = self->root_x - parent->root_x;
surface->y = self->root_y - parent->root_y;
}
else
{
surface->x = self->root_x;
surface->y = self->root_y;
}
if (surface->width != content_rect.size.width ||
@@ -791,48 +866,12 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
g_clear_object (&self->front);
_gdk_surface_update_size (surface);
gdk_surface_request_layout (surface);
gdk_surface_invalidate_rect (surface, NULL);
}
_gdk_macos_surface_reposition_children (self);
}
void
_gdk_macos_surface_publish_timings (GdkMacosSurface *self,
gint64 presentation_time,
gint64 refresh_interval)
{
GdkFrameTimings *timings;
GdkFrameClock *frame_clock;
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
if (!(frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
return;
if (self->pending_frame_counter)
{
timings = gdk_frame_clock_get_timings (frame_clock, self->pending_frame_counter);
if (timings != NULL)
{
timings->presentation_time = presentation_time - refresh_interval;
timings->complete = TRUE;
}
self->pending_frame_counter = 0;
}
timings = gdk_frame_clock_get_current_timings (frame_clock);
if (timings != NULL)
{
timings->refresh_interval = refresh_interval;
timings->predicted_presentation_time = presentation_time;
}
}
void
_gdk_macos_surface_show (GdkMacosSurface *self)
{
@@ -843,22 +882,17 @@ _gdk_macos_surface_show (GdkMacosSurface *self)
if (GDK_SURFACE_DESTROYED (self))
return;
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display));
self->show_on_next_swap = TRUE;
was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
if (!was_mapped)
gdk_surface_set_is_mapped (GDK_SURFACE (self), TRUE);
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display));
self->show_on_next_swap = TRUE;
if (!was_mapped)
{
if (gdk_surface_get_mapped (GDK_SURFACE (self)))
{
_gdk_macos_surface_configure (self);
gdk_surface_thaw_updates (GDK_SURFACE (self));
}
gdk_surface_set_is_mapped (GDK_SURFACE (self), TRUE);
gdk_surface_request_layout (GDK_SURFACE (self));
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
gdk_surface_thaw_updates (GDK_SURFACE (self));
}
}
@@ -911,36 +945,59 @@ _gdk_macos_surface_move_resize (GdkMacosSurface *self,
GdkDisplay *display;
NSRect content_rect;
NSRect frame_rect;
gboolean ignore_move;
gboolean ignore_size;
GdkRectangle current;
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
if ((x == -1 || (x == self->root_x)) &&
(y == -1 || (y == self->root_y)) &&
(width == -1 || (width == surface->width)) &&
(height == -1 || (height == surface->height)))
/* Query for up-to-date values in case we're racing against
* an incoming frame notify which could be queued behind whatever
* we're processing right now.
*/
frame_rect = [self->window frame];
content_rect = [self->window contentRectForFrameRect:frame_rect];
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display),
content_rect.origin.x, content_rect.origin.y,
&current.x, &current.y);
current.width = content_rect.size.width;
current.height = content_rect.size.height;
/* Check if we can ignore the operation all together */
ignore_move = (x == -1 || (x == current.x)) &&
(y == -1 || (y == current.y));
ignore_size = (width == -1 || (width == current.width)) &&
(height == -1 || (height == current.height));
if (ignore_move && ignore_size)
return;
display = gdk_surface_get_display (surface);
if (width == -1)
width = surface->width;
width = current.width;
if (height == -1)
height = surface->height;
height = current.height;
if (x == -1)
x = self->root_x;
x = current.x;
if (y == -1)
y = self->root_y;
y = current.y;
_gdk_macos_display_to_display_coords (GDK_MACOS_DISPLAY (display),
x, y + height,
&x, &y);
content_rect = NSMakeRect (x, y, width, height);
if (!ignore_move)
content_rect.origin = NSMakePoint (x, y);
if (!ignore_size)
content_rect.size = NSMakeSize (width, height);
frame_rect = [self->window frameRectForContentRect:content_rect];
[self->window setFrame:frame_rect display:YES];
[self->window setFrame:frame_rect display:NO];
}
void
@@ -995,14 +1052,24 @@ void
_gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
{
GListModel *monitors;
GdkMonitor *best = NULL;
GdkRectangle rect;
GdkRectangle intersect;
GdkDisplay *display;
GdkMonitor *monitor;
guint n_monitors;
int best_area = 0;
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
if (self->in_change_monitor)
return;
self->in_change_monitor = TRUE;
_gdk_macos_surface_cancel_frame (self);
_gdk_macos_surface_configure (self);
rect.x = self->root_x;
rect.y = self->root_y;
rect.width = GDK_SURFACE (self)->width;
@@ -1042,29 +1109,10 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
g_clear_object (&self->buffer);
g_clear_object (&self->front);
_gdk_macos_surface_configure (self);
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
}
GdkMonitor *
_gdk_macos_surface_get_best_monitor (GdkMacosSurface *self)
{
GdkMonitor *best = NULL;
GdkRectangle rect;
int best_area = 0;
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
rect.x = self->root_x;
rect.y = self->root_y;
rect.width = GDK_SURFACE (self)->width;
rect.height = GDK_SURFACE (self)->height;
/* Determine the best-fit monitor */
for (guint i = 0; i < self->monitors->len; i++)
{
GdkMonitor *monitor = g_ptr_array_index (self->monitors, i);
GdkRectangle intersect;
monitor = g_ptr_array_index (self->monitors, i);
if (gdk_rectangle_intersect (&monitor->geometry, &rect, &intersect))
{
@@ -1072,13 +1120,62 @@ _gdk_macos_surface_get_best_monitor (GdkMacosSurface *self)
if (area > best_area)
{
best = monitor;
best_area = area;
best = monitor;
}
}
}
return best;
if (g_set_object (&self->best_monitor, best))
{
GDK_NOTE (MISC,
g_message ("Surface \"%s\" moved to monitor \"%s\"",
self->title ? self->title : "unknown",
gdk_monitor_get_connector (best)));
_gdk_macos_surface_configure (self);
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
{
_gdk_macos_surface_request_frame (self);
gdk_surface_request_layout (GDK_SURFACE (self));
}
for (const GList *iter = GDK_SURFACE (self)->children;
iter != NULL;
iter = iter->next)
{
GdkMacosSurface *child = iter->data;
GdkRectangle area;
g_set_object (&child->best_monitor, best);
area.x = self->root_x + GDK_SURFACE (child)->x + child->shadow_left;
area.y = self->root_y + GDK_SURFACE (child)->y + child->shadow_top;
area.width = GDK_SURFACE (child)->width - child->shadow_left - child->shadow_right;
area.height = GDK_SURFACE (child)->height - child->shadow_top - child->shadow_bottom;
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (best), &area);
area.x -= child->shadow_left;
area.y -= child->shadow_top;
_gdk_macos_surface_move (child, area.x, area.y);
gdk_surface_invalidate_rect (GDK_SURFACE (child), NULL);
}
}
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
self->in_change_monitor = FALSE;
}
GdkMonitor *
_gdk_macos_surface_get_best_monitor (GdkMacosSurface *self)
{
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
return self->best_monitor;
}
NSView *
@@ -1154,11 +1251,15 @@ _gdk_macos_surface_get_buffer (GdkMacosSurface *self)
static void
_gdk_macos_surface_do_delayed_show (GdkMacosSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_assert (GDK_IS_MACOS_SURFACE (self));
self->show_on_next_swap = FALSE;
[self->window showAndMakeKey:YES];
gdk_surface_request_motion (GDK_SURFACE (self));
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
gdk_surface_request_motion (surface);
}
void
+57 -15
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)
@@ -174,6 +187,14 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
_gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
GDK_NOTE (MISC,
g_message ("Resizing \"%s\" to %dx%d",
GDK_MACOS_SURFACE (self)->title ?
GDK_MACOS_SURFACE (self)->title :
"untitled",
width, height));
_gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
/* Maximized state */
@@ -194,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;
@@ -202,6 +225,13 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
GDK_MACOS_SURFACE (self),
&x, &y);
GDK_NOTE (MISC,
g_message ("Placing new toplevel \"%s\" at %d,%d",
GDK_MACOS_SURFACE (self)->title ?
GDK_MACOS_SURFACE (self)->title :
"untitled",
x, y));
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x, y);
}
@@ -421,7 +451,8 @@ _gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
GDK_TOPLEVEL_STATE_RIGHT_TILED |
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
GDK_TOPLEVEL_STATE_LEFT_TILED |
GDK_TOPLEVEL_STATE_MINIMIZED))
GDK_TOPLEVEL_STATE_MINIMIZED) ||
[macos_surface->window inLiveResize])
return FALSE;
/* If we delayed a user resize until the beginning of the frame,
@@ -632,10 +663,10 @@ _gdk_macos_toplevel_surface_new (GdkMacosDisplay *display,
GdkMacosWindow *window;
GdkMacosSurface *self;
NSScreen *screen;
NSUInteger style_mask;
NSRect content_rect;
NSRect screen_rect;
NSRect visible_frame;
NSScreen *screen;
int nx;
int ny;
@@ -648,14 +679,17 @@ _gdk_macos_toplevel_surface_new (GdkMacosDisplay *display,
NSWindowStyleMaskMiniaturizable |
NSWindowStyleMaskResizable);
_gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
if (parent != NULL)
{
x += GDK_MACOS_SURFACE (parent)->root_x;
y += GDK_MACOS_SURFACE (parent)->root_y;
}
_gdk_macos_display_to_display_coords (display, x, y + height, &nx, &ny);
screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
screen_rect = [screen visibleFrame];
nx -= screen_rect.origin.x;
ny -= screen_rect.origin.y;
content_rect = NSMakeRect (nx, ny - height, width, height);
visible_frame = [screen visibleFrame];
content_rect = NSMakeRect (nx - visible_frame.origin.x, ny - visible_frame.origin.y, width, height);
window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
styleMask:style_mask
backing:NSBackingStoreBuffered
@@ -691,13 +725,21 @@ _gdk_macos_toplevel_surface_attach_to_parent (GdkMacosToplevelSurface *self)
{
NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->transient_for));
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
int x, y;
[parent addChildWindow:window ordered:NSWindowAbove];
if (GDK_SURFACE (self)->modal_hint)
[window setLevel:NSModalPanelWindowLevel];
surface->x = 0;
surface->y = 0;
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
_gdk_macos_display_position_surface (GDK_MACOS_DISPLAY (surface->display),
GDK_MACOS_SURFACE (surface),
&x, &y);
_gdk_macos_surface_move (GDK_MACOS_SURFACE (surface), x, y);
}
}
+1
View File
@@ -8,6 +8,7 @@ gdk_macos_sources = files([
'gdkmacoscursor.c',
'gdkmacosdevice.c',
'gdkmacosdisplay.c',
'gdkmacosdisplay-feedback.c',
'gdkmacosdisplay-settings.c',
'gdkmacosdisplay-translate.c',
'gdkmacosdisplay-wm.c',
+66 -28
View File
@@ -200,23 +200,51 @@ wl_cursor_destroy(struct wl_cursor *cursor)
}
static struct wl_cursor *
wl_cursor_create_from_xcursor_images(XcursorImages *images,
struct wl_cursor_theme *theme,
wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
const char *name,
unsigned int load_size)
unsigned int size,
unsigned int scale)
{
char *path;
XcursorImages *images;
struct cursor *cursor;
struct cursor_image *image;
int i, size;
int i, nbytes;
unsigned int load_size;
int load_scale = 1;
load_size = size * scale;
path = g_strconcat (theme->path, "/", name, NULL);
images = xcursor_load_images (path, load_size);
if (!images)
{
g_free (path);
return NULL;
}
if (images->images[0]->width != load_size ||
images->images[0]->height != load_size)
{
xcursor_images_destroy (images);
images = xcursor_load_images (path, size);
load_scale = scale;
}
g_free (path);
cursor = malloc(sizeof *cursor);
if (!cursor)
if (!cursor) {
xcursor_images_destroy (images);
return NULL;
}
cursor->cursor.images =
malloc(images->nimage * sizeof cursor->cursor.images[0]);
if (!cursor->cursor.images) {
free(cursor);
xcursor_images_destroy (images);
return NULL;
}
@@ -232,22 +260,37 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
image->theme = theme;
image->buffer = NULL;
image->image.width = images->images[i]->width;
image->image.height = images->images[i]->height;
image->image.hotspot_x = images->images[i]->xhot;
image->image.hotspot_y = images->images[i]->yhot;
image->image.width = images->images[i]->width * load_scale;
image->image.height = images->images[i]->height * load_scale;
image->image.hotspot_x = images->images[i]->xhot * load_scale;
image->image.hotspot_y = images->images[i]->yhot * load_scale;
image->image.delay = images->images[i]->delay;
size = image->image.width * image->image.height * 4;
image->offset = shm_pool_allocate(theme->pool, size);
nbytes = image->image.width * image->image.height * 4;
image->offset = shm_pool_allocate(theme->pool, nbytes);
if (image->offset < 0) {
free(image);
break;
}
/* copy pixels to shm pool */
memcpy(theme->pool->data + image->offset,
images->images[i]->pixels, size);
if (load_scale == 1) {
/* copy pixels to shm pool */
memcpy(theme->pool->data + image->offset,
images->images[i]->pixels, nbytes);
}
else {
/* scale image up while copying it */
for (int y = 0; y < image->image.height; y++) {
char *p = theme->pool->data + image->offset + y * image->image.width * 4;
char *q = ((char *)images->images[i]->pixels) + (y / load_scale) * images->images[i]->width * 4;
for (int x = 0; x < image->image.width; x++) {
p[4 * x] = q[4 * (x/load_scale)];
p[4 * x + 1] = q[4 * (x/load_scale) + 1];
p[4 * x + 2] = q[4 * (x/load_scale) + 2];
p[4 * x + 3] = q[4 * (x/load_scale) + 3];
}
}
}
cursor->total_delay += image->image.delay;
cursor->cursor.images[i] = (struct wl_cursor_image *) image;
}
@@ -257,27 +300,24 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
free(cursor->cursor.name);
free(cursor->cursor.images);
free(cursor);
xcursor_images_destroy (images);
return NULL;
}
xcursor_images_destroy (images);
return &cursor->cursor;
}
static void
load_cursor(struct wl_cursor_theme *theme, const char *name, unsigned int size)
load_cursor(struct wl_cursor_theme *theme,
const char *name,
unsigned int size,
unsigned int scale)
{
XcursorImages *images;
struct wl_cursor *cursor;
char *path;
path = g_strconcat (theme->path, "/", name, NULL);
images = xcursor_load_images (path, size);
g_free (path);
if (!images)
return;
cursor = wl_cursor_create_from_xcursor_images(images, theme, name, size);
cursor = wl_cursor_create_from_xcursor_images(theme, name, size, scale);
if (cursor) {
theme->cursor_count++;
@@ -292,8 +332,6 @@ load_cursor(struct wl_cursor_theme *theme, const char *name, unsigned int size)
theme->cursors[theme->cursor_count - 1] = cursor;
}
}
xcursor_images_destroy (images);
}
/** Load a cursor theme to memory shared with the compositor
@@ -373,7 +411,7 @@ wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
return theme->cursors[i];
}
load_cursor (theme, name, size);
load_cursor (theme, name, theme->size, scale);
if (i < theme->cursor_count) {
if (size == theme->cursors[i]->size &&
+3 -2
View File
@@ -73,8 +73,9 @@ gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context
xdg_activation_token_v1_set_serial (token,
_gdk_wayland_seat_get_last_implicit_grab_serial (seat, NULL),
gdk_wayland_seat_get_wl_seat (GDK_SEAT (seat)));
xdg_activation_token_v1_set_surface (token,
gdk_wayland_surface_get_wl_surface (focus_surface));
if (focus_surface)
xdg_activation_token_v1_set_surface (token,
gdk_wayland_surface_get_wl_surface (focus_surface));
xdg_activation_token_v1_commit (token);
while (app_launch_data.token == NULL)
+16 -5
View File
@@ -178,6 +178,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
if (c)
{
struct wl_cursor_image *image;
int cursor_scale;
if (image_index >= c->image_count)
{
@@ -189,12 +190,22 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
image = c->images[image_index];
*hotspot_x = image->hotspot_x / desired_scale;
*hotspot_y = image->hotspot_y / desired_scale;
cursor_scale = desired_scale;
if ((image->width % cursor_scale != 0) ||
(image->height % cursor_scale != 0))
{
g_warning (G_STRLOC " cursor image size (%dx%d) not an integer"
"multiple of scale (%d)", image->width, image->height,
cursor_scale);
cursor_scale = 1;
}
*width = image->width / desired_scale;
*height = image->height / desired_scale;
*scale = desired_scale;
*hotspot_x = image->hotspot_x / cursor_scale;
*hotspot_y = image->hotspot_y / cursor_scale;
*width = image->width / cursor_scale;
*height = image->height / cursor_scale;
*scale = cursor_scale;
return wl_cursor_image_get_buffer (image);
}
+4
View File
@@ -854,6 +854,10 @@ gdk_wayland_display_notify_startup_complete (GdkDisplay *display,
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
char *free_this = NULL;
/* Will be signaled with focus activation */
if (display_wayland->xdg_activation)
return;
if (startup_id == NULL)
{
startup_id = free_this = display_wayland->startup_notification_id;
+71 -20
View File
@@ -113,6 +113,7 @@ struct _GdkWaylandSurface
PopupState popup_state;
unsigned int popup_thaw_upon_show : 1;
unsigned int initial_configure_received : 1;
unsigned int has_uncommitted_ack_configure : 1;
unsigned int mapped : 1;
@@ -2984,6 +2985,9 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
if (GDK_IS_POPUP (surface))
{
impl->popup_thaw_upon_show = TRUE;
gdk_surface_freeze_updates (surface);
switch (impl->popup_state)
{
case POPUP_STATE_WAITING_FOR_REPOSITIONED:
@@ -3223,6 +3227,12 @@ show_popup (GdkSurface *surface,
if (!impl->display_server.wl_surface)
gdk_wayland_surface_create_surface (surface);
if (impl->popup_thaw_upon_show)
{
impl->popup_thaw_upon_show = FALSE;
gdk_surface_thaw_updates (surface);
}
gdk_wayland_surface_map_popup (surface, width, height, layout);
}
@@ -3453,39 +3463,80 @@ gdk_wayland_surface_destroy (GdkSurface *surface,
display->toplevels = g_list_remove (display->toplevels, surface);
}
static void
token_done (gpointer data,
struct xdg_activation_token_v1 *provider,
const char *token)
{
char **token_out = data;
*token_out = g_strdup (token);
}
static const struct xdg_activation_token_v1_listener token_listener = {
token_done,
};
static void
gdk_wayland_surface_focus (GdkSurface *surface,
guint32 timestamp)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
gchar *startup_id = NULL;
if (!impl->display_server.gtk_surface)
return;
startup_id = g_steal_pointer (&display_wayland->startup_notification_id);
if (timestamp == GDK_CURRENT_TIME)
if (display_wayland->xdg_activation)
{
GdkWaylandDisplay *display_wayland =
GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkWaylandSeat *seat =
GDK_WAYLAND_SEAT (gdk_display_get_default_seat (display));
if (display_wayland->startup_notification_id)
/* If the focus request does not have a startup ID associated, get a
* new token to activate the window.
*/
if (!startup_id)
{
if (display_wayland->xdg_activation)
{
xdg_activation_v1_activate (display_wayland->xdg_activation,
display_wayland->startup_notification_id,
impl->display_server.wl_surface);
}
else if (display_wayland->gtk_shell_version >= 3)
{
gtk_surface1_request_focus (impl->display_server.gtk_surface,
display_wayland->startup_notification_id);
}
struct xdg_activation_token_v1 *token;
struct wl_event_queue *event_queue;
g_clear_pointer (&display_wayland->startup_notification_id, g_free);
event_queue = wl_display_create_queue (display_wayland->wl_display);
token = xdg_activation_v1_get_activation_token (display_wayland->xdg_activation);
wl_proxy_set_queue ((struct wl_proxy *) token, event_queue);
xdg_activation_token_v1_add_listener (token,
&token_listener,
&startup_id);
xdg_activation_token_v1_set_serial (token,
_gdk_wayland_seat_get_last_implicit_grab_serial (seat, NULL),
gdk_wayland_seat_get_wl_seat (GDK_SEAT (seat)));
xdg_activation_token_v1_set_surface (token,
gdk_wayland_surface_get_wl_surface (surface));
xdg_activation_token_v1_commit (token);
while (startup_id == NULL)
wl_display_dispatch_queue (display_wayland->wl_display, event_queue);
xdg_activation_token_v1_destroy (token);
wl_event_queue_destroy (event_queue);
}
xdg_activation_v1_activate (display_wayland->xdg_activation,
startup_id,
impl->display_server.wl_surface);
}
else
gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
else if (impl->display_server.gtk_surface)
{
if (timestamp != GDK_CURRENT_TIME)
gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
else if (startup_id && display_wayland->gtk_shell_version >= 3)
gtk_surface1_request_focus (impl->display_server.gtk_surface,
startup_id);
}
g_free (startup_id);
}
static void
+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
+3 -4
View File
@@ -1219,11 +1219,10 @@ inner_clipboard_window_procedure (HWND hwnd,
return DefWindowProcW (hwnd, message, wparam, lparam);
}
SetLastError (0);
hwnd_owner = GetClipboardOwner ();
if ((hwnd_owner == NULL) &&
(GetLastError () != ERROR_SUCCESS))
WIN32_API_FAILED ("GetClipboardOwner");
if (hwnd_owner == NULL && GetLastError () != 0)
WIN32_API_FAILED ("GetClipboardOwner");
hwnd_opener = GetOpenClipboardWindow ();
+55 -68
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
+25 -24
View File
@@ -229,14 +229,9 @@ fail1:
return NULL;
}
/*
* Get the file path of the keyboard layout dll.
* The result is heap-allocated and should be freed with g_free().
*/
static char*
get_keyboard_layout_file (const char *layout_name)
_get_keyboard_layout_file (const char *layout_name)
{
char *final_layout_name = NULL;
HKEY hkey = 0;
DWORD var_type = REG_SZ;
char *result = NULL;
@@ -249,24 +244,8 @@ get_keyboard_layout_file (const char *layout_name)
"Keyboard Layouts\\";
char kbdKeyPath[sizeof (prefix) + KL_NAMELENGTH];
/* The user may have a keyboard substitute configured */
final_layout_name = get_keyboard_layout_substituted_name (layout_name);
if (final_layout_name != NULL)
{
g_debug ("Substituting keyboard layout name from '%s' to '%s'",
layout_name, final_layout_name);
g_snprintf (kbdKeyPath, sizeof (prefix) + KL_NAMELENGTH, "%s%s",
prefix, final_layout_name);
g_free (final_layout_name);
final_layout_name = NULL;
}
else
{
g_debug ("Could not get substitute keyboard layout name for '%s', "
"will use '%s' directly", layout_name, layout_name);
g_snprintf (kbdKeyPath, sizeof (prefix) + KL_NAMELENGTH, "%s%s",
prefix, layout_name);
}
g_snprintf (kbdKeyPath, sizeof (prefix) + KL_NAMELENGTH, "%s%s",
prefix, layout_name);
status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, (LPCSTR) kbdKeyPath, 0,
KEY_QUERY_VALUE, &hkey);
@@ -326,6 +305,28 @@ fail1:
return NULL;
}
/*
* Get the file path of the keyboard layout dll.
* The result is heap-allocated and should be freed with g_free().
*/
static char*
get_keyboard_layout_file (const char *layout_name)
{
char *result = _get_keyboard_layout_file (layout_name);
/* If we could not retrieve a path, it may be that we need to perform layout
* substitution
*/
if (result == NULL)
{
char *substituted = get_keyboard_layout_substituted_name (layout_name);
result = _get_keyboard_layout_file (substituted);
g_free (substituted);
}
return result;
}
static void
clear_keyboard_layout_info (gpointer data)
{
+11 -2
View File
@@ -4152,6 +4152,9 @@ gdk_win32_surface_fullscreen (GdkSurface *window)
g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
fi->style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
impl->inhibit_configure = TRUE;
impl->force_recompute_size = FALSE;
/* Send state change before configure event */
gdk_synthesize_surface_state (window, 0, GDK_TOPLEVEL_STATE_FULLSCREEN);
@@ -4160,7 +4163,7 @@ gdk_win32_surface_fullscreen (GdkSurface *window)
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
x, y, width, height,
SWP_NOCOPYBITS | SWP_SHOWWINDOW));
SWP_NOCOPYBITS | SWP_SHOWWINDOW | SWP_FRAMECHANGED));
}
}
@@ -4184,11 +4187,17 @@ gdk_win32_surface_unfullscreen (GdkSurface *window)
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_NOTOPMOST,
fi->r.left, fi->r.top,
fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
SWP_NOCOPYBITS | SWP_SHOWWINDOW));
SWP_NOCOPYBITS | SWP_SHOWWINDOW | SWP_FRAMECHANGED));
g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
g_free (fi);
_gdk_win32_surface_update_style_bits (window);
if (impl->inhibit_configure)
{
impl->inhibit_configure = FALSE;
impl->force_recompute_size = TRUE;
}
}
}
+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);
+1 -1
View File
@@ -280,7 +280,7 @@ compute_toplevel_size (GdkSurface *surface,
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
if (size.shadow.is_valid && update_geometry)
if (size.shadow.is_valid)
{
update_shadow_size (surface,
size.shadow.left,
+1 -1
View File
@@ -831,7 +831,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.
+57 -3
View File
@@ -24,6 +24,7 @@
#include <gdk/gdkdisplayprivate.h>
#include <gdk/gdkglcontextprivate.h>
#include <gdk/gdksurfaceprivate.h>
#include <gdk/gdkintl.h>
#include <gsk/gskdebugprivate.h>
#include <gsk/gskrendererprivate.h>
#include <gsk/gskrendernodeprivate.h>
@@ -93,6 +94,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
GdkDisplay *display;
gboolean ret = FALSE;
gboolean debug_shaders = FALSE;
GdkGLAPI api;
if (self->context != NULL)
return TRUE;
@@ -115,6 +117,24 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
if (!context || !gdk_gl_context_realize (context, error))
goto failure;
api = gdk_gl_context_get_api (context);
if (api == GDK_GL_API_GLES)
{
gdk_gl_context_make_current (context);
if (!gdk_gl_context_has_vertex_half_float (context))
{
int major, minor;
gdk_gl_context_get_version (context, &major, &minor);
g_set_error (error,
GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
_("This GLES %d.%d implementation does not support half-float vertex data"),
major, minor);
goto failure;
}
}
#ifdef G_ENABLE_DEBUG
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), SHADERS))
debug_shaders = TRUE;
@@ -306,10 +326,9 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
GskGLRenderer *self = (GskGLRenderer *)renderer;
GskGLRenderTarget *render_target;
GskGLRenderJob *job;
GdkTexture *texture = NULL;
GdkTexture *texture;
guint texture_id;
int width;
int height;
int width, height, max_size;
int format;
g_assert (GSK_IS_GL_RENDERER (renderer));
@@ -317,6 +336,37 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
width = ceilf (viewport->size.width);
height = ceilf (viewport->size.height);
max_size = self->command_queue->max_texture_size;
if (width > max_size || height > max_size)
{
gsize x, y, size, stride;
GBytes *bytes;
guchar *data;
stride = width * 4;
size = stride * height;
data = g_malloc_n (stride, height);
for (y = 0; y < height; y += max_size)
{
for (x = 0; x < width; x += max_size)
{
texture = gsk_gl_renderer_render_texture (renderer, root,
&GRAPHENE_RECT_INIT (x, y,
MIN (max_size, viewport->size.width - x),
MIN (max_size, viewport->size.height - y)));
gdk_texture_download (texture,
data + stride * y + x * 4,
stride);
g_object_unref (texture);
}
}
bytes = g_bytes_new_take (data, size);
texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
g_bytes_unref (bytes);
return texture;
}
format = gsk_render_node_prefers_high_depth (root) ? GL_RGBA32F : GL_RGBA8;
@@ -342,6 +392,10 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
gsk_gl_driver_after_frame (self->driver);
}
else
{
g_assert_not_reached ();
}
return g_steal_pointer (&texture);
}
+89 -51
View File
@@ -3869,7 +3869,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 +3876,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 +4002,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 +4019,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 +4036,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);
+37 -1
View File
@@ -107,8 +107,44 @@ gsk_cairo_renderer_render_texture (GskRenderer *renderer,
GdkTexture *texture;
cairo_surface_t *surface;
cairo_t *cr;
int width, height;
/* limit from cairo's source code */
#define MAX_IMAGE_SIZE 32767
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (viewport->size.width), ceil (viewport->size.height));
width = ceil (viewport->size.width);
height = ceil (viewport->size.height);
if (width > MAX_IMAGE_SIZE || height > MAX_IMAGE_SIZE)
{
gsize x, y, size, stride;
GBytes *bytes;
guchar *data;
stride = width * 4;
size = stride * height;
data = g_malloc_n (stride, height);
for (y = 0; y < height; y += MAX_IMAGE_SIZE)
{
for (x = 0; x < width; x += MAX_IMAGE_SIZE)
{
texture = gsk_cairo_renderer_render_texture (renderer, root,
&GRAPHENE_RECT_INIT (x, y,
MIN (MAX_IMAGE_SIZE, viewport->size.width - x),
MIN (MAX_IMAGE_SIZE, viewport->size.height - y)));
gdk_texture_download (texture,
data + stride * y + x * 4,
stride);
g_object_unref (texture);
}
}
bytes = g_bytes_new_take (data, size);
texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
g_bytes_unref (bytes);
return texture;
}
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
cr = cairo_create (surface);
cairo_translate (cr, - viewport->origin.x, - viewport->origin.y);
+6 -6
View File
@@ -5130,10 +5130,10 @@ gsk_gl_shader_node_diff (GskRenderNode *node1,
* @shader: the `GskGLShader`
* @bounds: the rectangle to render the shader into
* @args: Arguments for the uniforms
* @children: (array length=n_children): array of child nodes, these will
* be rendered to textures and used as input.
* @children: (nullable) (array length=n_children): array of child nodes,
* these will be rendered to textures and used as input.
* @n_children: Length of @children (currenly the GL backend supports
* up to 4 children)
* up to 4 children)
*
* Creates a `GskRenderNode` that will render the given @shader into the
* area given by @bounds.
@@ -5167,10 +5167,10 @@ gsk_gl_shader_node_new (GskGLShader *shader,
g_return_val_if_fail (GSK_IS_GL_SHADER (shader), NULL);
g_return_val_if_fail (bounds != NULL, NULL);
g_return_val_if_fail ((args == NULL && gsk_gl_shader_get_n_uniforms (shader) == 0) ||
(args != NULL && g_bytes_get_size (args) == gsk_gl_shader_get_args_size (shader)), NULL);
g_return_val_if_fail (args != NULL, NULL);
g_return_val_if_fail (g_bytes_get_size (args) == gsk_gl_shader_get_args_size (shader), NULL);
g_return_val_if_fail ((children == NULL && n_children == 0) ||
(children != NULL && n_children == gsk_gl_shader_get_n_textures (shader)), NULL);
(n_children == gsk_gl_shader_get_n_textures (shader)), NULL);
self = gsk_render_node_alloc (GSK_GL_SHADER_NODE);
node = (GskRenderNode *) self;
+24 -14
View File
@@ -436,7 +436,11 @@ get_parent_context_ref (GtkAccessible *accessible)
gtk_accessible_get_at_context (GTK_ACCESSIBLE (parent));
if (parent_context != NULL)
res = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (parent_context));
{
gtk_at_context_realize (parent_context);
res = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (parent_context));
}
}
if (res == NULL)
@@ -1418,7 +1422,7 @@ gtk_at_spi_context_unregister_object (GtkAtSpiContext *self)
g_clear_pointer (&self->interfaces, g_variant_unref);
}
/* }}} */
/* {{{ GObject boilerplate */
/* {{{ GObject boilerplate */
static void
gtk_at_spi_context_finalize (GObject *gobject)
{
@@ -1443,6 +1447,22 @@ gtk_at_spi_context_constructed (GObject *gobject)
static const char *get_bus_address (GdkDisplay *display);
static void
register_object (GtkAtSpiRoot *root,
GtkAtSpiContext *context)
{
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (context));
gtk_atspi_connect_text_signals (accessible,
(GtkAtspiTextChangedCallback *)emit_text_changed,
(GtkAtspiTextSelectionCallback *)emit_text_selection_changed,
context);
gtk_atspi_connect_selection_signals (accessible,
(GtkAtspiSelectionCallback *)emit_selection_changed,
context);
gtk_at_spi_context_register_object (context);
}
static void
gtk_at_spi_context_realize (GtkATContext *context)
{
@@ -1489,11 +1509,10 @@ gtk_at_spi_context_realize (GtkATContext *context)
if (self->connection == NULL)
return;
GtkAccessible *accessible = gtk_at_context_get_accessible (context);
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (A11Y))
{
GtkAccessible *accessible = gtk_at_context_get_accessible (context);
GtkAccessibleRole role = gtk_at_context_get_accessible_role (context);
char *role_name = g_enum_to_string (GTK_TYPE_ACCESSIBLE_ROLE, role);
g_message ("Realizing ATSPI context “%s” for accessible “%s”, with role: “%s”",
@@ -1504,16 +1523,7 @@ gtk_at_spi_context_realize (GtkATContext *context)
}
#endif
gtk_atspi_connect_text_signals (accessible,
(GtkAtspiTextChangedCallback *)emit_text_changed,
(GtkAtspiTextSelectionCallback *)emit_text_selection_changed,
self);
gtk_atspi_connect_selection_signals (accessible,
(GtkAtspiSelectionCallback *)emit_selection_changed,
self);
gtk_at_spi_context_register_object (self);
gtk_at_spi_root_queue_register (self->root, self);
gtk_at_spi_root_queue_register (self->root, self, register_object);
}
static void
+35 -11
View File
@@ -474,16 +474,24 @@ gtk_at_spi_root_child_changed (GtkAtSpiRoot *self,
window_ref);
}
typedef struct {
GtkAtSpiRoot *root;
GtkAtSpiRootRegisterFunc register_func;
} RegistrationData;
static void
on_registration_reply (GObject *gobject,
GAsyncResult *result,
gpointer user_data)
{
GtkAtSpiRoot *self = user_data;
RegistrationData *data = user_data;
GtkAtSpiRoot *self = data->root;
GError *error = NULL;
GVariant *reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (gobject), result, &error);
self->register_id = 0;
if (error != NULL)
{
g_critical ("Unable to register the application: %s", error->message);
@@ -509,19 +517,27 @@ on_registration_reply (GObject *gobject,
/* Drain the list of queued GtkAtSpiContexts, and add them to the cache */
if (self->queued_contexts != NULL)
{
for (GList *l = self->queued_contexts; l != NULL; l = l->next)
gtk_at_spi_cache_add_context (self->cache, l->data);
for (GList *l = g_list_reverse (self->queued_contexts); l != NULL; l = l->next)
{
if (data->register_func != NULL)
data->register_func (self, l->data);
gtk_at_spi_cache_add_context (self->cache, l->data);
}
g_clear_pointer (&self->queued_contexts, g_list_free);
}
self->toplevels = gtk_window_get_toplevels ();
g_free (data);
}
static gboolean
root_register (gpointer data)
root_register (gpointer user_data)
{
GtkAtSpiRoot *self = data;
RegistrationData *data = user_data;
GtkAtSpiRoot *self = data->root;
const char *unique_name;
/* Register the root element; every application has a single root, so we only
@@ -577,9 +593,7 @@ root_register (gpointer data)
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
on_registration_reply,
self);
self->register_id = 0;
data);
return G_SOURCE_REMOVE;
}
@@ -587,18 +601,24 @@ root_register (gpointer data)
/*< private >
* gtk_at_spi_root_queue_register:
* @self: a `GtkAtSpiRoot`
* @context: the AtSpi context to register
* @func: the function to call when the root has been registered
*
* Queues the registration of the root object on the AT-SPI bus.
*/
void
gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
GtkAtSpiContext *context)
gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
GtkAtSpiContext *context,
GtkAtSpiRootRegisterFunc func)
{
/* The cache is available if the root has finished registering itself; if we
* are still waiting for the registration to finish, add the context to a queue
*/
if (self->cache != NULL)
{
if (func != NULL)
func (self, context);
gtk_at_spi_cache_add_context (self->cache, context);
return;
}
@@ -612,7 +632,11 @@ gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
if (self->register_id != 0)
return;
self->register_id = g_idle_add (root_register, self);
RegistrationData *data = g_new (RegistrationData, 1);
data->root = self;
data->register_func = func;
self->register_id = g_idle_add (root_register, data);
gdk_source_set_static_name_by_id (self->register_id, "[gtk] ATSPI root registration");
}
+5 -1
View File
@@ -34,9 +34,13 @@ G_DECLARE_FINAL_TYPE (GtkAtSpiRoot, gtk_at_spi_root, GTK, AT_SPI_ROOT, GObject)
GtkAtSpiRoot *
gtk_at_spi_root_new (const char *bus_address);
typedef void (* GtkAtSpiRootRegisterFunc) (GtkAtSpiRoot *root,
GtkAtSpiContext *context);
void
gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
GtkAtSpiContext *context);
GtkAtSpiContext *context,
GtkAtSpiRootRegisterFunc func);
void
gtk_at_spi_root_unregister (GtkAtSpiRoot *self,
+1 -1
View File
@@ -425,7 +425,7 @@ gtk_accessible_reset_property (GtkAccessible *self,
* gtk_accessible_update_relation (accessible,
* GTK_ACCESSIBLE_RELATION_CONTROLS,
* ref1, NULL,
* GTK_ACCESSIBLE_LABELLED_BY,
* GTK_ACCESSIBLE_RELATION_LABELLED_BY,
* ref1, ref2, ref3, NULL,
* -1);
* ```
+7 -5
View File
@@ -991,13 +991,15 @@ gtk_action_muxer_unregister_observer (GtkActionObservable *observable,
GtkActionObserver *observer)
{
GtkActionMuxer *muxer = GTK_ACTION_MUXER (observable);
Action *action;
Action *action = find_observers (muxer, name);
action = find_observers (muxer, name);
if (action)
{
g_object_weak_unref (G_OBJECT (observer), gtk_action_muxer_weak_notify, action);
gtk_action_muxer_unregister_internal (action, observer);
if (g_slist_find (action->watchers, observer) != NULL)
{
g_object_weak_unref (G_OBJECT (observer), gtk_action_muxer_weak_notify, action);
gtk_action_muxer_unregister_internal (action, observer);
}
}
}
@@ -1269,7 +1271,7 @@ gtk_action_muxer_insert (GtkActionMuxer *muxer,
if (!muxer->groups)
muxer->groups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gtk_action_muxer_free_group);
group = g_slice_new (Group);
group = g_slice_new0 (Group);
group->muxer = muxer;
group->group = g_object_ref (action_group);
group->prefix = g_strdup (prefix);
+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
+41 -2
View File
@@ -288,6 +288,12 @@ gtk_box_layout_compute_opposite_size (GtkBoxLayout *self,
*natural = largest_nat;
}
/* if widgets haven't reached their min opposite size at this
* huge value, things went massively wrong and we need to bail to not
* cause an infinite loop.
*/
#define MAX_ALLOWED_SIZE (1 << 20)
static int
distribute_remaining_size (GtkRequestedSize *sizes,
gsize n_sizes,
@@ -321,7 +327,40 @@ distribute_remaining_size (GtkRequestedSize *sizes,
{
int test;
if (max == G_MAXINT)
if (min > MAX_ALLOWED_SIZE)
{
/* sanity check! */
for (i = 0; i < n_sizes; i++)
{
int check_min, check_nat;
gtk_widget_measure (sizes[i].data,
orientation,
MAX_ALLOWED_SIZE,
&sizes[i].minimum_size, &sizes[i].natural_size,
NULL, NULL);
gtk_widget_measure (sizes[i].data,
orientation,
-1,
&check_min, &check_nat,
NULL, NULL);
if (check_min < sizes[i].minimum_size)
{
g_critical ("%s %p reports a minimum %s of %u, but minimum %s for %s of %u is %u. Expect overlapping widgets.",
G_OBJECT_TYPE_NAME (sizes[i].data), sizes[i].data,
orientation == GTK_ORIENTATION_HORIZONTAL ? "width" : "height",
check_min,
orientation == GTK_ORIENTATION_HORIZONTAL ? "width" : "height",
orientation == GTK_ORIENTATION_HORIZONTAL ? "height" : "width",
MAX_ALLOWED_SIZE, sizes[i].minimum_size);
sizes[i].minimum_size = check_min;
sizes[i].natural_size = check_nat;
}
total_size += sizes[i].minimum_size;
}
return MAX (0, available - total_size);
}
if (max == MAX_ALLOWED_SIZE)
test = min * 2;
else
test = (min + max) / 2;
@@ -465,7 +504,7 @@ gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self,
self->orientation,
available,
min_size,
G_MAXINT);
MAX_ALLOWED_SIZE);
/* Bring children up to size first */
available = gtk_distribute_natural_allocation (available, nvis_children, sizes);
+8 -8
View File
@@ -239,7 +239,7 @@ gtk_css_node_dispose (GObject *object)
}
gtk_css_node_set_invalid (cssnode, FALSE);
g_clear_pointer (&cssnode->cache, gtk_css_node_style_cache_unref);
G_OBJECT_CLASS (gtk_css_node_parent_class)->dispose (object);
@@ -292,7 +292,7 @@ may_use_global_parent_cache (GtkCssNode *node)
{
GtkStyleProvider *provider;
GtkCssNode *parent;
parent = gtk_css_node_get_parent (node);
if (parent == NULL)
return FALSE;
@@ -700,10 +700,10 @@ gtk_css_node_invalidate_style (GtkCssNode *cssnode)
cssnode->style_is_invalid = TRUE;
gtk_css_node_set_invalid (cssnode, TRUE);
if (cssnode->first_child)
gtk_css_node_invalidate_style (cssnode->first_child);
if (cssnode->next_sibling)
gtk_css_node_invalidate_style (cssnode->next_sibling);
}
@@ -796,7 +796,7 @@ gtk_css_node_reposition (GtkCssNode *node,
gtk_css_node_invalidate_style (node->next_sibling);
}
gtk_css_node_invalidate (node, GTK_CSS_CHANGE_ANY_PARENT
gtk_css_node_invalidate (node, (old_parent != new_parent ? GTK_CSS_CHANGE_ANY_PARENT : 0)
| GTK_CSS_CHANGE_ANY_SIBLING
| GTK_CSS_CHANGE_NTH_CHILD
| (node->previous_sibling ? 0 : GTK_CSS_CHANGE_FIRST_CHILD)
@@ -842,7 +842,7 @@ gtk_css_node_insert_before (GtkCssNode *parent,
g_return_if_fail (next_sibling == NULL || next_sibling->parent == parent);
g_return_if_fail (cssnode != next_sibling);
if (cssnode->next_sibling == next_sibling &&
if (cssnode->next_sibling == next_sibling &&
cssnode->parent == parent)
return;
@@ -1067,7 +1067,7 @@ gtk_css_node_set_visible (GtkCssNode *cssnode,
}
}
}
if (cssnode->previous_sibling)
{
if (gtk_css_node_is_last_child (cssnode))
@@ -1424,7 +1424,7 @@ gtk_css_node_print (GtkCssNode *cssnode,
change = gtk_css_static_style_get_change (gtk_css_style_get_static_style (style));
g_string_append (string, " ");
gtk_css_change_print (change, string);
gtk_css_change_print (change, string);
}
g_string_append_c (string, '\n');
+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
+2 -1
View File
@@ -149,7 +149,8 @@ gtk_event_controller_focus_handle_crossing (GtkEventController *controller,
double x,
double y)
{
if (crossing->type == GTK_CROSSING_FOCUS)
if (crossing->type == GTK_CROSSING_FOCUS ||
crossing->type == GTK_CROSSING_ACTIVE)
update_focus (controller, crossing);
}
+10 -15
View File
@@ -238,28 +238,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 +269,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 +291,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 +331,7 @@ gtk_event_controller_scroll_handle_hold_event (GtkEventController *controller,
break;
}
return handled;
return GDK_EVENT_PROPAGATE;
}
static gboolean
+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.
+46 -15
View File
@@ -236,6 +236,7 @@ struct _GtkFileChooserWidget
LocationMode location_mode;
GtkWidget *external_entry;
GtkEventController *external_entry_controller;
GtkWidget *choice_box;
GHashTable *choices;
@@ -2193,7 +2194,9 @@ 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 ||
impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
gtk_widget_set_sensitive (button, sensitive);
g_object_unref (files);
@@ -2300,6 +2303,28 @@ forward_key (GtkEventControllerKey *key,
return gtk_event_controller_key_forward (key, GTK_WIDGET (impl));
}
static void
external_entry_setup (GtkFileChooserWidget *impl)
{
/* Make keybindings (for example, Ctrl+H to toggle showing hidden files)
* work even when the focus is on the external entry (which is outside
* the hierarchy of GtkFileChooserWidget) */
impl->external_entry_controller = gtk_event_controller_key_new ();
gtk_event_controller_set_propagation_phase (impl->external_entry_controller,
GTK_PHASE_BUBBLE);
g_signal_connect (impl->external_entry_controller, "key-pressed",
G_CALLBACK (forward_key), impl);
gtk_widget_add_controller (impl->external_entry, impl->external_entry_controller);
}
static void
external_entry_disconnect (GtkFileChooserWidget *impl)
{
gtk_widget_remove_controller (impl->external_entry, impl->external_entry_controller);
impl->external_entry_controller = NULL;
}
/* Creates the widgets specific to Save mode */
static void
save_widgets_create (GtkFileChooserWidget *impl)
@@ -2321,10 +2346,7 @@ save_widgets_create (GtkFileChooserWidget *impl)
impl->location_entry = impl->external_entry;
g_object_add_weak_pointer (G_OBJECT (impl->external_entry), (gpointer *)&impl->location_entry);
location_entry_setup (impl);
g_signal_connect_after (gtk_entry_get_key_controller (GTK_ENTRY (impl->external_entry)),
"key-pressed",
G_CALLBACK (forward_key), impl);
external_entry_setup (impl);
return;
}
@@ -2361,9 +2383,7 @@ save_widgets_destroy (GtkFileChooserWidget *impl)
{
if (impl->external_entry && impl->external_entry == impl->location_entry)
{
g_signal_handlers_disconnect_by_func (gtk_entry_get_key_controller (GTK_ENTRY (impl->external_entry)),
forward_key, impl);
external_entry_disconnect (impl);
location_entry_disconnect (impl);
impl->location_entry = NULL;
}
@@ -3102,7 +3122,6 @@ gtk_file_chooser_widget_dispose (GObject *object)
GtkFileChooserWidget *impl = (GtkFileChooserWidget *) object;
cancel_all_operations (impl);
g_clear_pointer (&impl->rename_file_popover, gtk_widget_unparent);
g_clear_pointer (&impl->browse_files_popover, gtk_widget_unparent);
g_clear_object (&impl->extra_widget);
@@ -3110,6 +3129,7 @@ gtk_file_chooser_widget_dispose (GObject *object)
if (impl->external_entry && impl->location_entry == impl->external_entry)
{
external_entry_disconnect (impl);
location_entry_disconnect (impl);
impl->external_entry = NULL;
}
@@ -4748,9 +4768,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));
@@ -5440,7 +5466,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
* So we want the selection to be "bar/foo.txt". Jump to the case for the
* filename entry to see if that is the case.
*/
if (info.result == NULL && impl->location_entry)
if (g_list_model_get_n_items (G_LIST_MODEL (info.result)) == 0 && impl->location_entry)
goto file_entry;
}
else if (impl->location_entry &&
@@ -5458,7 +5484,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
goto out;
if (!is_well_formed)
return NULL;
goto empty;
if (info.file_from_entry)
{
@@ -5468,7 +5494,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
else if (!file_list_seen)
goto file_list;
else
return NULL;
goto empty;
}
else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
goto file_list;
@@ -5489,7 +5515,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
* then we fall back to the current directory
*/
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
info.result == NULL)
g_list_model_get_n_items (G_LIST_MODEL (info.result)) == 0)
{
GFile *current_folder;
@@ -5500,6 +5526,11 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
}
return G_LIST_MODEL (info.result);
empty:
g_list_store_remove_all (info.result);
return G_LIST_MODEL (info.result);
}
/* Shows or hides the filter widgets */
@@ -7841,11 +7872,11 @@ gtk_file_chooser_widget_set_save_entry (GtkFileChooserWidget *impl,
g_return_if_fail (GTK_IS_FILE_CHOOSER_WIDGET (impl));
g_return_if_fail (entry == NULL || GTK_IS_FILE_CHOOSER_ENTRY (entry));
impl->external_entry = entry;
if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
save_widgets_destroy (impl);
impl->external_entry = entry;
save_widgets_create (impl);
}
}
+5 -3
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;
@@ -338,7 +339,7 @@ parser_end_element (GtkBuildableParseContext *context,
{
SubParserData *data = (SubParserData*)user_data;
if (data->string)
if (data->string && data->parsing)
{
switch (data->type)
{
@@ -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
+13 -13
View File
@@ -72,8 +72,8 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
static FlattenNode *
gtk_flatten_list_model_get_nth (GtkRbTree *tree,
guint position,
guint *model_position)
guint position,
guint *model_position)
{
FlattenNode *node, *tmp;
guint model_n_items;
@@ -110,8 +110,8 @@ gtk_flatten_list_model_get_nth (GtkRbTree *tree,
static FlattenNode *
gtk_flatten_list_model_get_nth_model (GtkRbTree *tree,
guint position,
guint *items_before)
guint position,
guint *items_before)
{
FlattenNode *node, *tmp;
guint before;
@@ -202,11 +202,11 @@ G_DEFINE_TYPE_WITH_CODE (GtkFlattenListModel, gtk_flatten_list_model, G_TYPE_OBJ
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_flatten_list_model_model_init))
static void
gtk_flatten_list_model_items_changed_cb (GListModel *model,
guint position,
guint removed,
guint added,
gpointer _node)
gtk_flatten_list_model_items_changed_cb (GListModel *model,
guint position,
guint removed,
guint added,
gpointer _node)
{
FlattenNode *node = _node, *parent, *left;
GtkFlattenListModel *self = node->list;
@@ -323,10 +323,10 @@ gtk_flatten_list_model_set_property (GObject *object,
}
static void
gtk_flatten_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
gtk_flatten_list_model_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkFlattenListModel *self = GTK_FLATTEN_LIST_MODEL (object);
+1 -1
View File
@@ -1291,7 +1291,7 @@ gtk_grid_view_set_factory (GtkGridView *self,
GtkListItemFactory *factory)
{
g_return_if_fail (GTK_IS_GRID_VIEW (self));
g_return_if_fail (factory == NULL || GTK_LIST_ITEM_FACTORY (factory));
g_return_if_fail (factory == NULL || GTK_IS_LIST_ITEM_FACTORY (factory));
if (factory == gtk_list_item_manager_get_factory (self->item_manager))
return;
+1 -1
View File
@@ -54,7 +54,7 @@
* maximize and close buttons, or the window icon.
*
* For these reasons, `GtkHeaderBar` is the natural choice for use as the
* custom titlebar widget of a `GtkWindow (see [method@Gtk.Window.set_titlebar]),
* custom titlebar widget of a `GtkWindow` (see [method@Gtk.Window.set_titlebar]),
* as it gives features typical of titlebars while allowing the addition of
* child widgets.
*
+28 -10
View File
@@ -132,7 +132,9 @@ gtk_image_definition_new_paintable (GdkPaintable *paintable)
GtkImageDefinition *
gtk_image_definition_ref (GtkImageDefinition *def)
{
def->empty.ref_count++;
GtkImageDefinitionEmpty *empty = (GtkImageDefinitionEmpty *) def;
empty->ref_count++;
return def;
}
@@ -140,9 +142,11 @@ gtk_image_definition_ref (GtkImageDefinition *def)
void
gtk_image_definition_unref (GtkImageDefinition *def)
{
def->empty.ref_count--;
GtkImageDefinitionEmpty *empty = (GtkImageDefinitionEmpty *) def;
if (def->empty.ref_count > 0)
empty->ref_count--;
if (empty->ref_count > 0)
return;
switch (def->type)
@@ -152,13 +156,22 @@ gtk_image_definition_unref (GtkImageDefinition *def)
g_assert_not_reached ();
break;
case GTK_IMAGE_PAINTABLE:
g_object_unref (def->paintable.paintable);
{
GtkImageDefinitionPaintable *paintable = (GtkImageDefinitionPaintable *) def;
g_object_unref (paintable->paintable);
}
break;
case GTK_IMAGE_ICON_NAME:
g_free (def->icon_name.icon_name);
{
GtkImageDefinitionIconName *icon_name = (GtkImageDefinitionIconName *) def;
g_free (icon_name->icon_name);
}
break;
case GTK_IMAGE_GICON:
g_object_unref (def->gicon.gicon);
{
GtkImageDefinitionGIcon *gicon = (GtkImageDefinitionGIcon *) def;
g_object_unref (gicon->gicon);
}
break;
}
@@ -189,27 +202,32 @@ gtk_image_definition_get_scale (const GtkImageDefinition *def)
const char *
gtk_image_definition_get_icon_name (const GtkImageDefinition *def)
{
const GtkImageDefinitionIconName *icon_name = (const GtkImageDefinitionIconName *) def;
if (def->type != GTK_IMAGE_ICON_NAME)
return NULL;
return def->icon_name.icon_name;
return icon_name->icon_name;
}
GIcon *
gtk_image_definition_get_gicon (const GtkImageDefinition *def)
{
const GtkImageDefinitionGIcon *gicon = (const GtkImageDefinitionGIcon *) def;
if (def->type != GTK_IMAGE_GICON)
return NULL;
return def->gicon.gicon;
return gicon->gicon;
}
GdkPaintable *
gtk_image_definition_get_paintable (const GtkImageDefinition *def)
{
const GtkImageDefinitionPaintable *paintable = (const GtkImageDefinitionPaintable *) def;
if (def->type != GTK_IMAGE_PAINTABLE)
return NULL;
return def->paintable.paintable;
return paintable->paintable;
}
+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;
}
+54 -22
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;
@@ -172,6 +174,9 @@ text_input_preedit_apply (GtkIMContextWaylandGlobal *global)
return;
context = GTK_IM_CONTEXT_WAYLAND (global->current);
if (context->pending_preedit.text == NULL &&
context->current_preedit.text == NULL)
return;
state_change = ((context->pending_preedit.text == NULL)
!= (context->current_preedit.text == NULL));
@@ -207,11 +212,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 +241,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 +252,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 +266,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 +292,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;
@@ -357,11 +363,13 @@ notify_cursor_location (GtkIMContextWayland *context)
{
GtkIMContextWaylandGlobal *global;
cairo_rectangle_int_t rect;
double x, y;
double x, y, sx, sy;
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,
@@ -369,8 +377,11 @@ notify_cursor_location (GtkIMContextWayland *context)
rect.x, rect.y,
&x, &y);
rect.x = x;
rect.y = y;
gtk_native_get_surface_transform (gtk_widget_get_native (context->widget),
&sx, &sy);
rect.x = x + sx;
rect.y = y + sy;
zwp_text_input_v3_set_cursor_rectangle (global->text_input,
rect.x, rect.y,
rect.width, rect.height);
@@ -449,6 +460,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,
@@ -546,16 +559,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 ();
@@ -566,7 +584,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;
}
}
@@ -884,17 +913,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)
+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++)
{
+16
View File
@@ -247,6 +247,22 @@ gtk_list_item_new (void)
return g_object_new (GTK_TYPE_LIST_ITEM, NULL);
}
void
gtk_list_item_do_notify (GtkListItem *list_item,
gboolean notify_item,
gboolean notify_position,
gboolean notify_selected)
{
GObject *object = G_OBJECT (list_item);
if (notify_item)
g_object_notify_by_pspec (object, properties[PROP_ITEM]);
if (notify_position)
g_object_notify_by_pspec (object, properties[PROP_POSITION]);
if (notify_selected)
g_object_notify_by_pspec (object, properties[PROP_SELECTED]);
}
/**
* gtk_list_item_get_item: (attributes org.gtk.Method.get_property=item)
* @self: a `GtkListItem`
-4
View File
@@ -162,9 +162,5 @@ gtk_list_item_factory_update (GtkListItemFactory *self,
list_item = gtk_list_item_widget_get_list_item (widget);
g_object_freeze_notify (G_OBJECT (list_item));
GTK_LIST_ITEM_FACTORY_GET_CLASS (self)->update (self, widget, list_item, position, item, selected);
g_object_thaw_notify (G_OBJECT (list_item));
}
+1 -1
View File
@@ -825,7 +825,7 @@ gtk_list_item_manager_set_factory (GtkListItemManager *self,
GSList *l;
g_return_if_fail (GTK_IS_LIST_ITEM_MANAGER (self));
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (factory));
g_return_if_fail (factory == NULL || GTK_IS_LIST_ITEM_FACTORY (factory));
if (self->factory == factory)
return;
+5
View File
@@ -40,6 +40,11 @@ struct _GtkListItem
GtkListItem * gtk_list_item_new (void);
void gtk_list_item_do_notify (GtkListItem *list_item,
gboolean notify_item,
gboolean notify_position,
gboolean notify_selected);
G_END_DECLS
+23 -16
View File
@@ -485,20 +485,27 @@ gtk_list_item_widget_update (GtkListItemWidget *self,
gboolean selected)
{
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
gboolean was_selected;
was_selected = priv->selected;
if (priv->list_item)
gtk_list_item_factory_update (priv->factory, self, position, item, selected);
else
gtk_list_item_widget_default_update (self, NULL, position, item, selected);
if (selected)
gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE);
else
gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED);
/* don't look at selected variable, it's not reentrancy safe */
if (was_selected != priv->selected)
{
if (priv->selected)
gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE);
else
gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED);
gtk_accessible_update_state (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_STATE_SELECTED, selected,
-1);
gtk_accessible_update_state (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_STATE_SELECTED, priv->selected,
-1);
}
}
void
@@ -554,29 +561,29 @@ gtk_list_item_widget_default_update (GtkListItemWidget *self,
gpointer item,
gboolean selected)
{
/* Track notify manually instead of freeze/thaw_notify for performance reasons. */
gboolean notify_item = FALSE, notify_position = FALSE, notify_selected = FALSE;
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
/* FIXME: It's kinda evil to notify external objects from here... */
if (g_set_object (&priv->item, item))
{
if (list_item)
g_object_notify (G_OBJECT (list_item), "item");
}
notify_item = TRUE;
if (priv->position != position)
{
priv->position = position;
if (list_item)
g_object_notify (G_OBJECT (list_item), "position");
notify_position = TRUE;
}
if (priv->selected != selected)
{
priv->selected = selected;
if (list_item)
g_object_notify (G_OBJECT (list_item), "selected");
notify_selected = TRUE;
}
if (list_item)
gtk_list_item_do_notify (list_item, notify_item, notify_position, notify_selected);
}
void
+1 -1
View File
@@ -1032,7 +1032,7 @@ gtk_list_view_set_factory (GtkListView *self,
GtkListItemFactory *factory)
{
g_return_if_fail (GTK_IS_LIST_VIEW (self));
g_return_if_fail (factory == NULL || GTK_LIST_ITEM_FACTORY (factory));
g_return_if_fail (factory == NULL || GTK_IS_LIST_ITEM_FACTORY (factory));
if (factory == gtk_list_item_manager_get_factory (self->item_manager))
return;
+1 -3
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
}
+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);
}
}
+12 -12
View File
@@ -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)
+2 -1
View File
@@ -921,7 +921,8 @@ create_cloud_provider_account_row (GtkPlacesSidebar *sidebar,
g_free (tooltip);
g_free (mount_uri);
g_object_unref (end_icon);
g_clear_object (&end_icon);
return TRUE;
}
else

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