Compare commits

..

168 Commits

Author SHA1 Message Date
Matthias Clasen eccbd4fe5f gizmo: Set the name
This helps with debugging.
2019-05-04 18:20:27 +00:00
Matthias Clasen 3b967f1242 widget: Improve warning messages
When we print warnings about a widget, using
gtk_widget_get_name() is slightly better than
G_OBJECT_TYPE_NAME(), since it will give us
the widgets unique name when available.
2019-05-04 18:20:20 +00:00
Asier Sarasua Garmendia 1a4c988a22 Update Basque translation 2019-05-04 09:54:08 +00:00
Mohammed Sadiq d936a9ae89 docs: fix typo in function name 2019-05-04 15:09:35 +05:30
Matthias Clasen 67e6d1087e emoji chooser: populate incrementally
It takes half a second on my system to initially
populate the Emoji chooser. That is too long. Do
the work in 8 millisecond chunks to give GTK a
chance to get some frames done.
2019-05-04 02:12:02 +00:00
Matthias Clasen 29bafd1e15 docs: Add an actions overview
Add an introduction chapter explaining actions
in detail. Most of this content is taken from
the GAction HowDoI page.
2019-05-04 01:26:45 +00:00
Matthias Clasen 65697e3324 docs: Some additions to the overview
Mention graphene and gsk.
2019-05-04 01:26:45 +00:00
Matthias Clasen bceca277ea docs: Some updates to the input overview
Remove references to no longer existing apis,
and reword some things. Say surface instead of
window. Start filling out the keyboard section.
2019-05-04 01:26:45 +00:00
Jordi Mas 16c8fb52df Update Catalan translation 2019-05-03 20:54:07 +02:00
Timm Bäder d702bfe7b7 filechooserbutton: Clean up finalize & destroy 2019-05-03 20:06:25 +02:00
Timm Bäder 596c9a3c0b filechooserbutton: Clear model in destroy()
Since we're destroying priv->chooser right after. We can't wait until
finalize() since clearing the model will try to work with priv->chooser.
2019-05-03 20:06:23 +02:00
Timm Bäder c675d1c9e1 filechooserbutton: Use a bin layout 2019-05-03 20:06:10 +02:00
Daniel Mustieles bd490ed511 Updated Spanish translation 2019-05-03 14:36:45 +02:00
Piotr Drąg bcf180642d Update Polish translation 2019-05-03 13:42:45 +02:00
Piotr Drąg 5882e22f89 Update POTFILES.skip 2019-05-03 13:19:12 +02:00
Matthias Clasen 6f25168db3 Make the newly added test a bit more robust
Follow the style of the other tests and provide
style for both the test and ref.
2019-05-03 02:15:07 +00:00
Matthias Clasen 2a4b5862ae Merge branch 'font-families' into 'master'
Font families

Closes #1854

See merge request GNOME/gtk!813
2019-05-03 01:50:45 +00:00
Matthias Clasen 7037ff8f3d Add a reftest for multiple font families
This tests that listing multiple font
families in the css font-family property
works as expected.
2019-05-03 01:44:29 +00:00
Matthias Clasen 1c9a486d60 css: Use multiple font-family values
Pango API to support this, so we can implement
this very easily.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1854
2019-05-03 01:44:02 +00:00
Matthias Clasen eb9284e9ca migration guide: Updates
Add recent changes here.
2019-05-02 23:44:57 +00:00
Matthias Clasen 77e3b72b15 NEWS: Updates 2019-05-02 22:20:31 +00:00
Matthias Clasen 05cb7e7412 Merge branch 'event-controller-sensitive' into 'master'
Event controller sensitive

Closes #1861

See merge request GNOME/gtk!812
2019-05-02 21:03:41 +00:00
Matthias Clasen 299422994a fixup! event controller: Don't deliver events to insensitive widgets 2019-05-02 20:20:20 +00:00
Matthias Clasen b1d90cc171 spin button: Listen for ::cancel on gestures
Otherwise, we keep spinning when we should stop.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1861
2019-05-02 15:54:17 -04:00
Matthias Clasen af2207bc0b widget: Reset controllers when going numb
Reset event controllers when their
widget is going insensitive. This is
the expected behavior.
2019-05-02 15:53:30 -04:00
Matthias Clasen 522bbc182d gesture: Chain up in filter_event
This is the right thing to do.
We want to exclude more events.
2019-05-02 15:53:30 -04:00
Matthias Clasen 65233726f8 event controller: Don't deliver events to insensitive widgets
This is another way to avoid delivering events
to insensitive widgets.
2019-05-02 15:50:44 -04:00
Benjamin Otte 19227d9789 rendernode: Compute border node colors properly
Change the way we compute border color cutoffs to the same method that
browsers use. This method does not consider the corner sizes at all and
only looks at border-width.
2019-05-02 19:35:45 +02:00
Benjamin Otte 8915d60900 roundedrect: Mke sure shrinking borders works
Previously, when borders were too big - ie when a 100x100 rect had only
one 100x100 border, like the black part of ◔ - and then shrinking this
rect by 25px on either side, we'd end up with a 50x50 rect with a 75x75
border, and that's obviously not correct.
2019-05-02 19:35:45 +02:00
Matthias Clasen ed52c029a0 gtk: Small documentation fixes 2019-05-01 23:24:14 -04:00
Matthias Clasen 7b1201cd4d box layout: Documentation additions 2019-05-01 23:24:14 -04:00
Matthias Clasen 3f940715e4 gsk: Documentation tweaks
Add some missing symbols.
2019-05-01 23:24:14 -04:00
Matthias Clasen f6225901e8 gdk: Documentation improvements
Document some new x11 symbols.
2019-05-02 02:39:36 +00:00
Matthias Clasen eff4b6377d Merge branch 'inspector-menus' into 'master'
inspector: Fix showing of menus

See merge request GNOME/gtk!810
2019-05-02 02:12:28 +00:00
Matthias Clasen a18647af0e Merge branch 'inspector-actions' into 'master'
inspector: Show the default.activate action

See merge request GNOME/gtk!809
2019-05-02 02:09:03 +00:00
Matthias Clasen c7df0c907a inspector: Fix showing of menus
We were hitting an assertion in some leftover
code that assumed property editors are popovers.
2019-05-02 02:05:46 +00:00
Matthias Clasen b74407a343 Merge branch 'filechooser-save-again' into 'master'
Make file chooser saving work again

See merge request GNOME/gtk!808
2019-05-02 01:55:28 +00:00
Matthias Clasen cd5c39834d inspector: Show the default.activate action
We were hardcoding that GtkApplicationWindow only
has a single action group with prefix 'win', but
that is no longer the case. Simply use the code
for the general widget case that can handle multiple
action groups.
2019-05-02 01:53:57 +00:00
Matthias Clasen 574a25b09c Merge branch 'kill-display-changed' into 'master'
Kill display changed

See merge request GNOME/gtk!807
2019-05-02 01:49:31 +00:00
Matthias Clasen 6e0b13b81f Make file chooser saving work again
I was a little overzealous when going
for the new default handling here. We
can't switch to gtk_widget_activate_default
before we actually handle the default.activate
action.
2019-05-02 01:41:23 +00:00
Matthias Clasen bea8025fb5 Drop the GtkWidget::display-changed signal
Display changes now happen exclusively through
the ::root and ::unroot vfuncs. Third parties
can observe display changes by listening
for notify::root.
2019-05-02 01:33:41 +00:00
Matthias Clasen 965d0e04d1 gtk: Use root/unroot instead of display-changed
The display-changed signal is going away
2019-05-02 01:33:41 +00:00
Matthias Clasen d7c54920ee menu: Listen only for notify::root
We no longer emit the display-changed signal,
so stop listening.
2019-05-01 23:05:09 +00:00
Matthias Clasen 33a8108f19 window: Implement display change via root/unroot
Export gtk_widget_root/unroot privately,
make them work on roots, and use them in
gtk_window_set_display. This gets us to a
single way to listen for display changes,
the root property.
2019-05-01 23:05:09 +00:00
Matthias Clasen 78d254370c Merge branch 'inspector-menu-fix' into 'master'
Inspector menu fix

See merge request GNOME/gtk!804
2019-05-01 23:01:50 +00:00
Matthias Clasen 377ec33069 menus: Fix menus on non-default displays
Currently, we sometimes emit display-changed
when the display changed, and sometimes we don't
since the display is changed via gtk_widget_root.

Listen for notify::root as well and update our
display. This is a temporary fix - all display
changes should go through gtk_widget_root,
eventually.
2019-05-01 22:50:29 +00:00
Benjamin Otte 2952ba07e1 Merge branch 'kill-menu-display' into 'master'
Kill menu display

See merge request GNOME/gtk!806
2019-05-01 22:09:13 +00:00
Matthias Clasen 62b7ea7611 Remove gtk_menu_set_display
Menus should always be attached to a toplevel,
in which case they get their display that way.
2019-05-01 21:54:57 +00:00
Matthias Clasen c9eca55c5e tests: Stop using gtk_menu_set_display
It is not needed here.
2019-05-01 21:54:57 +00:00
Matthias Clasen 435bc269e9 Merge branch 'expander-demo-fix' into 'master'
gtk-demo: Make the expander demo behave again

See merge request GNOME/gtk!805
2019-05-01 21:19:27 +00:00
Matthias Clasen 0d2a7f876b gtk-demo: Make the expander demo behave again
Changes to the dialog hierarchy have affected
this demo, that admittedly pokes at message
dialog internals. Do that some more, to fix
things up.
2019-05-01 21:12:36 +00:00
Matthias Clasen 737400ddbc wayland: sanity check events at the source
Sanity check events before we throw them into
the event queue, as this makes it much easier
to track down the culprit.
2019-05-01 20:51:43 +00:00
Matthias Clasen 134e159bc9 gdk: add a sanity check for events
Before delivering events to GTK, make sure
they're sane. For now, this means making sure
the surface and device are from the same
display.
2019-05-01 20:50:24 +00:00
Matthias Clasen 6f0b47681b seat: Add a sanity check
apis that takes multiple display-relative objects
should make sure that they are all from the same
display, or hard-to-track-down badness will happen
later on.

Add such a check for the surface and device arguments
of gdk_seat_grab. This helped in tracking down
critical warnings from combo boxes in the inspector.
2019-05-01 20:46:02 +00:00
Matthias Clasen d53981fdbb Merge branch 'add-color-button-fix' into 'master'
Adwaita: Fix 'add color' button corners

Closes #1856

See merge request GNOME/gtk!801
2019-05-01 17:26:34 +00:00
Matthias Clasen e09beee62a Adwaita: Fix 'add color' button corners
The specification for border-radius goes
top-left top-right bottom-right bottom-left.
The css for the add button in the color
chooser got this wrong, and was showing
a broken top-right corner.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1856
2019-05-01 17:18:39 +00:00
Rico Tzschichholz 724ec3ca92 Add a few placeholder documentation block to have g-i annotations 2019-05-01 15:03:16 +02:00
Matthias Clasen 3ce6a710a3 Merge branch 'entry-fix' into 'master'
Fix Emoji insertion

See merge request GNOME/gtk!800
2019-05-01 05:21:09 +00:00
Matthias Clasen e41596d6a1 text: Make Emoji insertion work properly
We are now getting focus-out and focus-in events
when the Emoji chooser is shown and hidden, and
this is causing the text to select-on-entry before
inserting the Emoji, which then deletes the selection.

Avoid this by saving and restoring the selection
when presenting the Emoji chooser.
2019-05-01 05:13:52 +00:00
Matthias Clasen 0fa4d54316 inspector: Track readonly property values
That a property can't be set does not mean
its value can't change. This was showing up
as the cursor-position and selection-bound
properties in GtkText not showing their
current value in the inspector.
2019-05-01 04:57:54 +00:00
Matthias Clasen e7cbb7a76c inspector: Don't listen for notify twice
The property list now uses property editors
for the value, which listen for updates by
themselves, so no need for the list to do it.
2019-05-01 04:44:07 +00:00
Matthias Clasen b2a23a9a90 entry: only notify properties we have
GtkText now has the propagate-text-width property,
which is not present on GtkEntry, so we can't just
blindly forward all properties.
2019-05-01 04:41:28 +00:00
Matthias Clasen 6878c2bae0 Merge branch 'minus-one' into 'master'
fix signedness issues in api

Closes #1555

See merge request GNOME/gtk!799
2019-05-01 03:38:42 +00:00
Matthias Clasen 5b8f1aa2ee Merge branch 'xdg-output' into 'master'
[gtk4] wayland: Add support for xdg-output

Closes #1828

See merge request GNOME/gtk!751
2019-05-01 03:34:56 +00:00
Matthias Clasen 6b4a82224c Merge branch 'window-activate-revert-master' into 'master'
Revert "gdk: deactivate/activate surface on keyboard grabs"

See merge request GNOME/gtk!795
2019-05-01 03:32:12 +00:00
Matthias Clasen 1f30b7742b textutil: Fix signedness issues in api
A length argument that can be -1 should be signed.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1555
2019-05-01 03:25:29 +00:00
Matthias Clasen 54e7a94d70 builder: Fix signedness issues in apis
Whenever we take a length argument that can
be -1 for 'nul-terminated', it should be
gssize, not gsize.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1555
2019-05-01 03:21:29 +00:00
Matthias Clasen f1919c706f Merge branch 'grab-cursor-fix' into 'master'
window: Prevent resize cursors from sticking

Closes #23

See merge request GNOME/gtk!797
2019-05-01 00:42:09 +00:00
Matthias Clasen 26b17473aa window: Prevent resize cursors from sticking
When a modal dialog is smaller than its parent,
we were keeping the resize cursor from the dialogs
edge all over the parent window, which looks
really irritating, since the resize cursors are
closely associated with the window edge. Fix
this by falling back to the default cursor
outside the grab widgets surface.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/23
2019-04-30 20:19:35 -04:00
Samuel Thibault 99eee5cea9 Revert "gdk: deactivate/activate surface on keyboard grabs"
This reverts commits 35417a5a74 and
01455399e8.

This reintroduces #85, but see discussion in
https://gitlab.gnome.org/GNOME/gtk/merge_requests/433 for the unforeseen
invasive consequences of these commits.
2019-04-30 16:48:16 +02:00
Timm Bäder 074a0014c1 filechooserwidget: Only query clock-format setting once
We don't support that setting life-updating anyway. So, instead of
getting the value *every time we format a time*, get it once for the
filechooserwidget and reuse that value.
2019-04-30 06:43:42 +02:00
Timm Bäder 091cac00b2 Adwaita: Fix active spinbutton button image color
The spinbutton>button>image is currently blue when the image is clicked
and dark-ish when the button is clicked(but not the image). This was not
the case before since we didn't even propagate :active down to the image
child. Fix this by only applying the blue color to direct image children
of entries.
2019-04-30 05:54:00 +02:00
Timm Bäder 175e3d751d filechooserwidget: Remove unnecessary deprecation guards 2019-04-30 05:36:20 +02:00
Timm Bäder 83e9361005 filechooserwidget: Stop using gtk_widget_get_allocat* 2019-04-30 05:36:20 +02:00
Timm Bäder 17bb1248b5 filechooserwidget: Shorten cancel_all_operations() impl 2019-04-30 05:36:20 +02:00
Timm Bäder 8211e79be9 filechooserwidget: Shorten dispose impl a bit 2019-04-30 05:36:20 +02:00
Timm Bäder d5282862e5 filechooserwidget: Remove some unnecessary show() calls
Widgets are visible by default now.
2019-04-30 05:36:20 +02:00
Timm Bäder 26b6d18563 filechooserwidget: Use a bin layout
Instead of implementing size_allocate and measure manually.
2019-04-30 05:36:20 +02:00
Timm Bäder 31fb5cc2d4 filechooserwidget: Shorten finalize implementation a bit 2019-04-30 05:36:20 +02:00
Timm Bäder 90301c6813 filechooserwidget: Inline fuction into only caller 2019-04-30 05:36:20 +02:00
Timm Bäder ccdf50aafd filechooserwidget: Fix rename popover widget alignment 2019-04-30 05:36:20 +02:00
Timm Bäder af5c80248d placesview: Bring spacing in the actionbar back
In particular between the Connect button and the adjacent button/entry
combination.
2019-04-30 05:36:20 +02:00
Timm Bäder 1d81a58cf1 filechooserwidget: Pick reasonable default sidebar width
The old default of 148px doesn't work everywhere. Instead, pick a
default value of -1 and measure() the sidebar widget in the
filechooserwidget in that case. Other values >= 0 are still handled as
before.
2019-04-30 05:36:20 +02:00
Timm Bäder 09cec2e6a1 filechooserwidget: Delay view switch to search hits
Leave it to the ::hits-added handler to switch to the list of search
hits. This way we don't get a weird transition when the current search
didn't have any hits and the next one doesn't either.
Searches with hits still feel good.
2019-04-30 05:36:20 +02:00
Chun-wei Fan efed2641f4 Merge branch 'fix-win32-gl-resize' into 'master'
Fix win32 gl resize

See merge request GNOME/gtk!694
2019-04-30 03:35:16 +00:00
Matthias Clasen 97a5ca74d2 Merge branch 'modelbutton-focus' into 'master'
Adwaita: Give model buttons visible focus

See merge request GNOME/gtk!794
2019-04-29 19:32:31 +00:00
Matthias Clasen 5b5b215dea Merge branch 'frameclock-property' into 'master'
surface: Add a frame-clock property

See merge request GNOME/gtk!791
2019-04-29 19:23:09 +00:00
Matthias Clasen 7a06859f38 Adwaita: Give model buttons visible focus
Hard to use keynav, otherwise.  Also, hard
to debug focus issues if you can't see where
the focus is.
2019-04-29 15:21:40 -04:00
Matthias Clasen 24fa104b61 surface: Add a frame-clock property
Now that GdkSurface has properties, it makes
sense to turn the frame clock into one too.

This will make it easier to reshuffle some
of the surface constructors later.
2019-04-29 15:11:58 -04:00
Matthias Clasen 89861faa04 Merge branch 'tooltip-cleanup' into 'master'
tooltip: Remove an unused gdk_surface_get_root_coords call

See merge request GNOME/gtk!793
2019-04-29 19:04:49 +00:00
Benjamin Otte 5fd94e2027 Merge branch 'window-cursor' into 'master'
window: Set cursor on the right surface

See merge request GNOME/gtk!792
2019-04-29 19:02:21 +00:00
Benjamin Otte 1f4d02740e Merge branch 'accessible-present' into 'master'
icon view accessible: Stop presenting windows

See merge request GNOME/gtk!790
2019-04-29 19:02:15 +00:00
Matthias Clasen 0023b9036b tooltip: Remove an unused gdk_surface_get_root_coords call
The tx and ty variables are not used, so don't
bother setting them.
2019-04-29 14:56:00 -04:00
Matthias Clasen 89d1f8c3ca window: Set cursor on the right surface
Set the cursor on the surface of the target
widget, not the surface of some of its parents.

This does not make a difference currently.
But it will in the future, when we have
parented widgets with surfaces.
2019-04-29 14:51:55 -04:00
Matthias Clasen 7d9364655d icon view accessible: Stop presenting windows
Thats really not its business.
2019-04-29 14:46:40 -04:00
Matthias Clasen 86d2fcef16 Merge branch 'wayland-grab-fix' into 'master'
wayland: Only check incorrect top-most for grabbing popups

See merge request GNOME/gtk!789
2019-04-29 18:42:46 +00:00
Jonas Ådahl 5f8543fe81 wayland: Only check top-most for grabbing popups
Non-grabbing popups are not limited to a single
nesting stack, as per the spec, so we should not
prevent that on the client-side.
2019-04-29 16:00:53 +00:00
Matthias Clasen aae7816557 wayland: Reshuffle some internals
Make find_grab_input_seat return a GdkWaylandSeat
instead of a struct wl_seat, so we can use it and
avoid calling gdk_display_get_default_seat when
we need to get a serial later.
2019-04-29 16:00:09 +00:00
Jakub Steiner 6fbf13965c Adwaita: tone down lowres icon aid
Fixes https://gitlab.gnome.org/GNOME/gtk/issues/1818
2019-04-29 15:08:49 +02:00
Alexander Larsson 484e330e4a Merge branch 'wip/baedert/fix-gl-debug' into 'master'
Fix GL debugging

See merge request GNOME/gtk!778
2019-04-29 11:42:04 +00:00
Kristjan SCHMIDT f27ecde1e2 Update Esperanto translation 2019-04-29 06:16:28 +00:00
Benjamin Otte c06d1a69ae Merge branch 'transform-fixes' into 'master'
Small fixes to GskTransform

See merge request GNOME/gtk!660
2019-04-29 00:42:28 +00:00
Emmanuele Bassi cf9deb7cf5 Use getters for translation and scaling components
Instead of accessing the matrix cells directly.
2019-04-29 02:26:31 +02:00
Emmanuele Bassi 40beb69487 Never compare floats for equality
Floating point values cannot ever be compared for equality. GLib has a
G_APPROX_VALUE macro that lets us compare two value within a provided
precision, so we should use that instead.
2019-04-29 02:26:31 +02:00
Emmanuele Bassi f1cadee196 Use matrix equality in GskTransform
Graphene has new API to check for equality, so we should use it instead
of doing a byte-by-byte comparison.
2019-04-29 02:26:31 +02:00
Emmanuele Bassi f6594ff073 Update the version of Graphene
We're going to use newly added API soon.
2019-04-29 02:26:31 +02:00
Emmanuele Bassi 478fdaa632 Use atomic boxing instead of manual refcounting
Artisanal, homegrown, locally sourced, vegan reference counting has been
replaced by the appropriate API in GLib, which does small things like
saturation and type checking.
2019-04-29 02:25:18 +02:00
Matthias Clasen 6c472ed2b8 Merge branch 'default-handling' into 'master'
Default handling

See merge request GNOME/gtk!786
2019-04-28 23:51:17 +00:00
Matthias Clasen 30942c4e3d Fix builder parser tests
The line numbers changed here because we
removed some properties.
2019-04-28 23:44:07 +00:00
Matthias Clasen bf7d1e7b5a tests: Fix a default-related test
The test was setting has-default, but testing
receives-default.
2019-04-28 23:40:57 +00:00
Matthias Clasen 92e21c3f1c Drop the can-default property
It was added at a time when default buttons
had a very large external border that would disrupt
aligment. Not a problem nowadays.
2019-04-28 23:28:39 +00:00
Matthias Clasen 8880d27460 inspector: Stop showing default widget in misc
This is just a regular window property now,
no need for special casing.
2019-04-28 23:23:11 +00:00
Matthias Clasen 59d50be737 widget: Drop gtk_widget_grab_default
The default widget is mostly a dialog concept,
and does not really need this generic api.

If you need to mark a widget as default,
use gtk_window_set_default() directly.
2019-04-28 23:23:11 +00:00
Matthias Clasen 6d73443131 widget: Remove special handling for has-default
We used to handle has-default specially in ui
files. It was awkward, so stop doing that. If you
need to influence the default widget in a window,
you can just set the default-widget property.
2019-04-28 23:23:11 +00:00
Matthias Clasen fe3796ed5b widget-factory: Stop setting has-default in ui files
We can just set the default-widget property. The
special handling for has-default in ui files is
going away.
2019-04-28 23:21:51 +00:00
Matthias Clasen 89f7b974f2 Stop using gtk_widget_grab_default
Replace gtk_widget_grab_default by gtk_window_set_default_widget.
2019-04-28 23:21:51 +00:00
Matthias Clasen 0ae958d45b Drop gtk_window_activate_default
This api has been replaced by an action that
can be activated with gtk_widget_activate_action.
2019-04-28 23:21:50 +00:00
Matthias Clasen 3d1fdf77dc file chooser: Stop using gtk_window_activate_default
Instead, use the new way of activating default.

I think most of the default handling in
GtkFileChooserDialog should be dropped, but
for now this keeps things working.
2019-04-28 23:20:13 +00:00
Matthias Clasen 0ae71cacb4 mount operation: Handle default activation via action
Switch to the new way of activating default.
2019-04-28 23:20:13 +00:00
Matthias Clasen 218d635ca2 entry: Activate default via action
Switch to the new way of activating default.
2019-04-28 23:20:13 +00:00
Matthias Clasen 7553d0c471 label: Activate default via action
Switch to the new way of activating default.
2019-04-28 23:20:13 +00:00
Matthias Clasen f4880f5df5 Add gtk_widget_activate_default
This is a convenience wrapper for
activating the "default.activate" action.
2019-04-28 23:20:13 +00:00
Matthias Clasen 3ccdad76de popover: Add a default.activate action
This is a first example of a widget intercepting
the default.activate for its own handling.
2019-04-28 23:20:13 +00:00
Matthias Clasen e464c08545 window: Add a default.activate action
Activating this action will replace other
activate_default apis. It is more flexible,
since intermediate widgets can intercept the
action and do their own handling.
2019-04-28 23:20:13 +00:00
Matthias Clasen 56e95ddfc8 popover: Add a default-widget property
This is part of redoing default widget handling.
2019-04-28 23:20:13 +00:00
Matthias Clasen 65052a5d6c Rename gtk_window_set_default
Call it gtk_window_set_default_widget, to match
the getter, and the property name. Update all
callers.
2019-04-28 23:20:13 +00:00
Matthias Clasen 1364eb2f62 window: Add a default-widget property
This is a part of redoing default widget handling.
2019-04-28 23:20:13 +00:00
Matthias Clasen aa8ada3fed widget: Add a convenience api to activate actions
Since actions are used increasingly, we should
have a convenient way to trigger an action in
the context of a widget.
2019-04-28 23:19:05 +00:00
Matthias Clasen 3643a9fe86 Merge branch 'focus-cleanup' into 'master'
Focus cleanup

See merge request GNOME/gtk!788
2019-04-28 23:17:46 +00:00
Matthias Clasen 25f4bb2e17 Avoid critical warnings
These critical warnings break the tests, otherwise.
2019-04-28 22:55:43 +00:00
Matthias Clasen 3b62d9c027 Drop gtk_window_activate_focus
This api wasn't used anywhere in GTK. And since
we've dropped the variant for the default widget,
this one should go too. If it is needed, it should
become and action too.
2019-04-28 22:21:09 +00:00
Matthias Clasen c92938b378 widget: Remove special handling of has-focus
We used to handle has-focus in ui files specially.
It was awkward, so stop doing that. If you need
to influence the initial focus of a window, you
can just set the focus-widget property.
2019-04-28 22:21:03 +00:00
Matthias Clasen c98313016e window: Fix up the buildable implementation
We were assuming that the parent class has a custom
set_property, which may not be the case. Be more
careful.
2019-04-28 22:20:55 +00:00
Matthias Clasen e43839114d Merge branch 'inspector-prop-sort' into 'master'
inspector: Make property list sortable again

See merge request GNOME/gtk!787
2019-04-28 22:03:31 +00:00
Matthias Clasen b6c1786165 inspector: Make property list sortable again
We lost this when moving from a treeview to
a listbox. Bring it back, with homegrown list
headers.
2019-04-28 21:56:10 +00:00
Matthias Clasen 3a40555202 Merge branch 'file-chooser-location-escape' into 'master'
file chooser: Stay focused

Closes #1851

See merge request GNOME/gtk!785
2019-04-28 16:16:31 +00:00
Matthias Clasen ff604e1906 file chooser: Stay focused
When hitting Escape in the location entry,
we were not moving the focus anywhere,
causing focus to be NULL, and key bindings
to stop working. The visible effect was
that Ctrl-L / Escape / Ctrl-L would not
get back to the location entry, as expected.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1851
2019-04-28 16:08:21 +00:00
Matthias Clasen 34974a8a66 Merge branch 'wip/baedert/filechooser2' into 'master'
Assorted filechooser improvements

See merge request GNOME/gtk!783
2019-04-28 15:33:07 +00:00
Matthias Clasen 7c15daf99e Merge branch 'file-chooser-escape' into 'master'
file chooser: Prevent accidental search

Closes #1850

See merge request GNOME/gtk!784
2019-04-28 15:27:51 +00:00
Matthias Clasen b9467a4dc7 file chooser: Prevent accidental search
When hitting Escape, the file chooser will go
into search mode, because the search entry
consumes the key to emit the ::search-stopped
signal. Recognize this situation and avoid
switching to search mode in this case.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1850
2019-04-28 15:20:07 +00:00
Timm Bäder 5a1c37a8c8 filechooserwidget: Use a center box for the search entry
This way we can avoid a slight position offset when we show or hide the
spinner during a search.
2019-04-28 11:30:13 +02:00
Timm Bäder b75bc8aa64 filechooserwidget: Allow keynav from the treeview to the search entry 2019-04-28 11:27:42 +02:00
Timm Bäder ed4c08d9b3 window: Check whether the new focus widget is the old one
We generally do that for all properties.
2019-04-28 11:27:21 +02:00
Timm Bäder 929cdd9259 treeview: Don't always grab_focus() when moving the cursor
This doesn't really make sense, we can assume that the treeview already
has the focus when it receives key events.
2019-04-28 11:26:40 +02:00
Timm Bäder 78049f452a filechooserwidget: Remove unneeded function prototype 2019-04-28 11:08:09 +02:00
Timm Bäder cf2ef4863b filechooserwidget: Don't focus treeview when searching
It's just weird that the search entry does not have focus while we type.
2019-04-28 11:07:14 +02:00
Timm Bäder 2bd348558e filechooserwidget: Remove some GdkEvent usage 2019-04-28 11:05:37 +02:00
Timm Bäder 0f6d83bb5f filechooserbutton: Remove some dead code 2019-04-28 11:02:59 +02:00
Timm Bäder 7e20232607 colorbutton: Remove unneeded snapshot implementation 2019-04-28 10:55:10 +02:00
Timm Bäder dcc55e3a73 Adwaita: Bring filechooserbutton spacing back
Add some space between the icons and the text, like there was in gtk3.
2019-04-28 10:40:54 +02:00
Timm Bäder 59fd48cee0 entry: Fix primary icon allocation in RTL entries
The primary icon is on the right in RTL, so don't offset the text child
to the right for it.
Fixes the text and icon overlapping in the second entry
in tests/testentryicons
2019-04-28 08:36:36 +02:00
Timm Bäder c848b9014b gl renderer: Add simple blend node implementation 2019-04-28 07:58:31 +02:00
Timm Bäder 1e16cb088a treeview: Always update expand when allocating columns
It doesn't make sense to keep track of all the last_* values anymore now
that widgets only get allocated when their size changes anyway.
Remove all the associated (and thus now unused) flags as well.
2019-04-28 06:54:10 +02:00
Timm Bäder f4cf43359d treeview: Remove a useless check 2019-04-28 06:50:57 +02:00
Timm Bäder 6c8a5f5e2f treeview: Remove unused member 2019-04-28 06:45:33 +02:00
Matthias Clasen da64d687d1 Merge branch 'popover-demos' into 'master'
Popover demos

See merge request GNOME/gtk!782
2019-04-27 18:09:57 +00:00
Matthias Clasen aab803b7ae widget-factory: Make a resizing popover
Add an expander to a popover to test how
changing sizes works with popovers.
2019-04-27 18:00:22 +00:00
Matthias Clasen 936aba884a Merge branch 'file-chooser-search' into 'master'
file chooser: Fix Ctrl-L

Closes #1829

See merge request GNOME/gtk!781
2019-04-27 17:52:02 +00:00
Matthias Clasen e1200230c4 widget-factory: Add some nested popovers
These are mainly for stress-testing our
popover implementations.
2019-04-27 17:50:22 +00:00
Matthias Clasen d3ad816d63 widget-factory: Add non-modal popovers
This makes is easy to test moving the toplevel
or repositioning the parent while the popover
is shown.
2019-04-27 17:50:14 +00:00
Matthias Clasen eea1388cf4 file chooser: Fix Ctrl-L
We were forwarding key events to the search entry
and unconditionally considered search started
afterwards. That is not correct, since things
like a Ctrl key press should not trigger search.
Fix this by only switching to search mode when
the event was actually consumed.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1829
2019-04-27 17:43:59 +00:00
Matthias Clasen f3747d1776 Merge branch 'font-chooser-search' into 'master'
fontchooser: Fix type-to-search

Closes #1842

See merge request GNOME/gtk!780
2019-04-27 16:08:53 +00:00
Matthias Clasen 6277f2fccc fontchooser: Fix type-to-search
The key capture was interfering with other
entries in the dialog, so be smarter about
when we want to capture keys and when we
don't.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1842
2019-04-27 15:59:45 +00:00
Timm Bäder 931b0b3752 gl renderer: Move texture labeling below initialization
Apparently genTextures and friends only "reserves names", initializing
them will actually create them. Using glObjectLabel on textures before
initializing them will throw a GL_INVALID_VALUE error.
2019-04-27 10:44:37 +02:00
Timm Bäder 6f3e608331 gdkglcontext: Limit gl debug label length
There's a maximum length we have to adhere to, otherwise GL throws a
GL_INVALID_VALUE error.
2019-04-27 10:44:23 +02:00
Olivier Fourdan 1f58e0ed6b wayland: Add support for xdg-output
Previously, the GDK backend for Wayland would deduce the logical size
of the monitors from the wl_output size and scale.

With the addition of fractional scaling which advertises a larger scale
value and then scale down the client surface, the computed logical size
of the monitors in GDK would be wrong and confuse applications which
insist on using the monitor size and position (like Firefox).

The xdg-output protocol aims at describing outputs in a way which is more
in line with the concept of an output on desktop oriented systems by
presenting the outputs using their logical size and position appropriately
transformed.

Add support for the optional xdg-output protocol so that the size and
position of the monitors as reported by GDK is correct even when using
fractional scaling.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/1828
2019-04-16 16:14:43 +02:00
Chun-wei Fan 7a45768efe gdkglcontext-win32.c: Fix Resizing and moving
We preiously did not apply the resizes and moves as they were previously
only done in the Cairo drawing context on Win32.  Fix this by applying
this too in the GL drawing context.
2019-04-01 14:51:29 +08:00
Chun-wei Fan 3a56da60dd gdk/win32/gdkcairocontext-win32.c: Make functions shared in backend
Make gdk_win32_surface_get_queued_window_rect() and
gdk_win32_surface_apply_queued_move_resize() not static functions, as we
want to use them in gdkglcontext-win32.c, to fix resizing and moving.
2019-04-01 14:51:13 +08:00
247 changed files with 10127 additions and 12191 deletions
+1
View File
@@ -32,6 +32,7 @@ xvfb-run -a -s "-screen 0 1024x768x24" \
--timeout-multiplier 2 \
--print-errorlogs \
--suite=gtk \
--no-suite=gtk:gsk \
--no-suite=gtk:a11y
# Save the exit code
+23 -16
View File
@@ -12,13 +12,13 @@ Overview of Changes in GTK+ 3.96.0
* The use of global coordinates in GDK apis has been reduced. This
work is still incomplete
* Events have been simplified and are just used for input
- expose events have been replaced by a GdkSurface::render signal
- configure events have been replaced by a GdkSurface::size-changed signal
- map events have been replaced by a GdkSurface::mapped property
- gdk_event_handler_set has been replaced by a GdkSurface::event signal
- key events no longer contain a string
- events on unmapped widgets are ignored
* Events have been simplified and are used just for input
- expose events have been replaced by a GdkSurface::render signal
- configure events have been replaced by a GdkSurface::size-changed signal
- map events have been replaced by a GdkSurface::mapped property
- gdk_event_handler_set has been replaced by a GdkSurface::event signal
- key events no longer contain a string
- events on unmapped widgets are ignored
* Warping the pointer is no longer supported
@@ -36,11 +36,11 @@ Overview of Changes in GTK+ 3.96.0
* A number of list models have been introduced, for internal use
and as public api:
- GtkMapListModel
- GtkSliceListModel
- GtkSortListModel
- GtkSelectionModel
- GtkSingleSelection
- GtkMapListModel
- GtkSliceListModel
- GtkSortListModel
- GtkSelectionModel
- GtkSingleSelection
* Support for tabular menus and combo boxes has been dropped
@@ -70,9 +70,13 @@ Overview of Changes in GTK+ 3.96.0
* GtkWidget can now use a GtkLayoutManager for size allocation.
Layout managers can optionally use layout children holding layout
properties. GtkBinLayout, GtkBoxLayout, GtkGridLayout, GtkFixedLayout
and GtkCustomLayout are currently available, more layout manager
implementations will appear in the future.
properties. A number of layout managers are available:
- GtkBinLayout
- GtkBoxLayout
- GtkGridLayout
- GtkFixedLayout
- GtkCustomLayout
More layout manager implementations will appear in the future.
* GtkAssistant, GtkStack and GtkNotebook now have publicly
accessible page objects for their children. The page objects
@@ -82,8 +86,11 @@ Overview of Changes in GTK+ 3.96.0
child properties have been removed, converted to regular properties,
moved to layout properties or moved to child meta objects.
* GtkListBox has gained a ::show-separators property that gets
translated into a CSS style class.
* A number of X11-specific GtkWindow and GdkSurface apis have been
removed
removed or changed to backend APIs.
* GtkBuilder can specify object-valued properties inline.
+7
View File
@@ -31,6 +31,7 @@ do_expander (GtkWidget *do_widget)
GtkWidget *toplevel;
GtkWidget *area;
GtkWidget *expander;
GtkWidget *label;
GtkWidget *sw;
GtkWidget *tv;
GtkTextBuffer *buffer;
@@ -50,13 +51,19 @@ do_expander (GtkWidget *do_widget)
area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (window));
label = gtk_widget_get_last_child (area);
gtk_label_set_line_wrap (GTK_LABEL (label), FALSE);
gtk_widget_set_vexpand (label, FALSE);
expander = gtk_expander_new ("Details:");
gtk_widget_set_vexpand (expander, TRUE);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 100);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (sw), TRUE);
tv = gtk_text_view_new ();
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
+1 -11
View File
@@ -101,51 +101,41 @@ do_menus (GtkWidget *do_widget)
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add (GTK_CONTAINER (window), box);
gtk_widget_show (box);
box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (box), box1);
gtk_widget_show (box1);
menubar = gtk_menu_bar_new ();
gtk_widget_set_hexpand (menubar, TRUE);
gtk_container_add (GTK_CONTAINER (box1), menubar);
gtk_widget_show (menubar);
menu = create_menu (2);
menuitem = gtk_menu_item_new_with_label ("test\nline2");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_label ("foo");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (3));
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_label ("bar");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (4));
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
gtk_widget_show (menuitem);
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_container_add (GTK_CONTAINER (box1), box2);
gtk_widget_show (box2);
button = gtk_button_new_with_label ("Flip");
g_signal_connect (button, "clicked",
G_CALLBACK (change_orientation), menubar);
gtk_container_add (GTK_CONTAINER (box2), button);
gtk_widget_show (button);
button = gtk_button_new_with_label ("Close");
g_signal_connect_swapped (button, "clicked",
G_CALLBACK(gtk_widget_destroy), window);
gtk_container_add (GTK_CONTAINER (box2), button);
gtk_widget_set_can_default (button, TRUE);
gtk_widget_grab_default (button);
gtk_widget_show (button);
gtk_window_set_default_widget (GTK_WINDOW (window), button);
}
if (!gtk_widget_get_visible (window))
+1 -2
View File
@@ -76,8 +76,7 @@ do_password_entry (GtkWidget *do_widget)
gtk_widget_set_sensitive (button, FALSE);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);
gtk_widget_set_can_default (button, TRUE);
gtk_window_set_default (GTK_WINDOW (window), button);
gtk_window_set_default_widget (GTK_WINDOW (window), button);
}
if (!gtk_widget_get_visible (window))
+1 -2
View File
@@ -99,8 +99,7 @@ do_tagged_entry (GtkWidget *do_widget)
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);
gtk_widget_set_can_default (button, TRUE);
gtk_window_set_default (GTK_WINDOW (window), button);
gtk_window_set_default_widget (GTK_WINDOW (window), button);
}
if (!gtk_widget_get_visible (window))
-1
View File
@@ -1,4 +1,3 @@
subdir('gtk-demo')
subdir('icon-browser')
subdir('node-editor')
subdir('widget-factory')
-28
View File
@@ -1,28 +0,0 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include <node-editor-application.h>
int
main (int argc, char *argv[])
{
return g_application_run (G_APPLICATION (node_editor_application_new ()), argc, argv);
}
-17
View File
@@ -1,17 +0,0 @@
node_editor_sources = [
'main.c',
'node-editor-application.c',
'node-editor-window.c',
]
node_editor_resources = gnome.compile_resources('node_editor_resources',
'node-editor.gresource.xml',
source_dir: '.')
executable('gtk4-node-editor',
node_editor_sources, node_editor_resources,
dependencies: libgtk_dep,
include_directories: confinc,
gui_app: true,
link_args: extra_demo_ldflags,
install: false)
-114
View File
@@ -1,114 +0,0 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "node-editor-application.h"
#include "node-editor-window.h"
struct _NodeEditorApplication
{
GtkApplication parent;
};
struct _NodeEditorApplicationClass
{
GtkApplicationClass parent_class;
};
G_DEFINE_TYPE(NodeEditorApplication, node_editor_application, GTK_TYPE_APPLICATION);
static void
node_editor_application_init (NodeEditorApplication *app)
{
}
static void
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
g_application_quit (G_APPLICATION (data));
}
static GActionEntry app_entries[] =
{
{ "quit", quit_activated, NULL, NULL, NULL }
};
static void
node_editor_application_startup (GApplication *app)
{
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (node_editor_application_parent_class)->startup (app);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
}
static void
node_editor_application_activate (GApplication *app)
{
NodeEditorWindow *win;
win = node_editor_window_new (NODE_EDITOR_APPLICATION (app));
gtk_window_present (GTK_WINDOW (win));
}
static void
node_editor_application_open (GApplication *app,
GFile **files,
gint n_files,
const gchar *hint)
{
NodeEditorWindow *win;
gint i;
for (i = 0; i < n_files; i++)
{
win = node_editor_window_new (NODE_EDITOR_APPLICATION (app));
node_editor_window_load (win, files[i]);
gtk_window_present (GTK_WINDOW (win));
}
}
static void
node_editor_application_class_init (NodeEditorApplicationClass *class)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
application_class->startup = node_editor_application_startup;
application_class->activate = node_editor_application_activate;
application_class->open = node_editor_application_open;
}
NodeEditorApplication *
node_editor_application_new (void)
{
return g_object_new (NODE_EDITOR_APPLICATION_TYPE,
"application-id", "org.gtk.gtk4.NodeEditor",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}
@@ -1,38 +0,0 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __NODE_EDITOR_APPLICATION_H__
#define __NODE_EDITOR_APPLICATION_H__
#include <gtk/gtk.h>
#define NODE_EDITOR_APPLICATION_TYPE (node_editor_application_get_type ())
#define NODE_EDITOR_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NODE_EDITOR_APPLICATION_TYPE, NodeEditorApplication))
typedef struct _NodeEditorApplication NodeEditorApplication;
typedef struct _NodeEditorApplicationClass NodeEditorApplicationClass;
GType node_editor_application_get_type (void);
NodeEditorApplication *node_editor_application_new (void);
#endif /* __NODE_EDITOR_APPLICATION_H__ */
-431
View File
@@ -1,431 +0,0 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "node-editor-window.h"
#include "gsk/gskrendernodeparserprivate.h"
typedef struct
{
gsize start_chars;
gsize end_chars;
char *message;
} TextViewError;
struct _NodeEditorWindow
{
GtkApplicationWindow parent;
GtkWidget *picture;
GtkWidget *text_view;
GtkTextBuffer *text_buffer;
GArray *errors;
};
struct _NodeEditorWindowClass
{
GtkApplicationWindowClass parent_class;
};
G_DEFINE_TYPE(NodeEditorWindow, node_editor_window, GTK_TYPE_APPLICATION_WINDOW);
static void
text_view_error_free (TextViewError *e)
{
g_free (e->message);
}
static gchar *
get_current_text (GtkTextBuffer *buffer)
{
GtkTextIter start, end;
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
gtk_text_buffer_remove_all_tags (buffer, &start, &end);
return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
}
static void
deserialize_error_func (const GtkCssSection *section,
const GError *error,
gpointer user_data)
{
const GtkCssLocation *start_location = gtk_css_section_get_start_location (section);
const GtkCssLocation *end_location = gtk_css_section_get_end_location (section);
NodeEditorWindow *self = user_data;
GtkTextIter start_iter, end_iter;
TextViewError text_view_error;
gtk_text_buffer_get_iter_at_line_offset (self->text_buffer, &start_iter,
start_location->lines,
start_location->line_chars);
gtk_text_buffer_get_iter_at_line_offset (self->text_buffer, &end_iter,
end_location->lines,
end_location->line_chars);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "error",
&start_iter, &end_iter);
text_view_error.start_chars = start_location->chars;
text_view_error.end_chars = end_location->chars;
text_view_error.message = g_strdup (error->message);
g_array_append_val (self->errors, text_view_error);
}
static void
text_changed (GtkTextBuffer *buffer,
NodeEditorWindow *self)
{
GskRenderNode *node;
char *text;
GBytes *bytes;
g_array_remove_range (self->errors, 0, self->errors->len);
text = get_current_text (self->text_buffer);
bytes = g_bytes_new_take (text, strlen (text));
/* If this is too slow, go fix the parser performance */
node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
g_bytes_unref (bytes);
if (node)
{
/* XXX: Is this code necessary or can we have API to turn nodes into paintables? */
GtkSnapshot *snapshot;
GdkPaintable *paintable;
graphene_rect_t bounds;
snapshot = gtk_snapshot_new ();
gsk_render_node_get_bounds (node, &bounds);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
g_clear_object (&paintable);
}
else
{
gtk_picture_set_paintable (GTK_PICTURE (self->picture), NULL);
}
}
static gboolean
text_view_query_tooltip_cb (GtkWidget *widget,
int x,
int y,
gboolean keyboard_tip,
GtkTooltip *tooltip,
NodeEditorWindow *self)
{
GtkTextIter iter;
guint i;
if (keyboard_tip)
{
gint offset;
g_object_get (self->text_buffer, "cursor-position", &offset, NULL);
gtk_text_buffer_get_iter_at_offset (self->text_buffer, &iter, offset);
}
else
{
gint bx, by, trailing;
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (self->text_view), GTK_TEXT_WINDOW_TEXT,
x, y, &bx, &by);
gtk_text_view_get_iter_at_position (GTK_TEXT_VIEW (self->text_view), &iter, &trailing, bx, by);
}
for (i = 0; i < self->errors->len; i ++)
{
const TextViewError *e = &g_array_index (self->errors, TextViewError, i);
GtkTextIter start_iter, end_iter;
gtk_text_buffer_get_iter_at_offset (self->text_buffer, &start_iter, e->start_chars);
gtk_text_buffer_get_iter_at_offset (self->text_buffer, &end_iter, e->end_chars);
if (gtk_text_iter_in_range (&iter, &start_iter, &end_iter))
{
gtk_tooltip_set_text (tooltip, e->message);
return TRUE;
}
}
return FALSE;
}
gboolean
node_editor_window_load (NodeEditorWindow *self,
GFile *file)
{
GtkTextIter end;
GBytes *bytes;
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
if (bytes == NULL)
return FALSE;
if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL))
{
g_bytes_unref (bytes);
return FALSE;
}
gtk_text_buffer_get_end_iter (self->text_buffer, &end);
gtk_text_buffer_insert (self->text_buffer,
&end,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes));
return TRUE;
}
static void
open_response_cb (GtkWidget *dialog,
gint response,
NodeEditorWindow *self)
{
gtk_widget_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
node_editor_window_load (self, file);
g_object_unref (file);
}
gtk_widget_destroy (dialog);
}
static void
open_cb (GtkWidget *button,
NodeEditorWindow *self)
{
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Open node file",
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Load", GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_widget_show (dialog);
}
static void
save_response_cb (GtkWidget *dialog,
gint response,
NodeEditorWindow *self)
{
gtk_widget_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
char *text, *filename;
GError *error = NULL;
text = get_current_text (self->text_buffer);
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!g_file_set_contents (filename, text, -1, &error))
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Saving failed");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
g_error_free (error);
}
g_free (filename);
}
gtk_widget_destroy (dialog);
}
static void
save_cb (GtkWidget *button,
NodeEditorWindow *self)
{
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Save node",
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Save", GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_widget_show (dialog);
}
static GdkTexture *
create_texture (NodeEditorWindow *self)
{
GdkPaintable *paintable;
GtkSnapshot *snapshot;
GskRenderer *renderer;
GskRenderNode *node;
GdkTexture *texture;
paintable = gtk_picture_get_paintable (GTK_PICTURE (self->picture));
if (paintable == NULL ||
gdk_paintable_get_intrinsic_width (paintable) <= 0 ||
gdk_paintable_get_intrinsic_height (paintable) <= 0)
return NULL;
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, gdk_paintable_get_intrinsic_width (paintable), gdk_paintable_get_intrinsic_height (paintable));
node = gtk_snapshot_free_to_node (snapshot);
if (node == NULL)
return NULL;
/* ahem */
renderer = GTK_ROOT_GET_IFACE (gtk_widget_get_root (GTK_WIDGET (self)))->get_renderer (gtk_widget_get_root (GTK_WIDGET (self)));
texture = gsk_renderer_render_texture (renderer, node, NULL);
gsk_render_node_unref (node);
return texture;
}
static void
export_image_response_cb (GtkWidget *dialog,
gint response,
GdkTexture *texture)
{
gtk_widget_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!gdk_texture_save_to_png (texture, filename))
{
GtkWidget *message_dialog;
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (dialog))),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Exporting to image failed");
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (message_dialog);
}
g_free (filename);
}
gtk_widget_destroy (dialog);
g_object_unref (texture);
}
static void
export_image_cb (GtkWidget *button,
NodeEditorWindow *self)
{
GdkTexture *texture;
GtkWidget *dialog;
texture = create_texture (self);
if (texture == NULL)
return;
dialog = gtk_file_chooser_dialog_new ("",
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Save", GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
g_signal_connect (dialog, "response", G_CALLBACK (export_image_response_cb), texture);
gtk_widget_show (dialog);
}
static void
node_editor_window_finalize (GObject *object)
{
NodeEditorWindow *self = (NodeEditorWindow *)object;
g_array_free (self->errors, TRUE);
G_OBJECT_CLASS (node_editor_window_parent_class)->finalize (object);
}
static void
node_editor_window_class_init (NodeEditorWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->finalize = node_editor_window_finalize;
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/gtk4/node-editor/node-editor-window.ui");
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_buffer);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_view);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, picture);
gtk_widget_class_bind_template_callback (widget_class, text_changed);
gtk_widget_class_bind_template_callback (widget_class, text_view_query_tooltip_cb);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
gtk_widget_class_bind_template_callback (widget_class, save_cb);
gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
}
static void
node_editor_window_init (NodeEditorWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->errors = g_array_new (FALSE, TRUE, sizeof (TextViewError));
g_array_set_clear_func (self->errors, (GDestroyNotify)text_view_error_free);
}
NodeEditorWindow *
node_editor_window_new (NodeEditorApplication *application)
{
return g_object_new (NODE_EDITOR_WINDOW_TYPE,
"application", application,
NULL);
}
-42
View File
@@ -1,42 +0,0 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __NODE_EDITOR_WINDOW_H__
#define __NODE_EDITOR_WINDOW_H__
#include <gtk/gtk.h>
#include "node-editor-application.h"
#define NODE_EDITOR_WINDOW_TYPE (node_editor_window_get_type ())
#define NODE_EDITOR_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NODE_EDITOR_WINDOW_TYPE, NodeEditorWindow))
typedef struct _NodeEditorWindow NodeEditorWindow;
typedef struct _NodeEditorWindowClass NodeEditorWindowClass;
GType node_editor_window_get_type (void);
NodeEditorWindow * node_editor_window_new (NodeEditorApplication *application);
gboolean node_editor_window_load (NodeEditorWindow *self,
GFile *file);
#endif /* __NODE_EDITOR_WINDOW_H__ */
-99
View File
@@ -1,99 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkTextTagTable" id="tags">
<child type="tag">
<object class="GtkTextTag">
<property name="name">error</property>
<property name="underline">error</property>
</object>
</child>
</object>
<object class="GtkTextBuffer" id="text_buffer">
<property name="tag-table">tags</property>
<signal name="changed" handler="text_changed"/>
</object>
<template class="NodeEditorWindow" parent="GtkApplicationWindow">
<style>
<class name="devel"/>
</style>
<property name="title" translatable="yes">GTK Node Editor</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="title" translatable="yes">GTK Node Editor</property>
<property name="show-title-buttons">1</property>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-open-symbolic</property>
<property name="tooltip-text">Open node file</property>
<signal name="clicked" handler="open_cb"/>
</object>
</child>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-save-symbolic</property>
<property name="tooltip-text">Save to node file</property>
<signal name="clicked" handler="save_cb"/>
</object>
</child>
<child type="start">
<object class="GtkButton">
<property name="icon-name">insert-image-symbolic</property>
<property name="tooltip-text">Export to image</property>
<signal name="clicked" handler="export_image_cb"/>
</object>
</child>
<child type="title">
<object class="GtkLabel">
<property name="label" translatable="yes">GTK Node Editor</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPaned">
<property name="shrink-child2">false</property>
<property name="position">400</property>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="expand">1</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="buffer">text_buffer</property>
<property name="wrap-mode">word</property>
<property name="monospace">1</property>
<property name="has-focus">1</property>
<property name="top-margin">6</property>
<property name="left-margin">6</property>
<property name="right-margin">6</property>
<property name="bottom-margin">6</property>
<property name="has-tooltip">1</property>
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="expand">1</property>
<property name="min-content-height">100</property>
<property name="min-content-width">100</property>
<child>
<object class="GtkViewport">
<child>
<object class="GtkPicture" id="picture">
<property name="can-shrink">0</property>
<property name="halign">center</property>
<property name="valign">center</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gtk/gtk4/node-editor">
<file preprocess="xml-stripblanks">node-editor-window.ui</file>
</gresource>
</gresources>
+85 -9
View File
@@ -2880,6 +2880,17 @@ microphone-sensitivity-medium-symbolic</property>
<child>
<object class="GtkNotebook">
<property name="show-border">0</property>
<child type="action-end">
<object class="GtkMenuButton">
<property name="valign">center</property>
<property name="popover">notebook_info_popover2</property>
<property name="icon-name">emblem-important-symbolic</property>
<property name="relief">none</property>
<style>
<class name="circular"/>
</style>
</object>
</child>
<child>
<object class="GtkNotebookPage">
<property name="tab-expand">1</property>
@@ -3143,6 +3154,7 @@ bad things might happen.</property>
<property name="use-header-bar">1</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">
<object class="GtkBox">
<child>
@@ -3164,8 +3176,6 @@ bad things might happen.</property>
</child>
<child type="action">
<object class="GtkButton" id="act_action_dialog">
<property name="can-default">1</property>
<property name="has-default">1</property>
<property name="label" translatable="yes">_Act</property>
<property name="use-underline">1</property>
</object>
@@ -3303,6 +3313,7 @@ bad things might happen.</property>
<property name="use-header-bar">1</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">
<object class="GtkBox">
<child>
@@ -3324,8 +3335,6 @@ bad things might happen.</property>
</child>
<child type="action">
<object class="GtkButton" id="select_selection_dialog">
<property name="can-default">1</property>
<property name="has-default">1</property>
<property name="label" translatable="yes">_Select</property>
<property name="use-underline">1</property>
</object>
@@ -3386,6 +3395,7 @@ bad things might happen.</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
@@ -3398,22 +3408,52 @@ bad things might happen.</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkExpander">
<child type="label">
<object class="GtkLabel">
<property name="label">Extra Info</property>
</object>
</child>
<child>
<object class="GtkEntry">
<property name="placeholder-text">Tell me anything…</property>
</object>
</child>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkMenuButton">
<property name="halign">end</property>
<property name="icon-name">emblem-system-symbolic</property>
<property name="menu-model">gear_menu</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="open_popover_button">
<property name="halign">end</property>
<property name="halign">fill</property>
<property name="label">_Open</property>
<property name="use-underline">1</property>
<property name="sensitive">0</property>
<property name="can-default">1</property>
<style>
<class name="suggested-action"/>
</style>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
<property name="left-attach">2</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -3439,8 +3479,9 @@ bad things might happen.</property>
</widgets>
</object>
<object class="GtkPopover" id="notebook_info_popover">
<property name="modal">0</property>
<child>
<object class="GtkLabel" id="notebook_info_label">
<object class="GtkLabel">
<property name="label">No updates at this time</property>
<accessibility>
<role type="static"/>
@@ -3448,4 +3489,39 @@ bad things might happen.</property>
</object>
</child>
</object>
<object class="GtkPopover" id="notebook_info_popover3">
<property name="modal">0</property>
<child>
<object class="GtkLabel">
<property name="label">You're in too deep!</property>
<accessibility>
<role type="static"/>
</accessibility>
</object>
</child>
</object>
<object class="GtkPopover" id="notebook_info_popover2">
<property name="modal">0</property>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<child>
<object class="GtkLabel">
<property name="label">Hidden gems:</property>
</object>
</child>
<child>
<object class="GtkMenuButton">
<property name="valign">center</property>
<property name="popover">notebook_info_popover3</property>
<property name="icon-name">emblem-important-symbolic</property>
<property name="relief">none</property>
<style>
<class name="circular"/>
</style>
</object>
</child>
</object>
</child>
</object>
</interface>
+1 -1
View File
@@ -231,6 +231,7 @@ gdk_surface_get_scale_factor
gdk_surface_set_opaque_region
gdk_surface_create_gl_context
gdk_surface_create_vulkan_context
gdk_surface_create_cairo_context
<SUBSECTION>
gdk_surface_queue_expose
@@ -988,7 +989,6 @@ gdk_wayland_device_get_wl_seat
gdk_wayland_display_get_wl_compositor
gdk_wayland_display_get_wl_display
gdk_wayland_display_query_registry
gdk_wayland_surface_new_subsurface
gdk_wayland_surface_get_wl_surface
GdkWaylandSurfaceExported
gdk_wayland_surface_export_handle
+4
View File
@@ -62,6 +62,7 @@ gsk_outset_shadow_node_get_spread
gsk_outset_shadow_node_get_blur_radius
gsk_cairo_node_new
gsk_cairo_node_get_draw_context
gsk_cairo_node_peek_surface
gsk_container_node_new
gsk_container_node_get_n_children
gsk_container_node_get_child
@@ -88,6 +89,7 @@ GskShadow
gsk_shadow_node_new
gsk_shadow_node_peek_shadow
gsk_shadow_node_get_n_shadows
gsk_shadow_node_get_child
GskBlendMode
gsk_blend_node_new
gsk_blend_node_get_bottom_child
@@ -103,6 +105,7 @@ gsk_text_node_peek_glyphs
gsk_text_node_peek_color
gsk_text_node_get_x
gsk_text_node_get_y
gsk_text_node_get_num_glyphs
gsk_blur_node_new
gsk_blur_node_get_child
gsk_blur_node_get_radius
@@ -162,6 +165,7 @@ gsk_transform_to_translate
gsk_transform_transform
gsk_transform_invert
gsk_transform_matrix
gsk_transform_matrix_with_category
gsk_transform_translate
gsk_transform_translate_3d
gsk_transform_rotate
+373
View File
@@ -0,0 +1,373 @@
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
]>
<refentry id="chap-actions">
<refmeta>
<refentrytitle>The GTK Action Model</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GTK Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>The GTK Action Model</refname>
<refpurpose>
How actions are used in GTK
</refpurpose>
</refnamediv>
<refsect1 id="actions-overview">
<title>Overview of actions in GTK</title>
<para>
This chapter describes in detail how GTK uses actions to connect
activatable UI elements to callbacks. GTK inherits the underlying
architecture of GAction and GMenu for describing abstract actions
and menus from the GIO library.
</para>
<refsect2>
<title>Basics about actions</title>
<para>
A GAction is essentially a way to tell the toolkit about a
piece of functionality in your program, and to give it a name.
</para>
<para>
Actions are purely functional. They do not contain any
presentational information.
</para>
<para>
An action has four pieces of information associated with it:
<itemizedlist>
<listitem><para>
a name as an identifier (usually all-lowercase, untranslated
English string)
</para></listitem>
<listitem><para>
an enabled flag indicating if the action can be activated or
not (like the "sensitive" property on widgets)
</para></listitem>
<listitem><para>
an optional state value, for stateful actions (like a boolean
for toggles)
</para></listitem>
<listitem><para>
an optional parameter type, used when activating the action
</para></listitem>
</itemizedlist>
</para>
<para>
An action supports two operations. You can activate it, which
requires passing a parameter of the correct type
And you can request to change the actions state (for stateful
actions) to a new state value of the correct type.
</para>
<para>
Here are some rules about an action:
<itemizedlist>
<listitem><para>
the name is immutable (in the sense that it will never
change) and it is never %NULL
</para></listitem>
<listitem><para>
the enabled flag can change
</para></listitem>
<listitem><para>
the parameter type is immutable
</para></listitem>
<listitem><para>
the parameter type is optional: it can be %NULL
</para></listitem>
<listitem><para>
if the parameter type is %NULL then action activation must
be done without a parameter (ie: a %NULL GVariant pointer)
</para></listitem>
<listitem><para>
if the parameter type is non-%NULL then the parameter must
have this type
</para></listitem>
<listitem><para>
the state can change, but it cannot change type
</para></listitem>
<listitem><para>
if the action was stateful when it was created, it will
always have a state and it will always have exactly the same
type (such as boolean or string)
</para></listitem>
<listitem><para>
if the action was stateless when it was created, it can never
have a state
</para></listitem>
<listitem><para>
you can only request state changes on stateful actions and it
is only possible to request that the state change to a value
of the same type as the existing state
</para></listitem>
</itemizedlist>
</para>
<para>
An action does not have any sort of presentational information
such as a label, an icon or a way of creating a widget from it.
</para>
</refsect2>
<refsect2>
<title>Action state and parameters</title>
<para>
Most actions in your application will be stateless actions with
no parameters. These typically appear as menu items with no
special decoration. An example is "quit".
</para>
<para>
Stateful actions are used to represent an action which has a
closely-associated state of some kind. A good example is a
"fullscreen" action. For this case, you'd expect to see a
checkmark next to the menu item when the fullscreen option
is active. This is usually called a toggle action, and it has
a boolean state. By convention, toggle actions have no parameter
type for activation: activating the action always toggles the
state.
</para>
<para>
Another common case is to have an action representing a
enumeration of possible values of a given type (typically
string). This is often called a radio action and is usually
represented in the user interface with radio buttons or radio
menu items, or sometimes a combobox. A good example is
"text-justify" with possible values "left", "center", and
"right". By convention, these types of actions have a parameter
type equal to their state type, and activating them with a
particular parameter value is equivalent to changing their
state to that value.
</para>
<para>
This approach to handling radio buttons is different than many
other action systems such as GtkAction. With GAction, there is
only one action for "text-justify" and "left", "center" and
"right" are possible states on that action. There are not three
separate "justify-left", "justify-center" and "justify-right"
actions.
</para>
<para>
The final common type of action is a stateless action with a
parameter. This is typically used for actions like
"open-bookmark" where the parameter to the action would be
the identifier of the bookmark to open.
</para>
<para>
Because some types of actions cannot be invoked without a
parameter, it is often important to specify a parameter when
referring to the action from a place where it will be invoked
(such as from a radio button that sets the state to a particular
value or from a menu item that opens a specific bookmark). In
these contexts, the value used for the action parameter is
typically called the target of the action.
</para>
<para>
Even though toggle actions have a state, they do not have a
parameter. Therefore, a target value is not needed when
referring to them — they will always be toggled on activation.
</para>
<para>
Most APIs that allow using a GAction (such as GMenuModel and
GtkActionable) allow use of detailed action names. This is a
convenient way of specifying an action name and an action target
with a single string.
</para>
<para>
In the case that the action target is a string with no unusual
characters (ie: only alpha-numeric, plus '-' and '.') then you
can use a detailed action name of the form "justify::left" to
specify the justify action with a target of left.
</para>
<para>
In the case that the action target is not a string, or contains
unusual characters, you can use the more general format
"action-name(5)", where the "5" here is any valid text-format
GVariant (ie: a string that can be parsed by g_variant_parse()).
Another example is "open-bookmark('http://gnome.org/')".
</para>
<para>
You can convert between detailed action names and split-out
action names and target values using g_action_parse_detailed_action_name()
and g_action_print_detailed_action_name() but usually you will
not need to. Most APIs will provide both ways of specifying
actions with targets.
</para>
</refsect2>
<refsect2>
<title>Action scopes</title>
<para>
Actions are always scoped to a particular object on which they
operate.
</para>
<para>
In GTK, actions are typically scoped to either an application
or a window, but any widget can have actions associated with it.
</para>
<para>
Actions scoped to windows should be the actions that
specifically impact that window. These are actions like
"fullscreen" and "close", or in the case that a window contains
a document, "save" and "print".
</para>
<para>
Actions that impact the application as a whole rather than one
specific window are scoped to the application. These are actions
like "about" and "preferences".
</para>
<para>
If a particular action is scoped to a window then it is scoped
to a specific window. Another way of saying this: if your
application has a "fullscreen" action that applies to windows
and it has three windows, then it will have three fullscreen
actions: one for each window.
</para>
<para>
Having a separate action per-window allows for each window to
have a separate state for each instance of the action as well
as being able to control the enabled state of the action on a
per-window basis.
</para>
<para>
Actions are added to their relevant scope (application or
window) either using the GActionMap interface, or by using
gtk_widget_insert_action_group().
</para>
</refsect2>
<refsect2>
<title>Action groups and action maps</title>
<para>
Actions rarely occurs in isolation. It is common to have groups
of related actions, which are represented by instances of the
GActionGroup interface.
</para>
<para>
Action maps are a variant of action groups that allow to change
the name of the action as it is looked up. In GTK, the convention
is to add a prefix to the action name to indicate the scope of
the actions, such as "app." for the actions with application scope
or "win." for those with window scope.
</para>
<para>
When referring to actions on a GActionMap only the name of the
action itself is used (ie: "quit", not "app.quit"). The
"app.quit" form is only used when referring to actions from
places like a GMenu or GtkActionable widget where the scope
of the action is not already known.
</para>
<para>
GtkApplication and GtkApplicationWindow implement the GActionMap
interface, so you can just add actions directly to them. For
other widgets, use gtk_widget_insert_action_group() to add
actions to it.
</para>
<para>
If you want to insert several actions at the same time, it is
typically faster and easier to use GActionEntry.
</para>
</refsect2>
<refsect2>
<title>Connecting actions to widgets</title>
<para>
Any widget that implements the GtkActionable interface can
be connected to an action just by setting the ::action-name
property. If the action has a parameter, you will also need
to set the ::action-target property.
Widgets that implement GtkAction include GtkSwitch, GtkButton,
GtkMenuItem and their respective subclasses.
</para>
<para>
Another of obtaining widgets that are connected to actions is
to create a menu using a GMenu menu model. GMenu provides an
abstract way to describe typical menus: nested groups of items
where each item can have a label, and icon, and an action.
</para>
<para>
Typical uses of GMenu inside GTK are to set up an application
menu or menubar with gtk_application_set_app_menu() or
gtk_application_set_menubar(). Another, maybe more common use
is to create a popover for a menubutton, using
gtk_menu_button_set_menu_model().
</para>
<para>
Unlike traditional menus, those created from menu models don't
have keyboard accelerators associated with menu items. Instead,
GtkApplication offers the gtk_application_set_accels_for_action()
API to associate keyboard shortcuts with actions.
</para>
</refsect2>
<refsect2>
<title>Activation</title>
<para>
When a widget with a connected action is activated, GTK finds
the action to activate by walking up the widget hierarchy,
looking for a matching action, ending up at the GtkApplication.
</para>
</refsect2>
<refsect2>
<title>Built-in Actions</title>
<para>
GTK uses actions for its own purposes in a number places. These
built-in actions can sometimes be activated by applications, and
you should avoid naming conflicts with them when creating your
own actions.
<variablelist>
<varlistentry>
<term>default.activate</term>
<listitem><para>Activates the default widget in a context
(typically a GtkWindow, GtkDialog or GtkPopover)
</para></listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
</refsect1>
</refentry>
+1 -1
View File
@@ -12,7 +12,7 @@
<refnamediv>
<refname>The GTK Drawing Model</refname>
<refpurpose>
The GTK drawing model in detail
How widgets draw
</refpurpose>
</refnamediv>
+2 -1
View File
@@ -24,8 +24,9 @@
<xi:include href="xml/getting_started.xml"/>
<xi:include href="resources.sgml" />
<xi:include href="xml/question_index.sgml" />
<xi:include href="drawing-model.xml" />
<xi:include href="xml/drawing-model.xml" />
<xi:include href="xml/input-handling.xml" />
<xi:include href="xml/actions.xml" />
</part>
<part id="gtkobjects">
+4 -8
View File
@@ -1779,7 +1779,6 @@ GtkMenu
GtkArrowPlacement
gtk_menu_new
gtk_menu_new_from_model
gtk_menu_set_display
gtk_menu_reorder_child
gtk_menu_popup_at_rect
gtk_menu_popup_at_widget
@@ -4433,7 +4432,6 @@ gtk_widget_event
gtk_widget_activate
gtk_widget_is_focus
gtk_widget_grab_focus
gtk_widget_grab_default
gtk_widget_set_name
gtk_widget_get_name
gtk_widget_set_sensitive
@@ -4504,8 +4502,6 @@ gtk_widget_compute_point
gtk_widget_contains
GtkPickFlags
gtk_widget_pick
gtk_widget_get_can_default
gtk_widget_set_can_default
gtk_widget_get_can_focus
gtk_widget_set_can_focus
gtk_widget_get_focus_on_click
@@ -4538,13 +4534,15 @@ gtk_widget_get_realized
gtk_widget_get_mapped
gtk_widget_device_is_shadowed
gtk_widget_get_modifier_mask
gtk_widget_insert_action_group
gtk_widget_get_opacity
gtk_widget_set_opacity
gtk_widget_get_overflow
gtk_widget_set_overflow
gtk_widget_insert_action_group
gtk_widget_list_action_prefixes
gtk_widget_get_action_group
gtk_widget_activate_action
gtk_widget_activate_default
gtk_widget_measure
gtk_widget_snapshot_child
gtk_widget_get_next_sibling
@@ -4647,8 +4645,6 @@ gtk_window_set_resizable
gtk_window_get_resizable
gtk_window_add_accel_group
gtk_window_remove_accel_group
gtk_window_activate_focus
gtk_window_activate_default
gtk_window_set_modal
gtk_window_set_default_size
gtk_window_set_hide_on_close
@@ -4671,7 +4667,7 @@ gtk_window_propagate_key_event
gtk_window_get_focus
gtk_window_set_focus
gtk_window_get_default_widget
gtk_window_set_default
gtk_window_set_default_widget
gtk_window_present
gtk_window_present_with_time
gtk_window_close
+133 -123
View File
@@ -4,15 +4,15 @@
]>
<refentry id="chap-input-handling">
<refmeta>
<refentrytitle>The GTK Input and Event Handling Model</refentrytitle>
<refentrytitle>The GTK Input Model</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GTK Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>The GTK Input and Event Handling Model</refname>
<refname>The GTK Input Model</refname>
<refpurpose>
GTK input and event handling in detail
input and event handling in detail
</refpurpose>
</refnamediv>
@@ -52,13 +52,12 @@
with any pointing device or keyboard.
</para>
<!-- input events: button, touch, key, motion, etc -->
<para>
When a user interacts with an input device (e.g. moves a mouse or presses
a key on the keyboard), GTK receives events from the windowing system.
These are typically directed at a specific window - for pointer events,
the window under the pointer (grabs complicate this), for keyboard events,
the window with the keyboard focus.
These are typically directed at a specific surface - for pointer events,
the surface under the pointer (grabs complicate this), for keyboard events,
the surface with the keyboard focus.
</para>
<para>
GDK translates these raw windowing system events into #GdkEvents.
@@ -81,9 +80,10 @@
</simplelist>
</para>
<para>
When GTK is initialized, it sets up an event handler function with
gdk_event_handler_set(), which receives all of these input events
(as well as others, for instance window management related events).
When GTK creates a GdkSurface, it connects to the ::event signal
on it, which receives all of these input events. Surfaces have
have signals and properties, e.g. to deal with window management
related events.
</para>
</refsect2>
@@ -91,8 +91,8 @@
<title>Event propagation</title>
<para>
For widgets which have a #GdkSurface set, events are received from the
windowing system and passed to gtk_main_do_event(). See its documentation
The function which initially receives input events on the GTK
side is gtk_main_do_event(). See its documentation
for details of what it does: compression of enter/leave events,
identification of the widget receiving the event, pushing the event onto a
stack for gtk_get_current_event(), and propagating the event to the
@@ -120,62 +120,55 @@
<para>
An event is propagated to a widget using gtk_propagate_event().
Propagation differs between event types: key events (%GDK_KEY_PRESS,
%GDK_KEY_RELEASE) are delivered to the top-level #GtkWindow; other events
are propagated down and up the widget hierarchy in three phases (see
#GtkPropagationPhase).
Propagation goes down and up the widget hierarchy in three phases
(see #GtkPropagationPhase) towards a target widget.
</para>
<para>
For key events, the top-level windows default #GtkWindow::key-press-event
and #GtkWindow::key-release-event signal handlers handle mnemonics and
accelerators first. Other key presses are then passed to
gtk_window_propagate_key_event() which propagates the event upwards from
the windows current focus widget (gtk_window_get_focus()) to the
top-level.
For key events, the top-level window gets a first shot at activating
mnemonics and accelerators. If that does not consume the events,
the target widget for event propagation is window's current focus
widget (see gtk_window_get_focus()).
</para>
<para>
For other events, in the first phase (the “capture” phase) the event is
delivered to each widget from the top-most (for example, the top-level
For pointer events, the target widget is determined by picking
the widget at the events coordinates (see gtk_window_pick()).
</para>
<para>In the first phase (the “capture” phase) the event is
delivered to each widget from the top-most (the top-level
#GtkWindow or grab widget) down to the target #GtkWidget.
<link linkend="event-controllers-and-gestures">Gestures</link> that are
attached with %GTK_PHASE_CAPTURE get a chance to react to the event.
<link linkend="event-controllers-and-gestures">Event
controllers</link> that are attached with %GTK_PHASE_CAPTURE
get a chance to react to the event.
</para>
<para>
After the “capture” phase, the widget that was intended to be the
destination of the event will run gestures attached to it with
%GTK_PHASE_TARGET. This is known as the “target” phase, and only
happens on that widget.
destination of the event will run event controllers attached to
it with %GTK_PHASE_TARGET. This is known as the “target” phase,
and only happens on that widget.
</para>
<para>
Next, the #GtkWidget::event signal is emitted.
Handling these signals was the primary way to handle input in GTK widgets
before gestures were introduced. The signal is emitted from
the target widget up to the top-level, as part of the “bubble” phase.
In the last phase (the “bubble” phase), the event is delivered
to each widget from the target to the top-most, and event
controllers attached with %GTK_PHASE_BUBBLE are run.
</para>
<para>
The default handlers for the event signals send the event
to gestures that are attached with %GTK_PHASE_BUBBLE. Therefore,
gestures in the “bubble” phase are only used if the widget does
not have its own event handlers, or takes care to chain up to the
default #GtkWidget handlers.
Events are not delivered to a widget which is insensitive or
unmapped.
</para>
<para>
Events are not delivered to a widget which is insensitive or unmapped.
</para>
<para>
Any time during the propagation phase, a widget may indicate that a
received event was consumed and propagation should therefore be stopped.
In traditional event handlers, this is hinted by returning %GDK_EVENT_STOP.
If gestures are used, this may happen when the widget tells the gesture
to claim the event touch sequence (or the pointer events) for its own. See the
"gesture states" section below to know more of the latter.
Any time during the propagation phase, a controller may indicate
that a received event was consumed and propagation should
therefore be stopped. If gestures are used, this may happen
when the gesture claims the event touch sequence (or the
pointer events) for its own. See the “gesture states” section
below to learn more about gestures and sequences.
</para>
</refsect2>
@@ -183,27 +176,10 @@
<title>Touch events</title>
<para>
Touch events are emitted as events of type %GDK_TOUCH_BEGIN, %GDK_TOUCH_UPDATE or
%GDK_TOUCH_END, those events contain an “event sequence” that univocally identifies
the physical touch until it is lifted from the device.
</para>
<para>
On some windowing platforms, multitouch devices perform pointer emulation, this works
by granting a “pointer emulating” hint to one of the currently interacting touch
sequences, which will be reported on every #GdkEventTouch event from that sequence. By
default, if a widget didn't request touch events by setting %GDK_TOUCH_MASK on its
event mask and didn't override #GtkWidget::touch-event, GTK will transform these
“pointer emulating” events into semantically similar #GdkEventButton and #GdkEventMotion
events. Depending on %GDK_TOUCH_MASK being in the event mask or not, non-pointer-emulating
sequences could still trigger gestures or just get filtered out, regardless of the widget
not handling those directly.
</para>
<para>
If the widget sets %GDK_TOUCH_MASK on its event mask and doesn't chain up on
#GtkWidget::touch-event, only touch events will be received, and no pointer emulation
will be performed.
Touch events are emitted as events of type %GDK_TOUCH_BEGIN,
%GDK_TOUCH_UPDATE or %GDK_TOUCH_END, those events contain an
“event sequence” that univocally identifies the physical touch
until it is lifted from the device.
</para>
</refsect2>
@@ -211,43 +187,66 @@
<title>Grabs</title>
<para>
Grabs are a method to claim all input events from a device, they happen
either implicitly on pointer and touch devices, or explicitly. Implicit grabs
happen on user interaction, when a #GdkEventButtonPress happens, all events from
then on, until after the corresponding #GdkEventButtonRelease, will be reported
to the widget that got the first event. Likewise, on touch events, every
#GdkEventSequence will deliver only events to the widget that received its
%GDK_TOUCH_BEGIN event.
Grabs are a method to claim all input events from a device,
they happen either implicitly on pointer and touch devices,
or explicitly. Implicit grabs happen on user interaction, when
a #GdkEventButtonPress happens, all events from then on, until
after the corresponding #GdkEventButtonRelease, will be reported
to the widget that got the first event. Likewise, on touch events,
every #GdkEventSequence will deliver only events to the widget
that received its %GDK_TOUCH_BEGIN event.
</para>
<para>
Explicit grabs happen programatically (both activation and deactivation),
and can be either system-wide (GDK grabs) or application-wide (GTK grabs).
On the windowing platforms that support it, GDK grabs will prevent any
interaction with any other application/window/widget than the grabbing one,
whereas GTK grabs will be effective only within the application (across all
its windows), still allowing for interaction with other applications.
Explicit grabs happen programatically (both activation and
deactivation), and can be either system-wide (GDK grabs) or
application-wide (GTK grabs). On the windowing platforms that
support it, GDK grabs will prevent any interaction with any other
application/window/widget than the grabbing one, whereas GTK grabs
will be effective only within the application (across all its
windows), still allowing for interaction with other applications.
</para>
<para>
But one important aspect of grabs is that they may potentially happen at any
point somewhere else, even while the pointer/touch device is already grabbed.
This makes it necessary for widgets to handle the cancellation of any ongoing
interaction. Depending on whether a GTK or GDK grab is causing this, the
widget will respectively receive a #GtkWidget::grab-notify signal, or a
But one important aspect of grabs is that they may potentially
happen at any point somewhere else, even while the pointer/touch
device is already grabbed. This makes it necessary for widgets to
handle the cancellation of any ongoing interaction. Depending on
whether a GTK or GDK grab is causing this, the widget will
respectively receive a #GtkWidget::grab-notify signal, or a
#GdkEventGrabBroken event.
</para>
<para>
On gestures, these signals are handled automatically, causing the gesture
to cancel all tracked pointer/touch events, and signal the end of recognition.
On gestures, these signals are handled automatically, causing the
gesture to cancel all tracked pointer/touch events, and signal
the end of recognition.
</para>
</refsect2>
<refsect2>
<title>Keyboard input</title>
<!-- focus, tab, directional navigation -->
<para>
Every #GtkWindow maintains a single focus location (in
the ::focus-widget property). The focus widget is the
target widget for key events sent to the window. Only
widgets which have ::can-focus set to %TRUE can become
the focus. Typically these are input controls such as
entries or text fields, but e.g. buttons can take the
focus too.
</para>
<para>
Input widgets can be given the focus by clicking on them,
but focus can also be moved around with certain key
events (this is known as “keyboard navigation”). GTK
reserves the Tab key to move the focus to the next location,
and Shift-Tab to move it back to the previous one. In addition
many containers allow “directional navigation” with the
arrow keys.
</para>
<!-- mnemonics, accelerators, bindings -->
</refsect2>
@@ -255,37 +254,43 @@
<title>Event controllers and gestures</title>
<para>
Event controllers are standalone objects that can perform specific actions
upon received #GdkEvents. These are tied to a #GtkWidget, and can be told of
the event propagation phase at which they will manage the events.
Event controllers are standalone objects that can perform
specific actions upon received #GdkEvents. These are tied
to a #GtkWidget, and can be told of the event propagation
phase at which they will manage the events.
</para>
<para>
Gestures are a set of specific controllers that are prepared to handle pointer
and/or touch events, each gestures implementation attempts to recognize specific
actions out the received events, notifying of the state/progress accordingly to
let the widget react to those. On multi-touch gestures, every interacting touch
sequence will be tracked independently.
Gestures are a set of specific controllers that are prepared
to handle pointer and/or touch events, each gesture
implementation attempts to recognize specific actions out the
received events, notifying of the state/progress accordingly to
let the widget react to those. On multi-touch gestures, every
interacting touch sequence will be tracked independently.
</para>
<para>
Being gestures “simple” units, it is not uncommon to tie several together to
perform higher level actions, grouped gestures handle the same event sequences
simultaneously, and those sequences share a same state across all grouped
Since gestures are “simple” units, it is not uncommon to tie
several together to perform higher level actions, grouped
gestures handle the same event sequences simultaneously, and
those sequences share a same state across all grouped
gestures. Some examples of grouping may be:
<simplelist>
<member>
A “drag” and a “swipe” gestures may want grouping. The former will report
events as the dragging happens, the latter will tell the swipe X/Y velocities
only after gesture has finished.
A “drag” and a “swipe” gestures may want grouping.
The former will report events as the dragging happens,
the latter will tell the swipe X/Y velocities only after
recognition has finished.
</member>
<member>
Grouping a “drag” gesture with a “pan” gesture will only effectively allow
dragging in the panning orientation, as both gestures share state.
Grouping a “drag” gesture with a “pan” gesture will only
effectively allow dragging in the panning orientation, as
both gestures share state.
</member>
<member>
If “press” and “long press” are wanted simultaneously, those would need grouping.
If “press” and “long press” are wanted simultaneously,
those would need grouping.
</member>
</simplelist>
</para>
@@ -294,34 +299,39 @@
<refsect2>
<title>Gesture states</title>
<para>
Gestures have a notion of “state” for each individual touch sequence. When events
from a touch sequence are first received, the touch sequence will have “none” state,
this means the touch sequence is being handled by the gesture to possibly trigger
Gestures have a notion of “state” for each individual touch
sequence. When events from a touch sequence are first received,
the touch sequence will have “none” state, this means the touch
sequence is being handled by the gesture to possibly trigger
actions, but the event propagation will not be stopped.
</para>
<para>
When the gesture enters recognition, or at a later point in time, the widget may
choose to claim the touch sequences (individually or as a group), hence stopping
event propagation after the event is run through every gesture in that widget and
propagation phase. Anytime this happens, the touch sequences are cancelled downwards
the propagation chain, to let these know that no further events will be sent.
When the gesture enters recognition, or at a later point in time,
the widget may choose to claim the touch sequences (individually
or as a group), hence stopping event propagation after the event
is run through every gesture in that widget and propagation phase.
Anytime this happens, the touch sequences are cancelled downwards
the propagation chain, to let these know that no further events
will be sent.
</para>
<para>
Alternatively, or at a later point in time, the widget may choose to deny the touch
sequences, thus letting those go through again in event propagation. When this happens
in the capture phase, and if there are no other claiming gestures in the widget,
Alternatively, or at a later point in time, the widget may choose
to deny the touch sequences, thus letting those go through again
in event propagation. When this happens in the capture phase, and
if there are no other claiming gestures in the widget,
a %GDK_TOUCH_BEGIN/%GDK_BUTTON_PRESS event will be emulated and
propagated downwards, in order to preserve consistency.
</para>
<para>
Grouped gestures always share the same state for a given touch sequence, so setting
the state on one does transfer the state to the others. They also are mutually exclusive,
within a widget there may be only one gesture group claiming a given sequence. If
another gesture group claims later that same sequence, the first group will deny the
sequence.
Grouped gestures always share the same state for a given touch
sequence, so setting the state on one does transfer the state to
the others. They also are mutually exclusive, within a widget
there may be only one gesture group claiming a given sequence.
If another gesture group claims later that same sequence, the
first group will deny the sequence.
</para>
</refsect2>
+2
View File
@@ -333,6 +333,7 @@ images = [
]
content_files = [
'actions.xml',
'broadway.xml',
'building.sgml',
'compiling.sgml',
@@ -368,6 +369,7 @@ content_files = [
]
expand_content_files = [
'actions.xml',
'compiling.sgml',
'drawing-model.xml',
'glossary.xml',
+108 -27
View File
@@ -11,7 +11,7 @@
compared to GTK 3.x. Thankfully, most of the changes are not hard
to adapt to and there are a number of steps that you can take to
prepare your GTK 3.x application for the switch to GTK 4. After
that, there's a small number of adjustments that you may have to do
that, there's a number of adjustments that you may have to do
when you actually switch your application to build against GTK 4.
</para>
@@ -22,7 +22,7 @@
The steps outlined in the following sections assume that your
application is working with GTK 3.24, which is the final stable
release of GTK 3.x. It includes all the necessary APIs and tools
to help you port your application to GTK 4. If you are still using
to help you port your application to GTK 4. If you are using
an older version of GTK 3.x, you should first get your application
to build and work with the latest minor release in the 3.24 series.
</para>
@@ -84,9 +84,9 @@
</para>
<para>
GTK 4 also removes the GDK_WA_VISUAL flag, and always uses
an RGBA visual for windows. To prepare your code for this,
use gdk_window_set_visual (gdk_screen_get_rgba_visual ()) after
creating your window.
an RGBA visual for windows. To prepare your code for this, use
<literal>gdk_window_set_visual (gdk_screen_get_rgba_visual ())</literal>
after creating your window.
</para>
<para>
GTK 4 also removes the GDK_WA_WMCLASS flag. If you need this
@@ -110,7 +110,7 @@
<section>
<title>Stop using GtkBox:padding, GtkBox:fill and GtkBox:expand</title>
<para>
GTK4 removes these #GtkBox child properties, so you should not use them.
GTK 4 removes these #GtkBox child properties, so you should not use them.
You can replace GtkBox:padding using the #GtkWidget:margin properties
on your #GtkBox child widgets.
</para>
@@ -172,35 +172,30 @@
<section>
<title>Stop using GtkWidget event signals</title>
<para>
Event controllers and #GtkGestures replace event signals in GTK 4. They
have been backported to GTK 3.x so you can prepare for this change.
Event controllers and #GtkGestures replace event signals in GTK 4.
They have been backported to GTK 3.x so you can prepare for this change.
</para>
</section>
<section>
<title>Set a proper app_id</title>
<title>Set a proper application ID</title>
<para>
In GTK4 we want the application's #GApplication
In GTK 4 we want the application's #GApplication
'application-id' (and therefore the D-Bus name), the desktop
file basename and Wayland's xdg-shell app_id to match. In
order to achieve this with GTK3 call g_set_prgname() with the same
application id you passed to #GtkApplication. Rename your
desktop files to match the application id if needed.
order to achieve this with GTK 3.x call g_set_prgname() with the same
application ID you passed to #GtkApplication. Rename your
desktop files to match the application ID if needed.
</para>
<para>
The call to g_set_prgname() can be removed once you fully migrated
to GTK4.
to GTK 4.
</para>
</section>
<section>
<title>Stop using GtkBox's pack-type child property</title>
<para>
In order to improve performance and simplify the widget, GtkBox lost its
'pack-type' child property. In GTK4, every GtkBox instance has a simple
list of child widgets that it allocates from start to end.
The old behavior of pack-type=END can be emulated by simply making the
box child in the center hexpand and right-align the ones at the end.
You should be aware that changing the application ID makes your
application appear as a new, different app to application installers.
You should consult the appstream documentation for best practices
around renaming applications.
</para>
</section>
@@ -216,6 +211,17 @@
have been either impossible or impractical.
</para>
<section>
<title>Convert your ui files</title>
<para>
A number of the changes outlined below affect .ui files. The
gtk4-builder-tool simplify command can perform many of the
necessary changes automatically, when called with the --3to4
option. You should always review the resulting changes.
</para>
</section>
<section>
<title>Stop using GdkScreen</title>
<para>
@@ -301,9 +307,9 @@
</section>
<section>
<title>Adapt to coordinate api changes</title>
<title>Adapt to coordinate API changes</title>
<para>
A number of coordinate apis in GTK 3 had _double variants:
A number of coordinate APIs in GTK 3 had _double variants:
gdk_device_get_position(), gdk_device_get_surface_at_position(),
gdk_surface_get_device_position(). These have been changed to use
doubles, and the _double variants have been removed. Update your
@@ -395,6 +401,10 @@
their #GError argument. If you want to handle CSS loading errors,
use the #GtkCssProvider::parsing-error signal instead.
</para>
<para>
gtk_css_provider_get_named() has been replaced by
gtk_css_provider_load_named().
</para>
</section>
<section>
@@ -411,7 +421,7 @@
<para>
GTK 3 used five different virtual functions in GtkWidget to
implement size requisition, namely the gtk_widget_get_preferred_width()
family of functions. To simplify widget implementations, GTK4 uses
family of functions. To simplify widget implementations, GTK 4 uses
only one virtual function, GtkWidgetClass::measure() that widgets
have to implement.
</para>
@@ -640,7 +650,7 @@
</section>
<section>
<title>Adapt to changes in the API of GtkEntry, GtkSearchEntry adn GtkSpinButton</title>
<title>Adapt to changes in the API of GtkEntry, GtkSearchEntry and GtkSpinButton</title>
<para>
The GtkEditable has been made more useful, and the core functionality of
GtkEntry has been broken out as a GtkText widget. GtkEntry, GtkSearchEntry,
@@ -675,6 +685,77 @@
of the existing GtkFixed container widget.
</para>
</section>
<section>
<title>Adapt to search entry changes</title>
<para>
The way search entries are connected to global events has changed;
gtk_search_entry_handle_event() has been dropped and replaced by
gtk_search_entry_set_key_capture_widget() and
gtk_event_controller_key_forward().
</para>
</section>
<section>
<title>Stop using child properties</title>
<para>
GtkContainer no longer provides facilities for defining and using
child properties. If you have custom widgets using child properties,
they will have to be converted either to layout properties provided
by a layout manager (if they are layout-related), or handled in
some other way. One possibility is to use child meta objects,
as seen with GtkAssistantPage, GtkStackPage and the like.
</para>
</section>
<section>
<title>Stop using tabular menus</title>
<para>
Tabular menus were rarely used and complicated the menu code,
so they have been removed. If you need complex layout in menu-like
popups, consider using a #GtkPopover instead.
</para>
</section>
<section>
<title>Stop using gtk_menu_set_display()</title>
<para>
This function has been removed. Menus should always be
attached to a widget and get their display that way.
</para>
</section>
<section>
<title>Stop using gtk_window_activate_default()</title>
<para>
The handling of default widgets has been changed, and activating
the default now works by calling gtk_widget_activate_default()
on the widget that caused the activation.
</para>
<para>
If you have a custom widget that wants to override the default
handling, you can provide an implementation of the default.activate
action in your widgets' action groups.
</para>
</section>
<section>
<title>Stop setting ::has-default and ::has-focus in .ui files</title>
<para>
The special handling for the ::has-default and ::has-focus properties
has been removed. If you want to define the initial focus or the
the default widget in a .ui file, set the ::default-widget or
::focus-widget properties of the toplevel window.
</para>
</section>
<section>
<title>Stop using the GtkWidget::display-changed signal</title>
<para>
To track the current display, use the GtkWidget::root property
instead.
</para>
</section>
</section>
</chapter>
+20 -2
View File
@@ -79,12 +79,30 @@ Use a GdkPixbuf in combination with GtkImage to display images.
</para></listitem>
</varlistentry>
<varlistentry>
<term>graphene</term>
<listitem><para>
This is a small library which provides vector and matrix datatypes
and operations. graphene provides optimized implementations using
various SIMD instruction sets such as SSE.
</para></listitem>
</varlistentry>
<varlistentry>
<term>GDK</term>
<listitem><para>
GDK is the abstraction layer that allows GTK to support multiple
windowing systems. GDK provides window system facilities on X11, Windows,
and OS X.
windowing systems. GDK provides window system facilities on Wayland,
X11, Windows, and OS X.
</para></listitem>
</varlistentry>
<varlistentry>
<term>GSK</term>
<listitem><para>
GSK is a library for creating a scene graph from render nodes,
and rendering it using different rendering APIs. GSK provides renderers
for OpenGL, Vulkan and cairo.
</para></listitem>
</varlistentry>
+36 -3
View File
@@ -146,15 +146,48 @@ gdk_event_class_init (GdkEventClass *klass)
g_object_class_install_properties (object_class, N_PROPS, event_props);
}
void
_gdk_event_emit (GdkEvent *event)
gboolean
check_event_sanity (GdkEvent *event)
{
GdkDisplay *display;
GdkSurface *surface;
GdkDevice *device;
display = gdk_event_get_display (event);
surface = gdk_event_get_surface (event);
device = gdk_event_get_device (event);
if (gdk_event_get_event_type (event) == GDK_NOTHING)
{
g_warning ("Ignoring GDK_NOTHING events; they're good for nothing");
return;
return FALSE;
}
if (surface && display != gdk_surface_get_display (surface))
{
char *type = g_enum_to_string (GDK_TYPE_EVENT_TYPE, event->any.type);
g_warning ("Event of type %s with mismatched surface display", type);
g_free (type);
return FALSE;
}
if (device && display != gdk_device_get_display (device))
{
char *type = g_enum_to_string (GDK_TYPE_EVENT_TYPE, event->any.type);
g_warning ("Event of type %s with mismatched device display", type);
g_free (type);
return FALSE;
}
return TRUE;
}
void
_gdk_event_emit (GdkEvent *event)
{
if (!check_event_sanity (event))
return;
if (gdk_drag_handle_source_event (event))
return;
+2
View File
@@ -645,5 +645,7 @@ void gdk_event_set_related_target (GdkEvent *event,
GObject *user_data);
GObject * gdk_event_get_related_target (const GdkEvent *event);
gboolean check_event_sanity (GdkEvent *event);
#endif /* __GDK_EVENTS_PRIVATE_H__ */
+1
View File
@@ -293,6 +293,7 @@ gdk_seat_grab (GdkSeat *seat,
g_return_val_if_fail (GDK_IS_SEAT (seat), GDK_GRAB_FAILED);
g_return_val_if_fail (GDK_IS_SURFACE (surface), GDK_GRAB_FAILED);
g_return_val_if_fail (gdk_surface_get_display (surface) == gdk_seat_get_display (seat), GDK_GRAB_FAILED);
capabilities &= GDK_SEAT_CAPABILITY_ALL;
g_return_val_if_fail (capabilities != GDK_SEAT_CAPABILITY_NONE, GDK_GRAB_FAILED);
+16
View File
@@ -107,6 +107,7 @@ enum {
PROP_0,
PROP_CURSOR,
PROP_DISPLAY,
PROP_FRAME_CLOCK,
PROP_STATE,
PROP_MAPPED,
LAST_PROP
@@ -268,6 +269,13 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
properties[PROP_FRAME_CLOCK] =
g_param_spec_object ("frame-clock",
P_("Frame Clock"),
P_("Frame Clock"),
GDK_TYPE_FRAME_CLOCK,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
properties[PROP_STATE] =
g_param_spec_flags ("state",
P_("State"),
@@ -462,6 +470,10 @@ gdk_surface_set_property (GObject *object,
g_assert (surface->display != NULL);
break;
case PROP_FRAME_CLOCK:
gdk_surface_set_frame_clock (surface, GDK_FRAME_CLOCK (g_value_get_object (value)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -486,6 +498,10 @@ gdk_surface_get_property (GObject *object,
g_value_set_object (value, surface->display);
break;
case PROP_FRAME_CLOCK:
g_value_set_object (value, surface->frame_clock);
break;
case PROP_STATE:
g_value_set_flags (value, surface->state);
break;
+7 -9
View File
@@ -5028,31 +5028,29 @@ _gdk_wayland_device_get_implicit_grab_serial (GdkWaylandDevice *device,
}
}
return GDK_WAYLAND_SEAT (seat)->pointer_info.press_serial;
return GDK_WAYLAND_SEAT (seat)->pointer_info.press_serial;
}
uint32_t
_gdk_wayland_seat_get_last_implicit_grab_serial (GdkSeat *seat,
_gdk_wayland_seat_get_last_implicit_grab_serial (GdkWaylandSeat *seat,
GdkEventSequence **sequence)
{
GdkWaylandSeat *wayland_seat;
GdkWaylandTouchData *touch;
GHashTableIter iter;
GList *l;
uint32_t serial;
wayland_seat = GDK_WAYLAND_SEAT (seat);
g_hash_table_iter_init (&iter, wayland_seat->touches);
g_hash_table_iter_init (&iter, seat->touches);
if (sequence)
*sequence = NULL;
serial = wayland_seat->keyboard_key_serial;
serial = seat->keyboard_key_serial;
if (wayland_seat->pointer_info.press_serial > serial)
serial = wayland_seat->pointer_info.press_serial;
if (seat->pointer_info.press_serial > serial)
serial = seat->pointer_info.press_serial;
for (l = wayland_seat->tablets; l; l = l->next)
for (l = seat->tablets; l; l = l->next)
{
GdkWaylandTabletData *tablet = l->data;
+155 -21
View File
@@ -396,6 +396,8 @@ static void gdk_wayland_display_add_output (GdkWaylandDisplay *display_wa
guint32 version);
static void gdk_wayland_display_remove_output (GdkWaylandDisplay *display_wayland,
guint32 id);
static void gdk_wayland_display_init_xdg_output (GdkWaylandDisplay *display_wayland);
static void gdk_wayland_display_get_xdg_output (GdkWaylandMonitor *monitor);
static void
gdk_registry_handle_global (void *data,
@@ -527,6 +529,13 @@ gdk_registry_handle_global (void *data,
&server_decoration_listener,
display_wayland);
}
else if (strcmp(interface, "zxdg_output_manager_v1") == 0)
{
display_wayland->xdg_output_manager =
wl_registry_bind (registry, id, &zxdg_output_manager_v1_interface, 1);
gdk_wayland_display_init_xdg_output (display_wayland);
_gdk_wayland_display_async_roundtrip (display_wayland);
}
g_hash_table_insert (display_wayland->known_globals,
GUINT_TO_POINTER (id), g_strdup (interface));
@@ -2170,6 +2179,123 @@ update_scale (GdkDisplay *display)
g_list_free (seats);
}
static void
gdk_wayland_display_init_xdg_output (GdkWaylandDisplay *display_wayland)
{
int i;
GDK_NOTE (MISC,
g_message ("init xdg-output support, %d monitor(s) already present",
display_wayland->monitors->len));
for (i = 0; i < display_wayland->monitors->len; i++)
gdk_wayland_display_get_xdg_output (display_wayland->monitors->pdata[i]);
}
static gboolean
display_has_xdg_output_support (GdkWaylandDisplay *display_wayland)
{
return (display_wayland->xdg_output_manager != NULL);
}
static gboolean
monitor_has_xdg_output (GdkWaylandMonitor *monitor)
{
return (monitor->xdg_output != NULL);
}
static gboolean
should_update_monitor (GdkWaylandMonitor *monitor)
{
return (GDK_MONITOR (monitor)->geometry.width != 0 &&
monitor->version < OUTPUT_VERSION_WITH_DONE);
}
static void
apply_monitor_change (GdkWaylandMonitor *monitor)
{
GDK_NOTE (MISC,
g_message ("monitor %d changed position %d %d, size %d %d",
monitor->id,
monitor->x, monitor->y,
monitor->width, monitor->height));
gdk_monitor_set_position (GDK_MONITOR (monitor), monitor->x, monitor->y);
gdk_monitor_set_size (GDK_MONITOR (monitor), monitor->width, monitor->height);
monitor->wl_output_done = FALSE;
monitor->xdg_output_done = FALSE;
update_scale (GDK_MONITOR (monitor)->display);
}
static void
xdg_output_handle_logical_position (void *data,
struct zxdg_output_v1 *xdg_output,
int32_t x,
int32_t y)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *) data;
GDK_NOTE (MISC,
g_message ("handle logical position xdg-output %d, position %d %d",
monitor->id, x, y));
monitor->x = x;
monitor->y = y;
}
static void
xdg_output_handle_logical_size (void *data,
struct zxdg_output_v1 *xdg_output,
int32_t width,
int32_t height)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *) data;
GDK_NOTE (MISC,
g_message ("handle logical size xdg-output %d, size %d %d",
monitor->id, width, height));
monitor->width = width;
monitor->height = height;
}
static void
xdg_output_handle_done (void *data,
struct zxdg_output_v1 *xdg_output)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *) data;
GDK_NOTE (MISC,
g_message ("handle done xdg-output %d", monitor->id));
monitor->xdg_output_done = TRUE;
if (monitor->wl_output_done)
apply_monitor_change (monitor);
}
static const struct zxdg_output_v1_listener xdg_output_listener = {
xdg_output_handle_logical_position,
xdg_output_handle_logical_size,
xdg_output_handle_done,
};
static void
gdk_wayland_display_get_xdg_output (GdkWaylandMonitor *monitor)
{
GdkDisplay *display = GDK_MONITOR (monitor)->display;
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GDK_NOTE (MISC,
g_message ("get xdg-output for monitor %d", monitor->id));
monitor->xdg_output =
zxdg_output_manager_v1_get_xdg_output (display_wayland->xdg_output_manager,
monitor->output);
zxdg_output_v1_add_listener (monitor->xdg_output,
&xdg_output_listener,
monitor);
}
static void
output_handle_geometry (void *data,
struct wl_output *wl_output,
@@ -2188,13 +2314,17 @@ output_handle_geometry (void *data,
g_message ("handle geometry output %d, position %d %d, phys. size %d %d, subpixel layout %s, manufacturer %s, model %s, transform %s",
monitor->id, x, y, physical_width, physical_height, subpixel_to_string (subpixel), make, model, transform_to_string (transform)));
gdk_monitor_set_position (GDK_MONITOR (monitor), x, y);
monitor->x = x;
monitor->y = y;
gdk_monitor_set_physical_size (GDK_MONITOR (monitor), physical_width, physical_height);
gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), subpixel);
gdk_monitor_set_manufacturer (GDK_MONITOR (monitor), make);
gdk_monitor_set_model (GDK_MONITOR (monitor), model);
if (GDK_MONITOR (monitor)->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
if (should_update_monitor (monitor) || !monitor_has_xdg_output (monitor))
apply_monitor_change (monitor);
if (should_update_monitor (monitor))
update_scale (GDK_MONITOR (monitor)->display);
}
@@ -2203,19 +2333,14 @@ output_handle_done (void *data,
struct wl_output *wl_output)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
GdkDisplay *display = gdk_monitor_get_display (GDK_MONITOR (monitor));
GDK_NOTE (MISC,
g_message ("handle done output %d", monitor->id));
if (!monitor->added)
{
monitor->added = TRUE;
g_ptr_array_add (GDK_WAYLAND_DISPLAY (display)->monitors, monitor);
gdk_display_monitor_added (display, GDK_MONITOR (monitor));
}
monitor->wl_output_done = TRUE;
update_scale (display);
if (!monitor_has_xdg_output (monitor) || monitor->xdg_output_done)
apply_monitor_change (monitor);
}
static void
@@ -2232,6 +2357,9 @@ output_handle_scale (void *data,
GDK_NOTE (MISC,
g_message ("handle scale output %d, scale %d", monitor->id, scale));
if (monitor_has_xdg_output (monitor))
return;
gdk_monitor_get_geometry (GDK_MONITOR (monitor), &previous_geometry);
previous_scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor));
@@ -2239,10 +2367,11 @@ output_handle_scale (void *data,
height = previous_geometry.height * previous_scale;
gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), scale);
gdk_monitor_set_size (GDK_MONITOR (monitor), width / scale, height / scale);
monitor->width = width / scale;
monitor->height = height / scale;
if (GDK_MONITOR (monitor)->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
update_scale (GDK_MONITOR (monitor)->display);
if (should_update_monitor (monitor))
apply_monitor_change (monitor);
}
static void
@@ -2264,11 +2393,12 @@ output_handle_mode (void *data,
return;
scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor));
gdk_monitor_set_size (GDK_MONITOR (monitor), width / scale, height / scale);
monitor->width = width / scale;
monitor->height = height / scale;
gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh);
if (width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
update_scale (GDK_MONITOR (monitor)->display);
if (should_update_monitor (monitor) || !monitor_has_xdg_output (monitor))
apply_monitor_change (monitor);
}
static const struct wl_output_listener output_listener =
@@ -2295,13 +2425,17 @@ gdk_wayland_display_add_output (GdkWaylandDisplay *display_wayland,
monitor->output = output;
monitor->version = version;
if (monitor->version < OUTPUT_VERSION_WITH_DONE)
{
g_ptr_array_add (display_wayland->monitors, monitor);
gdk_display_monitor_added (GDK_DISPLAY (display_wayland), GDK_MONITOR (monitor));
}
g_ptr_array_add (display_wayland->monitors, monitor);
gdk_display_monitor_added (GDK_DISPLAY (display_wayland), GDK_MONITOR (monitor));
wl_output_add_listener (output, &output_listener, monitor);
GDK_NOTE (MISC,
g_message ("xdg_output_manager %p",
display_wayland->xdg_output_manager));
if (display_has_xdg_output_support (display_wayland))
gdk_wayland_display_get_xdg_output (monitor);
}
struct wl_output *
+2
View File
@@ -35,6 +35,7 @@
#include <gdk/wayland/xdg-foreign-unstable-v1-client-protocol.h>
#include <gdk/wayland/keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h>
#include <gdk/wayland/server-decoration-client-protocol.h>
#include <gdk/wayland/xdg-output-unstable-v1-client-protocol.h>
#include <glib.h>
#include <gdk/gdkkeys.h>
@@ -109,6 +110,7 @@ struct _GdkWaylandDisplay
struct zxdg_importer_v1 *xdg_importer;
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
struct org_kde_kwin_server_decoration_manager *server_decoration_manager;
struct zxdg_output_manager_v1 *xdg_output_manager;
GList *async_roundtrips;
+3
View File
@@ -151,6 +151,9 @@ _gdk_wayland_display_deliver_event (GdkDisplay *display,
{
GList *node;
if (!check_event_sanity (event))
g_warning ("Snap! delivering insane events\n");
node = _gdk_event_queue_append (display, event);
_gdk_windowing_got_event (display, node, event,
_gdk_display_get_next_serial (display));
+9
View File
@@ -30,6 +30,15 @@ struct _GdkWaylandMonitor {
guint32 version;
struct wl_output *output;
gboolean added;
struct zxdg_output_v1 *xdg_output;
/* Size and position, can be either from wl_output or xdg_output */
int32_t x;
int32_t y;
int32_t width;
int32_t height;
gboolean wl_output_done;
gboolean xdg_output_done;
};
struct _GdkWaylandMonitorClass {
+2 -1
View File
@@ -34,6 +34,7 @@
#include <gdk/gdkcursor.h>
#include <gdk/wayland/gdkwayland.h>
#include <gdk/wayland/gdkdisplay-wayland.h>
#include <gdk/wayland/gdkseat-wayland.h>
#include <xkbcommon/xkbcommon.h>
@@ -138,7 +139,7 @@ void _gdk_wayland_display_remove_seat (GdkWaylandDisplay *displa
GdkKeymap *_gdk_wayland_device_get_keymap (GdkDevice *device);
uint32_t _gdk_wayland_device_get_implicit_grab_serial(GdkWaylandDevice *device,
const GdkEvent *event);
uint32_t _gdk_wayland_seat_get_last_implicit_grab_serial (GdkSeat *seat,
uint32_t _gdk_wayland_seat_get_last_implicit_grab_serial (GdkWaylandSeat *seat,
GdkEventSequence **seqence);
struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_device);
void gdk_wayland_device_set_selection (GdkDevice *gdk_device,
+23 -20
View File
@@ -33,6 +33,7 @@
#include "gdkdeviceprivate.h"
#include "gdkprivate-wayland.h"
#include "gdkmonitor-wayland.h"
#include "gdkseat-wayland.h"
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
#include <stdlib.h>
@@ -861,7 +862,7 @@ gdk_wayland_surface_update_dialogs (GdkSurface *surface)
GdkSurface *w = l->data;
GdkSurfaceImplWayland *impl;
if (!GDK_IS_SURFACE_IMPL_WAYLAND(w->impl))
if (!GDK_IS_SURFACE_IMPL_WAYLAND (w->impl))
continue;
impl = GDK_SURFACE_IMPL_WAYLAND (w->impl);
@@ -2185,14 +2186,12 @@ create_simple_positioner (GdkSurface *surface,
static void
gdk_wayland_surface_create_xdg_popup (GdkSurface *surface,
GdkSurface *parent,
struct wl_seat *seat)
GdkWaylandSeat *grab_input_seat)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
GdkSurfaceImplWayland *parent_impl = GDK_SURFACE_IMPL_WAYLAND (parent->impl);
gpointer positioner;
GdkSeat *gdk_seat;
guint32 serial;
if (!impl->display_server.wl_surface)
return;
@@ -2210,10 +2209,11 @@ gdk_wayland_surface_create_xdg_popup (GdkSurface *surface,
g_warning ("Can't map popup, already mapped");
return;
}
if ((display->current_popups &&
g_list_last (display->current_popups)->data != parent) ||
(!display->current_popups &&
!is_realized_toplevel (parent)))
if (grab_input_seat &&
((display->current_popups &&
g_list_last (display->current_popups)->data != parent) ||
(!display->current_popups &&
!is_realized_toplevel (parent))))
{
g_warning ("Tried to map a popup with a non-top most parent");
return;
@@ -2264,10 +2264,13 @@ gdk_wayland_surface_create_xdg_popup (GdkSurface *surface,
g_assert_not_reached ();
}
if (seat)
if (grab_input_seat)
{
gdk_seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_seat, NULL);
struct wl_seat *seat;
guint32 serial;
seat = gdk_wayland_seat_get_wl_seat (GDK_SEAT (grab_input_seat));
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (grab_input_seat, NULL);
switch (display->shell_variant)
{
@@ -2288,7 +2291,7 @@ gdk_wayland_surface_create_xdg_popup (GdkSurface *surface,
display->current_popups = g_list_append (display->current_popups, surface);
}
static struct wl_seat *
static GdkWaylandSeat *
find_grab_input_seat (GdkSurface *surface,
GdkSurface *transient_for)
{
@@ -2301,7 +2304,7 @@ find_grab_input_seat (GdkSurface *surface,
* grab before showing the popup surface.
*/
if (impl->grab_input_seat)
return gdk_wayland_seat_get_wl_seat (impl->grab_input_seat);
return GDK_WAYLAND_SEAT (impl->grab_input_seat);
/* HACK: GtkMenu grabs a special surface known as the "grab transfer surface"
* and then transfers the grab over to the correct surface later. Look for
@@ -2314,7 +2317,7 @@ find_grab_input_seat (GdkSurface *surface,
{
tmp_impl = GDK_SURFACE_IMPL_WAYLAND (attached_grab_surface->impl);
if (tmp_impl->grab_input_seat)
return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
return GDK_WAYLAND_SEAT (tmp_impl->grab_input_seat);
}
while (transient_for)
@@ -2322,7 +2325,7 @@ find_grab_input_seat (GdkSurface *surface,
tmp_impl = GDK_SURFACE_IMPL_WAYLAND (transient_for->impl);
if (tmp_impl->grab_input_seat)
return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
return GDK_WAYLAND_SEAT (tmp_impl->grab_input_seat);
transient_for = tmp_impl->transient_for;
}
@@ -2418,7 +2421,7 @@ gdk_wayland_surface_map (GdkSurface *surface)
if (should_map_as_popup (surface))
{
gboolean create_fallback = FALSE;
struct wl_seat *grab_input_seat;
GdkWaylandSeat *grab_input_seat;
/* Popup menus can appear without a transient parent, which means they
* cannot be positioned properly on Wayland. This attempts to guess the
@@ -2492,8 +2495,8 @@ gdk_wayland_surface_map (GdkSurface *surface)
if (!create_fallback)
{
gdk_wayland_surface_create_xdg_popup (surface,
transient_for,
grab_input_seat);
transient_for,
grab_input_seat);
}
else
{
@@ -3581,7 +3584,7 @@ gdk_wayland_surface_begin_resize_drag (GdkSurface *surface,
if (!is_realized_toplevel (surface))
return;
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (gdk_device_get_seat (device)),
&sequence);
switch (display_wayland->shell_variant)
@@ -3632,7 +3635,7 @@ gdk_wayland_surface_begin_move_drag (GdkSurface *surface,
if (!is_realized_toplevel (surface))
return;
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (gdk_device_get_seat (device)),
&sequence);
switch (display_wayland->shell_variant)
{
+1
View File
@@ -58,6 +58,7 @@ proto_sources = [
['tablet', 'unstable', 'v2', ],
['keyboard-shortcuts-inhibit', 'unstable', 'v1', ],
['server-decoration', 'private' ],
['xdg-output', 'unstable', 'v1', ],
]
gdk_wayland_gen_headers = []
+2 -2
View File
@@ -31,7 +31,7 @@
G_DEFINE_TYPE (GdkWin32CairoContext, gdk_win32_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
static void
void
gdk_win32_surface_get_queued_window_rect (GdkSurface *surface,
gint scale,
RECT *return_window_rect)
@@ -53,7 +53,7 @@ gdk_win32_surface_get_queued_window_rect (GdkSurface *surface,
*return_window_rect = window_rect;
}
static void
void
gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
RECT window_rect)
{
+21 -1
View File
@@ -166,6 +166,27 @@ gdk_win32_gl_context_begin_frame (GdkDrawContext *draw_context,
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
GdkSurface *surface;
GdkSurfaceImplWin32 *impl;
RECT queued_window_rect;
surface = gdk_gl_context_get_surface (context);
impl = GDK_SURFACE_IMPL_WIN32 (surface->impl);
gdk_win32_surface_get_queued_window_rect (surface,
gdk_surface_get_scale_factor (surface),
&queued_window_rect);
/* Apply queued resizes GL windows before painting them
* (we paint on the window DC directly, it must have the right size).
* Due to some poorly-understood issue delayed
* resizing of double-buffered windows can produce weird
* artefacts, so these are also resized before we paint.
*/
if (impl->drag_move_resize_context.native_move_resize_pending)
{
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
gdk_win32_surface_apply_queued_move_resize (surface, queued_window_rect);
}
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_parent_class)->begin_frame (draw_context, update_area);
if (gdk_gl_context_get_shared_context (context))
@@ -176,7 +197,6 @@ gdk_win32_gl_context_begin_frame (GdkDrawContext *draw_context,
/* If nothing else is known, repaint everything so that the back
buffer is fully up-to-date for the swapbuffer */
surface = gdk_gl_context_get_surface (context);
cairo_region_union_rectangle (update_area, &(GdkRectangle) {
0, 0,
gdk_surface_get_width (surface),
+9
View File
@@ -384,6 +384,15 @@ void _gdk_win32_update_layered_window_from_cache (GdkSurface *window,
gboolean do_paint);
void
gdk_win32_surface_get_queued_window_rect (GdkSurface *surface,
gint scale,
RECT *return_window_rect);
void
gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
RECT window_rect);
G_END_DECLS
#endif /* __GDK_SURFACE_WIN32_H__ */
+4 -4
View File
@@ -31,8 +31,8 @@
#define APPEARS_FOCUSED(toplevel) \
((toplevel)->has_focus || (toplevel)->has_focus_window || (toplevel)->has_pointer_focus)
#define HAS_FOCUS(toplevel) \
((toplevel)->has_focus || (toplevel)->has_pointer_focus)
static void gdk_x11_device_manager_core_finalize (GObject *object);
static void gdk_x11_device_manager_core_constructed (GObject *object);
@@ -752,7 +752,7 @@ _gdk_device_manager_core_handle_focus (GdkSurface *surface,
if (toplevel->focus_window == original)
return;
had_focus = APPEARS_FOCUSED (toplevel);
had_focus = HAS_FOCUS (toplevel);
x11_screen = GDK_X11_SCREEN (GDK_SURFACE_SCREEN (surface));
switch (detail)
@@ -814,7 +814,7 @@ _gdk_device_manager_core_handle_focus (GdkSurface *surface,
break;
}
if (APPEARS_FOCUSED (toplevel) != had_focus)
if (HAS_FOCUS (toplevel) != had_focus)
{
GdkEvent *event;
+4 -4
View File
@@ -36,8 +36,8 @@ static void gdk_event_source_finalize (GSource *source);
static GQuark quark_needs_enter = 0;
#define APPEARS_FOCUSED(toplevel) \
((toplevel)->has_focus || (toplevel)->has_focus_window || (toplevel)->has_pointer_focus)
#define HAS_FOCUS(toplevel) \
((toplevel)->has_focus || (toplevel)->has_pointer_focus)
struct _GdkEventSource
{
@@ -108,10 +108,10 @@ handle_focus_change (GdkEventCrossing *event)
if (!event->focus || toplevel->has_focus_window)
return;
had_focus = APPEARS_FOCUSED (toplevel);
had_focus = HAS_FOCUS (toplevel);
toplevel->has_pointer_focus = focus_in;
if (APPEARS_FOCUSED (toplevel) != had_focus)
if (HAS_FOCUS (toplevel) != had_focus)
{
GdkEvent *focus_event;
+32
View File
@@ -1867,6 +1867,14 @@ gdk_x11_surface_set_modal_hint (GdkSurface *surface,
NULL);
}
/**
* gdk_x11_surface_set_skip_taskbar_hint:
* @surface: (type GdkX11Surface): a native #GdkSurface
* @skips_taskbar: %TRUE to skip taskbars
*
* Sets a hint on @surface that taskbars should not
* display it. See the EWMH for details.
*/
void
gdk_x11_surface_set_skip_taskbar_hint (GdkSurface *surface,
gboolean skips_taskbar)
@@ -1888,6 +1896,14 @@ gdk_x11_surface_set_skip_taskbar_hint (GdkSurface *surface,
NULL);
}
/**
* gdk_x11_surface_set_skip_pager_hint:
* @surface: (type GdkX11Surface): a #GdkSurface
* @skips_pager: %TRUE to skip pagers
*
* Sets a hint on @surface that pagers should not
* display it. See the EWMH for details.
*/
void
gdk_x11_surface_set_skip_pager_hint (GdkSurface *surface,
gboolean skips_pager)
@@ -1909,6 +1925,14 @@ gdk_x11_surface_set_skip_pager_hint (GdkSurface *surface,
NULL);
}
/**
* gdk_x11_surface_set_urgency_hint:
* @surface: (type GdkX11Surface): a native #GdkSurface
* @urgent: %TRUE to indicate urgenct attention needed
*
* Sets a hint on @surface that it needs user attention.
* See the ICCCM for details.
*/
void
gdk_x11_surface_set_urgency_hint (GdkSurface *surface,
gboolean urgent)
@@ -3377,6 +3401,14 @@ gdk_x11_surface_get_group (GdkSurface *surface)
return toplevel->group_leader;
}
/**
* gdk_x11_surface_set_group:
* @surface: (type GdkX11Surface): a native #GdkSurface
* @leader: a #GdkSurface
*
* Sets the group leader of @surface to be @leader.
* See the ICCCM for details.
*/
void
gdk_x11_surface_set_group (GdkSurface *surface,
GdkSurface *leader)
+41 -8
View File
@@ -42,7 +42,6 @@
#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeparserprivate.h"
#include <graphene-gobject.h>
@@ -329,11 +328,19 @@ gsk_render_node_diff (GskRenderNode *node1,
GBytes *
gsk_render_node_serialize (GskRenderNode *node)
{
GVariant *node_variant, *variant;
GBytes *result;
char *str;
str = gsk_render_node_serialize_to_string (node);
result = g_bytes_new_take (str, strlen (str));
node_variant = gsk_render_node_serialize_node (node);
variant = g_variant_new ("(suuv)",
GSK_RENDER_NODE_SERIALIZATION_ID,
(guint32) GSK_RENDER_NODE_SERIALIZATION_VERSION,
(guint32) gsk_render_node_get_node_type (node),
node_variant);
result = g_variant_get_data_as_bytes (variant);
g_variant_unref (variant);
return result;
}
@@ -387,13 +394,39 @@ gsk_render_node_write_to_file (GskRenderNode *node,
* error.
**/
GskRenderNode *
gsk_render_node_deserialize (GBytes *bytes,
GskParseErrorFunc error_func,
gpointer user_data)
gsk_render_node_deserialize (GBytes *bytes,
GError **error)
{
char *id_string;
guint32 version, node_type;
GVariant *variant, *node_variant;
GskRenderNode *node = NULL;
node = gsk_render_node_deserialize_from_bytes (bytes, error_func, user_data);
variant = g_variant_new_from_bytes (G_VARIANT_TYPE ("(suuv)"), bytes, FALSE);
g_variant_get (variant, "(suuv)", &id_string, &version, &node_type, &node_variant);
if (!g_str_equal (id_string, GSK_RENDER_NODE_SERIALIZATION_ID))
{
g_set_error (error, GSK_SERIALIZATION_ERROR, GSK_SERIALIZATION_UNSUPPORTED_FORMAT,
"Data not in GskRenderNode serialization format.");
goto out;
}
if (version != GSK_RENDER_NODE_SERIALIZATION_VERSION)
{
g_set_error (error, GSK_SERIALIZATION_ERROR, GSK_SERIALIZATION_UNSUPPORTED_VERSION,
"Format version %u not supported.", version);
goto out;
}
node = gsk_render_node_deserialize_node (node_type, node_variant, error);
out:
g_free (id_string);
g_variant_unref (node_variant);
g_variant_unref (variant);
return node;
}
+2 -8
View File
@@ -25,7 +25,6 @@
#include <gsk/gskroundedrect.h>
#include <gsk/gsktypes.h>
#include <gtk/css/gtkcss.h>
G_BEGIN_DECLS
@@ -53,10 +52,6 @@ struct _GskShadow
float radius;
};
typedef void (* GskParseErrorFunc) (const GtkCssSection *section,
const GError *error,
gpointer user_data);
GDK_AVAILABLE_IN_ALL
GType gsk_render_node_get_type (void) G_GNUC_CONST;
@@ -86,9 +81,8 @@ gboolean gsk_render_node_write_to_file (GskRenderNode *
const char *filename,
GError **error);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_render_node_deserialize (GBytes *bytes,
GskParseErrorFunc error_func,
gpointer user_data);
GskRenderNode * gsk_render_node_deserialize (GBytes *bytes,
GError **error);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_debug_node_new (GskRenderNode *child,
+1337 -9
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-12
View File
@@ -1,12 +0,0 @@
#ifndef __GSK_RENDER_NODE_PARSER_PRIVATE_H__
#define __GSK_RENDER_NODE_PARSER_PRIVATE_H__
#include "gskrendernode.h"
GskRenderNode * gsk_render_node_deserialize_from_bytes (GBytes *bytes,
GskParseErrorFunc error_func,
gpointer user_data);
char * gsk_render_node_serialize_to_string (GskRenderNode *root);
#endif
+8
View File
@@ -33,6 +33,9 @@ struct _GskRenderNodeClass
void (* diff) (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
GVariant * (* serialize) (GskRenderNode *node);
GskRenderNode * (* deserialize) (GVariant *variant,
GError **error);
};
GskRenderNode * gsk_render_node_new (const GskRenderNodeClass *node_class,
@@ -47,6 +50,11 @@ void gsk_render_node_diff_impossible (GskRenderNode *nod
GskRenderNode *node2,
cairo_region_t *region);
GVariant * gsk_render_node_serialize_node (GskRenderNode *node);
GskRenderNode * gsk_render_node_deserialize_node (GskRenderNodeType type,
GVariant *variant,
GError **error);
GskRenderNode * gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds,
cairo_surface_t *surface);
+13 -7
View File
@@ -197,9 +197,10 @@ gsk_rounded_rect_offset (GskRoundedRect *self,
}
static void
border_radius_shrink (graphene_size_t *corner,
double width,
double height)
border_radius_shrink (graphene_size_t *corner,
double width,
double height,
const graphene_size_t *max)
{
if (corner->width > 0)
corner->width -= width;
@@ -211,6 +212,11 @@ border_radius_shrink (graphene_size_t *corner,
corner->width = 0;
corner->height = 0;
}
else
{
corner->width = MIN (corner->width, max->width);
corner->height = MIN (corner->height, max->height);
}
}
/**
@@ -260,10 +266,10 @@ gsk_rounded_rect_shrink (GskRoundedRect *self,
self->bounds.size.height -= top + bottom;
}
border_radius_shrink (&self->corner[GSK_CORNER_TOP_LEFT], left, top);
border_radius_shrink (&self->corner[GSK_CORNER_TOP_RIGHT], right, top);
border_radius_shrink (&self->corner[GSK_CORNER_BOTTOM_RIGHT], right, bottom);
border_radius_shrink (&self->corner[GSK_CORNER_BOTTOM_LEFT], left, bottom);
border_radius_shrink (&self->corner[GSK_CORNER_TOP_LEFT], left, top, &self->bounds.size);
border_radius_shrink (&self->corner[GSK_CORNER_TOP_RIGHT], right, top, &self->bounds.size);
border_radius_shrink (&self->corner[GSK_CORNER_BOTTOM_RIGHT], right, bottom, &self->bounds.size);
border_radius_shrink (&self->corner[GSK_CORNER_BOTTOM_LEFT], left, bottom, &self->bounds.size);
return self;
}
+24 -31
View File
@@ -19,7 +19,7 @@
/**
* SECTION:gsktransform
* SECTION:GskTransform
* @Title: GskTransform
* @Short_description: A description for transform operations
*
@@ -42,8 +42,7 @@ typedef struct _GskTransformClass GskTransformClass;
struct _GskTransform
{
const GskTransformClass *transform_class;
volatile int ref_count;
GskTransformCategory category;
GskTransform *next;
};
@@ -113,10 +112,9 @@ gsk_transform_alloc (const GskTransformClass *transform_class,
g_return_val_if_fail (transform_class != NULL, NULL);
self = g_malloc0 (transform_class->struct_size);
self = g_atomic_rc_box_alloc0 (transform_class->struct_size);
self->transform_class = transform_class;
self->ref_count = 1;
self->category = next ? MIN (category, next->category) : category;
self->next = gsk_transform_is_identity (next) ? NULL : next;
@@ -312,15 +310,15 @@ gsk_matrix_transform_apply_affine (GskTransform *transform,
break;
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
*out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0);
*out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1);
*out_scale_x *= graphene_matrix_get_value (&self->matrix, 0, 0);
*out_scale_y *= graphene_matrix_get_value (&self->matrix, 1, 1);
*out_dx += *out_scale_x * graphene_matrix_get_x_translation (&self->matrix);
*out_dy += *out_scale_y * graphene_matrix_get_y_translation (&self->matrix);
*out_scale_x *= graphene_matrix_get_x_scale (&self->matrix);
*out_scale_y *= graphene_matrix_get_y_scale (&self->matrix);
break;
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
*out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0);
*out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1);
*out_dx += *out_scale_x * graphene_matrix_get_x_translation (&self->matrix);
*out_dy += *out_scale_y * graphene_matrix_get_y_translation (&self->matrix);
break;
case GSK_TRANSFORM_CATEGORY_IDENTITY:
@@ -347,8 +345,8 @@ gsk_matrix_transform_apply_translate (GskTransform *transform,
break;
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
*out_dx += graphene_matrix_get_value (&self->matrix, 3, 0);
*out_dy += graphene_matrix_get_value (&self->matrix, 3, 1);
*out_dx += graphene_matrix_get_x_translation (&self->matrix);
*out_dy += graphene_matrix_get_y_translation (&self->matrix);
break;
case GSK_TRANSFORM_CATEGORY_IDENTITY:
@@ -421,8 +419,10 @@ gsk_matrix_transform_equal (GskTransform *first_transform,
GskMatrixTransform *first = (GskMatrixTransform *) first_transform;
GskMatrixTransform *second = (GskMatrixTransform *) second_transform;
/* Crude, but better than just returning FALSE */
return memcmp (&first->matrix, &second->matrix, sizeof (graphene_matrix_t)) == 0;
if (graphene_matrix_equal_fast (&first->matrix, &second->matrix))
return TRUE;
return graphene_matrix_equal (&first->matrix, &second->matrix);
}
static const GskTransformClass GSK_TRANSFORM_TRANSFORM_CLASS =
@@ -735,7 +735,7 @@ gsk_rotate_transform_equal (GskTransform *first_transform,
GskRotateTransform *first = (GskRotateTransform *) first_transform;
GskRotateTransform *second = (GskRotateTransform *) second_transform;
return first->angle == second->angle;
return G_APPROX_VALUE (first->angle, second->angle, 0.01f);
}
static void
@@ -837,8 +837,8 @@ gsk_rotate3d_transform_equal (GskTransform *first_transform,
GskRotate3dTransform *first = (GskRotate3dTransform *) first_transform;
GskRotate3dTransform *second = (GskRotate3dTransform *) second_transform;
return first->angle == second->angle
&& graphene_vec3_equal (&first->axis, &second->axis);
return G_APPROX_VALUE (first->angle, second->angle, 0.01f) &&
graphene_vec3_equal (&first->axis, &second->axis);
}
static void
@@ -996,9 +996,9 @@ gsk_scale_transform_equal (GskTransform *first_transform,
GskScaleTransform *first = (GskScaleTransform *) first_transform;
GskScaleTransform *second = (GskScaleTransform *) second_transform;
return first->factor_x == second->factor_x
&& first->factor_y == second->factor_y
&& first->factor_z == second->factor_z;
return G_APPROX_VALUE (first->factor_x, second->factor_x, 0.01f) &&
G_APPROX_VALUE (first->factor_y, second->factor_y, 0.01f) &&
G_APPROX_VALUE (first->factor_z, second->factor_z, 0.01f);
}
static void
@@ -1150,7 +1150,7 @@ gsk_perspective_transform_equal (GskTransform *first_transform,
GskPerspectiveTransform *first = (GskPerspectiveTransform *) first_transform;
GskPerspectiveTransform *second = (GskPerspectiveTransform *) second_transform;
return first->depth == second->depth;
return G_APPROX_VALUE (first->depth, second->depth, 0.001f);
}
static void
@@ -1217,8 +1217,6 @@ gsk_transform_finalize (GskTransform *self)
self->transform_class->finalize (self);
gsk_transform_unref (self->next);
g_free (self);
}
/**
@@ -1235,9 +1233,7 @@ gsk_transform_ref (GskTransform *self)
if (self == NULL)
return NULL;
g_atomic_int_inc (&self->ref_count);
return self;
return g_atomic_rc_box_acquire (self);
}
/**
@@ -1255,8 +1251,7 @@ gsk_transform_unref (GskTransform *self)
if (self == NULL)
return;
if (g_atomic_int_dec_and_test (&self->ref_count))
gsk_transform_finalize (self);
g_atomic_rc_box_release_full (self, (GDestroyNotify) gsk_transform_finalize);
}
/**
@@ -1695,7 +1690,6 @@ gsk_transform_parser_parse (GtkCssParser *parser,
if (gtk_css_token_is_ident (token, "none"))
{
gtk_css_parser_consume_token (parser);
*out_transform = NULL;
return TRUE;
}
@@ -1903,7 +1897,6 @@ gsk_transform_parse (const char *string,
result = FALSE;
}
gtk_css_parser_unref (parser);
g_bytes_unref (bytes);
return result;
-1
View File
@@ -35,7 +35,6 @@ gsk_private_sources = files([
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
'gskrendernodeparser.c',
'gl/gskshaderbuilder.c',
'gl/gskglprofiler.c',
'gl/gskglrenderer.c',
+16
View File
@@ -42,6 +42,13 @@ gtk_cell_accessible_parent_get_type (void)
return g_define_type_id__volatile;
}
/**
* gtk_cell_accessible_parent_get_cell_extents:
* @x: (out):
* @y: (out):
* @width: (out):
* @height: (out):
*/
void
gtk_cell_accessible_parent_get_cell_extents (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
@@ -61,6 +68,10 @@ gtk_cell_accessible_parent_get_cell_extents (GtkCellAccessibleParent *parent,
(iface->get_cell_extents) (parent, cell, x, y, width, height, coord_type);
}
/**
* gtk_cell_accessible_parent_get_cell_area:
* @cell_rect: (out):
*/
void
gtk_cell_accessible_parent_get_cell_area (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
@@ -188,6 +199,11 @@ gtk_cell_accessible_parent_update_relationset (GtkCellAccessibleParent *parent,
(iface->update_relationset) (parent, cell, relationset);
}
/**
* gtk_cell_accessible_parent_get_cell_position:
* @row: (out):
* @column: (out):
*/
void
gtk_cell_accessible_parent_get_cell_position (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
-8
View File
@@ -614,7 +614,6 @@ static gboolean
gtk_icon_view_item_accessible_grab_focus (AtkComponent *component)
{
GtkIconViewItemAccessible *item;
GtkWidget *toplevel;
g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (component), FALSE);
@@ -624,13 +623,6 @@ gtk_icon_view_item_accessible_grab_focus (AtkComponent *component)
gtk_widget_grab_focus (item->widget);
_gtk_icon_view_set_cursor_item (GTK_ICON_VIEW (item->widget), item->item, NULL);
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->widget));
if (gtk_widget_is_toplevel (toplevel))
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gtk_window_present (GTK_WINDOW (toplevel));
G_GNUC_END_IGNORE_DEPRECATIONS
}
return TRUE;
}
+6 -6
View File
@@ -432,7 +432,7 @@ add_action_widgets (GtkAssistant *assistant)
if (has_default)
{
gtk_widget_grab_default (child);
gtk_window_set_default_widget (GTK_WINDOW (assistant), child);
gtk_style_context_add_class (gtk_widget_get_style_context (child), GTK_STYLE_CLASS_SUGGESTED_ACTION);
}
}
@@ -807,7 +807,7 @@ update_buttons_state (GtkAssistant *assistant)
case GTK_ASSISTANT_PAGE_INTRO:
gtk_widget_set_sensitive (priv->cancel, TRUE);
gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
gtk_widget_grab_default (priv->forward);
gtk_window_set_default_widget (GTK_WINDOW (assistant), priv->forward);
gtk_widget_show (priv->forward);
gtk_widget_hide (priv->back);
gtk_widget_hide (priv->apply);
@@ -818,7 +818,7 @@ update_buttons_state (GtkAssistant *assistant)
gtk_widget_set_sensitive (priv->cancel, TRUE);
gtk_widget_set_sensitive (priv->back, TRUE);
gtk_widget_set_sensitive (priv->apply, priv->current_page->complete);
gtk_widget_grab_default (priv->apply);
gtk_window_set_default_widget (GTK_WINDOW (assistant), priv->apply);
gtk_widget_show (priv->back);
gtk_widget_show (priv->apply);
gtk_widget_hide (priv->forward);
@@ -829,7 +829,7 @@ update_buttons_state (GtkAssistant *assistant)
gtk_widget_set_sensitive (priv->cancel, TRUE);
gtk_widget_set_sensitive (priv->back, TRUE);
gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
gtk_widget_grab_default (priv->forward);
gtk_window_set_default_widget (GTK_WINDOW (assistant), priv->forward);
gtk_widget_show (priv->back);
gtk_widget_show (priv->forward);
gtk_widget_hide (priv->apply);
@@ -838,7 +838,7 @@ update_buttons_state (GtkAssistant *assistant)
break;
case GTK_ASSISTANT_PAGE_SUMMARY:
gtk_widget_set_sensitive (priv->close, priv->current_page->complete);
gtk_widget_grab_default (priv->close);
gtk_window_set_default_widget (GTK_WINDOW (assistant), priv->close);
gtk_widget_show (priv->close);
gtk_widget_hide (priv->back);
gtk_widget_hide (priv->forward);
@@ -849,7 +849,7 @@ update_buttons_state (GtkAssistant *assistant)
gtk_widget_set_sensitive (priv->cancel, priv->current_page->complete);
gtk_widget_set_sensitive (priv->back, priv->current_page->complete);
gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
gtk_widget_grab_default (priv->forward);
gtk_window_set_default_widget (GTK_WINDOW (assistant), priv->forward);
gtk_widget_show (priv->back);
gtk_widget_hide (priv->apply);
gtk_widget_hide (priv->close);
+39
View File
@@ -766,6 +766,14 @@ gtk_box_layout_init (GtkBoxLayout *self)
self->baseline_position = GTK_BASELINE_POSITION_CENTER;
}
/**
* gtk_box_layout_new:
* @orientation: the orientation for the new layout
*
* Creates a new box layout.
*
* Returns: a new box layout
*/
GtkLayoutManager *
gtk_box_layout_new (GtkOrientation orientation)
{
@@ -774,6 +782,14 @@ gtk_box_layout_new (GtkOrientation orientation)
NULL);
}
/**
* gtk_box_layout_set_homogeneous:
* @box_layout: a #GtkBoxLayout
* @homogeneous: %TRUE to set the box layout as homogeneous
*
* Sets whether the box layout will allocate the same
* size to all children.
*/
void
gtk_box_layout_set_homogeneous (GtkBoxLayout *box_layout,
gboolean homogeneous)
@@ -790,6 +806,14 @@ gtk_box_layout_set_homogeneous (GtkBoxLayout *box_layout,
g_object_notify_by_pspec (G_OBJECT (box_layout), box_layout_props[PROP_HOMOGENEOUS]);
}
/**
* gtk_box_layout_get_homogeneous:
* @box_layout: a #GtkBoxLayout
*
* Returns whether the layout is set to be homogeneous.
*
* Return: %TRUE if the layout is homogeneous
*/
gboolean
gtk_box_layout_get_homogeneous (GtkBoxLayout *box_layout)
{
@@ -798,6 +822,13 @@ gtk_box_layout_get_homogeneous (GtkBoxLayout *box_layout)
return box_layout->homogeneous;
}
/**
* gtk_box_layout_set_spacing:
* @box_layout: a #GtkBoxLayout
* @spacing: the spacing to apply between children
*
* Sets how much spacing to put between children.
*/
void
gtk_box_layout_set_spacing (GtkBoxLayout *box_layout,
guint spacing)
@@ -813,6 +844,14 @@ gtk_box_layout_set_spacing (GtkBoxLayout *box_layout,
g_object_notify_by_pspec (G_OBJECT (box_layout), box_layout_props[PROP_SPACING]);
}
/**
* gtk_box_layout_get_spacing:
* @box_layout: a #GtkBoxLayout
*
* Returns the space that @box_layout puts between children.
*
* Returns: the spacing of the layout
*/
guint
gtk_box_layout_get_spacing (GtkBoxLayout *box_layout)
{
+7 -7
View File
@@ -1094,7 +1094,7 @@ gtk_builder_add_from_file (GtkBuilder *builder,
priv->resource_prefix = NULL;
_gtk_builder_parser_parse_buffer (builder, filename,
buffer, length,
buffer, (gssize)length,
NULL,
&tmp_error);
@@ -1160,7 +1160,7 @@ gtk_builder_add_objects_from_file (GtkBuilder *builder,
priv->resource_prefix = NULL;
_gtk_builder_parser_parse_buffer (builder, filename,
buffer, length,
buffer, (gssize)length,
object_ids,
&tmp_error);
@@ -1198,7 +1198,7 @@ gtk_builder_extend_with_template (GtkBuilder *builder,
GtkWidget *widget,
GType template_type,
const gchar *buffer,
gsize length,
gssize length,
GError **error)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
@@ -1394,7 +1394,7 @@ gtk_builder_add_objects_from_resource (GtkBuilder *builder,
*
* Most users will probably want to use gtk_builder_new_from_string().
*
* Upon errors 0 will be returned and @error will be assigned a
* Upon errors %FALSE will be returned and @error will be assigned a
* #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or
* #G_VARIANT_PARSE_ERROR domain.
*
@@ -1407,7 +1407,7 @@ gtk_builder_add_objects_from_resource (GtkBuilder *builder,
gboolean
gtk_builder_add_from_string (GtkBuilder *builder,
const gchar *buffer,
gsize length,
gssize length,
GError **error)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
@@ -1449,7 +1449,7 @@ gtk_builder_add_from_string (GtkBuilder *builder,
* building only the requested objects and merges
* them with the current contents of @builder.
*
* Upon errors 0 will be returned and @error will be assigned a
* Upon errors %FALSE will be returned and @error will be assigned a
* #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
*
* If you are adding an object that depends on an object that is not
@@ -1461,7 +1461,7 @@ gtk_builder_add_from_string (GtkBuilder *builder,
gboolean
gtk_builder_add_objects_from_string (GtkBuilder *builder,
const gchar *buffer,
gsize length,
gssize length,
gchar **object_ids,
GError **error)
{
+3 -3
View File
@@ -128,7 +128,7 @@ gboolean gtk_builder_add_from_resource (GtkBuilder *builder,
GDK_AVAILABLE_IN_ALL
gboolean gtk_builder_add_from_string (GtkBuilder *builder,
const gchar *buffer,
gsize length,
gssize length,
GError **error);
GDK_AVAILABLE_IN_ALL
gboolean gtk_builder_add_objects_from_file (GtkBuilder *builder,
@@ -143,7 +143,7 @@ gboolean gtk_builder_add_objects_from_resource(GtkBuilder *builder,
GDK_AVAILABLE_IN_ALL
gboolean gtk_builder_add_objects_from_string (GtkBuilder *builder,
const gchar *buffer,
gsize length,
gssize length,
gchar **object_ids,
GError **error);
GDK_AVAILABLE_IN_ALL
@@ -228,7 +228,7 @@ gboolean gtk_builder_extend_with_template (GtkBuilder *builder,
GtkWidget *widget,
GType template_type,
const gchar *buffer,
gsize length,
gssize length,
GError **error);
G_END_DECLS
+1 -1
View File
@@ -1230,7 +1230,7 @@ void
_gtk_builder_parser_parse_buffer (GtkBuilder *builder,
const gchar *filename,
const gchar *buffer,
gsize length,
gssize length,
gchar **requested_objs,
GError **error)
{
+1 -1
View File
@@ -135,7 +135,7 @@ typedef GType (*GTypeGetFunc) (void);
void _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
const gchar *filename,
const gchar *buffer,
gsize length,
gssize length,
gchar **requested_objs,
GError **error);
GObject * _gtk_builder_construct (GtkBuilder *builder,
-15
View File
@@ -129,8 +129,6 @@ static void gtk_button_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gtk_button_display_changed (GtkWidget *widget,
GdkDisplay *previous_display);
static void gtk_button_unrealize (GtkWidget * widget);
static void gtk_real_button_clicked (GtkButton * button);
static void gtk_real_button_activate (GtkButton *button);
@@ -204,7 +202,6 @@ gtk_button_class_init (GtkButtonClass *klass)
gobject_class->set_property = gtk_button_set_property;
gobject_class->get_property = gtk_button_get_property;
widget_class->display_changed = gtk_button_display_changed;
widget_class->unrealize = gtk_button_unrealize;
widget_class->state_flags_changed = gtk_button_state_flags_changed;
widget_class->grab_notify = gtk_button_grab_notify;
@@ -923,18 +920,6 @@ gtk_button_get_use_underline (GtkButton *button)
return priv->use_underline;
}
static void
gtk_button_display_changed (GtkWidget *widget,
GdkDisplay *previous_display)
{
GtkButton *button = GTK_BUTTON (widget);
GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
/* If the button is being pressed while the display changes the
release might never occur, so we reset the state. */
priv->button_down = FALSE;
}
static void
gtk_button_state_flags_changed (GtkWidget *widget,
GtkStateFlags previous_state)
-11
View File
@@ -153,16 +153,6 @@ gtk_color_button_measure (GtkWidget *widget,
minimum_baseline, natural_baseline);
}
static void
gtk_color_button_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkColorButton *button = GTK_COLOR_BUTTON (widget);
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
gtk_widget_snapshot_child (widget, priv->button, snapshot);
}
static void
gtk_color_button_size_allocate (GtkWidget *widget,
int width,
@@ -193,7 +183,6 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
gobject_class->set_property = gtk_color_button_set_property;
gobject_class->finalize = gtk_color_button_finalize;
widget_class->snapshot = gtk_color_button_snapshot;
widget_class->measure = gtk_color_button_measure;
widget_class->size_allocate = gtk_color_button_size_allocate;
klass->color_set = NULL;
-23
View File
@@ -30,29 +30,6 @@ G_BEGIN_DECLS
#define GTK_IS_CSS_PROVIDER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GTK_TYPE_CSS_PROVIDER))
#define GTK_CSS_PROVIDER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_CSS_PROVIDER, GtkCssProviderClass))
/**
* GtkCssProviderError:
* @GTK_CSS_PROVIDER_ERROR_FAILED: Failed.
* @GTK_CSS_PROVIDER_ERROR_SYNTAX: Syntax error.
* @GTK_CSS_PROVIDER_ERROR_IMPORT: Import error.
* @GTK_CSS_PROVIDER_ERROR_NAME: Name error.
* @GTK_CSS_PROVIDER_ERROR_DEPRECATED: Deprecation error.
* @GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE: Unknown value.
* @GTK_CSS_PROVIDER_WARN_GENERAL: A general warning.
*
* Error codes for %GTK_CSS_PROVIDER_ERROR.
*/
typedef enum
{
GTK_CSS_PROVIDER_ERROR_FAILED,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
GTK_CSS_PROVIDER_ERROR_IMPORT,
GTK_CSS_PROVIDER_ERROR_NAME,
GTK_CSS_PROVIDER_ERROR_DEPRECATED,
GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
GTK_CSS_PROVIDER_WARN_GENERAL,
} GtkCssProviderError;
typedef struct _GtkCssProvider GtkCssProvider;
typedef struct _GtkCssProviderClass GtkCssProviderClass;
typedef struct _GtkCssProviderPrivate GtkCssProviderPrivate;
+12 -2
View File
@@ -1143,8 +1143,18 @@ pack_font_description (GtkCssShorthandProperty *shorthand,
v = (* query_func) (GTK_CSS_PROPERTY_FONT_FAMILY, query_data);
if (v)
{
/* xxx: Can we set all the families here somehow? */
pango_font_description_set_family (description, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, 0)));
int i;
GString *s = g_string_new ("");
for (i = 0; i < _gtk_css_array_value_get_n_values (v); i++)
{
if (i > 0)
g_string_append (s, ",");
g_string_append (s, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, i)));
}
pango_font_description_set_family (description, s->str);
g_string_free (s, TRUE);
}
v = (* query_func) (GTK_CSS_PROPERTY_FONT_SIZE, query_data);
+4 -7
View File
@@ -156,7 +156,6 @@
* </child>
* <child type="action">
* <object class="GtkButton" id="button_ok">
* <property name="can-default">True</property>
* </object>
* </child>
* <action-widgets>
@@ -456,7 +455,7 @@ gtk_dialog_constructed (GObject *object)
g_object_unref (child);
if (has_default)
gtk_widget_grab_default (child);
gtk_window_set_default_widget (GTK_WINDOW (dialog), child);
}
g_list_free (children);
@@ -865,7 +864,7 @@ gtk_dialog_add_action_widget (GtkDialog *dialog,
if (gtk_widget_has_default (child))
{
gtk_widget_grab_default (child);
gtk_window_set_default_widget (GTK_WINDOW (dialog), child);
update_suggested_action (dialog);
}
}
@@ -900,8 +899,6 @@ gtk_dialog_add_button (GtkDialog *dialog,
button = gtk_button_new_with_label (button_text);
gtk_button_set_use_underline (GTK_BUTTON (button), TRUE);
gtk_widget_set_can_default (button, TRUE);
gtk_widget_show (button);
gtk_dialog_add_action_widget (dialog, button, response_id);
@@ -1028,7 +1025,7 @@ gtk_dialog_set_default_response (GtkDialog *dialog,
ResponseData *rd = get_response_data (widget, FALSE);
if (rd && rd->response_id == response_id)
gtk_widget_grab_default (widget);
gtk_window_set_default_widget (GTK_WINDOW (dialog), widget);
tmp_list = tmp_list->next;
}
@@ -1528,7 +1525,7 @@ gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
}
if (item->is_default)
gtk_widget_grab_default (GTK_WIDGET (object));
gtk_window_set_default_widget (GTK_WINDOW (dialog), GTK_WIDGET (object));
}
g_slist_free_full (data->items, free_action_widget_info);
+48 -23
View File
@@ -70,6 +70,9 @@ struct _GtkEmojiChooser
EmojiSection flags;
GVariant *data;
GtkWidget *box;
GVariantIter *iter;
guint populate_idle;
GSettings *settings;
};
@@ -92,6 +95,9 @@ gtk_emoji_chooser_finalize (GObject *object)
{
GtkEmojiChooser *chooser = GTK_EMOJI_CHOOSER (object);
if (chooser->populate_idle)
g_source_remove (chooser->populate_idle);
g_variant_unref (chooser->data);
g_object_unref (chooser->settings);
@@ -399,47 +405,68 @@ add_emoji (GtkWidget *box,
gtk_flow_box_insert (GTK_FLOW_BOX (box), child, prepend ? 0 : -1);
}
static void
populate_emoji_chooser (GtkEmojiChooser *chooser)
static gboolean
populate_emoji_chooser (gpointer data)
{
GBytes *bytes = NULL;
GVariantIter iter;
GtkEmojiChooser *chooser = data;
GVariant *item;
GtkWidget *box;
guint64 start, now;
bytes = g_resources_lookup_data ("/org/gtk/libgtk/emoji/emoji.data", 0, NULL);
chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(auss)"), bytes, TRUE));
start = g_get_monotonic_time ();
g_variant_iter_init (&iter, chooser->data);
box = chooser->people.box;
while ((item = g_variant_iter_next_value (&iter)))
if (!chooser->data)
{
GBytes *bytes = g_resources_lookup_data ("/org/gtk/libgtk/emoji/emoji.data", 0, NULL);
chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(auss)"), bytes, TRUE));
g_bytes_unref (bytes);
}
if (!chooser->iter)
{
chooser->iter = g_variant_iter_new (chooser->data);
chooser->box = chooser->people.box;
}
while ((item = g_variant_iter_next_value (chooser->iter)))
{
const char *name;
g_variant_get_child (item, 1, "&s", &name);
if (strcmp (name, chooser->body.first) == 0)
box = chooser->body.box;
chooser->box = chooser->body.box;
else if (strcmp (name, chooser->nature.first) == 0)
box = chooser->nature.box;
chooser->box = chooser->nature.box;
else if (strcmp (name, chooser->food.first) == 0)
box = chooser->food.box;
chooser->box = chooser->food.box;
else if (strcmp (name, chooser->travel.first) == 0)
box = chooser->travel.box;
chooser->box = chooser->travel.box;
else if (strcmp (name, chooser->activities.first) == 0)
box = chooser->activities.box;
chooser->box = chooser->activities.box;
else if (strcmp (name, chooser->objects.first) == 0)
box = chooser->objects.box;
chooser->box = chooser->objects.box;
else if (strcmp (name, chooser->symbols.first) == 0)
box = chooser->symbols.box;
chooser->box = chooser->symbols.box;
else if (strcmp (name, chooser->flags.first) == 0)
box = chooser->flags.box;
chooser->box = chooser->flags.box;
add_emoji (box, FALSE, item, 0, chooser);
add_emoji (chooser->box, FALSE, item, 0, chooser);
g_variant_unref (item);
now = g_get_monotonic_time ();
if (now > start + 8000)
return G_SOURCE_CONTINUE;
}
g_bytes_unref (bytes);
/* We scroll to the top on show, so check the right button for the 1st time */
gtk_widget_set_state_flags (chooser->recent.button, GTK_STATE_FLAG_CHECKED, FALSE);
g_variant_iter_free (chooser->iter);
chooser->iter = NULL;
chooser->box = NULL;
chooser->populate_idle = 0;
return G_SOURCE_REMOVE;
}
static void
@@ -651,11 +678,9 @@ gtk_emoji_chooser_init (GtkEmojiChooser *chooser)
setup_section (chooser, &chooser->symbols, "ATM sign", "emoji-symbols-symbolic");
setup_section (chooser, &chooser->flags, "chequered flag", "emoji-flags-symbolic");
populate_emoji_chooser (chooser);
populate_recent_section (chooser);
/* We scroll to the top on show, so check the right button for the 1st time */
gtk_widget_set_state_flags (chooser->recent.button, GTK_STATE_FLAG_CHECKED, FALSE);
chooser->populate_idle = g_idle_add (populate_emoji_chooser, chooser);
}
static void
+10 -8
View File
@@ -1234,10 +1234,13 @@ notify_cb (GObject *object,
gpointer data)
{
gpointer iface;
gpointer class;
/* The editable interface properties are already forwarded by the editable delegate setup */
iface = g_type_interface_peek (g_type_class_peek (G_OBJECT_TYPE (object)), gtk_editable_get_type ());
if (!g_object_interface_find_property (iface, pspec->name))
class = g_type_class_peek (GTK_TYPE_ENTRY);
if (!g_object_interface_find_property (iface, pspec->name) &&
g_object_class_find_property (class, pspec->name))
g_object_notify (data, pspec->name);
}
@@ -1547,6 +1550,7 @@ gtk_entry_size_allocate (GtkWidget *widget,
int height,
int baseline)
{
const gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
GtkEntry *entry = GTK_ENTRY (widget);
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
gint i;
@@ -1572,8 +1576,8 @@ gtk_entry_size_allocate (GtkWidget *widget,
NULL, &icon_width,
NULL, NULL);
if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL && i == GTK_ENTRY_ICON_PRIMARY) ||
(gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR && i == GTK_ENTRY_ICON_SECONDARY))
if ((is_rtl && i == GTK_ENTRY_ICON_PRIMARY) ||
(!is_rtl && i == GTK_ENTRY_ICON_SECONDARY))
icon_alloc.x = width - icon_width;
else
icon_alloc.x = 0;
@@ -1584,7 +1588,9 @@ gtk_entry_size_allocate (GtkWidget *widget,
gtk_widget_size_allocate (icon_info->widget, &icon_alloc, baseline);
text_alloc.width -= icon_width;
if (i == 0)
if ((!is_rtl && i == GTK_ENTRY_ICON_PRIMARY) ||
(is_rtl && i == GTK_ENTRY_ICON_SECONDARY))
text_alloc.x += icon_width;
}
@@ -2117,10 +2123,6 @@ gtk_entry_get_text_length (GtkEntry *entry)
* widget for the window containing the entry. This usually means that
* the dialog box containing the entry will be closed, since the default
* widget is usually one of the dialog buttons.
*
* (For experts: if @setting is %TRUE, the entry calls
* gtk_window_activate_default() on the window containing the entry, in
* the default handler for the #GtkEntry::activate signal.)
**/
void
gtk_entry_set_activates_default (GtkEntry *entry,
+1 -2
View File
@@ -82,8 +82,7 @@ struct _GtkEntry
* non-%NULL, this will be called to add additional entries to the context
* menu when it is displayed.
* @activate: Class handler for the #GtkEntry::activate signal. The default
* implementation calls gtk_window_activate_default() on the entrys top-level
* window.
* implementation activates the gtk.activate-default action.
* @move_cursor: Class handler for the #GtkEntry::move-cursor signal. The
* default implementation specifies the standard #GtkEntry cursor movement
* behavior.
+13 -1
View File
@@ -73,6 +73,18 @@ gtk_event_controller_unset_widget (GtkEventController *self)
priv->widget = NULL;
}
static gboolean
gtk_event_controller_filter_event_default (GtkEventController *self,
const GdkEvent *event)
{
GtkEventControllerPrivate *priv = gtk_event_controller_get_instance_private (self);
if (priv->widget)
return !gtk_widget_is_sensitive (priv->widget);
return FALSE;
}
static gboolean
gtk_event_controller_handle_event_default (GtkEventController *self,
const GdkEvent *event)
@@ -128,7 +140,7 @@ gtk_event_controller_class_init (GtkEventControllerClass *klass)
klass->set_widget = gtk_event_controller_set_widget;
klass->unset_widget = gtk_event_controller_unset_widget;
klass->filter_event = gtk_event_controller_handle_event_default;
klass->filter_event = gtk_event_controller_filter_event_default;
klass->handle_event = gtk_event_controller_handle_event_default;
object_class->set_property = gtk_event_controller_set_property;
+22 -87
View File
@@ -49,6 +49,7 @@
#include "gtkfilechooserprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkmarshalers.h"
#include "gtkbinlayout.h"
#include "gtkfilechooserbutton.h"
@@ -256,12 +257,11 @@ static void gtk_file_chooser_button_drag_data_received (GtkWidget *wi
GtkSelectionData *data);
static void gtk_file_chooser_button_show (GtkWidget *widget);
static void gtk_file_chooser_button_hide (GtkWidget *widget);
static void gtk_file_chooser_button_root (GtkWidget *widget);
static void gtk_file_chooser_button_map (GtkWidget *widget);
static gboolean gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
static void gtk_file_chooser_button_style_updated (GtkWidget *widget);
static void gtk_file_chooser_button_display_changed (GtkWidget *widget,
GdkDisplay *old_display);
static void gtk_file_chooser_button_state_flags_changed (GtkWidget *widget,
GtkStateFlags previous_state);
@@ -340,41 +340,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkFileChooserButton, gtk_file_chooser_button, GTK_TYPE
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
gtk_file_chooser_button_file_chooser_iface_init))
static void
gtk_file_chooser_button_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
gtk_widget_measure (priv->child, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
gtk_file_chooser_button_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
gtk_widget_size_allocate (priv->child,
&(GtkAllocation) {
0, 0,
width, height
}, baseline);
}
static void
gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
{
@@ -395,11 +360,9 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
widget_class->hide = gtk_file_chooser_button_hide;
widget_class->map = gtk_file_chooser_button_map;
widget_class->style_updated = gtk_file_chooser_button_style_updated;
widget_class->display_changed = gtk_file_chooser_button_display_changed;
widget_class->root = gtk_file_chooser_button_root;
widget_class->mnemonic_activate = gtk_file_chooser_button_mnemonic_activate;
widget_class->state_flags_changed = gtk_file_chooser_button_state_flags_changed;
widget_class->measure = gtk_file_chooser_button_measure;
widget_class->size_allocate = gtk_file_chooser_button_size_allocate;
/**
* GtkFileChooserButton::file-set:
@@ -534,6 +497,8 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
target_list,
GDK_ACTION_COPY);
gdk_content_formats_unref (target_list);
gtk_widget_set_layout_manager (GTK_WIDGET (button), gtk_bin_layout_new ());
}
@@ -1023,17 +988,8 @@ gtk_file_chooser_button_finalize (GObject *object)
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
if (priv->selection_while_inactive)
g_object_unref (priv->selection_while_inactive);
if (priv->current_folder_while_inactive)
g_object_unref (priv->current_folder_while_inactive);
if (priv->model)
{
model_remove_rows (button, 0, gtk_tree_model_iter_n_children (priv->model, NULL));
g_object_unref (priv->model);
}
g_clear_object (&priv->selection_while_inactive);
g_clear_object (&priv->current_folder_while_inactive);
gtk_widget_unparent (priv->button);
gtk_widget_unparent (priv->combo_box);
@@ -1067,31 +1023,22 @@ gtk_file_chooser_button_destroy (GtkWidget *widget)
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
GSList *l;
if (priv->dialog != NULL)
if (priv->model)
{
gtk_widget_destroy (priv->dialog);
priv->dialog = NULL;
model_remove_rows (button, 0, gtk_tree_model_iter_n_children (priv->model, NULL));
g_clear_object (&priv->model);
}
g_clear_pointer (&priv->dialog, gtk_widget_destroy);
if (priv->native)
{
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (priv->native));
g_clear_object (&priv->native);
}
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (priv->native));
priv->chooser = NULL;
g_clear_object (&priv->native);
priv->chooser = NULL; /* Was either priv->dialog or priv->native! */
if (priv->dnd_select_folder_cancellable)
{
g_cancellable_cancel (priv->dnd_select_folder_cancellable);
priv->dnd_select_folder_cancellable = NULL;
}
if (priv->update_button_cancellable)
{
g_cancellable_cancel (priv->update_button_cancellable);
priv->update_button_cancellable = NULL;
}
g_clear_pointer (&priv->dnd_select_folder_cancellable, g_cancellable_cancel);
g_clear_pointer (&priv->update_button_cancellable, g_cancellable_cancel);
if (priv->change_icon_theme_cancellables)
{
@@ -1104,24 +1051,15 @@ gtk_file_chooser_button_destroy (GtkWidget *widget)
priv->change_icon_theme_cancellables = NULL;
}
if (priv->filter_model)
{
g_object_unref (priv->filter_model);
priv->filter_model = NULL;
}
g_clear_object (&priv->filter_model);
if (priv->fs)
{
g_signal_handler_disconnect (priv->fs, priv->fs_volumes_changed_id);
g_object_unref (priv->fs);
priv->fs = NULL;
g_clear_object (&priv->fs);
}
if (priv->bookmarks_manager)
{
_gtk_bookmarks_manager_free (priv->bookmarks_manager);
priv->bookmarks_manager = NULL;
}
g_clear_pointer (&priv->bookmarks_manager, _gtk_bookmarks_manager_free);
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->destroy (widget);
}
@@ -1494,16 +1432,13 @@ gtk_file_chooser_button_style_updated (GtkWidget *widget)
}
static void
gtk_file_chooser_button_display_changed (GtkWidget *widget,
GdkDisplay *old_display)
gtk_file_chooser_button_root (GtkWidget *widget)
{
if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->display_changed)
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->display_changed (widget, old_display);
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->root (widget);
change_icon_theme (GTK_FILE_CHOOSER_BUTTON (widget));
}
/* ******************* *
* Utility Functions *
* ******************* */
+2 -18
View File
@@ -341,17 +341,7 @@ static void
file_chooser_widget_file_activated (GtkFileChooser *chooser,
GtkFileChooserDialog *dialog)
{
GtkWidget *widget;
if (gtk_window_activate_default (GTK_WINDOW (dialog)))
return;
/* There probably isn't a default widget, so make things easier for the
* programmer by looking for a reasonable button on our own.
*/
widget = get_accept_action_widget (GTK_DIALOG (dialog), TRUE);
if (widget)
gtk_widget_activate (widget);
gtk_widget_activate_default (GTK_WIDGET (chooser));
}
static void
@@ -409,12 +399,6 @@ file_chooser_widget_response_requested (GtkWidget *widget,
dialog->priv->response_requested = TRUE;
if (gtk_window_activate_default (GTK_WINDOW (dialog)))
return;
/* There probably isn't a default widget, so make things easier for the
* programmer by looking for a reasonable button on our own.
*/
button = get_accept_action_widget (GTK_DIALOG (dialog), TRUE);
if (button)
{
@@ -563,7 +547,7 @@ ensure_default_response (GtkFileChooserDialog *dialog)
widget = get_accept_action_widget (GTK_DIALOG (dialog), TRUE);
if (widget)
gtk_widget_grab_default (widget);
gtk_window_set_default_widget (GTK_WINDOW (dialog), widget);
}
static void
+112 -221
View File
@@ -83,6 +83,7 @@
#include "gtkfilechoosererrorstackprivate.h"
#include "gtkentryprivate.h"
#include "gtkroot.h"
#include "gtkbinlayout.h"
#include <cairo-gobject.h>
@@ -347,6 +348,8 @@ struct _GtkFileChooserWidgetPrivate {
gint sort_column;
GtkSortType sort_order;
ClockFormat clock_format;
/* Flags */
guint local_only : 1;
@@ -363,6 +366,7 @@ struct _GtkFileChooserWidgetPrivate {
guint show_size_column : 1;
guint create_folders : 1;
guint auto_selecting_first_row : 1;
guint starting_search : 1;
};
#define MAX_LOADING_TIME 500
@@ -457,8 +461,6 @@ static void gtk_file_chooser_widget_unmap (GtkWidget *w
static void gtk_file_chooser_widget_root (GtkWidget *widget);
static void gtk_file_chooser_widget_unroot (GtkWidget *widget);
static void gtk_file_chooser_widget_style_updated (GtkWidget *widget);
static void gtk_file_chooser_widget_display_changed (GtkWidget *widget,
GdkDisplay *previous_display);
static gboolean gtk_file_chooser_widget_set_current_folder (GtkFileChooser *chooser,
GFile *folder,
@@ -532,6 +534,7 @@ static void search_shortcut_handler (GtkFileChooserWidget *impl);
static void recent_shortcut_handler (GtkFileChooserWidget *impl);
static void places_shortcut_handler (GtkFileChooserWidget *impl);
static void update_appearance (GtkFileChooserWidget *impl);
static void check_icon_theme (GtkFileChooserWidget *impl);
static void operation_mode_set (GtkFileChooserWidget *impl, OperationMode mode);
static void location_mode_set (GtkFileChooserWidget *impl, LocationMode new_mode);
@@ -555,8 +558,6 @@ static void list_row_activated (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
GtkFileChooserWidget *impl);
static void list_cursor_changed (GtkTreeView *treeview,
GtkFileChooserWidget *impl);
static void path_bar_clicked (GtkPathBar *path_bar,
GFile *file,
@@ -672,8 +673,7 @@ gtk_file_chooser_widget_finalize (GObject *object)
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (object);
GtkFileChooserWidgetPrivate *priv = impl->priv;
if (priv->choices)
g_hash_table_unref (priv->choices);
g_clear_pointer (&priv->choices, g_hash_table_unref);
if (priv->location_changed_id > 0)
g_source_remove (priv->location_changed_id);
@@ -683,21 +683,10 @@ gtk_file_chooser_widget_finalize (GObject *object)
g_free (priv->browse_files_last_selected_name);
g_slist_free_full (priv->filters, g_object_unref);
if (priv->current_filter)
g_object_unref (priv->current_filter);
if (priv->current_volume_file)
g_object_unref (priv->current_volume_file);
if (priv->current_folder)
g_object_unref (priv->current_folder);
if (priv->preview_file)
g_object_unref (priv->preview_file);
if (priv->browse_path_bar_size_group)
g_object_unref (priv->browse_path_bar_size_group);
g_clear_object (&priv->current_filter);
g_clear_object (&priv->current_volume_file);
g_clear_object (&priv->current_folder);
g_clear_object (&priv->browse_path_bar_size_group);
/* Free all the Models we have */
stop_loading_and_clear_list_model (impl, FALSE);
@@ -715,31 +704,6 @@ gtk_file_chooser_widget_finalize (GObject *object)
G_OBJECT_CLASS (gtk_file_chooser_widget_parent_class)->finalize (object);
}
/* Shows an error dialog set as transient for the specified window */
static void
error_message_with_parent (GtkWindow *parent,
const char *msg,
const char *detail)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (parent,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
msg);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", detail);
if (parent && gtk_window_has_group (parent))
gtk_window_group_add_window (gtk_window_get_group (parent),
GTK_WINDOW (dialog));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
/* Returns a toplevel GtkWindow, or NULL if none */
static GtkWindow *
get_toplevel (GtkWidget *widget)
@@ -759,7 +723,25 @@ error_message (GtkFileChooserWidget *impl,
const char *msg,
const char *detail)
{
error_message_with_parent (get_toplevel (GTK_WIDGET (impl)), msg, detail);
GtkWindow *parent = get_toplevel (GTK_WIDGET (impl));
GtkWidget *dialog;
dialog = gtk_message_dialog_new (parent,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
msg);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", detail);
if (parent && gtk_window_has_group (parent))
gtk_window_group_add_window (gtk_window_get_group (parent),
GTK_WINDOW (dialog));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
/* Shows a simple error dialog relative to a path. Frees the GError as well. */
@@ -920,7 +902,6 @@ update_preview_widget_visibility (GtkFileChooserWidget *impl)
priv->preview_label = gtk_label_new (priv->preview_display_name);
gtk_box_insert_child_after (GTK_BOX (priv->preview_box), priv->preview_label, NULL);
gtk_label_set_ellipsize (GTK_LABEL (priv->preview_label), PANGO_ELLIPSIZE_MIDDLE);
gtk_widget_show (priv->preview_label);
}
}
else
@@ -1259,13 +1240,10 @@ places_sidebar_show_error_message_cb (GtkPlacesSidebar *sidebar,
}
static gboolean
key_is_left_or_right (const GdkEvent *event)
key_is_left_or_right (guint keyval,
guint state)
{
guint modifiers, keyval, state;
if (!gdk_event_get_keyval (event, &keyval) ||
!gdk_event_get_state (event, &state))
return FALSE;
guint modifiers;
modifiers = gtk_accelerator_get_default_mod_mask ();
@@ -1326,11 +1304,8 @@ key_press_cb (GtkEventControllerKey *controller,
{
GtkFileChooserWidget *impl = (GtkFileChooserWidget *) data;
GtkFileChooserWidgetPrivate *priv = impl->priv;
const GdkEvent *event;
const char *string;
event = gtk_get_current_event ();
if (should_trigger_location_entry (impl, keyval, state, &string) &&
(priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER))
@@ -1339,7 +1314,7 @@ key_press_cb (GtkEventControllerKey *controller,
return GDK_EVENT_STOP;
}
if (key_is_left_or_right (event))
if (key_is_left_or_right (keyval, state))
{
if (gtk_widget_child_focus (priv->places_sidebar, GTK_DIR_LEFT))
return GDK_EVENT_STOP;
@@ -1354,25 +1329,8 @@ key_press_cb (GtkEventControllerKey *controller,
&& !(priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
{
GtkWidget *widget = GTK_WIDGET (impl);
GtkWindow *window;
window = get_toplevel (widget);
if (window)
{
GtkWidget *default_widget, *focus_widget;
default_widget = gtk_window_get_default_widget (window);
focus_widget = gtk_root_get_focus (GTK_ROOT (window));
if (widget != default_widget &&
!(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget))))
{
gtk_window_activate_default (window);
return GDK_EVENT_STOP;
}
}
gtk_widget_activate_default (GTK_WIDGET (impl));
return GDK_EVENT_STOP;
}
if (keyval == GDK_KEY_Escape &&
@@ -1395,11 +1353,8 @@ widget_key_press_cb (GtkEventControllerKey *controller,
GtkFileChooserWidget *impl = (GtkFileChooserWidget *) data;
GtkFileChooserWidgetPrivate *priv = impl->priv;
gboolean handled = FALSE;
GdkEvent *event;
const char *string;
event = gtk_get_current_event ();
if (should_trigger_location_entry (impl, keyval, state, &string))
{
if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
@@ -1411,16 +1366,17 @@ widget_key_press_cb (GtkEventControllerKey *controller,
}
else
{
gtk_event_controller_key_forward (controller, priv->search_entry);
priv->starting_search = TRUE;
if (gtk_event_controller_key_forward (controller, priv->search_entry))
{
if (priv->operation_mode != OPERATION_MODE_SEARCH &&
priv->starting_search)
operation_mode_set (impl, OPERATION_MODE_SEARCH);
if (priv->operation_mode != OPERATION_MODE_SEARCH)
operation_mode_set (impl, OPERATION_MODE_SEARCH);
handled = TRUE;
handled = TRUE;
}
}
g_object_unref (event);
return handled;
}
@@ -1709,7 +1665,6 @@ visit_file_cb (GSimpleAction *action,
g_slist_free_full (files, g_object_unref);
}
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
/* Callback used when the "Open this folder" menu item is activated */
static void
open_folder_cb (GSimpleAction *action,
@@ -1735,7 +1690,6 @@ open_folder_cb (GSimpleAction *action,
g_slist_free_full (files, g_object_unref);
}
G_GNUC_END_IGNORE_DEPRECATIONS
/* callback used when the "Show Hidden Files" menu item is toggled */
static void
@@ -2197,7 +2151,6 @@ file_list_build_popover (GtkFileChooserWidget *impl)
priv->browse_files_popover = gtk_popover_new (priv->browse_files_tree_view);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (box, "margin", 10, NULL);
gtk_widget_show (box);
gtk_container_add (GTK_CONTAINER (priv->browse_files_popover), box);
priv->visit_file_item = add_button (box, _("_Visit File"), "item.visit");
@@ -2267,7 +2220,12 @@ file_list_show_popover (GtkFileChooserWidget *impl,
GtkTreeModel *model;
GList *list;
GtkTreePath *path;
graphene_rect_t bounds;
if (!gtk_widget_compute_bounds (priv->browse_files_tree_view,
priv->browse_files_tree_view,
&bounds))
return;
file_list_update_popover (impl);
@@ -2280,7 +2238,7 @@ file_list_show_popover (GtkFileChooserWidget *impl,
gtk_tree_view_convert_bin_window_to_widget_coords (GTK_TREE_VIEW (priv->browse_files_tree_view),
rect.x, rect.y, &rect.x, &rect.y);
rect.x = CLAMP (x - 20, 0, gtk_widget_get_allocated_width (priv->browse_files_tree_view) - 40);
rect.x = CLAMP (x - 20, 0, bounds.size.width - 40);
rect.width = 40;
g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
@@ -2303,11 +2261,17 @@ list_popup_menu_cb (GtkWidget *widget,
GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
graphene_rect_t bounds;
file_list_show_popover (impl,
0.5 * gtk_widget_get_allocated_width (GTK_WIDGET (priv->browse_files_tree_view)),
0.5 * gtk_widget_get_allocated_height (GTK_WIDGET (priv->browse_files_tree_view)));
return TRUE;
if (gtk_widget_compute_bounds (priv->browse_files_tree_view,
priv->browse_files_tree_view,
&bounds))
{
file_list_show_popover (impl, 0.5 * bounds.size.width, 0.5 * bounds.size.height);
return TRUE;
}
return FALSE;
}
/* Callback used when a button is pressed on the file list. We trap button 3 to
@@ -2491,6 +2455,7 @@ static void
location_entry_close_clicked (GtkFileChooserWidget *impl)
{
location_mode_set (impl, LOCATION_MODE_PATH_BAR);
gtk_widget_grab_focus (GTK_WIDGET (impl));
}
static void
@@ -2608,7 +2573,6 @@ save_widgets_create (GtkFileChooserWidget *impl)
priv->save_widgets = vbox;
gtk_box_insert_child_after (GTK_BOX (priv->box), priv->save_widgets, NULL);
gtk_widget_show (priv->save_widgets);
}
/* Destroys the widgets specific to Save mode */
@@ -3468,29 +3432,10 @@ cancel_all_operations (GtkFileChooserWidget *impl)
pending_select_files_free (impl);
if (priv->file_list_drag_data_received_cancellable)
{
g_cancellable_cancel (priv->file_list_drag_data_received_cancellable);
priv->file_list_drag_data_received_cancellable = NULL;
}
if (priv->update_current_folder_cancellable)
{
g_cancellable_cancel (priv->update_current_folder_cancellable);
priv->update_current_folder_cancellable = NULL;
}
if (priv->should_respond_get_info_cancellable)
{
g_cancellable_cancel (priv->should_respond_get_info_cancellable);
priv->should_respond_get_info_cancellable = NULL;
}
if (priv->file_exists_get_info_cancellable)
{
g_cancellable_cancel (priv->file_exists_get_info_cancellable);
priv->file_exists_get_info_cancellable = NULL;
}
g_clear_pointer (&priv->file_list_drag_data_received_cancellable, g_cancellable_cancel);
g_clear_pointer (&priv->update_current_folder_cancellable, g_cancellable_cancel);
g_clear_pointer (&priv->should_respond_get_info_cancellable, g_cancellable_cancel);
g_clear_pointer (&priv->file_exists_get_info_cancellable, g_cancellable_cancel);
search_stop_searching (impl, TRUE);
recent_stop_loading (impl);
@@ -3525,25 +3470,10 @@ gtk_file_chooser_widget_dispose (GObject *object)
if (priv->rename_file_popover)
gtk_popover_set_relative_to (GTK_POPOVER (priv->rename_file_popover), NULL);
if (priv->browse_files_popover)
{
gtk_widget_destroy (priv->browse_files_popover);
priv->browse_files_popover = NULL;
}
if (priv->extra_widget)
{
g_object_unref (priv->extra_widget);
priv->extra_widget = NULL;
}
g_clear_pointer (&priv->browse_files_popover, gtk_widget_destroy);
g_clear_object (&priv->extra_widget);
remove_settings_signal (impl, gtk_widget_get_display (GTK_WIDGET (impl)));
if (priv->bookmarks_manager)
{
_gtk_bookmarks_manager_free (priv->bookmarks_manager);
priv->bookmarks_manager = NULL;
}
g_clear_pointer (&priv->bookmarks_manager, _gtk_bookmarks_manager_free);
if (priv->external_entry && priv->location_entry == priv->external_entry)
{
@@ -3551,11 +3481,7 @@ gtk_file_chooser_widget_dispose (GObject *object)
priv->external_entry = NULL;
}
if (priv->box)
{
gtk_widget_unparent (priv->box);
priv->box = NULL;
}
g_clear_pointer (&priv->box, gtk_widget_unparent);
G_OBJECT_CLASS (gtk_file_chooser_widget_parent_class)->dispose (object);
}
@@ -3611,6 +3537,10 @@ gtk_file_chooser_widget_unroot (GtkWidget *widget)
priv->toplevel_current_focus_widget = NULL;
}
remove_settings_signal (impl, gtk_widget_get_display (widget));
check_icon_theme (impl);
emit_default_size_changed (impl);
GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->unroot (widget);
}
@@ -3695,27 +3625,6 @@ gtk_file_chooser_widget_style_updated (GtkWidget *widget)
profile_end ("end", NULL);
}
static void
gtk_file_chooser_widget_display_changed (GtkWidget *widget,
GdkDisplay *previous_display)
{
GtkFileChooserWidget *impl;
profile_start ("start", NULL);
impl = GTK_FILE_CHOOSER_WIDGET (widget);
if (GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->display_changed)
GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->display_changed (widget, previous_display);
remove_settings_signal (impl, previous_display);
check_icon_theme (impl);
emit_default_size_changed (impl);
profile_end ("end", NULL);
}
static void
set_sort_column (GtkFileChooserWidget *impl)
{
@@ -3768,6 +3677,7 @@ settings_load (GtkFileChooserWidget *impl)
priv->startup_mode = startup_mode;
priv->sort_directories_first = sort_directories_first;
priv->show_time = date_format == DATE_FORMAT_WITH_TIME;
priv->clock_format = g_settings_get_enum (settings, "clock-format");
/* We don't call set_sort_column() here as the models may not have been
* created yet. The individual functions that create and set the models will
@@ -3775,6 +3685,14 @@ settings_load (GtkFileChooserWidget *impl)
*/
update_time_renderer_visible (impl);
if (sidebar_width < 0)
{
GtkWidget *sidebar = gtk_paned_get_child1 (GTK_PANED (priv->browse_widgets_hpaned));
gtk_widget_measure (sidebar, GTK_ORIENTATION_HORIZONTAL, -1,
NULL, &sidebar_width, NULL, NULL);
}
gtk_paned_set_position (GTK_PANED (priv->browse_widgets_hpaned), sidebar_width);
}
@@ -4636,13 +4554,11 @@ static char *
my_g_format_date_for_display (GtkFileChooserWidget *impl,
glong secs)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GDateTime *now, *time;
GDateTime *now_date, *date;
ClockFormat clock_format;
const gchar *format;
gchar *date_str;
GSettings *settings;
gint days_ago;
time = g_date_time_new_from_unix_local (secs);
@@ -4651,9 +4567,6 @@ my_g_format_date_for_display (GtkFileChooserWidget *impl,
g_date_time_get_day_of_month (time),
0, 0, 0);
settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
clock_format = g_settings_get_enum (settings, "clock-format");
now = g_date_time_new_now_local ();
now_date = g_date_time_new_local (g_date_time_get_year (now),
g_date_time_get_month (now),
@@ -4665,7 +4578,7 @@ my_g_format_date_for_display (GtkFileChooserWidget *impl,
{
if (priv->show_time)
format = "";
else if (clock_format == CLOCK_FORMAT_24)
else if (priv->clock_format == CLOCK_FORMAT_24)
/* Translators: see g_date_time_format() for details on the format */
format = _("%H:%M");
else
@@ -4703,18 +4616,14 @@ static char *
my_g_format_time_for_display (GtkFileChooserWidget *impl,
glong secs)
{
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GDateTime *time;
ClockFormat clock_format;
const gchar *format;
gchar *date_str;
GSettings *settings;
time = g_date_time_new_from_unix_local (secs);
settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
clock_format = g_settings_get_enum (settings, "clock-format");
if (clock_format == CLOCK_FORMAT_24)
if (priv->clock_format == CLOCK_FORMAT_24)
format = _("%H:%M");
else
format = _("%l:%M %p");
@@ -6200,7 +6109,6 @@ add_custom_button_to_dialog (GtkDialog *dialog,
GtkWidget *button;
button = gtk_button_new_with_mnemonic (mnemonic_label);
gtk_widget_set_can_default (button, TRUE);
gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, response_id);
}
@@ -7001,10 +6909,6 @@ search_engine_hits_added_cb (GtkSearchEngine *engine,
{
GList *l, *files, *files_with_info, *infos;
GFile *file;
gboolean select = FALSE;
if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (impl->priv->search_model), NULL) == 0)
select = TRUE;
files = NULL;
files_with_info = NULL;
@@ -7032,8 +6936,6 @@ search_engine_hits_added_cb (GtkSearchEngine *engine,
g_list_free_full (infos, g_object_unref);
gtk_stack_set_visible_child_name (GTK_STACK (impl->priv->browse_files_stack), "list");
if (select)
gtk_widget_grab_focus (impl->priv->browse_files_tree_view);
}
/* Callback used from GtkSearchEngine when the query is done running */
@@ -7182,8 +7084,6 @@ search_start_query (GtkFileChooserWidget *impl,
set_busy_cursor (impl, TRUE);
priv->show_progress_timeout = g_timeout_add (1500, show_spinner, impl);
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
if (priv->search_engine == NULL)
priv->search_engine = _gtk_search_engine_new ();
@@ -7217,6 +7117,10 @@ search_start_query (GtkFileChooserWidget *impl,
if (gtk_query_get_location (priv->search_query) &&
_gtk_file_consider_as_remote (gtk_query_get_location (priv->search_query)))
gtk_widget_show (priv->remote_warning_bar);
/* We're not showing the file list here already and instead rely on the
* GtkSearchEntry timout and the ::hits-added signal from above to
* switch. */
}
/* Callback used when the user presses Enter while typing on the search
@@ -7251,6 +7155,8 @@ search_entry_stop_cb (GtkFileChooserWidget *impl)
search_stop_searching (impl, FALSE);
else
g_object_set (impl, "search-mode", FALSE, NULL);
impl->priv->starting_search = FALSE;
}
/* Hides the path bar and creates the search entry */
@@ -7691,6 +7597,24 @@ list_cursor_changed (GtkTreeView *list,
check_preview_change (impl);
}
static gboolean
browse_files_tree_view_keynav_failed_cb (GtkWidget *widget,
GtkDirectionType direction,
gpointer user_data)
{
GtkFileChooserWidget *self = user_data;
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (self);
if (direction == GTK_DIR_UP && priv->operation_mode == OPERATION_MODE_SEARCH)
{
gtk_widget_grab_focus (priv->search_entry);
return TRUE;
}
return FALSE;
}
/* Callback used when a row in the file list is activated */
static void
list_row_activated (GtkTreeView *tree_view,
@@ -7954,39 +7878,6 @@ add_normal_and_shifted_binding (GtkBindingSet *binding_set,
signal_name, 0);
}
static void
gtk_file_chooser_widget_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkFileChooserWidget *self = GTK_FILE_CHOOSER_WIDGET (widget);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (self);
gtk_widget_measure (priv->box, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
gtk_file_chooser_widget_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkFileChooserWidget *self = GTK_FILE_CHOOSER_WIDGET (widget);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (self);
gtk_widget_size_allocate (priv->box,
&(GtkAllocation) {
0, 0,
width, height
},-1);
}
static void
gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
{
@@ -8010,9 +7901,6 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
widget_class->root = gtk_file_chooser_widget_root;
widget_class->unroot = gtk_file_chooser_widget_unroot;
widget_class->style_updated = gtk_file_chooser_widget_style_updated;
widget_class->display_changed = gtk_file_chooser_widget_display_changed;
widget_class->measure = gtk_file_chooser_widget_measure;
widget_class->size_allocate = gtk_file_chooser_widget_size_allocate;
/*
* Signals
@@ -8418,6 +8306,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_callback (widget_class, file_list_drag_end_cb);
gtk_widget_class_bind_template_callback (widget_class, list_selection_changed);
gtk_widget_class_bind_template_callback (widget_class, list_cursor_changed);
gtk_widget_class_bind_template_callback (widget_class, browse_files_tree_view_keynav_failed_cb);
gtk_widget_class_bind_template_callback (widget_class, filter_combo_changed);
gtk_widget_class_bind_template_callback (widget_class, path_bar_clicked);
gtk_widget_class_bind_template_callback (widget_class, places_sidebar_open_location_cb);
@@ -8578,6 +8467,8 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
*/
post_process_ui (impl);
gtk_widget_set_layout_manager (GTK_WIDGET (impl), gtk_bin_layout_new ());
profile_end ("end", NULL);
}
+7
View File
@@ -334,6 +334,13 @@ gtk_fixed_layout_init (GtkFixedLayout *self)
{
}
/**
* gtk_fixed_layout_new:
*
* Creates a new #GtkFixedLayout.
*
* Returns: the newly created #GtkFixedLayout
*/
GtkLayoutManager *
gtk_fixed_layout_new (void)
{
+80 -41
View File
@@ -55,6 +55,7 @@
#include "gtkcombobox.h"
#include "gtkgesturemultipress.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkroot.h"
#if defined(HAVE_HARFBUZZ) && defined(HAVE_PANGOFT)
#include <pango/pangofc-font.h>
@@ -168,9 +169,6 @@ static void gtk_font_chooser_widget_get_property (GObject *objec
GParamSpec *pspec);
static void gtk_font_chooser_widget_finalize (GObject *object);
static void gtk_font_chooser_widget_display_changed (GtkWidget *widget,
GdkDisplay *previous_display);
static gboolean gtk_font_chooser_widget_find_font (GtkFontChooserWidget *fontchooser,
const PangoFontDescription *font_desc,
GtkTreeIter *iter);
@@ -617,6 +615,35 @@ rows_changed_cb (GtkFontChooserWidget *fontchooser)
gtk_stack_set_visible_child_name (GTK_STACK (priv->list_stack), page);
}
static void
update_key_capture (GtkWidget *chooser)
{
GtkFontChooserWidgetPrivate *priv;
GtkWidget *capture_widget;
priv = gtk_font_chooser_widget_get_instance_private (GTK_FONT_CHOOSER_WIDGET (chooser));
if (gtk_widget_get_mapped (chooser) &&
g_str_equal (gtk_stack_get_visible_child_name (GTK_STACK (priv->stack)), "list"))
{
GtkWidget *toplevel;
GtkWidget *focus;
toplevel = gtk_widget_get_toplevel (chooser);
focus = gtk_root_get_focus (GTK_ROOT (toplevel));
if (GTK_IS_EDITABLE (focus) && focus != priv->search_entry)
capture_widget = NULL;
else
capture_widget = chooser;
}
else
capture_widget = NULL;
gtk_search_entry_set_key_capture_widget (GTK_SEARCH_ENTRY (priv->search_entry),
capture_widget);
}
static void
gtk_font_chooser_widget_map (GtkWidget *widget)
{
@@ -628,6 +655,53 @@ gtk_font_chooser_widget_map (GtkWidget *widget)
g_simple_action_set_state (G_SIMPLE_ACTION (priv->tweak_action), g_variant_new_boolean (FALSE));
GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->map (widget);
update_key_capture (widget);
}
static void
gtk_font_chooser_widget_unmap (GtkWidget *widget)
{
update_key_capture (widget);
GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->unmap (widget);
}
static void
fontconfig_changed (GtkFontChooserWidget *fontchooser)
{
gtk_font_chooser_widget_load_fonts (fontchooser, TRUE);
}
static void
gtk_font_chooser_widget_root (GtkWidget *widget)
{
GtkSettings *settings;
GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->root (widget);
g_signal_connect_swapped (gtk_widget_get_root (widget), "notify::focus-widget",
G_CALLBACK (update_key_capture), widget);
settings = gtk_widget_get_settings (widget);
g_signal_connect_object (settings, "notify::gtk-fontconfig-timestamp",
G_CALLBACK (fontconfig_changed), widget, G_CONNECT_SWAPPED);
gtk_font_chooser_widget_load_fonts (GTK_FONT_CHOOSER_WIDGET (widget), FALSE);
}
static void
gtk_font_chooser_widget_unroot (GtkWidget *widget)
{
GtkSettings *settings;
g_signal_handlers_disconnect_by_func (gtk_widget_get_root (widget),
update_key_capture, widget);
settings = gtk_widget_get_settings (widget);
g_signal_handlers_disconnect_by_func (settings, fontconfig_changed, widget);
GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->unroot (widget);
}
static void
@@ -685,10 +759,12 @@ gtk_font_chooser_widget_class_init (GtkFontChooserWidgetClass *klass)
g_type_ensure (GTK_TYPE_DELAYED_FONT_DESCRIPTION);
g_type_ensure (G_TYPE_THEMED_ICON);
widget_class->display_changed = gtk_font_chooser_widget_display_changed;
widget_class->measure = gtk_font_chooser_widget_measure;
widget_class->size_allocate = gtk_font_chooser_widget_size_allocate;
widget_class->root = gtk_font_chooser_widget_root;
widget_class->unroot = gtk_font_chooser_widget_unroot;
widget_class->map = gtk_font_chooser_widget_map;
widget_class->unmap = gtk_font_chooser_widget_unmap;
gobject_class->finalize = gtk_font_chooser_widget_finalize;
gobject_class->dispose = gtk_font_chooser_widget_dispose;
@@ -876,9 +952,6 @@ gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser)
gtk_font_chooser_widget_set_cell_size (fontchooser);
gtk_font_chooser_widget_take_font_desc (fontchooser, NULL);
gtk_search_entry_set_key_capture_widget (GTK_SEARCH_ENTRY (priv->search_entry),
GTK_WIDGET (fontchooser));
}
/**
@@ -1250,40 +1323,6 @@ gtk_font_chooser_widget_find_font (GtkFontChooserWidget *fontchooser,
return valid;
}
static void
fontconfig_changed (GtkFontChooserWidget *fontchooser)
{
gtk_font_chooser_widget_load_fonts (fontchooser, TRUE);
}
static void
gtk_font_chooser_widget_display_changed (GtkWidget *widget,
GdkDisplay *previous_display)
{
GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (widget);
GtkSettings *settings;
if (GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->display_changed)
GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->display_changed (widget, previous_display);
if (previous_display)
{
settings = gtk_settings_get_for_display (previous_display);
g_signal_handlers_disconnect_by_func (settings, fontconfig_changed, widget);
}
settings = gtk_widget_get_settings (widget);
g_signal_connect_object (settings, "notify::gtk-fontconfig-timestamp",
G_CALLBACK (fontconfig_changed), widget, G_CONNECT_SWAPPED);
if (previous_display == NULL)
previous_display = gdk_display_get_default ();
if (previous_display == gtk_widget_get_display (widget))
return;
gtk_font_chooser_widget_load_fonts (fontchooser, FALSE);
}
static PangoFontFamily *
gtk_font_chooser_widget_get_family (GtkFontChooser *chooser)
{
+4 -1
View File
@@ -628,7 +628,10 @@ gtk_gesture_filter_event (GtkEventController *controller,
* subclasses which punch the holes in for the events
* they can possibly handle.
*/
return EVENT_IS_TOUCHPAD_GESTURE (event);
if (EVENT_IS_TOUCHPAD_GESTURE (event))
return FALSE;
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_parent_class)->filter_event (controller, event);
}
static gboolean
+1
View File
@@ -107,6 +107,7 @@ gtk_gizmo_new (const char *css_name,
{
GtkGizmo *gizmo = GTK_GIZMO (g_object_new (GTK_TYPE_GIZMO,
"css-name", css_name,
"name", css_name,
NULL));
gizmo->measure_func = measure_func;
+1 -1
View File
@@ -1726,7 +1726,7 @@ gtk_grid_layout_init (GtkGridLayout *self)
}
/**
* gtk_grid_layou_new:
* gtk_grid_layout_new:
*
* Creates a new #GtkGridLayout.
*
+6 -3
View File
@@ -576,8 +576,6 @@ gtk_info_bar_add_button (GtkInfoBar *info_bar,
button = gtk_button_new_with_label (button_text);
gtk_button_set_use_underline (GTK_BUTTON (button), TRUE);
gtk_widget_set_can_default (button, TRUE);
gtk_widget_show (button);
gtk_info_bar_add_action_widget (info_bar, button, response_id);
@@ -744,7 +742,12 @@ gtk_info_bar_set_default_response (GtkInfoBar *info_bar,
ResponseData *rd = get_response_data (widget, FALSE);
if (rd && rd->response_id == response_id)
gtk_widget_grab_default (widget);
{
GtkWidget *window;
window = gtk_widget_get_ancestor (GTK_WIDGET (info_bar), GTK_TYPE_WINDOW);
gtk_window_set_default_widget (GTK_WINDOW (window), widget);
}
}
g_list_free (children);
+46 -78
View File
@@ -456,8 +456,6 @@ static void gtk_label_set_markup_internal (GtkLabel *label,
static void gtk_label_recalculate (GtkLabel *label);
static void gtk_label_root (GtkWidget *widget);
static void gtk_label_unroot (GtkWidget *widget);
static void gtk_label_display_changed (GtkWidget *widget,
GdkDisplay *old_display);
static gboolean gtk_label_popup_menu (GtkWidget *widget);
static void gtk_label_set_selectable_hint (GtkLabel *label);
@@ -609,7 +607,6 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->unmap = gtk_label_unmap;
widget_class->root = gtk_label_root;
widget_class->unroot = gtk_label_unroot;
widget_class->display_changed = gtk_label_display_changed;
widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
widget_class->drag_data_get = gtk_label_drag_data_get;
widget_class->grab_focus = gtk_label_grab_focus;
@@ -1803,28 +1800,6 @@ gtk_label_setup_mnemonic (GtkLabel *label,
g_object_set_qdata (G_OBJECT (label), quark_mnemonic_menu, mnemonic_menu);
}
static void
gtk_label_root (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GTK_WIDGET_CLASS (gtk_label_parent_class)->root (widget);
gtk_label_setup_mnemonic (label, gtk_widget_get_toplevel (widget), priv->mnemonic_keyval);
}
static void
gtk_label_unroot (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
gtk_label_setup_mnemonic (label, NULL, priv->mnemonic_keyval);
GTK_WIDGET_CLASS (gtk_label_parent_class)->unroot (widget);
}
static void
label_shortcut_setting_apply (GtkLabel *label)
{
@@ -1861,6 +1836,50 @@ label_shortcut_setting_changed (GtkSettings *settings)
g_list_free (list);
}
static void
gtk_label_root (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GtkSettings *settings;
gboolean shortcuts_connected;
GTK_WIDGET_CLASS (gtk_label_parent_class)->root (widget);
gtk_label_setup_mnemonic (label, gtk_widget_get_toplevel (widget), priv->mnemonic_keyval);
/* The PangoContext is replaced when the display changes, so clear the layouts */
gtk_label_clear_layout (GTK_LABEL (widget));
settings = gtk_widget_get_settings (widget);
shortcuts_connected =
GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (settings), quark_shortcuts_connected));
if (! shortcuts_connected)
{
g_signal_connect (settings, "notify::gtk-enable-accels",
G_CALLBACK (label_shortcut_setting_changed),
NULL);
g_object_set_qdata (G_OBJECT (settings), quark_shortcuts_connected,
GINT_TO_POINTER (TRUE));
}
label_shortcut_setting_apply (GTK_LABEL (widget));
}
static void
gtk_label_unroot (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
gtk_label_setup_mnemonic (label, NULL, priv->mnemonic_keyval);
GTK_WIDGET_CLASS (gtk_label_parent_class)->unroot (widget);
}
static void
mnemonics_visible_apply (GtkWidget *widget,
gboolean mnemonics_visible)
@@ -1913,35 +1932,6 @@ label_mnemonics_visible_changed (GtkWindow *window,
GINT_TO_POINTER (mnemonics_visible));
}
static void
gtk_label_display_changed (GtkWidget *widget,
GdkDisplay *old_display)
{
GtkSettings *settings;
gboolean shortcuts_connected;
/* The PangoContext is replaced when the display changes, so clear the layouts */
gtk_label_clear_layout (GTK_LABEL (widget));
settings = gtk_widget_get_settings (widget);
shortcuts_connected =
GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (settings), quark_shortcuts_connected));
if (! shortcuts_connected)
{
g_signal_connect (settings, "notify::gtk-enable-accels",
G_CALLBACK (label_shortcut_setting_changed),
NULL);
g_object_set_qdata (G_OBJECT (settings), quark_shortcuts_connected,
GINT_TO_POINTER (TRUE));
}
label_shortcut_setting_apply (GTK_LABEL (widget));
}
static void
label_mnemonic_widget_weak_notify (gpointer data,
GObject *where_the_object_was)
@@ -6203,31 +6193,9 @@ gtk_label_activate_current_link (GtkLabel *label)
link = gtk_label_get_focus_link (label);
if (link)
{
emit_activate_link (label, link);
}
emit_activate_link (label, link);
else
{
GtkWidget *toplevel;
GtkWindow *window;
GtkWidget *default_widget, *focus_widget;
toplevel = gtk_widget_get_toplevel (widget);
if (GTK_IS_WINDOW (toplevel))
{
window = GTK_WINDOW (toplevel);
if (window)
{
default_widget = gtk_window_get_default_widget (window);
focus_widget = gtk_root_get_focus (GTK_ROOT (window));
if (default_widget != widget &&
!(widget == focus_widget && (!default_widget || !gtk_widget_is_sensitive (default_widget))))
gtk_window_activate_default (window);
}
}
}
gtk_widget_activate_default (widget);
}
static GtkLabelLink *
+18 -39
View File
@@ -1046,12 +1046,12 @@ menu_change_display (GtkMenu *menu,
}
static void
attach_widget_display_changed (GtkWidget *attach_widget,
GdkDisplay *previous_display,
GtkMenu *menu)
attach_widget_root_changed (GObject *attach_widget,
GParamSpec *pspec,
gpointer menu)
{
if (!g_object_get_data (G_OBJECT (menu), "gtk-menu-explicit-display"))
menu_change_display (menu, gtk_widget_get_display (attach_widget));
menu_change_display (menu, gtk_widget_get_display (GTK_WIDGET (attach_widget)));
}
static void
@@ -1107,9 +1107,9 @@ gtk_menu_attach_to_widget (GtkMenu *menu,
data = g_slice_new (GtkMenuAttachData);
data->attach_widget = attach_widget;
g_signal_connect (attach_widget, "display-changed",
G_CALLBACK (attach_widget_display_changed), menu);
attach_widget_display_changed (attach_widget, NULL, menu);
g_signal_connect (attach_widget, "notify::root",
G_CALLBACK (attach_widget_root_changed), menu);
attach_widget_root_changed (G_OBJECT (attach_widget), NULL, menu);
data->detacher = detacher;
g_object_set_data (G_OBJECT (menu), I_(attach_data_key), data);
@@ -1189,7 +1189,7 @@ gtk_menu_detach (GtkMenu *menu)
}
g_signal_handlers_disconnect_by_func (data->attach_widget,
(gpointer) attach_widget_display_changed,
(gpointer) attach_widget_root_changed,
menu);
if (data->detacher)
@@ -1266,6 +1266,8 @@ popup_grab_on_surface (GdkSurface *surface,
GdkGrabStatus status;
GdkSeat *seat;
g_return_val_if_fail (gdk_surface_get_display (surface) == gdk_device_get_display (pointer), FALSE);
seat = gdk_device_get_seat (pointer);
status = gdk_seat_grab (seat, surface,
GDK_SEAT_CAPABILITY_ALL, TRUE,
@@ -1321,7 +1323,11 @@ gtk_menu_popup_internal (GtkMenu *menu,
device = NULL;
if (device == NULL)
device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
{
device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
g_return_if_fail (gdk_device_get_display (device) == display);
}
widget = GTK_WIDGET (menu);
menu_shell = GTK_MENU_SHELL (menu);
@@ -1331,6 +1337,8 @@ gtk_menu_popup_internal (GtkMenu *menu,
else
pointer = device;
g_return_if_fail (gdk_device_get_display (pointer) == display);
menu_shell->priv->parent_menu_shell = parent_menu_shell;
/* Find the last viewable ancestor, and make an X grab on it
@@ -1437,7 +1445,7 @@ gtk_menu_popup_internal (GtkMenu *menu,
parent_toplevel = NULL;
if (parent_menu_shell)
parent_toplevel = gtk_widget_get_toplevel (parent_menu_shell);
else if (!g_object_get_data (G_OBJECT (menu), "gtk-menu-explicit-display"))
else
{
GtkWidget *attach_widget = gtk_menu_get_attach_widget (menu);
if (attach_widget)
@@ -3604,35 +3612,6 @@ gtk_menu_select_item (GtkMenuShell *menu_shell,
GTK_MENU_SHELL_CLASS (gtk_menu_parent_class)->select_item (menu_shell, menu_item);
}
/**
* gtk_menu_set_display:
* @menu: a #GtkMenu
* @display: (allow-none): a #GdkDisplay, or %NULL if the display should be
* determined by the widget the menu is attached to
*
* Sets the #GdkDisplay on which the menu will be displayed.
*/
void
gtk_menu_set_display (GtkMenu *menu,
GdkDisplay *display)
{
g_return_if_fail (GTK_IS_MENU (menu));
g_return_if_fail (display == NULL || GDK_IS_DISPLAY (display));
g_object_set_data (G_OBJECT (menu), I_("gtk-menu-explicit-display"), display);
if (display)
{
menu_change_display (menu, display);
}
else
{
GtkWidget *attach_widget = gtk_menu_get_attach_widget (menu);
if (attach_widget)
attach_widget_display_changed (attach_widget, NULL, menu);
}
}
static gint
gtk_menu_get_popup_delay (GtkMenuShell *menu_shell)
{
-4
View File
@@ -172,10 +172,6 @@ void gtk_menu_reorder_child (GtkMenu *menu,
GtkWidget *child,
gint position);
GDK_AVAILABLE_IN_ALL
void gtk_menu_set_display (GtkMenu *menu,
GdkDisplay *display);
GDK_AVAILABLE_IN_ALL
void gtk_menu_set_monitor (GtkMenu *menu,
gint monitor_num);
+5 -5
View File
@@ -118,8 +118,7 @@ static gboolean gtk_menu_shell_key_press (GtkEventControllerKey *key,
guint keycode,
GdkModifierType modifiers,
GtkWidget *widget);
static void gtk_menu_shell_display_changed (GtkWidget *widget,
GdkDisplay *previous_display);
static void gtk_menu_shell_root (GtkWidget *widget);
static void multi_press_pressed (GtkGestureMultiPress *gesture,
gint n_press,
gdouble x,
@@ -188,7 +187,7 @@ gtk_menu_shell_class_init (GtkMenuShellClass *klass)
object_class->finalize = gtk_menu_shell_finalize;
object_class->dispose = gtk_menu_shell_dispose;
widget_class->display_changed = gtk_menu_shell_display_changed;
widget_class->root = gtk_menu_shell_root;
container_class->add = gtk_menu_shell_add;
container_class->remove = gtk_menu_shell_remove;
@@ -945,9 +944,10 @@ gtk_menu_shell_key_press (GtkEventControllerKey *key,
}
static void
gtk_menu_shell_display_changed (GtkWidget *widget,
GdkDisplay *previous_display)
gtk_menu_shell_root (GtkWidget *widget)
{
GTK_WIDGET_CLASS (gtk_menu_shell_parent_class)->root (widget);
gtk_menu_shell_reset_key_hash (GTK_MENU_SHELL (widget));
}
+1 -1
View File
@@ -455,7 +455,7 @@ pw_dialog_cycle_focus (GtkWidget *widget,
if (next_widget)
gtk_widget_grab_focus (next_widget);
else if (pw_dialog_input_is_valid (operation))
gtk_window_activate_default (GTK_WINDOW (priv->dialog));
gtk_widget_activate_default (widget);
}
static GtkWidget *
+1 -1
View File
@@ -446,7 +446,7 @@ gtk_password_entry_new (void)
/**
* gtk_password_entry_set_show_peek_icon:
* @entry: a #GtkPasswordEntry
* show_peek_icon: whether to show the peek icon
* @show_peek_icon: whether to show the peek icon
*
* Sets whether the entry should have a clickable icon
* to show the contents of the entry in clear text.
+14 -11
View File
@@ -151,8 +151,8 @@ static gboolean gtk_path_bar_slider_down_defocus (GtkWidget *widget,
GdkEventButton *event,
GtkPathBar *path_bar);
static void gtk_path_bar_style_updated (GtkWidget *widget);
static void gtk_path_bar_display_changed (GtkWidget *widget,
GdkDisplay *previous_display);
static void gtk_path_bar_root (GtkWidget *widget);
static void gtk_path_bar_unroot (GtkWidget *widget);
static void gtk_path_bar_check_icon_theme (GtkPathBar *path_bar);
static void gtk_path_bar_update_button_appearance (GtkPathBar *path_bar,
ButtonData *button_data,
@@ -273,7 +273,8 @@ gtk_path_bar_class_init (GtkPathBarClass *path_bar_class)
widget_class->measure = gtk_path_bar_measure;
widget_class->size_allocate = gtk_path_bar_size_allocate;
widget_class->style_updated = gtk_path_bar_style_updated;
widget_class->display_changed = gtk_path_bar_display_changed;
widget_class->root = gtk_path_bar_root;
widget_class->unroot = gtk_path_bar_unroot;
container_class->add = gtk_path_bar_add;
container_class->forall = gtk_path_bar_forall;
@@ -729,19 +730,21 @@ gtk_path_bar_style_updated (GtkWidget *widget)
}
static void
gtk_path_bar_display_changed (GtkWidget *widget,
GdkDisplay *previous_display)
gtk_path_bar_root (GtkWidget *widget)
{
if (GTK_WIDGET_CLASS (gtk_path_bar_parent_class)->display_changed)
GTK_WIDGET_CLASS (gtk_path_bar_parent_class)->display_changed (widget, previous_display);
/* We might nave a new settings, so we remove the old one */
if (previous_display)
remove_settings_signal (GTK_PATH_BAR (widget), previous_display);
GTK_WIDGET_CLASS (gtk_path_bar_parent_class)->root (widget);
gtk_path_bar_check_icon_theme (GTK_PATH_BAR (widget));
}
static void
gtk_path_bar_unroot (GtkWidget *widget)
{
remove_settings_signal (GTK_PATH_BAR (widget), gtk_widget_get_display (widget));
GTK_WIDGET_CLASS (gtk_path_bar_parent_class)->unroot (widget);
}
static gboolean
gtk_path_bar_scroll_controller_scroll (GtkEventControllerScroll *scroll,
gdouble dx,
-1
View File
@@ -2688,7 +2688,6 @@ create_rename_popover (GtkPlacesSidebar *sidebar)
gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
g_free (str);
button = gtk_button_new_with_mnemonic (_("_Rename"));
gtk_widget_set_can_default (button, TRUE);
gtk_style_context_add_class (gtk_widget_get_style_context (button), "suggested-action");
g_signal_connect (button, "clicked", G_CALLBACK (do_rename), sidebar);
error = gtk_label_new ("");
+56 -4
View File
@@ -155,6 +155,7 @@ enum {
PROP_POSITION,
PROP_MODAL,
PROP_CONSTRAIN_TO,
PROP_DEFAULT_WIDGET,
NUM_PROPERTIES
};
@@ -345,6 +346,40 @@ gesture_released (GtkGestureMultiPress *gesture,
gtk_popover_popdown (popover);
}
static void
activate_default_cb (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
GtkPopover *popover = data;
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
GtkWidget *focus_widget;
focus_widget = gtk_window_get_focus (GTK_WINDOW (gtk_widget_get_root (priv->widget)));
if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
(!focus_widget || !gtk_widget_get_receives_default (focus_widget)))
gtk_widget_activate (priv->default_widget);
else if (focus_widget && gtk_widget_is_sensitive (focus_widget))
gtk_widget_activate (focus_widget);
}
static void
add_actions (GtkPopover *popover)
{
GActionEntry entries[] = {
{ "activate", activate_default_cb, NULL, NULL, NULL },
};
GActionGroup *actions;
actions = G_ACTION_GROUP (g_simple_action_group_new ());
g_action_map_add_action_entries (G_ACTION_MAP (actions),
entries, G_N_ELEMENTS (entries),
popover);
gtk_widget_insert_action_group (GTK_WIDGET (popover), "default", actions);
g_object_unref (actions);
}
static void
gtk_popover_init (GtkPopover *popover)
{
@@ -389,6 +424,8 @@ gtk_popover_init (GtkPopover *popover)
g_signal_connect (controller, "released",
G_CALLBACK (gesture_released), popover);
gtk_widget_add_controller (widget, controller);
add_actions (popover);
}
static void
@@ -419,6 +456,10 @@ gtk_popover_set_property (GObject *object,
gtk_popover_set_constrain_to (GTK_POPOVER (object),
g_value_get_enum (value));
break;
case PROP_DEFAULT_WIDGET:
gtk_popover_set_default_widget (GTK_POPOVER (object),
g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -449,6 +490,9 @@ gtk_popover_get_property (GObject *object,
case PROP_CONSTRAIN_TO:
g_value_set_enum (value, priv->constraint);
break;
case PROP_DEFAULT_WIDGET:
g_value_set_object (value, priv->default_widget);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -818,7 +862,7 @@ gtk_popover_map (GtkWidget *widget)
gdk_surface_show (gtk_widget_get_surface (widget));
gtk_popover_update_position (GTK_POPOVER (widget));
gtk_window_set_default (priv->window, priv->default_widget);
gtk_window_set_default_widget (priv->window, priv->default_widget);
}
static void
@@ -832,7 +876,7 @@ gtk_popover_unmap (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_popover_parent_class)->unmap (widget);
if (gtk_window_get_default_widget (priv->window) == priv->default_widget)
gtk_window_set_default (priv->window, priv->prev_default);
gtk_window_set_default_widget (priv->window, priv->prev_default);
g_clear_object (&priv->prev_default);
}
@@ -1645,6 +1689,13 @@ gtk_popover_class_init (GtkPopoverClass *klass)
GTK_TYPE_POPOVER_CONSTRAINT, GTK_POPOVER_CONSTRAINT_WINDOW,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
properties[PROP_DEFAULT_WIDGET] =
g_param_spec_object ("default-widget",
P_("Default widget"),
P_("The default widget"),
GTK_TYPE_WIDGET,
GTK_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
/**
@@ -2378,7 +2429,6 @@ gtk_popover_set_default_widget (GtkPopover *popover,
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
g_return_if_fail (GTK_IS_POPOVER (popover));
g_return_if_fail (widget == NULL || gtk_widget_get_can_default (widget));
if (priv->default_widget == widget)
return;
@@ -2392,7 +2442,9 @@ gtk_popover_set_default_widget (GtkPopover *popover,
g_object_ref (priv->default_widget);
if (gtk_widget_get_mapped (GTK_WIDGET (popover)))
gtk_window_set_default (priv->window, priv->default_widget);
gtk_window_set_default_widget (priv->window, priv->default_widget);
g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_DEFAULT_WIDGET]);
}
/**
+10
View File
@@ -611,6 +611,16 @@ gtk_snapshot_ensure_identity (GtkSnapshot *snapshot)
gtk_snapshot_autopush_transform (snapshot);
}
/**
* gtk_snapshot_push_repeat:
* @snapshot: a #GtkSnapshot
* @bounds: the bounds within which to repeat
* @child_bounds: the bounds of the child
*
* Creates a node that repeats the child node.
*
* The child is recorded until the next call to gtk_snapshot_pop().
*/
void
gtk_snapshot_push_repeat (GtkSnapshot *snapshot,
const graphene_rect_t *bounds,
+10
View File
@@ -809,6 +809,14 @@ button_released_cb (GtkGestureMultiPress *gesture,
}
}
static void
button_cancel_cb (GtkGesture *gesture,
GdkEventSequence *sequence,
GtkSpinButton *spin_button)
{
gtk_spin_button_stop_spinning (spin_button);
}
static void
key_controller_key_released (GtkEventControllerKey *key,
guint keyval,
@@ -886,6 +894,7 @@ gtk_spin_button_init (GtkSpinButton *spin_button)
GTK_PHASE_CAPTURE);
g_signal_connect (gesture, "pressed", G_CALLBACK (button_pressed_cb), spin_button);
g_signal_connect (gesture, "released", G_CALLBACK (button_released_cb), spin_button);
g_signal_connect (gesture, "cancel", G_CALLBACK (button_cancel_cb), spin_button);
gtk_widget_add_controller (GTK_WIDGET (priv->down_button), GTK_EVENT_CONTROLLER (gesture));
priv->up_button = gtk_button_new ();
@@ -902,6 +911,7 @@ gtk_spin_button_init (GtkSpinButton *spin_button)
GTK_PHASE_CAPTURE);
g_signal_connect (gesture, "pressed", G_CALLBACK (button_pressed_cb), spin_button);
g_signal_connect (gesture, "released", G_CALLBACK (button_released_cb), spin_button);
g_signal_connect (gesture, "cancel", G_CALLBACK (button_cancel_cb), spin_button);
gtk_widget_add_controller (GTK_WIDGET (priv->up_button), GTK_EVENT_CONTROLLER (gesture));
gtk_spin_button_set_adjustment (spin_button, NULL);
+26 -28
View File
@@ -324,8 +324,7 @@ static void gtk_text_direction_changed (GtkWidget *widget,
GtkTextDirection previous_dir);
static void gtk_text_state_flags_changed (GtkWidget *widget,
GtkStateFlags previous_state);
static void gtk_text_display_changed (GtkWidget *widget,
GdkDisplay *old_display);
static void gtk_text_root (GtkWidget *widget);
static gboolean gtk_text_drag_drop (GtkWidget *widget,
GdkDrop *drop,
@@ -679,7 +678,7 @@ gtk_text_class_init (GtkTextClass *class)
widget_class->drag_end = gtk_text_drag_end;
widget_class->direction_changed = gtk_text_direction_changed;
widget_class->state_flags_changed = gtk_text_state_flags_changed;
widget_class->display_changed = gtk_text_display_changed;
widget_class->root = gtk_text_root;
widget_class->mnemonic_activate = gtk_text_mnemonic_activate;
widget_class->popup_menu = gtk_text_popup_menu;
widget_class->drag_drop = gtk_text_drag_drop;
@@ -3029,9 +3028,10 @@ gtk_text_state_flags_changed (GtkWidget *widget,
}
static void
gtk_text_display_changed (GtkWidget *widget,
GdkDisplay *old_display)
gtk_text_root (GtkWidget *widget)
{
GTK_WIDGET_CLASS (gtk_text_parent_class)->root (widget);
gtk_text_recompute (GTK_TEXT (widget));
}
@@ -3839,30 +3839,9 @@ static void
gtk_text_real_activate (GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GtkWindow *window;
GtkWidget *default_widget, *focus_widget;
GtkWidget *toplevel;
GtkWidget *widget;
widget = GTK_WIDGET (self);
if (priv->activates_default)
{
toplevel = gtk_widget_get_toplevel (widget);
if (GTK_IS_WINDOW (toplevel))
{
window = GTK_WINDOW (toplevel);
if (window)
{
default_widget = gtk_window_get_default_widget (window);
focus_widget = gtk_root_get_focus (GTK_ROOT (window));
if (widget != default_widget &&
!(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget))))
gtk_window_activate_default (window);
}
}
}
gtk_widget_activate_default (GTK_WIDGET (self));
}
static void
@@ -6617,9 +6596,25 @@ gtk_text_get_tabs (GtkText *self)
return priv->tabs;
}
static void
emoji_picked (GtkEmojiChooser *chooser,
const char *text,
GtkText *self)
{
int current_pos;
int selection_bound;
current_pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (chooser), "current-pos"));
selection_bound = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (chooser), "selection-bound"));
gtk_text_set_positions (self, current_pos, selection_bound);
gtk_text_enter_text (self, text);
}
static void
gtk_text_insert_emoji (GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GtkWidget *chooser;
if (gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_EMOJI_CHOOSER) != NULL)
@@ -6632,9 +6627,12 @@ gtk_text_insert_emoji (GtkText *self)
g_object_set_data (G_OBJECT (self), "gtk-emoji-chooser", chooser);
gtk_popover_set_relative_to (GTK_POPOVER (chooser), GTK_WIDGET (self));
g_signal_connect_swapped (chooser, "emoji-picked", G_CALLBACK (gtk_text_enter_text), self);
g_signal_connect (chooser, "emoji-picked", G_CALLBACK (emoji_picked), self);
}
g_object_set_data (G_OBJECT (chooser), "current-pos", GINT_TO_POINTER (priv->current_pos));
g_object_set_data (G_OBJECT (chooser), "selection-bound", GINT_TO_POINTER (priv->selection_bound));
gtk_popover_popup (GTK_POPOVER (chooser));
}
+1 -2
View File
@@ -38,8 +38,7 @@ typedef struct _GtkTextClass GtkTextClass;
* non-%NULL, this will be called to add additional entries to the context
* menu when it is displayed.
* @activate: Class handler for the #GtkText::activate signal. The default
* implementation calls gtk_window_activate_default() on the entrys top-level
* window.
* implementation activates the gtk.activate-default action.
* @move_cursor: Class handler for the #GtkText::move-cursor signal. The
* default implementation specifies the standard #GtkText cursor movement
* behavior.
+1 -1
View File
@@ -201,7 +201,7 @@ limit_layout_lines (PangoLayout *layout)
GdkPaintable *
gtk_text_util_create_drag_icon (GtkWidget *widget,
gchar *text,
gsize len)
gssize len)
{
GtkStyleContext *style_context;
GtkSnapshot *snapshot;
+1 -1
View File
@@ -40,7 +40,7 @@ void _gtk_text_util_append_special_char_menuitems (GtkMenuShell *me
GdkPaintable * gtk_text_util_create_drag_icon (GtkWidget *widget,
gchar *text,
gsize len);
gssize len);
GdkPaintable * gtk_text_util_create_rich_drag_icon (GtkWidget *widget,
GtkTextBuffer *buffer,
GtkTextIter *start,
+27 -27
View File
@@ -186,8 +186,8 @@ static gboolean gtk_toolbar_focus (GtkWidget *widget,
GtkDirectionType dir);
static void gtk_toolbar_move_focus (GtkWidget *widget,
GtkDirectionType dir);
static void gtk_toolbar_display_changed (GtkWidget *widget,
GdkDisplay *previous_display);
static void gtk_toolbar_root (GtkWidget *widget);
static void gtk_toolbar_unroot (GtkWidget *widget);
static void gtk_toolbar_finalize (GObject *object);
static void gtk_toolbar_dispose (GObject *object);
static void gtk_toolbar_add (GtkContainer *container,
@@ -362,7 +362,8 @@ gtk_toolbar_class_init (GtkToolbarClass *klass)
GTK_TYPE_TOOLBAR,
G_CALLBACK (gtk_toolbar_move_focus));
widget_class->display_changed = gtk_toolbar_display_changed;
widget_class->root = gtk_toolbar_root;
widget_class->unroot = gtk_toolbar_unroot;
widget_class->popup_menu = gtk_toolbar_popup_menu;
container_class->add = gtk_toolbar_add;
@@ -1645,41 +1646,40 @@ settings_change_notify (GtkSettings *settings,
}
static void
gtk_toolbar_display_changed (GtkWidget *widget,
GdkDisplay *previous_display)
gtk_toolbar_root (GtkWidget *widget)
{
GtkToolbar *toolbar = GTK_TOOLBAR (widget);
GtkToolbarPrivate *priv = toolbar->priv;
GtkSettings *old_settings = toolbar_get_settings (toolbar);
GtkSettings *settings;
GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->root (widget);
settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
if (settings == old_settings)
return;
if (old_settings)
{
g_signal_handler_disconnect (old_settings, priv->settings_connection);
priv->settings_connection = 0;
g_object_unref (old_settings);
}
if (settings)
{
priv->settings_connection =
g_signal_connect (settings, "notify",
G_CALLBACK (settings_change_notify),
toolbar);
priv->settings_connection =
g_signal_connect (settings, "notify",
G_CALLBACK (settings_change_notify),
toolbar);
priv->settings = g_object_ref (settings);
}
else
priv->settings = NULL;
priv->settings = g_object_ref (settings);
animation_change_notify (toolbar);
}
static void
gtk_toolbar_unroot (GtkWidget *widget)
{
GtkToolbar *toolbar = GTK_TOOLBAR (widget);
GtkToolbarPrivate *priv = toolbar->priv;
if (priv->settings_connection)
g_signal_handler_disconnect (priv->settings, priv->settings_connection);
priv->settings_connection = 0;
g_clear_object (&priv->settings);
GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unroot (widget);
}
static int
find_drop_index (GtkToolbar *toolbar,
gint x,
-3
View File
@@ -689,8 +689,6 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
{
gint tx, ty;
surface = tooltip->last_surface;
if (!GDK_IS_SURFACE (surface))
@@ -702,7 +700,6 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
x = round (px);
y = round (py);
gdk_surface_get_root_coords (surface, x, y, &tx, &ty);
tooltip_widget = _gtk_widget_find_at_coords (surface, x, y, &x, &y);
}
+3 -59
View File
@@ -398,11 +398,6 @@ struct _GtkTreeViewPrivate
gint drag_pos;
gint x_drag;
/* Non-interactive Header Resizing, expand flag support */
gint last_extra_space;
gint last_extra_space_per_column;
gint last_number_of_expand_columns;
/* Row drag-and-drop */
GtkTreeRowReference *drag_dest_row;
GtkTreeViewDropPosition drag_dest_pos;
@@ -502,8 +497,6 @@ struct _GtkTreeViewPrivate
guint in_grab : 1;
guint post_validation_flag : 1;
/* Whether our key press handler is to avoid sending an unhandled binding to the search entry */
guint search_entry_avoid_unhandled_binding : 1;
@@ -1704,8 +1697,6 @@ gtk_tree_view_init (GtkTreeView *tree_view)
priv->tooltip_column = -1;
priv->post_validation_flag = FALSE;
priv->event_last_x = -10000;
priv->event_last_y = -10000;
@@ -2397,11 +2388,10 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
GList *list, *first_column, *last_column;
GtkTreeViewColumn *column;
gint widget_width, width = 0;
gint extra, extra_per_column, extra_for_last;
gint extra, extra_per_column;
gint full_requested_width = 0;
gint number_of_expand_columns = 0;
gboolean rtl;
gboolean update_expand;
for (last_column = g_list_last (tree_view->priv->columns);
last_column &&
@@ -2436,41 +2426,14 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
number_of_expand_columns++;
}
/* Only update the expand value if the number of expand columns has changed,
* or if there are no expand columns, or if we didn't have an size-allocation
* yet after the last validated node.
*/
update_expand = number_of_expand_columns != tree_view->priv->last_number_of_expand_columns
|| number_of_expand_columns == 0
|| tree_view->priv->post_validation_flag == TRUE;
tree_view->priv->post_validation_flag = FALSE;
widget_width = gtk_widget_get_width (widget);
if (!update_expand)
{
extra = tree_view->priv->last_extra_space;
extra_for_last = MAX (widget_width - full_requested_width - extra, 0);
}
else
{
extra = MAX (widget_width - full_requested_width, 0);
extra_for_last = 0;
tree_view->priv->last_extra_space = extra;
}
extra = MAX (widget_width - full_requested_width, 0);
if (number_of_expand_columns > 0)
extra_per_column = extra/number_of_expand_columns;
else
extra_per_column = 0;
if (update_expand)
{
tree_view->priv->last_extra_space_per_column = extra_per_column;
tree_view->priv->last_number_of_expand_columns = number_of_expand_columns;
}
for (list = first_column;
list != last_column->next;
list = list->next)
@@ -2507,12 +2470,6 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
column_width += extra;
}
/* In addition to expand, the last column can get even more
* extra space so all available space is filled up.
*/
if (extra_for_last > 0 && list == last_column)
column_width += extra_for_last;
if (rtl)
_gtk_tree_view_column_allocate (column, widget_width - width - column_width + x_offset,
column_width, tree_view->priv->header_height);
@@ -2527,10 +2484,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
* which changes the total width of the tree view. This is of
* importance for getting the horizontal scroll bar right.
*/
if (tree_view->priv->width != width)
{
tree_view->priv->width = width;
}
tree_view->priv->width = width;
}
/* GtkWidget::size_allocate helper */
@@ -5686,7 +5640,6 @@ validate_row (GtkTreeView *tree_view,
gtk_tree_rbtree_node_set_height (tree, node, height);
}
gtk_tree_rbtree_node_mark_valid (tree, node);
tree_view->priv->post_validation_flag = TRUE;
return retval;
}
@@ -9441,16 +9394,12 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
GtkTreeRBTree *new_cursor_tree = NULL;
GtkTreeRBNode *new_cursor_node = NULL;
GtkTreePath *cursor_path = NULL;
gboolean grab_focus = TRUE;
gboolean selectable;
GtkDirectionType direction;
GtkCellArea *cell_area = NULL;
GtkCellRenderer *last_focus_cell = NULL;
GtkTreeIter iter;
if (! gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return;
if (tree_view->priv->cursor_node == NULL)
return;
@@ -9576,8 +9525,6 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
count < 0 ?
GTK_DIR_TAB_BACKWARD :
GTK_DIR_TAB_FORWARD);
grab_focus = FALSE;
}
}
else
@@ -9588,9 +9535,6 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
if (cell_area)
gtk_cell_area_set_focus_cell (cell_area, last_focus_cell);
}
if (grab_focus)
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
}
static void
+89 -267
View File
@@ -548,7 +548,6 @@ enum {
PROP_IS_FOCUS,
PROP_CAN_TARGET,
PROP_FOCUS_ON_CLICK,
PROP_CAN_DEFAULT,
PROP_HAS_DEFAULT,
PROP_RECEIVES_DEFAULT,
PROP_CURSOR,
@@ -633,8 +632,6 @@ static void gtk_widget_real_move_focus (GtkWidget
GtkDirectionType direction);
static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
GtkDirectionType direction);
static void gtk_widget_root (GtkWidget *widget);
static void gtk_widget_unroot (GtkWidget *widget);
#ifdef G_ENABLE_CONSISTENCY_CHECKS
static void gtk_widget_verify_invariants (GtkWidget *widget);
static void gtk_widget_push_verify_invariants (GtkWidget *widget);
@@ -676,10 +673,6 @@ static const gchar * gtk_widget_buildable_get_name (GtkBuildable
static GObject * gtk_widget_buildable_get_internal_child (GtkBuildable *buildable,
GtkBuilder *builder,
const gchar *childname);
static void gtk_widget_buildable_set_buildable_property (GtkBuildable *buildable,
GtkBuilder *builder,
const gchar *name,
const GValue *value);
static gboolean gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
@@ -923,7 +916,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->drag_motion = NULL;
klass->drag_drop = NULL;
klass->drag_data_received = NULL;
klass->display_changed = NULL;
klass->can_activate_accel = gtk_widget_real_can_activate_accel;
klass->query_tooltip = gtk_widget_real_query_tooltip;
klass->style_updated = gtk_widget_real_style_updated;
@@ -1037,19 +1029,12 @@ gtk_widget_class_init (GtkWidgetClass *klass)
TRUE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
widget_props[PROP_CAN_DEFAULT] =
g_param_spec_boolean ("can-default",
P_("Can default"),
P_("Whether the widget can be the default widget"),
FALSE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
widget_props[PROP_HAS_DEFAULT] =
g_param_spec_boolean ("has-default",
P_("Has default"),
P_("Whether the widget is the default widget"),
FALSE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY);
widget_props[PROP_RECEIVES_DEFAULT] =
g_param_spec_boolean ("receives-default",
@@ -2089,25 +2074,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
NULL,
G_TYPE_NONE, 0);
/**
* GtkWidget::display-changed:
* @widget: the object on which the signal is emitted
* @previous_display: (allow-none): the previous screen, or %NULL if the
* widget was not associated with a screen before
*
* The ::display-changed signal gets emitted when the
* display of a widget has changed.
*/
widget_signals[DISPLAY_CHANGED] =
g_signal_new (I_("display-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, display_changed),
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
GDK_TYPE_DISPLAY);
/**
* GtkWidget::can-activate-accel:
* @widget: the object which received the signal
@@ -2194,13 +2160,6 @@ gtk_widget_set_property (GObject *object,
case PROP_FOCUS_ON_CLICK:
gtk_widget_set_focus_on_click (widget, g_value_get_boolean (value));
break;
case PROP_CAN_DEFAULT:
gtk_widget_set_can_default (widget, g_value_get_boolean (value));
break;
case PROP_HAS_DEFAULT:
if (g_value_get_boolean (value))
gtk_widget_grab_default (widget);
break;
case PROP_RECEIVES_DEFAULT:
gtk_widget_set_receives_default (widget, g_value_get_boolean (value));
break;
@@ -2375,9 +2334,6 @@ gtk_widget_get_property (GObject *object,
case PROP_FOCUS_ON_CLICK:
g_value_set_boolean (value, gtk_widget_get_focus_on_click (widget));
break;
case PROP_CAN_DEFAULT:
g_value_set_boolean (value, gtk_widget_get_can_default (widget));
break;
case PROP_HAS_DEFAULT:
g_value_set_boolean (value, gtk_widget_has_default (widget));
break;
@@ -2887,21 +2843,22 @@ gtk_widget_new (GType type,
return widget;
}
static void
void
gtk_widget_root (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
/* roots are rooted by default */
if (GTK_IS_ROOT (widget))
return;
g_assert (priv->root == NULL);
g_assert (!priv->realized);
g_assert (priv->parent);
g_assert (priv->parent->priv->root);
priv->root = priv->parent->priv->root;
if (GTK_IS_ROOT (widget))
{
g_assert (priv->root == GTK_ROOT (widget));
}
else
{
g_assert (priv->root == NULL);
priv->root = priv->parent->priv->root;
}
if (priv->context)
gtk_style_context_set_display (priv->context, gtk_root_get_display (priv->root));
@@ -2911,19 +2868,16 @@ gtk_widget_root (GtkWidget *widget)
GTK_WIDGET_GET_CLASS (widget)->root (widget);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_ROOT]);
if (!GTK_IS_ROOT (widget))
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_ROOT]);
}
static void
void
gtk_widget_unroot (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkWidgetSurfaceTransformData *surface_transform_data;
/* roots are rooted by default and cannot be unrooted */
if (GTK_IS_ROOT (widget))
return;
g_assert (priv->root);
g_assert (!priv->realized);
@@ -2937,9 +2891,16 @@ gtk_widget_unroot (GtkWidget *widget)
if (priv->context)
gtk_style_context_set_display (priv->context, gdk_display_get_default ());
priv->root = NULL;
if (g_object_get_qdata (G_OBJECT (widget), quark_pango_context))
g_object_set_qdata (G_OBJECT (widget), quark_pango_context, NULL);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_ROOT]);
_gtk_tooltip_hide (widget);
if (!GTK_IS_ROOT (widget))
{
priv->root = NULL;
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_ROOT]);
}
}
/**
@@ -5478,7 +5439,8 @@ static void
gtk_widget_real_grab_focus (GtkWidget *focus_widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (focus_widget);
gtk_root_set_focus (priv->root, focus_widget);
if (priv->root)
gtk_root_set_focus (priv->root, focus_widget);
}
static gboolean
@@ -5818,58 +5780,12 @@ gtk_widget_get_focus_on_click (GtkWidget *widget)
return priv->focus_on_click;
}
/**
* gtk_widget_set_can_default:
* @widget: a #GtkWidget
* @can_default: whether or not @widget can be a default widget.
*
* Specifies whether @widget can be a default widget. See
* gtk_widget_grab_default() for details about the meaning of
* default.
**/
void
gtk_widget_set_can_default (GtkWidget *widget,
gboolean can_default)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
g_return_if_fail (GTK_IS_WIDGET (widget));
if (priv->can_default != can_default)
{
priv->can_default = can_default;
gtk_widget_queue_resize (widget);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_CAN_DEFAULT]);
}
}
/**
* gtk_widget_get_can_default:
* @widget: a #GtkWidget
*
* Determines whether @widget can be a default widget. See
* gtk_widget_set_can_default().
*
* Returns: %TRUE if @widget can be a default widget, %FALSE otherwise
**/
gboolean
gtk_widget_get_can_default (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
return priv->can_default;
}
/**
* gtk_widget_has_default:
* @widget: a #GtkWidget
*
* Determines whether @widget is the current default widget within its
* toplevel. See gtk_widget_set_can_default().
* toplevel.
*
* Returns: %TRUE if @widget is the current default widget within
* its toplevel, %FALSE otherwise
@@ -5901,47 +5817,14 @@ _gtk_widget_set_has_default (GtkWidget *widget,
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_DEFAULT);
}
/**
* gtk_widget_grab_default:
* @widget: a #GtkWidget
*
* Causes @widget to become the default widget. @widget must be able to be
* a default widget; typically you would ensure this yourself
* by calling gtk_widget_set_can_default() with a %TRUE value.
* The default widget is activated when
* the user presses Enter in a window. Default widgets must be
* activatable, that is, gtk_widget_activate() should affect them. Note
* that #GtkEntry widgets require the activates-default property
* set to %TRUE before they activate the default widget when Enter
* is pressed and the #GtkEntry is focused.
**/
void
gtk_widget_grab_default (GtkWidget *widget)
{
GtkWidget *window;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (gtk_widget_get_can_default (widget));
window = _gtk_widget_get_toplevel (widget);
if (window && _gtk_widget_is_toplevel (window))
gtk_window_set_default (GTK_WINDOW (window), widget);
else
g_warning (G_STRLOC ": widget not within a GtkWindow");
}
/**
* gtk_widget_set_receives_default:
* @widget: a #GtkWidget
* @receives_default: whether or not @widget can be a default widget.
*
* Specifies whether @widget will be treated as the default widget
* within its toplevel when it has the focus, even if another widget
* is the default.
*
* See gtk_widget_grab_default() for details about the meaning of
* default.
* Specifies whether @widget will be treated as the default
* widget within its toplevel when it has the focus, even if
* another widget is the default.
**/
void
gtk_widget_set_receives_default (GtkWidget *widget,
@@ -6480,6 +6363,7 @@ gtk_widget_set_sensitive (GtkWidget *widget,
gboolean sensitive)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l;
g_return_if_fail (GTK_IS_WIDGET (widget));
@@ -6490,6 +6374,13 @@ gtk_widget_set_sensitive (GtkWidget *widget,
priv->sensitive = sensitive;
for (l = priv->event_controllers; l; l = l->next)
{
GtkEventController *controller = l->data;
gtk_event_controller_reset (controller);
}
if (priv->parent == NULL
|| gtk_widget_is_sensitive (priv->parent))
{
@@ -6791,84 +6682,6 @@ gtk_widget_real_direction_changed (GtkWidget *widget,
gtk_widget_queue_resize (widget);
}
typedef struct {
GtkWidget *previous_toplevel;
GdkDisplay *previous_display;
GdkDisplay *new_display;
} HierarchyChangedInfo;
static void
do_display_change (GtkWidget *widget,
GdkDisplay *old_display,
GdkDisplay *new_display)
{
if (old_display != new_display)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
if (old_display)
{
PangoContext *context = g_object_get_qdata (G_OBJECT (widget), quark_pango_context);
if (context)
g_object_set_qdata (G_OBJECT (widget), quark_pango_context, NULL);
}
_gtk_tooltip_hide (widget);
if (new_display && priv->context)
gtk_style_context_set_display (priv->context, new_display);
g_signal_emit (widget, widget_signals[DISPLAY_CHANGED], 0, old_display);
}
}
static void
gtk_widget_propagate_display_changed_recurse (GtkWidget *widget,
gpointer client_data)
{
HierarchyChangedInfo *info = client_data;
GtkWidget *child;
g_object_ref (widget);
do_display_change (widget, info->previous_display, info->new_display);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
gtk_widget_propagate_display_changed_recurse (child, client_data);
}
g_object_unref (widget);
}
/**
* _gtk_widget_propagate_display_changed:
* @widget: a #GtkWidget
* @previous_display: Previous display
*
* Propagates changes in the display for a widget to all
* children, emitting #GtkWidget::display-changed.
**/
void
_gtk_widget_propagate_display_changed (GtkWidget *widget,
GdkDisplay *previous_display)
{
HierarchyChangedInfo info;
info.previous_display = previous_display;
info.new_display = gtk_widget_get_display (widget);
if (previous_display)
g_object_ref (previous_display);
gtk_widget_propagate_display_changed_recurse (widget, &info);
if (previous_display)
g_object_unref (previous_display);
}
static void
reset_style_recurse (GtkWidget *widget, gpointer user_data)
{
@@ -6926,17 +6739,17 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (!priv->realized)
g_warning ("%s %p is mapped but not realized",
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (widget), widget);
if (!priv->visible)
g_warning ("%s %p is mapped but not visible",
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (widget), widget);
if (!GTK_IS_ROOT (widget))
{
if (!priv->child_visible)
g_warning ("%s %p is mapped but not child_visible",
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (widget), widget);
}
}
else
@@ -6986,8 +6799,8 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (priv->realized)
g_warning ("%s %p is not realized but child %s %p is realized",
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
G_OBJECT_TYPE_NAME (widget), widget);
parent ? gtk_widget_get_name (parent) : "no parent", parent,
gtk_widget_get_name (widget), widget);
}
if (parent &&
@@ -6999,8 +6812,8 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (!priv->mapped)
g_warning ("%s %p is mapped but visible child %s %p is not mapped",
G_OBJECT_TYPE_NAME (parent), parent,
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (parent), parent,
gtk_widget_get_name (widget), widget);
}
else if (!GTK_IS_ROOT (widget))
{
@@ -7008,10 +6821,10 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (priv->mapped)
g_warning ("%s %p is mapped but visible=%d child_visible=%d parent %s %p mapped=%d",
G_OBJECT_TYPE_NAME (widget), widget,
gtk_widget_get_name (widget), widget,
priv->visible,
priv->child_visible,
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
parent ? gtk_widget_get_name (parent) : "no parent", parent,
parent ? parent->priv->mapped : FALSE);
}
}
@@ -9589,8 +9402,6 @@ gtk_widget_set_vexpand_set (GtkWidget *widget,
/*
* GtkBuildable implementation
*/
static GQuark quark_builder_has_default = 0;
static GQuark quark_builder_has_focus = 0;
static GQuark quark_builder_atk_relations = 0;
static GQuark quark_builder_set_name = 0;
@@ -9622,15 +9433,12 @@ gtk_widget_buildable_add_child (GtkBuildable *buildable,
static void
gtk_widget_buildable_interface_init (GtkBuildableIface *iface)
{
quark_builder_has_default = g_quark_from_static_string ("gtk-builder-has-default");
quark_builder_has_focus = g_quark_from_static_string ("gtk-builder-has-focus");
quark_builder_atk_relations = g_quark_from_static_string ("gtk-builder-atk-relations");
quark_builder_set_name = g_quark_from_static_string ("gtk-builder-set-name");
iface->set_name = gtk_widget_buildable_set_name;
iface->get_name = gtk_widget_buildable_get_name;
iface->get_internal_child = gtk_widget_buildable_get_internal_child;
iface->set_buildable_property = gtk_widget_buildable_set_buildable_property;
iface->parser_finished = gtk_widget_buildable_parser_finished;
iface->custom_tag_start = gtk_widget_buildable_custom_tag_start;
iface->custom_tag_end = gtk_widget_buildable_custom_tag_end;
@@ -9695,22 +9503,6 @@ gtk_widget_buildable_get_internal_child (GtkBuildable *buildable,
return NULL;
}
static void
gtk_widget_buildable_set_buildable_property (GtkBuildable *buildable,
GtkBuilder *builder,
const gchar *name,
const GValue *value)
{
if (strcmp (name, "has-default") == 0 && g_value_get_boolean (value))
g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_default,
GINT_TO_POINTER (TRUE));
else if (strcmp (name, "has-focus") == 0 && g_value_get_boolean (value))
g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_focus,
GINT_TO_POINTER (TRUE));
else
g_object_set_property (G_OBJECT (buildable), name, value);
}
typedef struct
{
gchar *action_name;
@@ -9749,18 +9541,6 @@ gtk_widget_buildable_parser_finished (GtkBuildable *buildable,
{
GSList *atk_relations;
if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_default))
{
gtk_widget_grab_default (GTK_WIDGET (buildable));
g_object_steal_qdata (G_OBJECT (buildable), quark_builder_has_default);
}
if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_focus))
{
gtk_widget_grab_focus (GTK_WIDGET (buildable));
g_object_steal_qdata (G_OBJECT (buildable), quark_builder_has_focus);
}
atk_relations = g_object_get_qdata (G_OBJECT (buildable),
quark_builder_atk_relations);
if (atk_relations)
@@ -12900,6 +12680,48 @@ gtk_widget_get_action_group (GtkWidget *widget,
return NULL;
}
/**
* gtk_widget_activate_action:
* @widget: a #GtkWidget
* @name: a prefixed action name
* @parameter: parameters that required by the action
*
* Looks up the action in the action groups associated
* with @widget and its ancestors, and activates it.
*
* The action name is expected to be prefixed with the
* prefix that was used when adding the action group
* with gtk_widget_insert_action_group().
*
* The @parameter must match the actions expected parameter
* type, as returned by g_action_get_parameter_type().
*/
void
gtk_widget_activate_action (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
GtkActionMuxer *muxer;
muxer = _gtk_widget_get_action_muxer (widget, FALSE);
if (muxer)
g_action_group_activate_action (G_ACTION_GROUP (muxer),
name,
parameter);
}
/**
* gtk_widget_activate_default:
* @widget: a #GtkWidget
*
* Activate the default.activate action from @widget.
*/
void
gtk_widget_activate_default (GtkWidget *widget)
{
gtk_widget_activate_action (widget, "default.activate", NULL);
}
void
gtk_widget_cancel_event_sequence (GtkWidget *widget,
GtkGesture *gesture,
@@ -13164,7 +12986,7 @@ gtk_widget_snapshot (GtkWidget *widget,
if (_gtk_widget_get_alloc_needed (widget))
{
g_warning ("Trying to snapshot %s %p without a current allocation", G_OBJECT_TYPE_NAME (widget), widget);
g_warning ("Trying to snapshot %s %p without a current allocation", gtk_widget_get_name (widget), widget);
return;
}
+8 -12
View File
@@ -209,8 +209,6 @@ struct _GtkWidget
* context menu.
* @get_accessible: Returns the accessible object that describes the
* widget to an assistive technology.
* @display_changed: Signal emitted when the #GdkDisplay of a widget has
* changed.
* @can_activate_accel: Signal allows applications and derived widgets
* to override the default GtkWidget handling for determining whether
* an accelerator can be activated.
@@ -314,8 +312,6 @@ struct _GtkWidgetClass
*/
AtkObject * (* get_accessible) (GtkWidget *widget);
void (* display_changed) (GtkWidget *widget,
GdkDisplay *previous_display);
gboolean (* can_activate_accel) (GtkWidget *widget,
guint signal_id);
@@ -474,16 +470,8 @@ void gtk_widget_set_can_target (GtkWidget *widget,
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_get_can_target (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_set_can_default (GtkWidget *widget,
gboolean can_default);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_get_can_default (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_has_default (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_grab_default (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_set_receives_default (GtkWidget *widget,
@@ -1011,6 +999,14 @@ GActionGroup *gtk_widget_get_action_group (GtkWidget *
GDK_AVAILABLE_IN_ALL
const gchar ** gtk_widget_list_action_prefixes (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_activate_action (GtkWidget *widget,
const char *name,
GVariant *parameter);
GDK_AVAILABLE_IN_ALL
void gtk_widget_activate_default (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_set_font_map (GtkWidget *widget,
PangoFontMap *font_map);
+2 -1
View File
@@ -81,7 +81,6 @@ struct _GtkWidgetPrivate
guint can_focus : 1;
guint has_focus : 1;
guint focus_on_click : 1;
guint can_default : 1;
guint has_default : 1;
guint receives_default : 1;
guint has_grab : 1;
@@ -210,6 +209,8 @@ struct _GtkWidgetPrivate
GdkCursor *cursor;
};
void gtk_widget_root (GtkWidget *widget);
void gtk_widget_unroot (GtkWidget *widget);
GtkCssNode * gtk_widget_get_css_node (GtkWidget *widget);
void _gtk_widget_set_visible_flag (GtkWidget *widget,
gboolean visible);

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