Compare commits

...

416 Commits

Author SHA1 Message Date
Guillaume Bernard 904e6a03a5 Update French translation 2023-03-16 10:24:29 +00:00
Emin Tufan Çetin 5fe6a571c4 Update Turkish translation 2023-01-11 07:04:38 +00:00
Nart Tlisha 73cba4a355 Add Abkhazian translation 2023-01-06 10:36:02 +00:00
Nart Tlisha 1477fa55e9 Add Abkhazian translation 2023-01-06 09:59:08 +00:00
Matthias Clasen 14995af52b 4.6.9 2022-12-22 23:04:48 -05:00
Matthias Clasen a22de46b4a Merge branch 'cherry-pick-4.6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!5337
2022-12-15 16:17:22 +00:00
Matthias Clasen 2eb252199c text: Prevent unexpected notify::direction emissions
Calling gdk_device_get_direction can trigger a
notify::direction emissions, since the X11 backend
determines the direction on demand. Prevent that by
forcing the direction to be determined ahead of time.

Fixes: #5311
2022-12-15 01:16:09 +02:00
Matthias Clasen 6c8c30b249 a11y: Be safe against state type changes
For some of the a11y states, calling gtk_accessible_reset_state
can change the type of the state value from boolean or tristate
to undefined.

Handle that, instead of throwing criticals.

Related: !4910
2022-12-15 01:13:52 +02:00
Carlos Garnacho 25a47cedde gdk/x11: Clear all data in GdkSurfaceX11 finalization
Currently, the GdkSurfaceX11 implementation relies that the upper
layers hid the surface before destruction, and that no
GdkSurfaceClass.compute_resize happened between them. If these
circumstances happened, there would be a compute_size timeout left
dangling after the surface got destroyed, poking at incorrect data
later on. Something that looks like this was reported in the
recent mutter-x11-frames "SSD frames server":

    mutter-x11-frames:423016): GLib-GObject-WARNING **: 19:41:16.869: invalid unclassed pointer in cast to 'GtkWindow'

    Thread 1 "mutter-x11-fram" received signal SIGTRAP, Trace/breakpoint trap.
    g_logv (log_domain=0x7ffff7f7c4f8 "GLib-GObject", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=<optimized out>) at ../../../glib/gmessages.c:1433
    1433	../../../glib/gmessages.c: No such file or directory.
    (gdb) bt
    #0  g_logv (log_domain=0x7ffff7f7c4f8 "GLib-GObject", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=<optimized out>) at ../../../glib/gmessages.c:1433
    #1  0x00007ffff73470ff in g_log (log_domain=log_domain@entry=0x7ffff7f7c4f8 "GLib-GObject", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x7ffff7f84da8 "invalid unclassed pointer in cast to '%s'")
        at ../../../glib/gmessages.c:1471
    #2  0x00007ffff7f72892 in g_type_check_instance_cast (type_instance=type_instance@entry=0x5555558e04b0, iface_type=<optimized out>) at ../../../gobject/gtype.c:4144
    #3  0x00007ffff791e77d in toplevel_compute_size (toplevel=<optimized out>, size=0x7fffffffe170, widget=0x5555558e04b0) at ../../../gtk/gtkwindow.c:4227
    #4  0x00007ffff7f4f3b0 in g_closure_invoke (closure=0x555555898cc0, return_value=return_value@entry=0x0, n_param_values=2, param_values=param_values@entry=0x7fffffffdeb0, invocation_hint=invocation_hint@entry=0x7fffffffde30)
        at ../../../gobject/gclosure.c:832
    #5  0x00007ffff7f62076 in signal_emit_unlocked_R
        (node=node@entry=0x55555588feb0, detail=detail@entry=0, instance=instance@entry=0x55555560e990, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffdeb0)
        at ../../../gobject/gsignal.c:3796
    #6  0x00007ffff7f68bf5 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffe050) at ../../../gobject/gsignal.c:3549
    #7  0x00007ffff7f68dbf in <emit signal ??? on instance 0x55555560e990 [GdkX11Toplevel]> (instance=<optimized out>, signal_id=<optimized out>, detail=detail@entry=0) at ../../../gobject/gsignal.c:3606
    #8  0x00007ffff7a8de96 in gdk_toplevel_notify_compute_size (toplevel=<optimized out>, size=size@entry=0x7fffffffe170) at ../../../gdk/gdktoplevel.c:112
    #9  0x00007ffff7a4b15a in compute_toplevel_size (surface=surface@entry=0x55555560e990 [GdkX11Toplevel], update_geometry=update_geometry@entry=1, width=width@entry=0x7fffffffe220, height=height@entry=0x7fffffffe224)
        at ../../../gdk/x11/gdksurface-x11.c:281
    #10 0x00007ffff7a4c3b2 in compute_size_idle (user_data=0x55555560e990) at ../../../gdk/x11/gdksurface-x11.c:356
    #11 0x00007ffff733f67f in g_main_dispatch (context=0x55555563f6e0) at ../../../glib/gmain.c:3444
    #12 g_main_context_dispatch (context=context@entry=0x55555563f6e0) at ../../../glib/gmain.c:4162
    #13 0x00007ffff733fa38 in g_main_context_iterate (context=0x55555563f6e0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../../../glib/gmain.c:4238
    #14 0x00007ffff733fcef in g_main_loop_run (loop=loop@entry=0x5555560874a0) at ../../../glib/gmain.c:4438
    #15 0x0000555555557de0 in main (argc=<optimized out>, argv=<optimized out>) at ../src/frames/main.c:68

It perhaps makes sense to warn in these situations, but either way
it sounds like gdk_surface_x11_finalize() could enforce the correct
behavior by ensuring there is no dangling timeouts/data. This commit
does that.
2022-12-14 23:41:36 +02:00
Matthias Clasen d0eee04409 Don't emit ::notify from a getter
GdkX11Keymap ddetermines the direction of the
keymap on demand, and was emitting notify::direction
2022-12-14 23:36:20 +02:00
Benjamin Otte a089bc075e Merge branch 'cherry-pick-a619e48' into 'gtk-4-6'
[4.6] GLX: Add extra glXMakeContextCurrent () call to work around a DRI issue

See merge request GNOME/gtk!5288
2022-12-03 11:07:21 +00:00
Luca Bacci a619e48a67 GLX: Add extra glXMakeContextCurrent () call to work around a DRI issue
Reference: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7808

Fixes #4499, #5387, #5170
2022-12-02 19:45:38 +02:00
Matthias Clasen b7ce33e83f Merge branch 'cherry-pick-4.6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!5214
2022-11-17 04:20:12 +00:00
Zurab Kargareteli 91cddf2d48 Update Georgian translation 2022-11-13 22:38:06 +00:00
Adam Williamson 8d7bde0e8a focus: fall back to old behaviour if we didn't focus anything
8455b9ac74 seems to have introduced a problem where we can wind
up focusing no widget at all if the `while (parent)` loop doesn't
find a widget it can successfully move the focus to. This 'fixes'
that by falling back to doing the previous thing if we make it
all the way through that loop without moving the focus. Thanks to
@coreyberla for a hint to improve the implementation.

Signed-off-by: Adam Williamson <awilliam@redhat.com>
2022-11-12 03:55:53 +02:00
Carlos Garnacho 799da2883a gdk/wayland: Fix button mask calculation on button events
There's 2 things broken here:
- The mask was calculated on top of the GDK button (i.e. skipping
  4-7 buttons), so GDK_BUTTON4_MASK and GDK_BUTTON5_MASK were not
  assigned. This is now calculated on the (continuous) BTN_ evcodes
  so it is guaranteed that the next 2 physical buttons (i.e.
  back/forward) get these two places in the mask assigned.
- Furthermore, these buttons would be pushed to places in the
  modifier mask that they didn't belong to. It is now checked hard
  that only the first 5 buttons enable a modifier flag.

Overall, this ensures that no event masks with bonkers values are
forwarded, and that no stale implicit grabs are left after additional
buttons are pressed.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5301
2022-11-12 03:55:41 +02:00
Kukuh Syafaat 2282e9f418 Update Indonesian translation 2022-11-03 03:49:18 +00:00
Matthias Clasen 18ff344464 Merge branch 'revert-cde32368f0eb4f83de8f5b1a443195a4aa15d874' into 'gtk-4-6'
[4.6] Revert "treepopover: Do not propagate natural width of content"

See merge request GNOME/gtk!5092
2022-10-26 22:08:00 +00:00
Matthias Clasen e5099da12d Post-release version bump 2022-10-24 13:46:17 -04:00
Matthias Clasen 73bea05c33 4.6.8 2022-10-24 08:55:31 -04:00
Matthias Clasen 9eec8e9e45 Merge branch 'fix-focus-4-6' into 'gtk-4-6'
[4.6] window: Fix focus updates

See merge request GNOME/gtk!5132
2022-10-21 17:34:01 +00:00
Matthias Clasen 2da2f7cf7f editablelabel: Defer changes on focus-out
We can get spurious focus-out/-in pairs when
the editable label is in a popover that gets
a Wayland keyboard enter event as a result of
clicking the editable label.

A timeout isn't a great solution, but nothing
better is available right now.

Fixes: #4864
2022-10-21 14:48:12 +03:00
Matthias Clasen f0906e45f2 window: Keep a reference to move_focus_widget
If we don't take a reference, it can happen that
the pointer is no longer valid by the time we
dereference it in after_paint.
2022-10-21 14:48:07 +03:00
Matthias Clasen 60399e05fb window: Don't focus invisible widgets
Only clear a queued move_focus if the widget
we are focusing is actually visible.

This was happening in some cases when popovers
are dismissed by clicking outside, and it was
causing us to miss proper focus updates that
were already queued.
2022-10-18 20:30:40 +03:00
Matthias Clasen c88f865aa7 window: Fix focus updates
This partially undoes changes from 3dbf5038fa.

That commit did two things:
1) Move the focus update to after-paint time
2) Change from grabbing focus to the visible parent
   to  calling move_focus (TAB)

The second part did have the unintended consequence
of moving focus laterally.

Fixes: #4903
2022-10-18 20:30:24 +03:00
Mat 3ecb30353a Revert "treepopover: Do not propagate natural width of content"
This reverts commit cde32368f0.
2022-10-06 19:09:13 +03:00
Matthias Clasen f464307f61 Merge branch 'wip/headless-infinite-bounds-4-6' into 'gtk-4-6'
[4.6] Fix shrinking windows on suspend/resume

See merge request GNOME/gtk!5089
2022-10-06 10:42:35 +00:00
Jonas Ådahl 92a74adc8c toplevel-size: Report zero bounds as infinite
Empty/zero bounds are sent by the Wayland compositor if there are no
valid bounds to report, e.g. if there are no connected monitors. Report
this to GTK, which uses this to clamp calculated sizes, as INT_MAX, so
that clamping isn't done until there are actual valid bounds to clamp
to.

This fixes clients sometimes shrinking to their minimum size during
hotplugs or after having suspended the session.

(cherry picked from commit b3a3a6ceb1)
2022-10-06 10:39:08 +02:00
Jonas Ådahl 0b312d878c surface/wayland: Handle no current monitor when calculating bounds
We shouldn't assume there is always a monitor to derive bounds from.
If there is no monitor, pass empty bounds, as this matches what
xdg_toplevel.configure_bounds do in this case.

(cherry picked from commit 148c133674)
2022-10-06 10:39:03 +02:00
Jürgen Benvenuti 4b5877972e Update German translation 2022-10-05 18:58:36 +00:00
Мирослав Николић 6ba7b4ad73 Update Serbian translation 2022-10-03 04:15:53 +00:00
Goran Vidović 0c3056b649 Update Croatian translation 2022-10-02 14:12:06 +00:00
Aleksandr Melman b4ba384d68 Update Russian translation 2022-10-01 15:41:20 +00:00
Goran Vidović bce7b5807a Update Croatian translation 2022-09-30 12:13:47 +00:00
Goran Vidović 7b15830fbc Update Croatian translation 2022-09-30 12:07:44 +00:00
Balázs Úr d40e55cf88 Update Hungarian translation 2022-09-29 16:41:45 +00:00
Goran Vidović acd47daa3b Update Croatian translation 2022-09-29 12:07:24 +00:00
Goran Vidović 0b7bf4c5d0 Update Croatian translation 2022-09-29 12:03:39 +00:00
Matthias Clasen 586dcb94d6 Merge branch 'cherry-pick-4.6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!5065
2022-09-29 10:25:47 +00:00
Carlos Garnacho 5db8a550db gdk/wayland: Drop surface checks on wl_pointer.leave handling
Even though the argument is non-nullable, GTK sometimes incurs in that
by itself by destroying the surface while the event is in flight. This
is the case of popping down a GtkDropdown. When this happens we simply
ignore the crossing event, but we should let it through instead, the
compositor did not send it in vain and we possibly still have pointer
state to undo.

Drop the surface checks, so that the event is propagated along GTK.
2022-09-29 01:58:02 +03:00
Carlos Garnacho 06afb5d354 gtkimcontextwayland: Shuffle full resets after IM changes
Doing reset() on the text widgets after commit and delete_surrounding
is still too eager for some IMs (e.g. those that expect being able
to commit text while keeping a preedit buffer shown).

However, reset() is more of a "synchronize state" action on Wayland,
and it is still desirable to do that after changes that do come from
the IM (e.g. requesting the new surrounding text and cursor/anchor
positions). Notably here, the text_input protocol may still come up
with a preedit string after this state synchronization happens.

Shuffle the code so that the text widgets do not reset() the IM
context after text is deleted or committed, but the Wayland IM does
apply its practical effects after these actions happen. This keeps
the Wayland IM fully up-to-date wrt text widget state, while not
altering the ::commit and ::delete-surrounding-text behavior for
other IM context implementations.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5200
Fixes: 5b78fe2721 (gtktextview: Also reset IM context after IM...)
Fixes: 7c0a395ff9 (gtktext: Also reset IM context after IM...)
Fixes: 52ac71b972 (gtktextview: Shuffle the places doing IM reset)
Fixes: 9e29739e66 (gtktext: Shuffle the places doing IM reset)
2022-09-29 01:58:02 +03:00
Simon McVittie 42a309f1a5 gdkevents: Don't ignore modifiers that are not currently active
The X11 backend can mark modifiers like Shift as consumed even if they
aren't actually active, which seems to be something to do with making
shortcuts like `<Control><Shift>plus` and `<Control>plus` work as
intended regardless of whether the plus symbol is obtained by pressing
Shift and a key (like `+/=` on American, British or French keyboards)
or not (like `*/+` on German keyboards).

However, this can go badly wrong when the modifier is *not* pressed.
For example, terminals normally have separate bindings for `<Control>c`
(send SIGINT) and `<Control><Shift>c` (copy). If we disregard the
consumed modifiers completely, when the X11 backend marks Shift as
consumed, pressing Ctrl+c would send SIGINT *and* copy to the clipboard,
which is not what was intended.

By masking out the members of `consumed` that are not in `state`, we
get the same interpretation for X11 and Wayland, and ensure that
keyboard shortcuts that explicitly mention Shift can only be triggered
while holding Shift. It continues to be possible to trigger keyboard
shortcuts that do not explicitly mention Shift (such as `<Control>plus`)
while holding Shift, if the backend reports Shift as having been
consumed in order to generate the plus keysym.

Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/5095
Bug-Debian: https://bugs.debian.org/1016927
Signed-off-by: Simon McVittie <smcv@debian.org>
2022-09-29 01:58:02 +03:00
Matthias Clasen e92e4c5728 portal: Use the right mimetype for file transfers
The filetransfer protocol says to use
application/vnd.portal.filetransfer, but I used
application/vnd.portal.files when I implemented the
protocol. Oops.

This commit dds the correct mimetype, but we still
support the old one to preserve interoperatibility
with existing flatpaks using GTK 4.6.

Fixes: #5182
2022-09-29 01:58:02 +03:00
Corey Berla 8d771eb26c gridview: Fix rubberbanding from negative x coordinates
This is a follow-up to 1e9a36ffa8. For GridView
we also need to make sure that we aren't rubberbanding below x=0 which
causes unexpected rubberbanding behavior.

Fixes: https://gitlab.gnome.org/GNOME/nautilus/-/issues/2492
2022-09-29 01:58:02 +03:00
Matthias Clasen 7aab4acecc filechooser: Restore ~ and . functionality
We'll have to keep patching up these things
until somebody rewrites the file chooser :(

Inspired by: !4970
2022-09-29 01:58:02 +03:00
Matthias Clasen 23d8b6063c Handle absence of portals
When the documents portal is not on the bus,
we still get an (unowned) proxy, and we need
to handle that situation.
2022-09-29 01:17:51 +03:00
Matthias Clasen af831e488b portals: Fix FileTransfer portal calls
We were not passing the right arguments to
the AddFiles call, causing the file transfer
to fail.
2022-09-29 01:17:35 +03:00
Matthias Clasen 11e90e4fa0 Make the file transfer portal setup sync again
We need to register the portal mime types before
the others to prefer them, doing this call async
messes up that ordering.

This is effectively reverting 69fb3648b2
2022-09-29 01:17:12 +03:00
Matthias Clasen 0b200e393f Stop recursion in registering serializers
This was probably unintentional, and messes up
the ordering of our registration.
2022-09-29 01:16:36 +03:00
Hugo Carvalho a18f52b7d4 Update Portuguese translation 2022-09-28 13:18:13 +00:00
Aurimas Černius 65e6846500 Updated Lithuanian translation 2022-09-27 22:22:36 +03:00
Rafael Fontenelle eabe4fd79b Update Brazilian Portuguese translation 2022-09-27 13:08:07 +00:00
Martin bdac484224 Update Slovenian translation 2022-09-27 08:47:01 +00:00
Piotr Drąg dcbba58487 Update Polish translation 2022-09-26 17:59:35 +02:00
Anders Jonsson e0c3d09e50 Update Swedish translation 2022-09-26 15:59:15 +00:00
Yuri Chornoivan cf11438f2f Update Ukrainian translation 2022-09-26 15:54:28 +00:00
Matthias Clasen 64891e11d4 Merge branch 'backport-4577' into 'gtk-4-6'
Make the presentation of the stack sidebar listbox nicer for A11Y

See merge request GNOME/gtk!5056
2022-09-26 15:50:34 +00:00
Lukáš Tyrychtr 447d79d908 Make the presentation of the stack sidebar listbox nicer for A11Y
This backports the fix for #4577.
2022-09-26 17:32:13 +02:00
Marek Černocký d7dbefa664 Updated Czech translation 2022-09-23 16:22:15 +02:00
Christian Kirbach 3d4685fca3 Update German translation 2022-09-18 12:28:27 +00:00
Martin ff83daa700 Update Slovenian translation 2022-09-18 11:08:34 +00:00
Emin Tufan Çetin 0ed327ba0e Update Turkish translation 2022-09-18 08:23:28 +00:00
Matthias Clasen 5fe9faf2e3 Merge branch 'cherry-pick-4.6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!5025
2022-09-12 23:33:54 +00:00
Matthias Clasen 7b15c68cd0 emojichooser: Fix arrow keynav
When some of the Emoji have been filtered out by
a search term, arrow keynav would behave oddly and
get stuck in invisible sections. Fix this by ignoring
any filtered out children when moving between
sections for arrow keynav.

Fixes: #5076
2022-09-12 23:00:00 +03:00
Matthias Clasen 75fed298b8 Add a test for treelistmodel row collapse
Test that we can expand and collapse a row, and then
add another child below it, without crashing.

Adapted from the testcase in #4595.

This tests the fix in the previous commit.
2022-09-12 22:58:11 +03:00
Matthias Clasen d21112a3ce treelistmodel: Fix handling of collapsed nodes
When we collapse a node, we clear out the children,
but we were not disconnecting the signal handler on
the child listmodel, leading to bad outcomes when
that model is persistent and changing.

Fixes: #4595
2022-09-12 22:57:53 +03:00
Carlos Garnacho 083d023b6b gtkwindow: Use pointer-oriented function to deal with crossing events
Commit adba0b97 fixed missed pointer crossings by using a helper function that
was already present and looked like did everything that was needed. However
this function was oriented to keyboard focus and it also did update the related
widget state. Doing these changes on pointer-based crossing was misuse, and
could cause weird interactions with keyboard focus management.

Fix this by using gtkmain.c gtk_synthesize_crossing_event() that is in fact
oriented to pointers.

Fixes: adba0b97 (gtkwindow: Synthesize pointer crossing events on state changes)
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5094
2022-09-12 22:49:57 +03:00
Georges Basile Stavracas Neto 89fc4efe6f paned: Warn if child is not actually a child
This will at least allow us to debug this in the future.
2022-09-12 22:49:13 +03:00
Georges Basile Stavracas Neto 7604eb1e39 paned: Protect against NULL variable
The inner loop in gtk_paned_set_focus_child() tries to find the
topmost GtkPaned, however, if the `w` variable ends up becoming
NULL after bubbling up the entire GtkWidget hierarchy, this loop
never breaks.

Check for NULL in this loop.

Closes https://gitlab.gnome.org/GNOME/gtk/-/issues/5094
2022-09-12 22:48:50 +03:00
Carlos Garnacho fda50855c6 gtkmain: Pass coordinates when synthesizing pointer events
Instead of passing an event and figuring out coordinates from it, pass
directly the toplevel coordinates so that we can use this outside event
handling.

All callers have been updated to pass the coordinates, in practical effects
they were already based on the GtkNative.
2022-09-12 22:48:38 +03:00
Carlos Garnacho dd82df9e32 gtkwindow: Synthesize pointer crossing events on state changes
When widgets go mapped/unmapped, we repick but don't generate crossing
events. Since there could be stateful controllers that use those in
the previously picked widget (e.g. GtkEventControllerMotion), skipping
those breaks their state.

Ensure to send the relevant crossing events on every situation that
changes the pointer focus, so these controllers get a fair opportunity
to undo their state.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/2877
2022-09-12 22:47:46 +03:00
Carlos Garnacho 1a459c5dcd gtktextview: Also reset IM context after IM surrounding text deletion
When the IM commands the GtkText to delete text, the cursor position
would change, and so would the surrounding text. Reset the IM context
so that these updates are properly picked up by the IM.

Fixes backspace	key behavior in	the GNOME Shell OSK, since that	relies
on the surrounding text	being properly updated for the next iteration.
2022-09-12 22:42:15 +03:00
Carlos Garnacho 735f803c2f gtktext: Also reset IM context after IM surrounding text deletion
When the IM commands the GtkText to delete text, the cursor position
would change, and so would the surrounding text. Reset the IM context
so that these updates are properly picked up by the IM.

Fixes backspace key behavior in the GNOME Shell OSK, since that relies
on the surrounding text being properly updated for the next iteration.
2022-09-12 22:42:01 +03:00
Carlos Garnacho 452d93c7ea gtktext: Avoid early IM reset on updates
Resetting the IM on IM updates is too eager and indeed the simple
IM context doesn't like that this happens in the middle of dead
key handling.

We however want to reset the IM after actual text buffer changes
(say, a committed string) moved the cursor position, altered the
surrounding text, etc. So that the IM implementation does know to
update its state.

Since there is going to be an actual IM reset anyways, it does
no longer make sense to try to preserve the old priv->need_im_reset
status during commit handling.

Fixes: 52ac71b972 ("gtktextview: Shuffle the places doing IM reset")
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5133
2022-09-12 22:41:45 +03:00
Carlos Garnacho c4f5358826 gtktext: Avoid early IM reset on updates
Resetting the IM on IM updates is too eager and indeed the simple
IM context doesn't like that this happens in the middle of dead
key handling.

We however want to reset the IM after actual text buffer changes
(say, a committed string) moved the cursor position, altered the
surrounding text, etc. So that the IM implementation does know to
update its state.

Fixes: 9e29739e66 ("gtktext: Shuffle the places doing IM reset")
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5133
2022-09-12 22:41:27 +03:00
Matthias Clasen d3e181f7de Make gtk_launch_uri more robust
We were failing to launch the uri if we are on
Wayland, but have no xdg_foreign protocol support.

Fixes: #5152
2022-09-12 22:38:15 +03:00
Mat cde32368f0 treepopover: Do not propagate natural width of content
Propagating the natural width of the tree popover contents breaks ellipsizing of items
(see 'Unconstrained menu' in tests/testcombo).
2022-09-12 22:37:18 +03:00
Matthias Clasen da82eb8e1c Merge branch 'cherry-pick-4.6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!5001
2022-09-06 20:13:56 +00:00
Balázs Úr 40e639fb6e Update Hungarian translation 2022-09-02 21:27:19 +00:00
Mat e3a23a9a9d treeview: Don't claim event sequence too early
We want to claim the event sequence in the click gesture when appropriate,
such as activating a row or clicking an editable cell, but this is currently
done too early, preventing other gestures for drag-and-drop and rubberband
selection entirely.

Fixes #3649
Fixes #3985
Fixes #4669
2022-09-02 17:01:37 +03:00
Matthias Clasen 8558560030 Merge branch 'cherry-pick-4.6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!4997
2022-09-01 17:24:15 +00:00
Matej Urbančič 52483b88ce Update Slovenian translation 2022-08-31 18:33:51 +00:00
Mat 2bb0d815ee gtknotebook: update arrow button state when reordering tabs
When reordering notebook tabs, updating the sensitivity state of the
arrow buttons is necessary if the tab is moved to the beginning or
end of the tab list.
2022-08-30 16:55:39 +03:00
Mat 887c743e3d gtknotebook: Claim event sequence after pressing notebook arrow buttons
When notebook tabs are reorderable, pressing the notebook arrow buttons to
change the active tab results in tabs reordering unexpectedly.
Claim the event sequence after pressing an arrow button to avoid conflicts
with the motion/drag gesture used for reordering.
2022-08-30 16:55:27 +03:00
Mat 3e5bbfb2a5 gtkatspiselection: Retrieve the correct GtkNotebook tab widget
A typo resulted in the tab container widget being retrieved instead of
the tab widget. If an adjacent action widget was present, an infinite
loop occurred when switching tabs while a screen reader was enabled.
2022-08-30 16:55:11 +03:00
Mat 2ca86eb969 treeview: Always call grab_focus_without_selecting on search entry
The search text entry is always a GtkText widget, not GtkEntry. If a
custom search entry is set, this part of the code is never reached.

Fixes #4551
2022-08-30 16:54:44 +03:00
Piotr Drąg 393dd5a838 Update Polish translation 2022-08-28 23:33:51 +02:00
Goran Vidović baba8aa9a5 Update Croatian translation 2022-08-28 14:44:55 +00:00
Sveinn í Felli a27ae5362c Update Icelandic translation 2022-08-23 11:49:37 +00:00
Sveinn í Felli e6d3c58ccf Update Icelandic translation 2022-08-23 11:38:38 +00:00
Matthias Clasen 59320f4aa1 Merge branch 'gtk46-backports' into 'gtk-4-6'
text: Respect no-emoji hint fully

See merge request GNOME/gtk!4975
2022-08-22 19:55:43 +00:00
Matthias Clasen dc397fce3c css: Fix freeing of calc values
We were getting our memory allocations mixed
up here.

Fixes: #5130
2022-08-22 15:38:19 -04:00
Matthias Clasen 317d4c8f8d text: Respect no-emoji hint fully
We were disabling the insert-emoji action when the
no-emoji input hint is set, but the Ctrl-. shortcut
was bypassing the action and kept working. Make
the shortcut activate the action instead.

Fixes: #5123
2022-08-22 15:37:35 -04:00
Carlos Garnacho 8d4968afb2 Merge branch 'wip/carlosg/im-fixes-4-6' into 'gtk-4-6'
gtkimcontextwayland: Refactor handling of client updates [4.6]

See merge request GNOME/gtk!4963
2022-08-18 20:56:33 +00:00
Carlos Garnacho 519258c382 gtkimcontextwayland: Refactor handling of client updates
Currently, the wayland IM context sends zwp_text_input_v3.commit from
a number of places, and some of them with partial data. In order to
make client state updates "atomic" and complete, make the communication
happen over an unified notify_im_change() function that happens on
a narrower set of circumstances:

  - The GtkIMContext is reset
  - The GtkIMContext is just focused
  - The gesture to invoke the OSK is triggered
  - The IM context is reacting to changes coming from the compositor

Notably, setting the cursor location or the surrounding text do not try
to commit state on their own, and now will be flushed with the corresponding
IM update or reset. But also, these requests won't be prevented from
happening individually on serial mismatch, instead it will be the whole
state commit which is held off.

With these changes in place, all client-side updates are notified
atomically to the compositor under a single .commit request.

(cherry-picked from commit f66ffde68d)
2022-08-18 20:03:40 +02:00
Carlos Garnacho 34693b0d9f gtktextview: Shuffle the places doing IM reset
During text widget manipulation (inserting or deleting text via keyboard)
the IM context is reset somewhat early, before the actual change took place.
This makes IM lag behind in terms of surrounding text and cursor position.

Shuffle these IM reset calls so that they happen after the changes, and
ensure that the IM is actually reset, since that is currently toggled on
a pretty narrow set of circumstances.

Also, fix a bug during GtkEventControllerKey::im-update where the condition
on cursor position editability to reset the IM context was inverted.

(cherry-picked from commit 52ac71b972)
2022-08-18 20:03:13 +02:00
Carlos Garnacho 919128d8c2 gtktext: Shuffle the places doing IM reset
During text widget manipulation (inserting or deleting text via keyboard)
the IM context is reset somewhat early, before the actual change took place.
This makes IM lag behind in terms of surrounding text and cursor position.

Shuffle these IM reset calls so that they happen after the changes, and
ensure that the IM is actually reset, since that is currently toggled on
a pretty narrow set of circumstances.

(cherry-picked from commit 9e29739e66)
2022-08-18 20:02:53 +02:00
Zurab Kargareteli 7f26ca0c32 Update Georgian translation 2022-08-18 14:11:38 +00:00
Matthias Clasen 42b14ce5f2 4.6.7 2022-08-17 13:03:24 -04:00
Matthias Clasen 68cff22966 Merge branch 'leak-fixes-46' into 'gtk-4-6'
a11y: Fix a memory leak

See merge request GNOME/gtk!4958
2022-08-17 11:14:48 +00:00
Matthias Clasen 86a137b2ff Merge branch 'cherry-pick-4.6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!4959
2022-08-16 21:34:04 +00:00
Mat 65f51d2d16 treeview: Do not set top row adjustment value while animating
gtk_tree_view_top_row_to_dy, which is called from GtkTreeView's
size_allocate function, changes the adjustment value. Since this
conflicts with the animation when changing the active row, bail
out until the animation is finished.

Fixes #4550
2022-08-16 23:29:00 +03:00
Mat e1dcbd4442 treeview: Use widget coordinates where required
When a GtkTreeView scrolled horizontally, it was not possible to
select rows outside the initial area due to an erroneous comparison
between widget and bin window coordinates.

Original change to widget coordinates occurred in commit
a0de570e47
2022-08-16 23:28:39 +03:00
Matthias Clasen 1722b39f92 gtk4-demo: Fix a memory leak
The gears demo was leaking its vertices.
2022-08-16 08:22:53 -04:00
Matthias Clasen 96d6ff16b6 wayland: Avoid leaking cursor textures
When we fall back to the default cursor and load it
from a resource, we need to free the texture.
2022-08-16 08:22:53 -04:00
Matthias Clasen 4962b76b47 cups printbackend: Plug memory leaks
This loop has many early exits, and all of them
need to free this info object that gets allocated
at the beginning.
2022-08-16 08:22:53 -04:00
Matthias Clasen 981690b12e Add more valgrind suppressions
This gets all GQuark functions out of the logs.
2022-08-16 08:22:53 -04:00
Matthias Clasen 412e77d500 a11y: Fix a memory leak
We need to free the queued context list in dispose
if we didn't get to register the contexts, and we also
need to free the list properly when we do get to
register them.

This showed up in valgrind as leaked GList structs.
2022-08-16 08:22:53 -04:00
Zurab Kargareteli df1c6956b4 Update Georgian translation 2022-08-15 18:37:05 +00:00
Matthias Clasen 77e0b09efc Merge branch 'improve-css-test-4.6' into 'gtk-4-6'
css: Propagate charset conversion errors

See merge request GNOME/gtk!4944
2022-08-12 16:52:54 +00:00
Goran Vidović 1d6416c12b Update Croatian translation 2022-08-12 14:30:13 +00:00
Matthias Clasen 6b019d4dd0 tests: Check the error first
The error contains useful information when
things fail, so check it first to get useful
output in case of failure.
2022-08-11 20:10:48 -04:00
Matthias Clasen ac18330f65 css: Propagate charset conversion errors
Lets not throw away informtation that
helps to figure out why things fail.
2022-08-11 20:10:48 -04:00
Matthias Clasen e93a5479de Merge branch 'wip/carlosg/scroll-speed-4-6' into 'gtk-4-6'
gtkscrolledwindow: Backport scroll speed from 4.7/main

See merge request GNOME/gtk!4946
2022-08-11 23:51:02 +00:00
Carlos Garnacho 9d01189f2f gtkscrolledwindow: Backport scroll speed from 4.7/main
Only the scroll velocity factor is backported here, the scroll unit
event API is notably missing, so this implicitly applies to all smooth
scroll events.

The number also accounts for the 1/10th factor applied in GDK, compared
to the code in main.
2022-08-12 01:10:50 +02:00
Daniel Mustieles 3149f1c934 Updated Spanish translation 2022-08-08 12:45:00 +02:00
Matthias Clasen e5d3cc20d9 Merge branch 'cherry-pick-c1d6160b' into 'gtk-4-6'
Merge branch 'otte-main-patch-86462' into 'main'

See merge request GNOME/gtk!4920
2022-08-03 11:56:41 +00:00
Matthias Clasen 57f6effa1a Merge branch 'for-gtk-4-6' into 'gtk-4-6'
frameclock: Run paint idle from flush idle (backport  !4858 to 4.6)

See merge request GNOME/gtk!4918
2022-08-01 23:07:08 +00:00
Benjamin Otte 584e9f93a4 Merge branch 'otte-main-patch-86462' into 'main'
Fix g_object_new(GTK_TYPE_SNAPSHOT)

See merge request GNOME/gtk!4919

(cherry picked from commit c1d6160bd4)

09f0c96b Fix g_object_new(GTK_TYPE_SNAPSHOT)
dbab69c4 snapshot: Don't critical on dispose
2022-08-01 20:47:27 +00:00
Benjamin Otte 41396e1344 frameclock: Run paint idle from flush idle
Don't return to the main loop, instead force a run of the paint idle.
The paint idle will know to skip all the phases that aren't requested.

This is critically important becuase gdksurface.c assumes the
FLUSH_EVENTS and RESUME_EVENTS phases are matched, and we cannot
guarantee that if we return to the main loop and let various reentrant
code change the frame clock state.

This would lead to bugs with events being paused and never unpaused
again or even crashes.

Fixes #4941
2022-08-01 19:45:14 +02:00
Aleksandr Melman 36ed85cc9c Update Russian translation 2022-08-01 13:12:35 +00:00
Luca Bacci d57594c709 Merge branch 'backport-mr-4900-to-gtk-4-6' into 'gtk-4-6'
Fix DnD on Windows

See merge request GNOME/gtk!4908
2022-07-29 13:07:29 +00:00
darkcutler 5b888393e5 Fix DnD on Windows
DnD under Windows needed 3 fixes to work with Gtk.DropTarget.

1. The droptarget_w32format_contentformat_map list never gets
filled so the gdk_win32_drop_read_async throws
"No compatible transfer format found".
This is an easy fix and done the same way in the win32 clipboard code.

2. After a drop no gdk_drop_emit_leave_event gets emitted.
This causes a second drop to trigger a bunch of assertion
'self->drop == drop' failed because the first drop is still active.
This is also an easy fix and done the same way by the macos backend.

3. Handling gdk_drop_status/gdk_drop_get_actions interaction.
In gtk_drop_target_do_drop the code
```gdk_drop_finish (self->drop, gdk_drop_get_actions (self->drop));```
calls the finish operation with the actions of the drop which triggers
```g_return_if_fail (gdk_drag_action_is_unique (action));```
in gdk_drop_finish. The code assumes that GdkDrop::actions gets
narrowed down by calling gdk_drop_status. This is hard to assure
because at the same time gdk_drop_get_actions is used by
gtk_drop_target_accept to figure out if a drag is accepted.
GdkDrop::actions serves a double purpose here as the supported source
actions and the currently agreed on action. Both the x11 and the
wayland backend get this wrong somewhat too. Under wayland/x11 when
a drag coming from a source that supports both MOVE and COPY is
first hovering a drop target that only supports COPY it is afterwards
no longer accepted by other drop targets only accepting MOVE.
Under x11 this is permanent for this drag but with wayland the drag
recovers when hovering other widgets. The win32 backend now sets the
supported source actions before any enter/move/drop and narrows them
down in gdk_win32_drop_status.

The patch only touches the win32 backend and fixes all three issues,
for me restoring DnD under windows.

Closes #4498
2022-07-29 14:44:26 +02:00
Matthias Clasen 2f138ce93b Merge branch 'cherrypick-for-4-6' into 'gtk-4-6'
Cherry-pick changes from main for gtk-4-6

See merge request GNOME/gtk!4894
2022-07-28 18:10:14 +00:00
Matthias Clasen a6d22b3af1 Merge branch 'cherry-pick-09da4db8' into 'gtk-4-6'
Merge branch 'dnd' into 'main'

See merge request GNOME/gtk!4891
2022-07-28 18:05:51 +00:00
Benjamin Otte 6479495fbf Merge branch 'cherry-pick-0c052c9a' into 'gtk-4-6'
Merge branch 'gridview' into 'main'

See merge request GNOME/gtk!4904
2022-07-26 17:25:49 +00:00
Benjamin Otte 1ea2643aa9 Merge branch 'gridview' into 'main'
Gridview fix rubberbanding issues

Closes #3462 and #3445

See merge request GNOME/gtk!4688

(cherry picked from commit 0c052c9a37)

2bcae546 gridview: Move gtk_grid_view_computer_total_height() up for reuse
c6f357e4 gridview: Limit rectangle to gridview columns
1e9a36ff gridview: Allow starting rubberband in empty space below last row
ba909cf9 gridview: Fix get_items_in_rect() selection
f3fc8f5b gridview: Return an empty bitset when selecting only empty space
57c032e6 listbase: Clear selection if rubberband selected an empty set
aba2d994 gridview: Fix typo in docstring for gtk_grid_view_get_cell_at_y()
e14b84ff listview: Return an empty bitset when selecting only empty space
d6fab140 listview: Allow starting rubberband in empty space below last row
a7bbc258 listview: Fix selection for last item in get_items_in_rect
2022-07-26 16:37:40 +00:00
Luca Bacci a241b4480e Merge branch 'backport-mr-4674-to-gtk-4-6' into 'gtk-4-6'
GtkFileChooserWidget: Propagate captured key events when the location entry is focused

See merge request GNOME/gtk!4714
2022-07-20 07:04:59 +00:00
Mat f8231cf1a7 treepopover: Add support for scrolling
Add support for scrolling large tree popovers in a similar fashion to GtkPopoverMenu.

Fixes #3674
Fixes #4877
2022-07-18 18:56:18 +03:00
Mat a730012006 droptarget: Provide a unique action for gdk_drop_finish
gdk_drop_finish() requires a unique drop action. Reuse the existing
make_action_unique() function to get one.

Fixes #5051
2022-07-18 18:55:59 +03:00
Mat 977a69ab84 treeview: Check for column header area in row click/drag gestures
Bail out if a row click/drag gesture is performed in the column header area,
since separate gestures handle column headers.

Fixes #4453
2022-07-18 18:55:38 +03:00
Mat 7e4d6b556c tree/iconview: Use a unique drag action in drag_enter/motion callbacks
Functions already exist for providing a unique drag action for gdk_drop_finish().
Reuse these functions in the drag_enter/motion callbacks, since they require
a unique action as the return value.

Fixes #3187
2022-07-18 18:55:09 +03:00
Benjamin Otte 45ff81848f Merge branch 'dnd' into 'main'
DnD Fix Preferred Action for X11

Closes #4259

See merge request GNOME/gtk!4785

(cherry picked from commit 09da4db81f)

c9c48d78 gdkdrop-x11: Fix preferred action
16fd2608 gdkdrop-x11: Use the preferred action if possible
2022-07-18 14:21:45 +00:00
Luca Bacci 73afd4976a Propagate key events when the location entry is focused
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/4880
2022-07-13 13:38:01 +02:00
Matthias Clasen 07c115a383 Merge branch 'fix-gtk-stack-get-page-annotation' into 'gtk-4-6'
Fix gi-docgen comments for gtk_stack_get_page.

See merge request GNOME/gtk!4794
2022-07-11 18:18:26 +00:00
Hugo Parente Lima a9f658ab8f Fix gi-docgen comments for gtk_stack_get_page. 2022-07-11 18:18:25 +00:00
Andika Triwidada 9c258a5441 Update Indonesian translation 2022-07-03 08:20:41 +00:00
Мирослав Николић 7c0cf9e0c9 Update Serbian translation 2022-07-03 02:18:43 +00:00
Matthias Clasen 57ba5ad39e 4.6.6 2022-07-02 14:38:25 -04:00
Sabri Ünal 1ba946d3ba Update Turkish translation 2022-06-10 05:53:37 +00:00
Rafael Fontenelle d43ddcb2e8 Update Brazilian Portuguese translation 2022-06-09 23:44:08 +00:00
Matthias Clasen 05e4079682 Merge branch 'hc-icontheme-for-4-6' into 'gtk-4-6'
Don't use the HighContrast icon theme

See merge request GNOME/gtk!4805
2022-06-08 18:48:15 +00:00
Florian Müllner 317209597d wayland/display: Don't force HighContrast icon theme
The theme is considered deprecated in favor of symbolic icons from
the regular theme.

Cherry-picked from main.
2022-06-08 14:33:07 -04:00
Matthias Clasen fad664c89e Merge branch 'builtin-icontheme-fix-for-4-6' into 'gtk-4-6'
Add scalable directories to the builtin hicolor index

See merge request GNOME/gtk!4797
2022-06-06 22:25:07 +00:00
Matthias Clasen e3c4076b27 Add more directories to the builtin hicolor index
We haven't had any scalable directories in this list.
Add some. Since we seem to have settled on including
just actions and status as subdirectories for each
size, add scalable/actions and scalable/status.

Fixes: #4960
2022-06-06 18:05:25 -04:00
Aleksandr Melman 99f7cc1e61 Update Russian translation 2022-06-05 12:33:06 +00:00
Carlos Garnacho 154107696a Merge branch 'wip/carlosg/activation-roundtrip-fix-4.6' into 'gtk-4-6'
gdk/wayland: Dispatch GdkAppLaunchContext activation token in its own queue

See merge request GNOME/gtk!4791
2022-06-03 11:20:39 +00:00
Carlos Garnacho 1cdb6ada4e gdk/wayland: Check the GdkSurface wl_surface before using it for activation
Double check the GdkSurface has a wl_surface before using it as the activation
token source, since we cannot use NULL surfaces here.

Fixes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1862

(cherry-picked from commit 4b41d4f78c)
2022-06-03 13:04:15 +02:00
Carlos Garnacho 56607e8cfe gdk/wayland: Dispatch GdkAppLaunchContext activation token in its own queue
Use a separate queue to dispatch the token object exclusively, just like we
do on the GdkSurface activation paths.

(cherry-picked from commit fb68600d88)
2022-06-03 13:03:58 +02:00
Matthias Clasen 94b47ce47a Merge branch 'fix-gtk-stack-get-page-annotation' into 'gtk-4-6'
Fix introspection annotation for gtk_stack_get_page

See merge request GNOME/gtk!4783
2022-06-02 10:40:49 +00:00
Matthias Clasen 3594df7f87 Merge branch 'fix-ui-file-translation' into 'gtk-4-6'
Fix ui files to work for translations

See merge request GNOME/gtk!4784
2022-06-01 23:00:14 +00:00
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
Hugo Parente Lima 69b1b4d95b Fix introspection annotation for gtk_stack_get_page
Annotate gtk_stack_get_page return value as nullable.

Fixes #4958
2022-05-31 20:49:58 -03: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
252 changed files with 94752 additions and 85768 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
+329
View File
@@ -1,3 +1,332 @@
Overview of Changes in 4.6.9, 23-12-2022
========================================
* GtkText:
- Prevent unexpected notify::direction emissions
* Wayland:
- Fix button masks
* X11:
- Fix some ordering problems with surface destruction
* Translation updates
Georgian
Indonesian
Overview of Changes in 4.6.8, 24-10-2022
========================================
* Input:
- Fix problems with input method interactions that caused
dead keys not to work
* GtkText:
- Respect the no-emoji input hint fully
* GtkNotebook:
- Fix an infinite loop in accessibility code
- Event handling fixes
* GtkFileChooser:
- Restore ~ and .functionality
* GtkTreeView:
- Event handling fixes
* GtkTreeListModel:
- Prevent possible crashes with collapsed nodes
* GtkGridView:
- Fix issues with rubberband selection
* GtkEmojiChooser:
- Fix navigation with arrow keys when filtered
* GtkPopover:
- Fix problems with focus when dismissing popovers
- Fix problems with focusing editable labels in popovers
* GtkStackSidebar:
- Improve accessible presentation
* Wayland:
- Make gtk_launch_uri more robust
- Make monitor bounds handling more robust
- Prevent shrinking clients due to wrong toplevel bounds
* Flatpak:
- Fix file DND with the FileTransfer portal
* Translation updates
Brazilian Portuguese
Croatian
Czech
Georgian
German
Hungarian
Icelandic
Lithuanian
Polish
Portuguese
Serbian
Slovenian
Swedish
Turkish
Overview of Changes in 4.6.7, 17-08-2022
========================================
* Miscellaneous memory leak fixes
* GtkTreeView:
- Fix a problem with DND
- Fix a problem with row selection
* GtkTreePopover:
- Support scrolling
* GtkGridView:
- Fix issues with rubberband selection
* GtkSnapshot:
- Make GtkSnapshot work from bindings
* X11:
- Fix preferred action for DND
* Windows:
- Fix DND
* Translation updates
Croatian
Georgian
Indonesian
Russian
Serbian
Spanish
Overview of Changes in 4.6.6, 02-07-2022
========================================
* Fix translations in GTKs own ui files
* Wayland:
- Fix a problem with the activation protocol
- Don't force the HighContrast icontheme
* Windows:
- Fix a problem with builtin icons if the
hicolor icontheme is not installed
* Translation updates:
Brazilian Portuguese
Russian
Turkish
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
View File
@@ -223,6 +223,7 @@ static void
destroy_gear (struct gear *g)
{
g_free (g->strips);
g_free (g->vertices);
g_free (g);
}
+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:
+53 -15
View File
@@ -97,7 +97,7 @@ add_files (GDBusProxy *proxy,
AddFileData *afd)
{
GUnixFDList *fd_list;
GVariantBuilder fds;
GVariantBuilder fds, options;
int i;
char *key;
@@ -146,9 +146,10 @@ add_files (GDBusProxy *proxy,
key = (char *)g_object_get_data (G_OBJECT (afd->task), "key");
g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
g_dbus_proxy_call_with_unix_fd_list (proxy,
"AddFiles",
g_variant_new ("(sah)", key, &fds),
g_variant_new ("(saha{sv})", key, &fds, &options),
0, -1,
fd_list,
NULL,
@@ -480,20 +481,36 @@ connection_closed (GDBusConnection *connection,
}
static void
got_proxy (GObject *source,
GAsyncResult *result,
gpointer data)
finish_registration (void)
{
GError *error = NULL;
gdk_content_register_serializer (G_TYPE_FILE,
"application/vnd.portal.filetransfer",
portal_file_serializer,
NULL,
NULL);
file_transfer_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
if (!file_transfer_proxy)
{
g_message ("Failed to get file transfer portal: %s", error->message);
g_clear_error (&error);
return;
}
gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
"application/vnd.portal.filetransfer",
portal_file_serializer,
NULL,
NULL);
gdk_content_register_deserializer ("application/vnd.portal.filetransfer",
GDK_TYPE_FILE_LIST,
portal_file_deserializer,
NULL,
NULL);
gdk_content_register_deserializer ("application/vnd.portal.filetransfer",
G_TYPE_FILE,
portal_file_deserializer,
NULL,
NULL);
/* FIXME: I missed up and used the wrong mime type here when
* I implemented my own protocol. Keep these around for a while
* so we can interoperate with existing flatpaks using GTK 4.6
*/
gdk_content_register_serializer (G_TYPE_FILE,
"application/vnd.portal.files",
portal_file_serializer,
@@ -523,6 +540,21 @@ got_proxy (GObject *source,
"closed", G_CALLBACK (connection_closed), NULL);
}
static gboolean
proxy_has_owner (GDBusProxy *proxy)
{
char *owner;
owner = g_dbus_proxy_get_name_owner (proxy);
if (owner)
{
g_free (owner);
return TRUE;
}
return FALSE;
}
void
file_transfer_portal_register (void)
{
@@ -531,7 +563,8 @@ file_transfer_portal_register (void)
if (!called)
{
called = TRUE;
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
file_transfer_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
| G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
@@ -540,8 +573,13 @@ file_transfer_portal_register (void)
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.FileTransfer",
NULL,
got_proxy,
NULL);
if (file_transfer_proxy && !proxy_has_owner (file_transfer_proxy))
g_clear_object (&file_transfer_proxy);
if (file_transfer_proxy)
finish_registration ();
}
}
+1 -3
View File
@@ -407,8 +407,6 @@ gdk_content_register_deserializer (const char *mime_type,
g_return_if_fail (mime_type != NULL);
g_return_if_fail (deserialize != NULL);
init ();
deserializer = g_slice_new0 (Deserializer);
deserializer->mime_type = g_intern_string (mime_type);
@@ -576,7 +574,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.
-2
View File
@@ -413,8 +413,6 @@ gdk_content_register_serializer (GType type,
g_return_if_fail (mime_type != NULL);
g_return_if_fail (serialize != NULL);
init ();
serializer = g_slice_new0 (Serializer);
serializer->mime_type = g_intern_string (mime_type);
+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;
+19 -3
View File
@@ -1764,7 +1764,7 @@ gdk_key_event_matches (GdkEvent *event,
guint ev_keyval;
int layout;
int level;
GdkModifierType consumed_modifiers;
GdkModifierType ignored_modifiers;
GdkModifierType shift_group_mask;
gboolean group_mod_is_accel_mod = FALSE;
const GdkModifierType mask = GDK_CONTROL_MASK |
@@ -1783,7 +1783,23 @@ gdk_key_event_matches (GdkEvent *event,
ev_keyval = self->translated[1].keyval;
layout = self->translated[1].layout;
level = self->translated[1].level;
consumed_modifiers = self->translated[1].consumed;
/*
* If a modifier is currently active (e.g. Shift is pressed) and was marked
* as consumed, we ignore it for the purposes of matching shortcuts.
* For example, when Ctrl+Shift+[plus/equals key] is translated into
* Ctrl+plus on a keyboard where Shift+equals is the plus sign, we want
* shortcuts for either <Control><Shift>plus or <Control>plus to match.
* (See https://bugzilla.gnome.org/show_bug.cgi?id=100439)
*
* If a modifier is *not* currently active, the X11 backend can sometimes
* mark it as consumed where the Wayland and Windows backends do not.
* In this case, we still want to pay attention to its state.
* For example, when Ctrl+x is translated into Ctrl+x, we only want to
* trigger shortcuts for <Control>x, not for <Control><Shift>x.
* (See https://gitlab.gnome.org/GNOME/gtk/-/issues/5095)
*/
ignored_modifiers = (self->translated[1].consumed & state);
/* if the group-toggling modifier is part of the default accel mod
* mask, and it is active, disable it for matching
@@ -1795,7 +1811,7 @@ gdk_key_event_matches (GdkEvent *event,
if (mask & shift_group_mask)
group_mod_is_accel_mod = TRUE;
if ((modifiers & ~consumed_modifiers & mask) == (state & ~consumed_modifiers & mask))
if ((modifiers & ~ignored_modifiers & mask) == (state & ~ignored_modifiers & mask))
{
/* modifier match */
GdkKeymapKey *keys;
+3
View File
@@ -373,6 +373,9 @@ gdk_frame_clock_flush_idle (void *data)
else
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
g_clear_handle_id (&priv->paint_idle_id, g_source_remove);
gdk_frame_clock_paint_idle (data);
return FALSE;
}
+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;
}
+12 -2
View File
@@ -32,6 +32,9 @@ G_DEFINE_POINTER_TYPE (GdkToplevelSize, gdk_toplevel_size)
#define UNCONFIGURED_WIDTH 400
#define UNCONFIGURED_HEIGHT 300
#define DEFAULT_BOUNDS_WIDTH INT_MAX
#define DEFAULT_BOUNDS_HEIGHT INT_MAX
void
gdk_toplevel_size_init (GdkToplevelSize *size,
int bounds_width,
@@ -68,8 +71,15 @@ gdk_toplevel_size_get_bounds (GdkToplevelSize *size,
g_return_if_fail (bounds_width);
g_return_if_fail (bounds_height);
*bounds_width = size->bounds_width;
*bounds_height = size->bounds_height;
if (size->bounds_width > 0)
*bounds_width = size->bounds_width;
else
*bounds_width = DEFAULT_BOUNDS_WIDTH;
if (size->bounds_height > 0)
*bounds_height = size->bounds_height;
else
*bounds_height = DEFAULT_BOUNDS_HEIGHT;
}
/**
+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 &&
+14 -4
View File
@@ -59,13 +59,17 @@ gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context
if (display->xdg_activation)
{
struct xdg_activation_token_v1 *token;
struct wl_event_queue *event_queue;
struct wl_surface *wl_surface = NULL;
GdkWaylandSeat *seat;
GdkSurface *focus_surface;
AppLaunchData app_launch_data = { 0 };
event_queue = wl_display_create_queue (display->wl_display);
seat = GDK_WAYLAND_SEAT (gdk_display_get_default_seat (GDK_DISPLAY (display)));
focus_surface = gdk_wayland_device_get_focus (gdk_seat_get_keyboard (GDK_SEAT (seat)));
token = xdg_activation_v1_get_activation_token (display->xdg_activation);
wl_proxy_set_queue ((struct wl_proxy *) token, event_queue);
xdg_activation_token_v1_add_listener (token,
&token_listener,
@@ -73,15 +77,21 @@ 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));
focus_surface = gdk_wayland_device_get_focus (gdk_seat_get_keyboard (GDK_SEAT (seat)));
if (focus_surface)
wl_surface = gdk_wayland_surface_get_wl_surface (focus_surface);
if (wl_surface)
xdg_activation_token_v1_set_surface (token, wl_surface);
xdg_activation_token_v1_commit (token);
while (app_launch_data.token == NULL)
wl_display_roundtrip (display->wl_display);
wl_display_dispatch_queue (display->wl_display, event_queue);
xdg_activation_token_v1_destroy (token);
id = app_launch_data.token;
wl_event_queue_destroy (event_queue);
}
else if (display->gtk_shell_version >= 3)
{
+19 -6
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);
}
@@ -204,7 +215,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
cairo_surface_t *surface;
struct wl_buffer *buffer;
texture = gdk_cursor_get_texture (cursor);
texture = g_object_ref (gdk_cursor_get_texture (cursor));
from_texture:
surface = g_hash_table_lookup (display->cursor_surface_cache, cursor);
@@ -234,6 +245,8 @@ from_texture:
buffer = _gdk_wayland_shm_surface_get_wl_buffer (surface);
wl_buffer_add_listener (buffer, &buffer_listener, surface);
g_object_unref (texture);
return buffer;
}
+6 -7
View File
@@ -83,6 +83,10 @@
#define BTN_STYLUS3 0x149 /* Linux 4.15 */
#endif
#define ALL_BUTTONS_MASK (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | \
GDK_BUTTON3_MASK | GDK_BUTTON4_MASK | \
GDK_BUTTON5_MASK)
#define GDK_SEAT_NOTE(seat,type,action) GDK_DISPLAY_NOTE(gdk_seat_get_display (GDK_SEAT (seat)),type,action)
typedef struct _GdkWaylandDevicePad GdkWaylandDevicePad;
@@ -1557,12 +1561,6 @@ pointer_handle_leave (void *data,
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
GdkDeviceGrabInfo *grab;
if (!surface)
return;
if (!GDK_IS_SURFACE (wl_surface_get_user_data (surface)))
return;
if (!seat->pointer_info.focus)
return;
@@ -1702,7 +1700,8 @@ pointer_handle_button (void *data,
gdk_wayland_seat_set_frame_event (seat, event);
modifier = 1 << (8 + gdk_button - 1);
modifier = (GDK_BUTTON1_MASK << (button - BUTTON_BASE - 1)) & ALL_BUTTONS_MASK;
if (state)
seat->pointer_info.button_modifiers |= modifier;
else
+5 -2
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;
@@ -2165,8 +2169,7 @@ gdk_wayland_display_get_setting (GdkDisplay *display,
{
if (strcmp (name, "gtk-decoration-layout") == 0)
set_decoration_layout_from_entry (display, entry, value);
else if (strcmp (name, "gtk-theme-name") == 0 ||
strcmp (name, "gtk-icon-theme-name") == 0)
else if (strcmp (name, "gtk-theme-name") == 0)
set_theme_from_entry (display, entry, value);
else
set_value_from_entry (display, entry, value);
+85 -25
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;
@@ -1394,7 +1395,6 @@ configure_toplevel_geometry (GdkSurface *surface)
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkMonitor *monitor;
GdkRectangle monitor_geometry;
int bounds_width, bounds_height;
GdkToplevelSize size;
GdkToplevelLayout *layout;
@@ -1402,10 +1402,20 @@ configure_toplevel_geometry (GdkSurface *surface)
GdkSurfaceHints mask;
monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
gdk_monitor_get_geometry (monitor, &monitor_geometry);
g_object_unref (monitor);
bounds_width = monitor_geometry.width;
bounds_height = monitor_geometry.height;
if (monitor)
{
GdkRectangle monitor_geometry;
gdk_monitor_get_geometry (monitor, &monitor_geometry);
g_object_unref (monitor);
bounds_width = monitor_geometry.width;
bounds_height = monitor_geometry.height;
}
else
{
bounds_width = 0;
bounds_height = 0;
}
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
@@ -2984,6 +2994,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 +3236,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 +3472,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 ();
+23 -11
View File
@@ -142,8 +142,6 @@ struct _drop_target_context
static void
gdk_win32_drop_init (GdkWin32Drop *drop)
{
drop->droptarget_w32format_contentformat_map = g_array_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair));
GDK_NOTE (DND, g_print ("gdk_win32_drop_init %p\n", drop));
}
@@ -414,9 +412,13 @@ set_source_actions_helper (GdkDrop *drop,
DWORD grfKeyState)
{
GdkDragAction user_action;
GdkWin32Drop *drop_win32;
user_action = get_user_action (grfKeyState);
drop_win32 = GDK_WIN32_DROP (drop);
drop_win32->actions = actions;
if (user_action != 0)
gdk_drop_set_actions (drop, user_action);
else
@@ -471,6 +473,7 @@ idroptarget_dragenter (LPDROPTARGET This,
GdkDragAction source_actions;
GdkDragAction dest_actions;
GdkContentFormats *formats;
GArray *droptarget_w32format_contentformat_map;
GDK_NOTE (DND, g_print ("idroptarget_dragenter %p @ %ld : %ld"
" for dest window 0x%p"
@@ -491,7 +494,8 @@ idroptarget_dragenter (LPDROPTARGET This,
display = gdk_surface_get_display (ctx->surface);
formats = query_object_formats (pDataObj, NULL);
droptarget_w32format_contentformat_map = g_array_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair));
formats = query_object_formats (pDataObj, droptarget_w32format_contentformat_map);
drop = gdk_drop_new (display,
gdk_seat_get_pointer (gdk_display_get_default_seat (display)),
drag,
@@ -499,7 +503,7 @@ idroptarget_dragenter (LPDROPTARGET This,
ctx->surface,
GDK_DRAG_PROTO_OLE2);
drop_win32 = GDK_WIN32_DROP (drop);
g_array_set_size (drop_win32->droptarget_w32format_contentformat_map, 0);
drop_win32->droptarget_w32format_contentformat_map = droptarget_w32format_contentformat_map;
gdk_content_formats_unref (formats);
ctx->drop = drop;
@@ -520,7 +524,7 @@ idroptarget_dragenter (LPDROPTARGET This,
drop_win32->last_key_state = grfKeyState;
drop_win32->last_x = pt_x;
drop_win32->last_y = pt_y;
dest_actions = filter_actions (drop_win32->actions, source_actions);
dest_actions = filter_actions (gdk_drop_get_actions (drop), source_actions);
*pdwEffect_and_dwOKEffects = drop_effect_for_actions (dest_actions);
GDK_NOTE (DND, g_print ("idroptarget_dragenter returns S_OK with actions %s"
@@ -554,9 +558,7 @@ idroptarget_dragover (LPDROPTARGET This,
GdkDragAction source_actions;
GdkDragAction dest_actions;
source_actions = set_source_actions_helper (ctx->drop,
actions_for_drop_effects (*pdwEffect_and_dwOKEffects),
grfKeyState);
source_actions = actions_for_drop_effects (*pdwEffect_and_dwOKEffects);
GDK_NOTE (DND, g_print ("idroptarget_dragover %p @ %d : %d"
" (raw %ld : %ld)"
@@ -569,7 +571,8 @@ idroptarget_dragover (LPDROPTARGET This,
if (pt_x != drop_win32->last_x ||
pt_y != drop_win32->last_y ||
grfKeyState != drop_win32->last_key_state)
grfKeyState != drop_win32->last_key_state ||
source_actions != drop_win32->actions)
{
double x = 0.0;
double y = 0.0;
@@ -578,13 +581,15 @@ idroptarget_dragover (LPDROPTARGET This,
x /= drop_win32->scale;
y /= drop_win32->scale;
set_source_actions_helper (ctx->drop, source_actions, grfKeyState);
gdk_drop_emit_motion_event (ctx->drop, TRUE, x, y, GDK_CURRENT_TIME);
drop_win32->last_key_state = grfKeyState;
drop_win32->last_x = pt_x;
drop_win32->last_y = pt_y;
}
dest_actions = filter_actions (drop_win32->actions, source_actions);
dest_actions = filter_actions (gdk_drop_get_actions (ctx->drop), source_actions);
*pdwEffect_and_dwOKEffects = drop_effect_for_actions (dest_actions);
GDK_NOTE (DND, g_print ("idroptarget_dragover returns S_OK with actions %s"
@@ -645,8 +650,12 @@ idroptarget_drop (LPDROPTARGET This,
x /= drop_win32->scale;
y /= drop_win32->scale;
gdk_drop_emit_motion_event (ctx->drop, TRUE, x, y, GDK_CURRENT_TIME);
gdk_drop_emit_drop_event (ctx->drop, TRUE, x, y, GDK_CURRENT_TIME);
gdk_drop_emit_leave_event (ctx->drop, TRUE, GDK_CURRENT_TIME);
while (!drop_win32->drop_finished)
g_main_context_iteration (NULL, FALSE);
@@ -824,7 +833,10 @@ gdk_win32_drop_status (GdkDrop *drop,
_gdk_win32_drag_action_to_string (gdk_drop_get_actions (drop)),
_gdk_win32_drag_action_to_string (preferred)));
drop_win32->actions = actions;
if (preferred != 0)
actions = preferred;
gdk_drop_set_actions (drop, drop_win32->actions & actions);
}
static void
+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);
+12 -16
View File
@@ -361,9 +361,9 @@ gdk_x11_drop_update_actions (GdkX11Drop *drop_x11)
if (!drop_x11->xdnd_have_actions)
actions = drop_x11->suggested_action;
else if (drop_x11->suggested_action & GDK_ACTION_ASK)
actions = drop_x11->xdnd_actions & GDK_ACTION_ALL;
actions = drop_x11->xdnd_actions | GDK_ACTION_ASK;
else
actions = drop_x11->suggested_action;
actions = drop_x11->xdnd_actions & GDK_ACTION_ALL;
gdk_drop_set_actions (GDK_DROP (drop_x11), actions);
}
@@ -769,22 +769,18 @@ gdk_x11_drop_status (GdkDrop *drop,
possible_actions = actions & gdk_drop_get_actions (drop);
if (drop_x11->suggested_action != 0)
if (preferred & possible_actions)
suggested_action = preferred;
else if (drop_x11->suggested_action & possible_actions)
suggested_action = drop_x11->suggested_action;
else if (possible_actions & GDK_ACTION_COPY)
suggested_action = GDK_ACTION_COPY;
else if (possible_actions & GDK_ACTION_MOVE)
suggested_action = GDK_ACTION_MOVE;
else if (possible_actions & GDK_ACTION_ASK)
suggested_action = GDK_ACTION_ASK;
else
suggested_action = preferred & possible_actions;
if (suggested_action == 0 && possible_actions != 0)
{
if (possible_actions & GDK_ACTION_COPY)
suggested_action = GDK_ACTION_COPY;
else if (possible_actions & GDK_ACTION_MOVE)
suggested_action = GDK_ACTION_MOVE;
else if (possible_actions & GDK_ACTION_ASK)
suggested_action = GDK_ACTION_ASK;
else
suggested_action = 0;
}
suggested_action = 0;
xev.xclient.type = ClientMessage;
xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "XdndStatus");
+6
View File
@@ -232,6 +232,12 @@ gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
g_message ("Making GLX context %p current to drawable %lu",
context, (unsigned long) drawable));
/* Work around a glitch, see
* https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/5281
*/
if (glXGetCurrentContext () != self->glx_context)
glXMakeContextCurrent (dpy, None, None, NULL);
if (!glXMakeContextCurrent (dpy, drawable, drawable, self->glx_context))
return FALSE;
+1 -1
View File
@@ -603,7 +603,7 @@ update_direction (GdkX11Keymap *keymap_x11,
keymap_x11->have_direction = TRUE;
}
if (!had_direction || old_direction != keymap_x11->current_direction)
if (had_direction && old_direction != keymap_x11->current_direction)
{
g_object_notify (G_OBJECT (keyboard), "direction");
return TRUE;
+3 -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,
@@ -759,6 +759,8 @@ gdk_x11_surface_finalize (GObject *object)
}
g_clear_pointer (&impl->surface_is_on_monitor, g_list_free);
g_clear_handle_id (&impl->compute_size_source_id, g_source_remove);
g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref);
g_free (impl->toplevel);
+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;
+8
View File
@@ -285,6 +285,14 @@
...
fun:g_intern_static_string
}
{
glib GQuark
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
...
fun:g_intern_string
}
# Threads
{
+67 -40
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)
@@ -949,22 +953,30 @@ gtk_at_spi_context_state_change (GtkATContext *ctx,
{
value = gtk_accessible_attribute_set_get_value (states, GTK_ACCESSIBLE_STATE_CHECKED);
switch (gtk_tristate_accessible_value_get (value))
if (value->value_class->type == GTK_ACCESSIBLE_VALUE_TYPE_TRISTATE)
{
switch (gtk_tristate_accessible_value_get (value))
{
case GTK_ACCESSIBLE_TRISTATE_TRUE:
emit_state_changed (self, "checked", TRUE);
emit_state_changed (self, "indeterminate", FALSE);
break;
case GTK_ACCESSIBLE_TRISTATE_MIXED:
emit_state_changed (self, "checked", FALSE);
emit_state_changed (self, "indeterminate", TRUE);
break;
case GTK_ACCESSIBLE_TRISTATE_FALSE:
emit_state_changed (self, "checked", FALSE);
emit_state_changed (self, "indeterminate", FALSE);
break;
default:
break;
}
}
else
{
case GTK_ACCESSIBLE_TRISTATE_TRUE:
emit_state_changed (self, "checked", TRUE);
emit_state_changed (self, "indeterminate", FALSE);
break;
case GTK_ACCESSIBLE_TRISTATE_MIXED:
emit_state_changed (self, "checked", FALSE);
emit_state_changed (self, "indeterminate", TRUE);
break;
case GTK_ACCESSIBLE_TRISTATE_FALSE:
emit_state_changed (self, "checked", FALSE);
emit_state_changed (self, "indeterminate", FALSE);
break;
default:
break;
}
}
@@ -1007,22 +1019,31 @@ gtk_at_spi_context_state_change (GtkATContext *ctx,
if (changed_states & GTK_ACCESSIBLE_STATE_CHANGE_PRESSED)
{
value = gtk_accessible_attribute_set_get_value (states, GTK_ACCESSIBLE_STATE_PRESSED);
switch (gtk_tristate_accessible_value_get (value))
if (value->value_class->type == GTK_ACCESSIBLE_VALUE_TYPE_TRISTATE)
{
switch (gtk_tristate_accessible_value_get (value))
{
case GTK_ACCESSIBLE_TRISTATE_TRUE:
emit_state_changed (self, "pressed", TRUE);
emit_state_changed (self, "indeterminate", FALSE);
break;
case GTK_ACCESSIBLE_TRISTATE_MIXED:
emit_state_changed (self, "pressed", FALSE);
emit_state_changed (self, "indeterminate", TRUE);
break;
case GTK_ACCESSIBLE_TRISTATE_FALSE:
emit_state_changed (self, "pressed", FALSE);
emit_state_changed (self, "indeterminate", FALSE);
break;
default:
break;
}
}
else
{
case GTK_ACCESSIBLE_TRISTATE_TRUE:
emit_state_changed (self, "pressed", TRUE);
emit_state_changed (self, "indeterminate", FALSE);
break;
case GTK_ACCESSIBLE_TRISTATE_MIXED:
emit_state_changed (self, "pressed", FALSE);
emit_state_changed (self, "indeterminate", TRUE);
break;
case GTK_ACCESSIBLE_TRISTATE_FALSE:
emit_state_changed (self, "pressed", FALSE);
emit_state_changed (self, "indeterminate", FALSE);
break;
default:
break;
}
}
@@ -1418,7 +1439,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 +1464,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 +1526,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 +1540,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
+36 -10
View File
@@ -106,6 +106,7 @@ gtk_at_spi_root_dispose (GObject *gobject)
g_clear_object (&self->cache);
g_clear_object (&self->connection);
g_clear_pointer (&self->queued_contexts, g_list_free);
G_OBJECT_CLASS (gtk_at_spi_root_parent_class)->dispose (gobject);
}
@@ -474,16 +475,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 +518,28 @@ on_registration_reply (GObject *gobject,
/* Drain the list of queued GtkAtSpiContexts, and add them to the cache */
if (self->queued_contexts != NULL)
{
self->queued_contexts = g_list_reverse (self->queued_contexts);
for (GList *l = self->queued_contexts; l != NULL; l = l->next)
gtk_at_spi_cache_add_context (self->cache, l->data);
{
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 +595,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 +603,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 +634,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
@@ -864,7 +864,7 @@ notebook_handle_method (GDBusConnection *connection,
for (child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (widget))
child = gtk_widget_get_next_sibling (child))
{
/* skip actions */
if (gtk_accessible_get_accessible_role (GTK_ACCESSIBLE (child)) != GTK_ACCESSIBLE_ROLE_TAB)
+12 -1
View File
@@ -152,13 +152,24 @@ gtk_css_data_url_parse (const char *url,
gsize read;
gsize written;
gpointer data;
GError *local_error = NULL;
data = g_convert_with_fallback (bdata, bsize,
"UTF-8", charset,
(char *) "*",
&read, &written, NULL);
&read, &written, &local_error);
g_free (bdata);
if (local_error)
{
g_propagate_error (error, local_error);
g_free (charset);
g_free (data);
g_free (mimetype);
return NULL;
}
bdata = data;
bsize = written;
}
+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');
+15 -3
View File
@@ -28,6 +28,7 @@
static GtkCssValue * gtk_css_calc_value_new (guint n_terms);
static GtkCssValue * gtk_css_calc_value_new_sum (GtkCssValue *a,
GtkCssValue *b);
static gsize gtk_css_value_calc_get_size (gsize n_terms);
enum {
TYPE_CALC = 0,
@@ -69,11 +70,22 @@ 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_free1 (gtk_css_value_calc_get_size (n_terms), number);
}
else
{
g_slice_free (GtkCssValue, number);
}
}
static double
+16 -16
View File
@@ -208,6 +208,21 @@ gtk_drop_target_end_drop (GtkDropTarget *self)
g_object_thaw_notify (G_OBJECT (self));
}
static GdkDragAction
make_action_unique (GdkDragAction actions)
{
if (actions & GDK_ACTION_COPY)
return GDK_ACTION_COPY;
if (actions & GDK_ACTION_MOVE)
return GDK_ACTION_MOVE;
if (actions & GDK_ACTION_LINK)
return GDK_ACTION_LINK;
return 0;
}
static void
gtk_drop_target_do_drop (GtkDropTarget *self)
{
@@ -219,7 +234,7 @@ gtk_drop_target_do_drop (GtkDropTarget *self)
g_signal_emit (self, signals[DROP], 0, &self->value, self->coords.x, self->coords.y, &success);
if (success)
gdk_drop_finish (self->drop, gdk_drop_get_actions (self->drop));
gdk_drop_finish (self->drop, make_action_unique (self->actions & gdk_drop_get_actions (self->drop)));
else
gdk_drop_finish (self->drop, 0);
@@ -348,21 +363,6 @@ gtk_drop_target_accept (GtkDropTarget *self,
return gdk_content_formats_match_gtype (self->formats, gdk_drop_get_formats (drop)) != G_TYPE_INVALID;
}
static GdkDragAction
make_action_unique (GdkDragAction actions)
{
if (actions & GDK_ACTION_COPY)
return GDK_ACTION_COPY;
if (actions & GDK_ACTION_MOVE)
return GDK_ACTION_MOVE;
if (actions & GDK_ACTION_LINK)
return GDK_ACTION_LINK;
return 0;
}
static GdkDragAction
gtk_drop_target_enter (GtkDropTarget *self,
double x,
+13 -1
View File
@@ -193,11 +193,23 @@ gtk_editable_label_prepare_drag (GtkDragSource *source,
gtk_label_get_label (GTK_LABEL (self->label)));
}
static gboolean
stop_editing_soon (gpointer data)
{
GtkEventController *controller = data;
GtkWidget *widget = gtk_event_controller_get_widget (controller);
if (!gtk_event_controller_focus_contains_focus (GTK_EVENT_CONTROLLER_FOCUS (controller)))
gtk_editable_label_stop_editing (GTK_EDITABLE_LABEL (widget), TRUE);
return FALSE;
}
static void
gtk_editable_label_focus_out (GtkEventController *controller,
GtkEditableLabel *self)
{
gtk_editable_label_stop_editing (self, TRUE);
g_timeout_add (100, stop_editing_soon, controller);
}
static void
+110 -52
View File
@@ -1034,6 +1034,34 @@ gtk_emoji_chooser_show (GtkWidget *widget)
gtk_editable_set_text (GTK_EDITABLE (chooser->search_entry), "");
}
static EmojiSection *
find_section (GtkEmojiChooser *chooser,
GtkWidget *box)
{
if (box == chooser->recent.box)
return &chooser->recent;
else if (box == chooser->people.box)
return &chooser->people;
else if (box == chooser->body.box)
return &chooser->body;
else if (box == chooser->nature.box)
return &chooser->nature;
else if (box == chooser->food.box)
return &chooser->food;
else if (box == chooser->travel.box)
return &chooser->travel;
else if (box == chooser->activities.box)
return &chooser->activities;
else if (box == chooser->objects.box)
return &chooser->objects;
else if (box == chooser->symbols.box)
return &chooser->symbols;
else if (box == chooser->flags.box)
return &chooser->flags;
else
return NULL;
}
static EmojiSection *
find_next_section (GtkEmojiChooser *chooser,
GtkWidget *box,
@@ -1105,81 +1133,111 @@ keynav_failed (GtkWidget *box,
GtkWidget *focus;
GtkWidget *child;
GtkWidget *sibling;
GtkAllocation alloc;
int i;
int column;
int n_columns = 7;
int child_x;
focus = gtk_root_get_focus (gtk_widget_get_root (box));
if (focus == NULL)
return FALSE;
/* determine the number of columns */
child_x = -1;
for (i = 0; i < 20; i++)
{
GtkAllocation alloc;
gtk_widget_get_allocation (GTK_WIDGET (gtk_flow_box_get_child_at_index (GTK_FLOW_BOX (box), i)),
&alloc);
if (alloc.x > child_x)
child_x = alloc.x;
else
{
n_columns = i;
break;
}
}
n_columns = MAX (n_columns, 1);
child = gtk_widget_get_ancestor (focus, GTK_TYPE_EMOJI_CHOOSER_CHILD);
i = 0;
column = 0;
child_x = G_MAXINT;
for (sibling = gtk_widget_get_first_child (box);
sibling != child;
sibling;
sibling = gtk_widget_get_next_sibling (sibling))
i++;
{
if (!gtk_widget_get_child_visible (sibling))
continue;
column = i % n_columns;
gtk_widget_get_allocation (sibling, &alloc);
if (alloc.x < child_x)
column = 0;
else
column++;
child_x = alloc.x;
if (sibling == child)
break;
}
if (direction == GTK_DIR_DOWN)
{
next = find_next_section (chooser, box, TRUE);
if (next == NULL)
return FALSE;
i = 0;
for (sibling = gtk_widget_get_first_child (next->box);
sibling;
sibling = gtk_widget_get_next_sibling (sibling), i++)
{
next = find_section (chooser, box);
while (TRUE)
{
if (i == column)
next = find_next_section (chooser, next->box, TRUE);
if (next == NULL)
return FALSE;
i = 0;
child_x = G_MAXINT;
for (sibling = gtk_widget_get_first_child (next->box);
sibling;
sibling = gtk_widget_get_next_sibling (sibling))
{
gtk_widget_grab_focus (sibling);
return TRUE;
if (!gtk_widget_get_child_visible (sibling))
continue;
gtk_widget_get_allocation (sibling, &alloc);
if (alloc.x < child_x)
i = 0;
else
i++;
child_x = alloc.x;
if (i == column)
{
gtk_widget_grab_focus (sibling);
return TRUE;
}
}
}
}
else if (direction == GTK_DIR_UP)
{
next = find_next_section (chooser, box, FALSE);
if (next == NULL)
return FALSE;
next = find_section (chooser, box);
while (TRUE)
{
next = find_next_section (chooser, next->box, FALSE);
if (next == NULL)
return FALSE;
i = 0;
child = NULL;
for (sibling = gtk_widget_get_first_child (next->box);
sibling;
sibling = gtk_widget_get_next_sibling (sibling), i++)
{
if ((i % n_columns) == column)
child = sibling;
}
if (child)
{
gtk_widget_grab_focus (child);
return TRUE;
i = 0;
child_x = G_MAXINT;
child = NULL;
for (sibling = gtk_widget_get_first_child (next->box);
sibling;
sibling = gtk_widget_get_next_sibling (sibling))
{
if (!gtk_widget_get_child_visible (sibling))
continue;
gtk_widget_get_allocation (sibling, &alloc);
if (alloc.x < child_x)
i = 0;
else
i++;
child_x = alloc.x;
if (i == column)
child = sibling;
}
if (child)
{
gtk_widget_grab_focus (child);
return TRUE;
}
}
}
+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.
+55 -16
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 */
@@ -7729,9 +7760,17 @@ captured_key (GtkEventControllerKey *controller,
impl->location_mode == LOCATION_MODE_FILENAME_ENTRY))
return GDK_EVENT_PROPAGATE;
if (keyval == GDK_KEY_slash)
if (keyval == GDK_KEY_slash || keyval == GDK_KEY_asciitilde || keyval == GDK_KEY_period)
return GDK_EVENT_PROPAGATE;
if (impl->location_entry)
{
GtkWidget *focus = gtk_root_get_focus (gtk_widget_get_root (GTK_WIDGET (impl)));
if (focus && gtk_widget_is_ancestor (focus, impl->location_entry))
return GDK_EVENT_PROPAGATE;
}
handled = gtk_event_controller_key_forward (controller, GTK_WIDGET (impl->search_entry));
if (handled == GDK_EVENT_STOP)
operation_mode_set (impl, OPERATION_MODE_SEARCH);
@@ -7841,11 +7880,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);
+24 -18
View File
@@ -204,7 +204,7 @@ cell_augment (GtkRbTree *tree,
* index of the returned row
* @offset: (out caller-allocates) (optional): stores the offset
* in pixels between y and top of cell.
* @offset: (out caller-allocates) (optional): stores the height
* @size: (out caller-allocates) (optional): stores the height
* of the cell
*
* Gets the Cell that occupies the leftmost position in the row at offset
@@ -413,6 +413,19 @@ gtk_grid_view_get_allocation_across (GtkListBase *base,
return TRUE;
}
static int
gtk_grid_view_compute_total_height (GtkGridView *self)
{
Cell *cell;
CellAugment *aug;
cell = gtk_list_item_manager_get_root (self->item_manager);
if (cell == NULL)
return 0;
aug = gtk_list_item_manager_get_item_augment (self->item_manager, cell);
return aug->size;
}
static gboolean
gtk_grid_view_get_position_from_allocation (GtkListBase *base,
int across,
@@ -428,6 +441,9 @@ gtk_grid_view_get_position_from_allocation (GtkListBase *base,
return FALSE;
n_items = gtk_list_base_get_n_items (base);
along = CLAMP (along, 0, gtk_grid_view_compute_total_height (self) - 1);
across = across < 0 ? 0 : across;
if (!gtk_grid_view_get_cell_at_y (self,
along,
&pos,
@@ -467,16 +483,19 @@ gtk_grid_view_get_items_in_rect (GtkListBase *base,
result = gtk_bitset_new_empty ();
if (rect->y >= gtk_grid_view_compute_total_height (self))
return result;
n_items = gtk_list_base_get_n_items (base);
if (n_items == 0)
return result;
first_column = floor (rect->x / self->column_width);
last_column = floor ((rect->x + rect->width) / self->column_width);
first_column = fmax (floor (rect->x / self->column_width), 0);
last_column = fmin (floor ((rect->x + rect->width) / self->column_width), self->n_columns - 1);
if (!gtk_grid_view_get_cell_at_y (self, rect->y, &first_row, NULL, NULL))
first_row = rect->y < 0 ? 0 : n_items - 1;
if (!gtk_grid_view_get_cell_at_y (self, rect->y + rect->height, &last_row, NULL, NULL))
last_row = rect->y < 0 ? 0 : n_items - 1;
last_row = rect->y + rect->height < 0 ? 0 : n_items - 1;
gtk_bitset_add_rectangle (result,
first_row + first_column,
@@ -722,19 +741,6 @@ cell_set_size (Cell *cell,
gtk_rb_tree_node_mark_dirty (cell);
}
static int
gtk_grid_view_compute_total_height (GtkGridView *self)
{
Cell *cell;
CellAugment *aug;
cell = gtk_list_item_manager_get_root (self->item_manager);
if (cell == NULL)
return 0;
aug = gtk_list_item_manager_get_item_augment (self->item_manager, cell);
return aug->size;
}
static void
gtk_grid_view_size_allocate (GtkWidget *widget,
int width,
@@ -1291,7 +1297,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.
*

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