Compare commits

...

260 Commits

Author SHA1 Message Date
Emmanuele Bassi 8e39ff4271 ci: Enable libcloudproviders support
We ended up breaking the build when it's enabled, so we should test the
feature in our CI pipeline.
2020-06-09 15:47:36 +01:00
Emmanuele Bassi dd7251cb9f Add libcloudproviders as a fallback subproject
We require a new version of libcloudproviders so that we can enable it
in our CI pipeline.
2020-06-09 15:47:36 +01:00
Emmanuele Bassi 2a7e4b278e ci: Move backend Meson flags into a variable
So we don't have to copy them around.
2020-06-09 15:47:36 +01:00
Emmanuele Bassi 04f25bf901 ci: Update the CI images 2020-06-09 15:47:36 +01:00
Emmanuele Bassi a6049c3be4 ci: Rebase the Fedora CI image 2020-06-09 15:47:36 +01:00
Emmanuele Bassi 1b9d165252 ci: Add libcloudproviders to the base CI image 2020-06-09 15:47:36 +01:00
Matthias Clasen 997fbbde8f Merge branch 'drop-device-history' into 'master'
Drop device history

See merge request GNOME/gtk!2065
2020-06-08 23:56:30 +00:00
Matthias Clasen 805ddc3c3a gdk: Drop gdk_device_get_history
This function is not implemented anywhere.
2020-06-08 18:24:20 -04:00
Matthias Clasen da9b3a9256 win32: Drop pointless vfuncs
These are not useful.
2020-06-08 18:24:20 -04:00
Matthias Clasen 876560924f wayland: Drop a pointless vfunc
A vfunc that just returns FALSE is not useful.
2020-06-08 18:24:20 -04:00
Matthias Clasen ca1c89c5bd broadway: Drop a pointless vfunc
A vfunc that just returns FALSE is not useful.
2020-06-08 18:24:20 -04:00
Jordi Mas 7875e28d9f Update Catalan translation 2020-06-08 22:50:03 +02:00
Benjamin Otte bd2f2a6f65 Merge branch 'wip/otte/for-master' into 'master'
Wip/otte/for master

See merge request GNOME/gtk!2064
2020-06-08 18:43:31 +00:00
Benjamin Otte 541aaa2392 selectionmodel: Add unselect_rest argument to select_callback
This is not just about consistency with other functions.

It is about avoiding reentrancy problems.

GtkListBase first doing an unselect_all() will then force the
SelectionModel to consider a state where all items are unselected
(and potentially deciding to autoselect one) and then cause a
"selection-changed" emission that unselects all items and potentially
updates all the list item widgets in the GtkListBase to the unselected
state.

After this, GtkListBase selects new items, but to the SelectionModel and
the list item widgets this looks like an enitrely new operation and
there is no way to associate it with the previous state, so the
SelectionModel cannot undo any previous actions it took when
unselecting.
And all listitem widgets will now think they were just selected and
start running animations about selecting.
2020-06-08 19:06:56 +02:00
Benjamin Otte d294b01cee selectionmodel: Rename "exclusive" to "unselect_rest"
The name is better at explaining what this boolean is meant to do.
2020-06-08 18:26:48 +02:00
Benjamin Otte 5d9dc25115 listitemmanager: Update selections properly
Replace a previous fix with a more correct one: Update the
selected state from the model instead of reusing the old state, the
model might have updated the selected state.
2020-06-08 18:14:24 +02:00
Daniel Mustieles c8988ec784 Updated Spanish translation 2020-06-08 17:21:58 +02:00
Daniel Mustieles 071dbc1115 Updated Spanish translation 2020-06-08 16:11:28 +02:00
Matthias Clasen 80c5e4a156 Merge branch 'matthiasc/for-master' into 'master'
dropdown: Use our own CSS name

See merge request GNOME/gtk!2061
2020-06-08 11:15:28 +00:00
Emmanuele Bassi 6eac3063fa Merge branch 'tintou/places-sidebar-cloudproviders' into 'master'
placessidebar: Fix build with libcloudproviders

See merge request GNOME/gtk!2062
2020-06-08 09:35:23 +00:00
Corentin Noël 27925fcb0e placessidebar: Fix build with libcloudproviders
Make it build with cloudproviders=true as the GtkPopover API for menus is now in GtkPopoverMenu.

Fix some leaks while looking at the code.
2020-06-08 10:40:46 +02:00
Matthias Clasen 5f4d21422a Merge branch 'fix-cell-editing' into 'master'
Fix cell editing

Closes #2831

See merge request GNOME/gtk!2060
2020-06-07 14:54:37 +00:00
Matthias Clasen b0bb413faa dropdown: Use our own CSS name
Use the name dropdown for the css node, and document it.
2020-06-07 09:01:20 -04:00
Matthias Clasen 37633985bd Drop gtknativeprivate.h
No need to ship empty headers.
2020-06-07 08:52:45 -04:00
Matthias Clasen 6ff8f1b2fd Merge branch 'gtk-demo-tweaks' into 'master'
Gtk demo tweaks

See merge request GNOME/gtk!2059
2020-06-07 12:51:34 +00:00
Matthias Clasen d13a3c7540 Fix cell editing
When translating coordinates from an event, we need to
take the surface transform into account. This makes
double-clicking on editable cells in treeviews work
again.

Fixes: #2831
2020-06-07 08:46:31 -04:00
Yuri Chornoivan 0a469d7bd6 Update Ukrainian translation 2020-06-07 08:51:44 +00:00
Piotr Drąg 115edc5fd1 Update POTFILES.in 2020-06-07 09:27:34 +02:00
Matthias Clasen a28c75f215 gtk-demo: Expand the sidebar by default
Seems better to show what we have. Plus, clicking
those arrows is a little fiddly.
2020-06-06 22:12:12 -04:00
Matthias Clasen b9d7dab329 gtk-demo: Improve display of image sources
Make the images expand to fill the space.
2020-06-06 22:12:12 -04:00
Matthias Clasen bb7500e984 gtk-demo: Cosmetics
Tweak the formatting of the descriptions of
various demos.
2020-06-06 22:05:52 -04:00
Matthias Clasen e94268944b gtk-demo: Cosmetics
Make the titles of some demos match between sidebar
and window.
2020-06-06 21:42:42 -04:00
Emmanuele Bassi 3225b487e8 Merge branch 'ebassi/for-master' into 'master'
Annotate the GtkSelectionModel callbacks

See merge request GNOME/gtk!2057
2020-06-07 01:42:21 +00:00
Matthias Clasen e35c0e043e gtk-demo: Add overline to the markup demo
This is a new-ish Pango feature.
2020-06-06 21:38:31 -04:00
Matthias Clasen b251893030 Drop pango version checks
We are requiring pango 1.45.0 now, so no need to
Keep these ifdefs in the code any longer.
2020-06-06 21:32:55 -04:00
Matthias Clasen 15257e3922 gtk-demo: Fix a leak
The themes demo was leaking its builder, and
therefore couldn't be closed.
2020-06-06 20:09:42 -04:00
Matthias Clasen 180a5a1ad7 gtk-demo: Cosmetic changes to the dropdown demo
Match the window title and the sidebar.
2020-06-06 20:08:50 -04:00
Matthias Clasen 11f971d870 gtk-demo: Cosmetic improvements to clocks demo
Reformat the code comments, and add a 10th clock.
2020-06-06 19:43:21 -04:00
Emmanuele Bassi 7c382c6b47 Annotate the GtkSelectionModel callbacks
We need a scope for the select and unselect callback arguments.
2020-06-07 00:39:33 +01:00
Jordi Mas 087f42d998 Update Catalan translation 2020-06-06 23:13:17 +02:00
Matthias Clasen 2abb5b6419 3.98.5 2020-06-06 16:03:38 -04:00
Matthias Clasen f2259adcdc Disable a failing test
For some reason, empty-linear-gradient is failing here,
with the broadway and opengl renderers, and I don't
know why. Disable it for now.
2020-06-06 15:32:26 -04:00
Matthias Clasen a73457237d Skip broken a11y tests 2020-06-06 14:18:44 -04:00
Matthias Clasen 9f335d3ee6 docs: Regroup the tree support parts
Give the chapter a title, and put some things in sections.
2020-06-06 13:54:58 -04:00
Matthias Clasen 856c8950ff docs: Put selection models into a section
This makes the documentation structure a bit clearer.
2020-06-06 13:54:58 -04:00
Matthias Clasen 61ccf4e719 docs: Fix up the GtkNativeDialog section
Without GtkNativeDialog in the section list,
links are not generated from the object hierarchy.
2020-06-06 13:54:58 -04:00
Matthias Clasen 1567db1f02 Merge branch 'misc-multiselection' into 'master'
Misc multiselection

See merge request GNOME/gtk!2055
2020-06-06 17:54:42 +00:00
Matthias Clasen 8316d5e366 Merge branch 'list-arrows' into 'master'
listbase: Make up/down arrows work

See merge request GNOME/gtk!2056
2020-06-06 17:47:05 +00:00
Matthias Clasen 8fca040163 Merge branch 'property-selection' into 'master'
Property selection

Closes #2826

See merge request GNOME/gtk!2054
2020-06-06 17:35:05 +00:00
Matthias Clasen c0fe1a7ffe listbase: Make up/down arrows work
We were missing a binding for up/down without modifiers.
2020-06-06 12:33:12 -04:00
Matthias Clasen e72c243aca singleselection: Clarify docs
Mention persistence and sorting.
2020-06-06 11:53:33 -04:00
Matthias Clasen 14605d4b92 gtk-demo: Use a property selection in the colors demo
This makes the property persist across sort changes.
2020-06-06 11:41:51 -04:00
Matthias Clasen d1509971d8 Add GtkPropertySelection
This is a selection model that stores the selection
state in a boolean property of the items, and thus
persists across reordering and similar changes.

Fixes: #2826
2020-06-06 11:41:51 -04:00
Matthias Clasen 951c9c5d73 Merge branch 'listitemmanager-selection' into 'master'
listitemmanager: Handle selection-changes properly

Closes #2827

See merge request GNOME/gtk!2053
2020-06-06 15:23:40 +00:00
Matthias Clasen 3e6e247e56 multiselection: Rewrite the select_callback implementation
Use a for loop to make this more obvious, and add some
assertions that the callback is behaving properly.
2020-06-06 11:22:48 -04:00
Matthias Clasen 27ce68b74a Add tests for select_callback 2020-06-06 11:22:48 -04:00
Matthias Clasen b0cf7a95b0 Add a forgotten export
gtk_selection_model_unselect_callback needs to be exported.
2020-06-06 11:22:48 -04:00
Matthias Clasen fd7f19c934 selectionmodel: Document the callback apis 2020-06-06 10:36:57 -04:00
Matthias Clasen 8090e213de Add a test for multiselection persistence
Add a test that verifies that newly added items
are always unselected.
2020-06-06 10:24:14 -04:00
Matthias Clasen de6327a885 multiselection: Clarify docs
Make it clear that GtkMultiSelection is not persistent
across resorting.
2020-06-06 10:24:14 -04:00
Yuri Chornoivan 8699c0f340 Update Ukrainian translation 2020-06-06 13:46:40 +00:00
Yuri Chornoivan bda5454549 Update Ukrainian translation 2020-06-06 13:44:29 +00:00
Matthias Clasen c3a6e35070 Drop an unnecessary include 2020-06-06 09:39:36 -04:00
Matthias Clasen 71c29bfcff listitemmanager: Handle selection-changes properly
The selection model will only emit one of items-changed
or selection-changed, so when we handle an items-changed,
we must assume that selection state may have changed for
any of the newly added items.

This fixes lingering selection state in the visible range
if you change the sorting of the colors demo.

Fixes: #2827
2020-06-06 08:36:11 -04:00
Piotr Drąg 647ed59d11 Update POTFILES.in and POTFILES.skip 2020-06-06 14:00:43 +02:00
Matthias Clasen a0c489048a Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2052
2020-06-06 05:30:30 +00:00
Benjamin Otte 0f9def660d Merge branch 'wip/otte/for-master' into 'master'
multiselection: Remove unused code

See merge request GNOME/gtk!2051
2020-06-06 05:16:47 +00:00
Matthias Clasen 9fa65eadae listitemwidget: Don't look at rubberbanding
Move the selection changes to button release, to
avoid conflict with the drag gesture for rubberbanding.
This avoids peeking at the parent, and is generally
nicer.

Among other things, you can now shift-click to select
a range in the colors demo in gtk4-demo.
2020-06-06 00:23:04 -04:00
Matthias Clasen facfff0022 listbase: Fix an off-by-one error
We were accidentally cutting off the set one-too-early,
which showed up as single clicks not selecting an item
anymore.
2020-06-06 00:15:50 -04:00
Matthias Clasen f8b4083f47 listbase: Fix a problem with rubberbands
When I changed things to only collect the set
in the stop() function, I overlooked that this
has the side-effect of only handling items which
are backed by a widget at the time stop() is called.
If we make a big rubberband and autoscroll down too
far, we loose the items that go out the visible range
at the top. Fix that by maintaining the set as we go.
2020-06-05 23:18:00 -04:00
Matthias Clasen b047b7838d multiselection: Don't emit nonsensical signals
I forgot to add a check here. We only want to emit
a ::selection-changed if we actually changed it.
2020-06-05 23:15:20 -04:00
Benjamin Otte b1c00ecee6 multiselection: Remove unused code
This is leftover code from an earlier SelectionModel API.
2020-06-06 05:02:37 +02:00
Matthias Clasen 93abd8da59 NEWS: Updates 2020-06-05 22:50:30 -04:00
Matthias Clasen 3412f0554f gtk: Documentation fixups
Document missing symbols, and other cleanups.
2020-06-05 22:50:30 -04:00
Matthias Clasen 61c83f9ffe gdk: Documentation fixups
Document some missing symbols.
2020-06-05 20:59:51 -04:00
Matthias Clasen 3d7c1f8950 gsk: Documentation fixups
Document a few missing symbols.
2020-06-05 20:19:45 -04:00
Matthias Clasen b0e81acc12 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2050
2020-06-05 23:55:12 +00:00
Matthias Clasen a682d97663 Merge branch 'wip/ebassi/a11y-2' into 'master'
Accessibility cleanup

See merge request GNOME/gtk!2049
2020-06-05 23:04:21 +00:00
Matthias Clasen 0e5137ae61 NEWS: Updates 2020-06-05 18:40:53 -04:00
Matthias Clasen 005a3da18f gtk-demo: Another way to trigger theme benchmark
The click on the headerbar seems broken atm, so add
an explicit button to trigger the cycling among the
themes.
2020-06-05 18:40:24 -04:00
Matthias Clasen be6bcf882d spinbuttonaccessible: Fix an oversight
We need to pass the accessible to the signal handler.
2020-06-05 17:21:26 -04:00
Matthias Clasen fb344e8108 Trivial typo fix 2020-06-05 17:08:43 -04:00
Emmanuele Bassi b99389bcb8 a11y: Drop GtkWidgetAccessibleClass.notify_gtk
It's finally unused.

Accessible types should either watch properties they are interested in
directly, or should have (private) API to allow widgets to update the
accessible state directly.
2020-06-05 20:35:11 +01:00
Emmanuele Bassi 0fefdc99b2 a11y: Simplify GtkEntryAccessible
Now that we don't have any additional subclasses of GtkEntryAccessible
in GTK, we can drop all the conditional fluff in the base class.

We still need to subscribe to the global notify signal, because of the
sheer amount of properties watched by GtkEntryAccessible.
2020-06-05 20:35:11 +01:00
Emmanuele Bassi e63419fbf4 a11y: Implement GtkPasswordEntryAccessible properly
GtkPasswordEntryAccessible is not a GtkEntryAccessible any more, so it
will need a proper implementation of various interfaces and
functionality in order to work like any other entry.
2020-06-05 20:35:11 +01:00
Emmanuele Bassi 428bb09a35 a11y: Make GtkSearchEntryAccessible a full GtkWidgetAccessible
We should not inherit from GtkEntryAccessible, given that GtkSearchEntry
is *not* a GtkEntry.
2020-06-05 20:35:11 +01:00
Emmanuele Bassi 7c2c795681 a11y: Simplify GtkScrollbarAccessible 2020-06-05 20:35:11 +01:00
Emmanuele Bassi 165f352c58 a11y: Simplify GtkScaleButtonAccessible 2020-06-05 20:35:11 +01:00
Emmanuele Bassi 3d6e702f63 a11y: Simplify GtkSpinButtonAccessible
We're already listening to the adjustment property on the spin button,
there's no need to reset the adjustment on widget set/unset, since the
accessible instance is always tied to the same widget.
2020-06-05 20:35:11 +01:00
Emmanuele Bassi 597e9a96b4 a11y: Simplify GtkTextAccessible 2020-06-05 20:35:11 +01:00
Emmanuele Bassi 6f4ed6c105 a11y: Simplify GtkTextViewAccessible
Drop the GtkWidgetAccessible.notify_gtk override.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi c3eafed472 a11y: Simplify GtkColorSwatchAccessible
Drop the GtkWidgetAccessible.notify_gtk override.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 7480fb703e a11y: Simplify GtkNotebookAccessible
Let the GtkNotebook explicitly update the accessible object that the
current page has changed, instead of overriding
GtkWidgetAccessible.notify_gtk.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 24e8b484e0 a11y: Simplify GtkWindowAccessible
Have GtkWindow notify of title changes, instead of overriding
GtkWidgetAccessible.notify_gtk.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi d60f7f2e7a a11y: Simplify GtkExpanderAccessible
Drop the GtkWidgetAccessible.notify_gtk and AtkObject.initialize
overrides, and have GtkExpander update the state of the accessible
object directly.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 0dcffe7c33 a11y: Simplify GtkLevelBarAccessible
Drop the GtkWidgetAccessible.notify_gtk and AtkObject.initialize
overrides, and have GtkLevelBar notify the accessible object of value
changes.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 9f09cfcfbd a11y: Split GtkSearchEntryAccessible from GtkEntryAccessible
Use a separate accessible object for the GtkSearchEntry, just like we
did for GtkPasswordEntry.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 7373cd962c a11y: Split password entry accessible from GtkEntryAccessible
Use a separate accessible object.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi ac3f0df083 a11y: Simplify GtkProgressBarAccessible
Drop the GtkWidgetAccessibleClass.notify_gtk and the
AtkObjectClass.initialize overrides: they don't do anything relevant.

Instead, have GtkProgressBar update the accessible state when the
fraction changes.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi f95d54a13d a11y: Use G_DECLARE macro for GtkWidgetAccessible
Allows us to drop the Private structure typedef.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi fc512f0b9f a11y: Update the accessible state when GtkIconView:model changes
Do not use a generic "notify" signal handler.

Additionally, clean up the GtkIconViewAccessible implementation to bring
it up with modern idiomatic GObject.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi f5ed59b7f2 a11y: Drop notify_gtk() from GtkRangeAccessible
Let the GtkRange notify the accessible instance when the adjustment
changes.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 9d51aa1443 a11y: Drop notify_gtk() from GtkButtonAccessible
Make GtkButton notify the accessible state directly when updating the
label.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi f0bdc865b9 a11y: Remove GtkToggleButtonAccessible notify_gtk implementation
The base GtkWidgetAccessible class does the right thing by default.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi eda1703f9d a11y: Update accessible state for GtkTreeView directly
Do not use GtkWidgetAccessibleClass.notify_gtk().
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 51fc382582 Notify accessibility state changes from GtkWidget
Piggybacking on blanket GObject::notify is not very efficient.
2020-06-05 20:35:10 +01:00
Emmanuele Bassi 6e52ef96a4 Move orientable style classes into GtkWidget
It feels slightly wrong to have GtkOrientable operate on widgets, but at
least what happens when an orientable widget changes orientation should
be part of GtkWidget.

This will allow to add more state changes without accessing widget state
from the outside of gtkwidget.c.
2020-06-05 20:35:09 +01:00
Emmanuele Bassi 9606c1eee9 Notify mapped state to the accessible object directly
Do not use signal connections: if we have an accessible object, notify
it directly when getting mapped and unmapped.
2020-06-05 20:32:27 +01:00
Emmanuele Bassi 959c101400 Drop unused AtkRegistry path
We expect widgets to use their own derived GtkWidgetAccessible type,
these days, and given that we hard code the default accessible type of a
GtkWidget to GtkWidgetAccessible, and that we enforce the dependency of
the type passed to gtk_widget_class_set_accessible_type(), the registry
code path is clearly unused.
2020-06-05 20:32:27 +01:00
Emmanuele Bassi 6b096e5c5b Make tooltip properties idiomatic
The tooltip handling in GtkWidget is "special":

 - the string is stored inside the qdata instead of the private
   instance data
 - the accessors call g_object_set() and g_object_get(), and the
   logic is all inside the property implementation, instead of
   being the other way around
 - the getters return a copy of the string
 - the setters don't really notify all the involved properties

The GtkWidgetAccessible uses the (escaped) tooltip text as a source for
the accessible object description, which means it has to store the
tooltip inside the object qdata, and update its copy at construction and
property notification time.

We can simplify this whole circus by making the tooltip properties (text
and markup) more idiomatic:

 - notify all side-effect properties
 - return a constant string from the getter
 - if tooltip-text is set:
   - store the text as is
   - escape the markup and store it separately for the markup getter
 - if tooltip-markup is set:
   - store the markup as is
   - parse the markup and store it separately for the text getter

The part of the testtooltips interactive test that checks that the
getters are doing the right thing is now part of the gtk testsuite, so
we ensure we don't regress in behaviour.
2020-06-05 20:32:26 +01:00
Emmanuele Bassi 9ac1eacdc8 Use modern GObject macros for GtkAccessible 2020-06-05 20:32:26 +01:00
Matthias Clasen 8e7395a7e3 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2048
2020-06-05 19:25:46 +00:00
Matthias Clasen 80fbc1b72d multiselection: Fix the select_range implementation
When exclusive is TRUE, we would not always emit a
::selection-changed signal that covers all the items
that were unselected.

This commit includes a test.
2020-06-05 14:57:59 -04:00
Matthias Clasen 17ea03eee2 set: Fix gtk_set_get_max
This function had an off-by-one error. Thankfully,
our selection tests are thorough enough to catch it.
2020-06-05 14:57:32 -04:00
Matthias Clasen 985b5a052e dropdown: Connect a forgotten signal handler
The code was exporting a search_stop function, but
the ui file didn't connect it to the ::stop-search
signal. Fix that.
2020-06-05 14:34:38 -04:00
Matthias Clasen ed1872f0a8 Merge branch 'frame-clock-start-time' into 'master'
Tweaks to frame clock for better ties to vsync

See merge request GNOME/gtk!2043
2020-06-05 18:33:48 +00:00
Matthias Clasen 34841c3a5f Merge branch 'master.msvc' into 'master'
Fix latest GTK master on Visual Studio

See merge request GNOME/gtk!2028
2020-06-05 18:31:08 +00:00
Matthias Clasen 185f0181ac Merge branch 'columnview-reorder-cells' into 'master'
Columnview reorder cells

See merge request GNOME/gtk!2047
2020-06-05 18:29:26 +00:00
Matthias Clasen 60d6a0f2d5 Merge branch 'rubberband-again' into 'master'
Rubberband again

See merge request GNOME/gtk!2041
2020-06-05 17:59:15 +00:00
Matthias Clasen 99a1d10bf1 multiselection: Fix the select_range implementation
When exclusive is TRUE, we would not always emit a
::selection-changed signal that covers all the items
that were unselected.

This commit includes a test.
2020-06-05 13:50:30 -04:00
Matthias Clasen 2f1028ed79 set: Add a few useful functions
Allow to find out if a set is empty, and its
min and max.
2020-06-05 13:49:23 -04:00
Matthias Clasen f631e0e1e0 columnview: Update column positions on reordering
Tell reordered columns to reorder their cells to
the new position. This is necessary to get things
like separators right. The visible symptom of this
problem was the lack of the right border when the
last column is reorder to another position, since
the title widget was still the last in its container,
so :last-child applied.
2020-06-05 13:28:44 -04:00
Matthias Clasen 6df489d5a9 columnviewcolumn: Add private api to set the position
This is needed to make columns reorder their cells when
their position in the column views list of columns
changes.
2020-06-05 13:28:44 -04:00
Matthias Clasen 15c6ad88c0 listitemwidget: Add api to reorder children
We need this to keep the rows in sync with the columns
when they are reordered.
2020-06-05 13:28:44 -04:00
Matthias Clasen 40f6a9d830 columnviewlayout: Handle for_size propertly
When we are given a for_size as width for the whole
column view, we need to distribute it over the columns
as gtk_column_view_allocate_columns would, in order
to find out which for_size to give to each cell.

This is a bit recursive, but works. Since we are
doing this recursion for every row, we should consider
adding a cache for those distributed widths.
2020-06-05 13:27:50 -04:00
Ray Strode bd06c00f3a Merge branch 'wip/damaged-but-no-frost-bite' into 'master'
x11: defer _NET_WM_FRAME_DRAWN update until frame usable by compositor

See merge request GNOME/gtk!1982
2020-06-05 15:58:37 +00:00
Matthias Clasen f6d23f0c29 Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Bring back the applauncher demo

See merge request GNOME/gtk!2040
2020-06-05 15:38:03 +00:00
Emmanuele Bassi 2a24459b92 Merge branch 'ebassi/for-master' into 'master'
Add missing annotation

See merge request GNOME/gtk!2046
2020-06-05 15:29:41 +00:00
Matthias Clasen f6da324670 columnview: Split gtk_column_view_allocate_columns
Split off a helper function that just distributes
the widths, without actually allocating the columns.

This will be used in measuring in the future.
2020-06-05 11:27:40 -04:00
Matthias Clasen 11a18bd61a columnview: Take column width into account for measuring
When measuring the height of a cell, we need to give
it it the width of its column, if we expect realistic
results.
2020-06-05 10:42:20 -04:00
Ray Strode 972134abe4 x11: Defer _NET_WM_FRAME_DRAWN update until frame usable by compositor
With the vendor provided Nvidia driver there is a small window of time
after drawing to a GL surface before the updates to that surface
can be used by the compositor.

Drawing is already coordinated with the compositor through the frame
synchronization protocol detailed here:

https://fishsoup.net/misc/wm-spec-synchronization.html

Unfortunately, at the moment, GdkX11Surface tells the compositor the
frame is ready immediately after drawing to the surface, not later,
when it's consumable by the compositor.

This commit defers announcing the frame as ready until it's consumable
by the compositor. It does this by listening for the X server to announce
damage events associated with the frame drawing.  It tries to find the
right damage event by waiting until fence placed at buffer swap time
signals.
2020-06-05 10:01:13 -04:00
Ray Strode f8770b78ea x11: Factor out some of frame sync code into subroutines
This commit moves some of the end frame sync counter handling
code to subroutines.

It's a minor readability win, but the main motivation is to
make it easier in a subsequent commit to defer updating the
sync counter until a more appropriate time.
2020-06-05 10:01:13 -04:00
Ray Strode 10f2b11fda x11: Add back support for the damage extension
commit 14bf58ec5d dropped support
for using the DAMAGE extension since there was no code that
needed it.

We're going to need it again, however, to address an NVidia
vendor driver issue.

This commit does the plumbing to add it back.
2020-06-05 10:01:13 -04:00
Timm Bäder ea1cc4b991 filechooserwidget: Avoid an uninitialised value
For NULL filters, we were never calling g_list_store_find, so leaving
filter_index undefined.
2020-06-05 15:38:55 +02:00
Timm Bäder 8bee3e2fe0 demos: Avoid shadowing a global from time.h
Sad but true.
2020-06-05 15:38:55 +02:00
Timm Bäder 1f7adfd9ff filterlistmodel: Fix fallthrough annotations in unreachable code
They are only unreachable in debug builds but still break the build on
clang.
2020-06-05 15:38:55 +02:00
Matthias Clasen 9e55cd68e4 columview: Make cells propagate request mode
I think this is necessary to make wrapping
labels work.
2020-06-05 09:37:21 -04:00
Matthias Clasen 2a6dc67fd7 gtk-demo: Improve wrapping in settings demo
The columnview overrides the width of its content,
so if a label is not willing to wrap its content
below a certain width, it will just get cut off.

Avoid that by not setting width-chars on the wrapping
content.
2020-06-05 09:35:56 -04:00
Emmanuele Bassi 1061ad289a Add missing annotation 2020-06-05 14:33:17 +01:00
Matthias Clasen 0f81b58545 columviewlayout: Skip children when we should
Every layout manager should call gtk_widget_should_layout
on their children before measuring or allocating them.
So do it here too.
2020-06-05 08:44:23 -04:00
Matthias Clasen 2437c5a0ae listview: Add an example to the docs
The example is an excerpt from the applauncher
demo in gtk4-demo.
2020-06-05 08:22:48 -04:00
Matthias Clasen 669a6ddeaa gtk-demo: Bring back the applauncher demo
Just without the coverflow. It was a well-documented
demo, so it is useful to keep around.
2020-06-05 08:22:48 -04:00
Yariv Barkan f5de46670b frame clock: schedule in refresh intervals
When the application does not receive "frame drawn" signals we schedule
the clock to run more or less at intervals equal to the last known
refresh interval. In order to minimize clock skew we have to aim for
exact intervals.
2020-06-05 11:57:49 +02:00
Alexander Larsson 91af8a705b frame clock: Better handle non-regular clock cycles
We try to step the frame clock in whole refresh_interval steps, but to
avoid drift and rounding issues we additionally try to converge it to
be synced to the physical vblank (actually the time we get the
frame-drawn message from the compositor, but these are tied together).

However, the convergence to vsync only really makes sense if the new
frame_time actually is tied to the vsync. It may very well be that
some other kind of event (say a network or mouse event) triggered
the redraw, and not a vsync presentation.

We used to assume that all frames that are close in time (< 4 frames
apart) were regular and thus tied to the vsync, but there is really no
guarantee of that. Even non regular times could be rapid.

This commit changes the code to only do the convergence-to-real-time
if the cause of the clock cycle was a thaw (i.e. last frame drawn and
animating). Paint cycles for any other kind of reason are always
scheduled an integer number of frames after the last cycle that was
caused by a thaw.
2020-06-05 11:30:47 +02:00
Alexander Larsson 82c314f1af frame clock: Track if paint is caused by thaw or not
When we get to a paint cycle we now know if this was caused by a
thaw, which typically means last frame was drawn, or some other event.

In the first case the time of the cycle is tied to the vblank in some
sense, and in the others it is essentially random. We can use this
information to compute better frame times. (Will be done in later
commits.)
2020-06-05 11:16:57 +02:00
Benjamin Otte 672413f1f6 Merge branch 'cleanup-snapshot-inhibit' into 'master'
reftest: Clean up reftest_inhibit_snapshot()

See merge request GNOME/gtk!2034
2020-06-05 07:38:52 +00:00
Matthias Clasen 843bf23f84 Drop gtk_multi_selection-copy
It is not used anymore.
2020-06-05 00:51:35 -04:00
Matthias Clasen eeb2d2cc38 listbase: Redo rubberbanding
Make it so that the selection is only updated in the end.
2020-06-05 00:51:35 -04:00
Chun-wei Fan c370b8f309 demos/gtk-demo/listview*.c: Include stdlib.h
atoi() and qsort() both require this header for them to be defined
2020-06-05 11:16:45 +08:00
Chun-wei Fan acd9c12667 modules: Fix build on Visual Studio
Visual Studio does not allow decorating functions with '__declspec (dllexport)'
if a prototype exists and is not decorated with '__declspec (dllexport)' as
well, so we cannot just decorate g_io_module_[load|unload|query] in the various
module sources with G_MODULE_EXPORT because the prototypes of these functions
have been marked with _GLIB_EXTERN, which equates to 'extern' unless overridden

Fix this by overriding _GLIB_EXTERN with the appropriate visibility flag, as we
have used to define _GDK_EXTERN.  Unfortunately, we can't just use _GDK_EXTERN
G_MODULE_EXPORT as they may have not been defined yet for our use

Do this across the board for all modules, even if they are not buildable on
Visual Studio nor Windows, for consistency's sake.
2020-06-05 11:16:45 +08:00
Timm Bäder 5535b26395 Merge branch 'fix-quadratic-add' into 'master'
Avoid quadratic slowdown in gtk_widget_add()

See merge request GNOME/gtk!2027
2020-06-05 02:57:38 +00:00
Matthias Clasen 20611cf68c Add gtk_selection_model_[un]select_callback
Add a methods to add or remove a whole set
(specified via a query-range style callback).
2020-06-04 22:28:54 -04:00
Matthias Clasen 06c34ce02f set: Add a few useful functions
Allow to find out if a set is empty, and its
min and max.
2020-06-04 21:36:23 -04:00
Matthias Clasen 4fb50c7408 Merge branch 'matthiasc/for-master' into 'master'
more documentation for list widgets

See merge request GNOME/gtk!2039
2020-06-04 21:17:21 +00:00
Matthias Clasen c37bea1676 Merge branch 'fribidi-include' into 'master'
wayland: Remove unused fribidi include

See merge request GNOME/gtk!2037
2020-06-04 20:03:13 +00:00
Matthias Clasen ed985640e8 docs: Expand list widget docs
Begin to flesh out the long descriptions for GtkListView,
GtkGridView and GtkColumnView.
2020-06-04 15:33:53 -04:00
Sebastian Keller 2bd938952d wayland: Remove unused fribidi include
The included fribidi header is not used in gdkkeys-wayland.c and already
included in gdk.c which causes linker issues due to the header defining
a global variable.
2020-06-04 20:44:55 +02:00
Matthias Clasen 623a56391c gtk-demo: Cosmetics
Remove a few instances of double semicolon.
2020-06-04 13:30:13 -04:00
Matthias Clasen 1b7fb10361 Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Allow editing in the settings demo

See merge request GNOME/gtk!2033
2020-06-04 16:32:21 +00:00
Matthias Clasen f6b6688186 Merge branch 'list-widget-styles' into 'master'
List widget styles

Closes #2818

See merge request GNOME/gtk!2035
2020-06-04 16:27:37 +00:00
Matthias Clasen 99453e937c Merge branch 'demo-drop-awards' into 'master'
gtk-demo: Drop the awards

See merge request GNOME/gtk!2036
2020-06-04 15:27:23 +00:00
Alexander Larsson d3e0a1f68c Avoid quadratic slowdown in gtk_widget_add()
If you add a widget to a parent, this will invalidate the css nodes
for parent/siblings. Afterwards, if the parent is mapped, we will
realize the new child. This calls gtk_widget_update_alpha() which
needs the css opacity, so it revalidates the css.

Thus, for each widget_add (while visible) will trigger a full
revalidation of each sibling. If you add N children to a parent that
leads to O(N^2) revalidations.

To demo this I changed gtk-demo to always double the count
(independent of the fps) and print the time it took. Here is the
results (after a bit):

Setting fishbowl count=256 took 3,4 msec
Setting fishbowl count=512 took 10,1 msec
Setting fishbowl count=1024 took 34,1 msec
Setting fishbowl count=2048 took 126,3 msec
Setting fishbowl count=4096 took 480,3 msec
Setting fishbowl count=8192 took 1892,7 msec
Setting fishbowl count=16384 took 7751,0 msec
Setting fishbowl count=32768 took 38097,7 msec
Setting fishbowl count=65536 took 191987,7 msec

To fix this we drop gtk_widget_update_alpha() and just
calculate it when needed (which is only in a single place).
It was really only necessary because we previously set
the alpha on the surface.

With this fix the above becomes:

Setting fishbowl count=256 took 1,0 msec
Setting fishbowl count=512 took 1,9 msec
Setting fishbowl count=1024 took 3,7 msec
Setting fishbowl count=2048 took 7,4 msec
Setting fishbowl count=4096 took 18,1 msec
Setting fishbowl count=8192 took 31,0 msec
Setting fishbowl count=16384 took 66,3 msec
Setting fishbowl count=32768 took 126,7 msec
Setting fishbowl count=65536 took 244,6 msec
Setting fishbowl count=131072 took 492,2 msec
Setting fishbowl count=262144 took 984,3 msec
2020-06-04 16:42:59 +02:00
Matthias Clasen 76ff1a2a49 gtk-demo: Drop the awards
This was a neat idea, but maintaining it at a sufficient
level is too much work.
2020-06-04 10:19:44 -04:00
Matthias Clasen 51c6ce1734 list widgets: Document css structure
We didn't fill in this expected part of the widget
documentation yet.
2020-06-04 10:05:17 -04:00
Benjamin Otte 1998b673f4 Merge branch 'ensure-style-no-recurse' into 'master'
Avoid recursion in gtk_css_node_ensure_style()

See merge request GNOME/gtk!2031
2020-06-04 14:04:55 +00:00
Matthias Clasen 627497f942 docs: Fix a parameter name mismatch 2020-06-04 09:52:17 -04:00
Matthias Clasen f9287941b4 Change css names of list widget
The new names are

GtkListView - listview row
GtkGridView - gridview child
GtkColumView - columnview header
               columnview listview row

Adwaita css has been updated to preserve
existing styles.

Fixes: #2818
2020-06-04 09:51:49 -04:00
Alexander Larsson 5059854a2e reftest: Clean up reftest_inhibit_snapshot()
This was done in a weird way where we always call reftest_uninhibit_snapshot()
on paint, and then re-inhibited it if it wasn't inhibited. To make this
work it also started with an extra inhibit.

This is very contorted and based on how this historically worked. This
changes it to just do:

  if (inhibit_count > 0)
    return;

And keep inhibit_count at its initial zero value unless it is actually
inhibited.
2020-06-04 15:45:29 +02:00
Benjamin Otte aa8a061a83 Merge branch 'fix-snapshot' into 'master'
snapshot: Fix assert if paint gets scheduled immediately

See merge request GNOME/gtk!2032
2020-06-04 13:43:44 +00:00
Matthias Clasen 3f2d44d517 gtk-demo: Allow editing in the settings demo
This gives us an example of a columnview with editable
content, which we didn't have so far.
2020-06-04 08:45:47 -04:00
Alexander Larsson b4af23be23 snapshot: Fix assert in inhibition
In https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2027 i was getting

Bail out! ERROR:../testsuite/reftests/reftest-snapshot.c:212:reftest_uninhibit_snapshot: assertion failed: (inhibit_count > 0)

In (for example the box-shadow-changes-modify-clip reftest. I can reproduce this (on master) with:

```
$ xvfb-run -a -s "-screen 0 1024x768x24" meson test --suite gtk:reftest "reftest box-shadow-changes-modify-clip.ui"
...
1/1 gtk:reftest / reftest box-shadow-changes-modify-clip.ui ERROR          0.77s
``

Fix this by re-inhibiting if we didn't draw anything, or we will get an assert the next paint.
2020-06-04 14:22:27 +02:00
Matthias Clasen 8ddf1f1ea5 Merge branch 'kjellahl/flowboxremove' into 'master'
flowbox: Don't use a removed and destroyed child

See merge request GNOME/gtk!2029
2020-06-04 12:13:57 +00:00
Matthias Clasen 475d8c4c11 Merge branch 'fishbowl-children' into 'master'
gtk-demo: Avoid list for children in GtkFishBowl

See merge request GNOME/gtk!2030
2020-06-04 12:10:51 +00:00
Alexander Larsson fc823eb610 Avoid recursion in gtk_css_node_ensure_style()
gtk_css_node_ensure_style() recurses over previous siblings to ensure
these have a style before its following sibling.  As seen in
https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2027 this can
cause us to stack overflow and crash if we have a lot of children.

And even if we don't have *that* many children its still somewhat
bad to have stack depths of the same magnitude as the number of
children, both for performance reasons and debuggability.
2020-06-04 12:10:31 +02:00
Alexander Larsson 8707bab450 gtk-demo: Avoid list for children in GtkFishBowl
This is a demo that measures performance, so keep the child
info in a hashtable instead of a list. This means adding or removing
a child is not O(n-children).
2020-06-04 12:06:42 +02:00
Kjell Ahlstedt 612955f2b7 flowbox: Don't use a removed child after it has been unparented
In gtk_flow_box_remove(), call g_sequence_remove() before the child is unparented.

See MR !2029
2020-06-04 11:23:46 +02:00
Timm Bäder 36314c3ff7 Merge branch 'santo/gtk4_spelling_fix' into 'master'
docs: Fix spelling of GDK_VERSION_MIN_REQUIRED.

See merge request GNOME/gtk!2026
2020-06-04 07:38:58 +00:00
Daniel Mustieles 33fb38d8de Updated Spanish translation 2020-06-04 09:18:01 +02:00
Daniel Mustieles 38e2a910df Updated Spanish translation 2020-06-04 09:17:16 +02:00
Santosh Mahto ef32df77be docs: Fix spelling of GDK_VERSION_MIN_REQUIRED. 2020-06-04 12:12:36 +05:30
Matthias Clasen 5154693ea4 Merge branch 'columnview-separators' into 'master'
Columnview separators

See merge request GNOME/gtk!2025
2020-06-03 23:34:48 +00:00
Matthias Clasen 4b68362981 columnview: Add a property for column separators
Rename the show-separators property to show-row-separators,
and add a matching show-column-separators property. It is
implemented by setting the .column-separators style class
on the column view.
2020-06-03 17:57:23 -04:00
Matthias Clasen 658e4c5357 listview: Use gtk_widget_add_css_class
No need to use the style context api for this anymore.
2020-06-03 17:51:22 -04:00
Matthias Clasen ce0dd650d7 settings demo: Don't select rows
We want no selection here, so use GtkNoSelection.
2020-06-03 17:51:22 -04:00
Matthias Clasen 77b65ada4f Merge branch 'columnview-printdialog' into 'master'
Port the printdialog to column view

See merge request GNOME/gtk!2010
2020-06-03 21:47:58 +00:00
Matthias Clasen fa37225a42 Merge branch 'columnview-rubberbanding' into 'master'
columnview: Implement rubberbanding

See merge request GNOME/gtk!2008
2020-06-03 21:46:13 +00:00
Matthias Clasen 78a06859b9 Merge branch 'columnview-expand' into 'master'
columnview: Implement expanding columns

See merge request GNOME/gtk!2007
2020-06-03 21:39:33 +00:00
Matthias Clasen 3ec8f4e84e Merge branch 'columnview-reordering' into 'master'
columnview: Implement interactive reordering

See merge request GNOME/gtk!2006
2020-06-03 21:38:59 +00:00
Matthias Clasen f13a596d15 Merge branch 'columnview-resizing' into 'master'
columnview: Implement interactive resizing

See merge request GNOME/gtk!2004
2020-06-03 20:04:17 +00:00
Matthias Clasen 94f14778a3 Merge branch 'columnview-scrolling' into 'master'
columnview: Implement horizontal scrolling

See merge request GNOME/gtk!1998
2020-06-03 19:50:59 +00:00
Benjamin Otte 7312284e4f Merge branch 'wip/otte/for-master' into 'master'
Wip/otte/for master

See merge request GNOME/gtk!2024
2020-06-03 17:40:26 +00:00
Matthias Clasen ebc07d1458 printdialog: Port to column view 2020-06-03 13:35:09 -04:00
Matthias Clasen 510f719975 gtk-demo: Make gridview demo use rubberbanding 2020-06-03 13:34:28 -04:00
Matthias Clasen 03c2202942 Add rubberband api
Add an ::enable-rubberband property to GtkListView,
GtkGridView and GtkColumnView.
2020-06-03 13:34:27 -04:00
Matthias Clasen b3a97cb755 listbase: Simplify rubberbanding
The new approach is:
 - plain: clear and start a new selection
 - extend: add to the existing selection
 - modify: subtract from the existing selection
2020-06-03 13:32:57 -04:00
Matthias Clasen a9273e1c73 listbase: Split off rubberband data 2020-06-03 13:32:57 -04:00
Matthias Clasen 14d11ebcab listbase: Use a widget for the rubberband
We no longer need to juggle manual css nodes. Just create
a widget for the rubberband, and update its allocation
as we rubberband.
2020-06-03 13:32:57 -04:00
Matthias Clasen 7dc458d925 Add autoscroll
This is an expected feature with rubberband selection:
as you get close to the edge while doing rubberband
selection, the list scrolls to extend your selection.
2020-06-03 13:32:57 -04:00
Matthias Clasen a0f04bdcf3 listbase: Add rubberband selection
Implement the typical rubberband selection, including
autoscroll. This is only useful with multiselection,
and not very compatible with single-click-activate.
Therefore, it is not enabled by default, and needs
to be turned on explicitly.
2020-06-03 13:32:57 -04:00
Matthias Clasen 28f6e27276 Add GtkMultiSelection
This is implemented using a private GtkSet helper.

Includes tests.
2020-06-03 13:32:57 -04:00
Matthias Clasen 5ef427bd65 gtk-demo: Expand columns in the settings demo
Expand the columns that are likely to appear
at the end.
2020-06-03 13:32:15 -04:00
Matthias Clasen 03c1fa43f4 inspector: Expand the actions list 2020-06-03 13:32:15 -04:00
Matthias Clasen 3b9f0ab866 inspector: Expand the resource list
This is an experiment with adding a filler column.
2020-06-03 13:32:15 -04:00
Matthias Clasen 9617a00ae3 inspector: Expand the property list
It looks better this way.
2020-06-03 13:32:15 -04:00
Matthias Clasen 1408199957 inspector: Expand the object tree
This is how it used to look, and it looks better that way.
2020-06-03 13:32:15 -04:00
Matthias Clasen 067df8d4dd columnview: Take expand into account
When allocating columns, distribute extra space
to columns that have expand set to TRUE.
2020-06-03 13:32:15 -04:00
Matthias Clasen 2ab1b13092 columnview: Add a GtkColumnViewColumn:expand property
This will be used to determine how to distribute
available extra space in a column view.
2020-06-03 13:32:15 -04:00
Matthias Clasen 964d0c219a columnview: Add autoscroll
Autoscroll when the pointer gets close to the
edge during column resizing or reordering. This
is similar to what the treeview does, but it is
implemented using a tick callback, and has
variable speed.
2020-06-03 13:31:39 -04:00
Matthias Clasen c58eb9c276 columnview: Allow to cancel reorder with Escape
The treeview does this too.
2020-06-03 13:31:39 -04:00
Matthias Clasen 5d4893b3f0 columnview: Interactive column reordering
Allow rearranging columns by dragging, in the same
way the treeview does.

We add the "dnd" style class to the header while
it is dragged, and we move the header of the dragged
column to the end of its parents children, so that
it gets drawn on top.
2020-06-03 13:31:39 -04:00
Matthias Clasen 11b4e0d4c0 columnview: Add a GtkColumnView:reorderable property
This property controls if users can reorder columns
by drag-and-drop. It defaults to TRUE.
2020-06-03 13:31:39 -04:00
Matthias Clasen e637693131 columnviewlayout: Use header allocation for titles
Normally, this will be identical to the column
allocation, but we will temporarily change it
during column reordering.
2020-06-03 13:31:39 -04:00
Matthias Clasen c9d5b77403 columnviewcolumn: Add reordering helpers
Add helper functions that let us temporarily give
a different allocation to headers. These will be
used to implement interactive column reordering
in GtkColumnView.
2020-06-03 13:31:39 -04:00
Matthias Clasen 574595993c columnviewtitle: Trigger action on release
This is necessary to make drag-to-reorder work
without triggering resorting.
2020-06-03 13:31:31 -04:00
Matthias Clasen 50f4e53aef Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Add a dropdown demo

See merge request GNOME/gtk!2023
2020-06-03 17:30:19 +00:00
Matthias Clasen ac082e5504 gtk-demo: Make some columns resizable
Make the columns in the List > Settings demo
resizable, to demonstrate this functionality.
2020-06-03 12:49:40 -04:00
Matthias Clasen f65f9591a1 columnview: Interactive column resizing
This copies just enough of the treeview code to
get columns moving.
2020-06-03 12:49:40 -04:00
Matthias Clasen a1eadde25b columnviewcolumn: Add a helper
We need to check whether clicks are in the headers
of columns, so let the column view get at the the
header widget.
2020-06-03 12:49:40 -04:00
Matthias Clasen 66e5027756 columnview: Add a GtkColumnViewColumn:resizable property
This will be used for interactive column resizing
in the future.
2020-06-03 12:49:38 -04:00
Matthias Clasen aa2d339508 columnview: Add a helper
The column code needs to get access to the
listitem widgets that are children of the listview,
so add a getter.
2020-06-03 12:48:56 -04:00
Matthias Clasen d43aacefc9 columnview: Add GtkColumnViewColumn:fixed-width
Add a fixed-width property similar to the same property
of GtkTreeViewColumn.
2020-06-03 12:48:39 -04:00
Matthias Clasen f0a0e20b2f columnview: Implement horizontal scrolling
The listview inside always thinks it gets its full size,
and updates its horizontal adjustment accordingly.

So keep our own adjustment, and update it when allocating.
2020-06-03 12:48:20 -04:00
Matthias Clasen befdd8bb66 columnview: Revise scroll-minimum handling
Tweak the behavior slightly. We don't show
a scrollbar as long as we have at least
min-size available, but we still give the
entire size to the child, up to nat-size.

This matches how viewports handle scroll-minimum.
2020-06-03 12:48:20 -04:00
Benjamin Otte 27ed2cc009 Merge branch 'wip/otte/for-master' into 'master'
Wip/otte/for master

See merge request GNOME/gtk!2022
2020-06-03 16:33:54 +00:00
Benjamin Otte a60c866a12 listbase: Don't grab_focus() when moving focus
We want to call gtk_widget_child_focus() to have Tab focus the right
widget.
2020-06-03 18:12:49 +02:00
Benjamin Otte a84f6228ca listitemwidget: Fix focus handling for columnview
ListItemWidget needs to be aware of potentially having multiple
children, so make it aware.
2020-06-03 18:12:00 +02:00
Matthias Clasen 19da93b675 Merge branch 'columnview-menu' into 'master'
columnview: Add header menus

See merge request GNOME/gtk!2001
2020-06-03 15:51:26 +00:00
Benjamin Otte aa38fc712f listbase: Fix leak
We were leaking the temporary tracker here.
2020-06-03 17:49:04 +02:00
Matthias Clasen 0b1c91dc7c gtk-demo: Add a dropdown demo
This shows a few examples of GtkDropDown.
Mostly taken from tests/testdropdown.c.
2020-06-03 11:34:06 -04:00
Matthias Clasen ab2c8de4de Merge branch 'matthiasc/for-master' into 'master'
selection model: Further documentation tweaks

See merge request GNOME/gtk!2021
2020-06-03 15:11:59 +00:00
Benjamin Otte 00f2b134e3 columnview: Make sure focus can move into cells
The cells themselves should never be focusable though.
2020-06-03 16:55:39 +02:00
Benjamin Otte 0b8cebd6ef ffmediafile: Add fixes for recent cflags changes
Related: #2771
2020-06-03 16:23:49 +02:00
Matthias Clasen 53a9b7f6c0 selection model: Further documentation tweaks
Reword this to use plain language instead of throwing
arond reentrancy and ordering.
2020-06-03 07:51:29 -04:00
Matthias Clasen 667fd927ee Merge branch 'selection-model-docs' into 'master'
selectionmodel: Clarify docs

Closes #2806

See merge request GNOME/gtk!2017
2020-06-03 05:27:46 +00:00
Matthias Clasen a8956838d3 selectionmodel: Clarify docs
Clarify some things that were not clear to me before
discussing them.

Fixes: #2806
2020-06-02 15:09:16 -04:00
Matthias Clasen f6be407e33 Merge branch 'carlosgc/emoji-chooser-fixes' into 'master'
Fix emoji chooser warnings on destroy

See merge request GNOME/gtk!2016
2020-06-02 16:06:47 +00:00
Carlos Garcia Campos 2bf9b37e59 emojichooser: Unparent the variations popup on dispose and before adding a new one
This was causing warnings when destroying the emoji chooser because it
had children left.
2020-06-02 16:47:56 +02:00
Carlos Garcia Campos d2e0ada794 textview: Unparent the emoji chooser on dispose
This was causing the warning "GtkEmojiChooser is not a child of
GtkTextView" when destroying a GtkTextView if the emoji chooser was
shown.
2020-06-02 16:47:56 +02:00
Matthias Clasen c07ae5806e Merge branch 'matthiasc/for-master' into 'master'
Cosmetic improvements to the filebrowser demo

See merge request GNOME/gtk!2015
2020-06-02 04:30:29 +00:00
Matthias Clasen 5afe6f7825 Cosmetic improvements to the filebrowser demo
Make it look good.
2020-06-01 23:13:20 -04:00
Matthias Clasen d02c48f987 Add more columns to the settings demo
Flesh out this demo more, so we can have a
non-trivial column editor here at some point.
2020-06-01 22:10:53 -04:00
Matthias Clasen c835214540 Add a header menu to settings demo
Allow toggling column visibility from here.
2020-06-01 22:10:53 -04:00
Matthias Clasen cb2901ec40 columnviewtitle: Display a context menu
When the ::header-menu property is set on the
column, use the menu model to create and show
a context menu.
2020-06-01 22:10:53 -04:00
Matthias Clasen f27bd061fb columnviewcolumn: Add a menu property
Add a ::header-menu property that will be used
to create a context menu for the header of the
column.
2020-06-01 22:10:53 -04:00
Matthias Clasen 572386e4ce Merge branch 'matthiasc/for-master' into 'master'
print backend: Fix list model handling in dispose

See merge request GNOME/gtk!2013
2020-06-02 00:07:45 +00:00
Matthias Clasen 67a972182e Merge branch 'ebassi/expression-type' into 'master'
Ebassi/expression type

See merge request GNOME/gtk!2014
2020-06-01 22:48:26 +00:00
Matej Urbančič 5955e11a5a Added Slovenian translation 2020-06-01 22:19:55 +02:00
Emmanuele Bassi 8daaafc864 Document how to define properties using GtkExpression
Use the GtkParamSpecExpression type to describe the property, and the
GValue API to set and get the expression instance.
2020-06-01 21:17:34 +01:00
Emmanuele Bassi ebaa96c0fa Turn GtkExpression into a GTypeInstance
Since it's a type with sub-classes, we need to use GTypeInstance (at the
very least), otherwise we won't be able to address each sub-class as
such.

This is similar to how GskRenderNode and GdkEvent are handled, with the
added difficulty that GtkExpression is meant to be used in properties,
in order to be deserialised by GtkBuilder. This requires adding a
GParamSpec sub-class that we can match on from within GtkBuilder,
alongside some convenience API for storing a GtkExpression inside a
GValue.
2020-06-01 21:07:53 +01:00
Emmanuele Bassi fb3d08c651 Print out the file name we're testing
We're printing out the file we're testing once we succeed, but it's hard
to know which file caused a failure. Let's add a g_test_message()
directive so we can look in our logs.
2020-06-01 21:06:04 +01:00
Matthias Clasen 9d15e64f0b gtk-demo: Plug a leak
We were leaking a reference to the settings demo.
This showed up as gtk4-demo --run listview_settings
not exiting when the window is closed.
2020-06-01 15:17:21 -04:00
Matthias Clasen b62564fd98 columnviewcolumn: Fix visibility implementation
We were not properly syncing initial visibility
with widgets.
2020-06-01 14:47:12 -04:00
Matthias Clasen 0266bcab7a Add a test for the previous fix
This checks that action muxer hierarchy is properly
updated when muxers appear in the middle.
2020-06-01 13:52:50 -04:00
Matthias Clasen 6652e14662 Update action muxer hierarchy propertly
When a new muxer appears, we must not only make it
inherit from the parent, we also have to update all
children to inherit from it.
2020-06-01 13:52:42 -04:00
Matthias Clasen 7a50f86f3f print backend: Fix list model handling in dispose
The print backends do some complicated dispose handling
where the implementations call gtk_print_backend_destroy().

Our tests (in particular, the templates test) trigger
situations where we use print backends after dispose,
and they can't handle the printers listmodel being
NULL at that time. So just remove the printers in
dispose, keep the empty liststore until finalize.
2020-06-01 13:52:21 -04:00
Kukuh Syafaat 59218d02c8 Update Indonesian translation 2020-06-01 13:29:20 +00:00
Matthias Clasen fe73730d21 Merge branch 'gtk-demo-run-no-main-window' into 'master'
gtk-demo: Don't show main window if --run is passed in

See merge request GNOME/gtk!1979
2020-06-01 12:26:15 +00:00
Matthias Clasen b814970bdd Merge branch 'fix-frameclock-going-backwards' into 'master'
Fix frameclock going backwards

See merge request GNOME/gtk!2011
2020-06-01 12:25:20 +00:00
Alexander Larsson a36e2bc764 Fix frameclock going backwards
When we run the frameclock RUN_FLUSH_IDLE idle before the paint,
then gdk_frame_clock_flush_idle() sets
```
  priv->phase = GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT
```
at the end if there is a paint comming.

But, before doing the paint cycle it may handle other X events, and
during that time the phase is set to BEFORE_PAINT. This means that the
current check on whether we're inside a paint is wrong:

```
  if (priv->phase != GDK_FRAME_CLOCK_PHASE_NONE &&
     priv->phase != GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS)
    return priv->smoothed_frame_time_base;
```

This caused us to sometimes use this smoothed_frame_time_base even
though we previously reported a later value during PHASE_NONE, thus
being non-monotonic.

We can't just additionally check for the BEGIN_PAINT phase though,
becasue if we are in the paint loop actually doing that phase we
should use the time base. Instead we check for `!(BEFORE_PAINT &&
in_paint_idle)`.
2020-06-01 10:53:24 +02:00
Alexander Larsson 0bd039a524 gtk-demo: Don't show main window if --run is passed in
Also, in that case, exit when the demo window is closed.
2020-05-29 13:51:31 +02:00
240 changed files with 17005 additions and 8855 deletions
+12 -15
View File
@@ -17,7 +17,12 @@ stages:
# Common variables
variables:
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true -Dvulkan=yes"
FEATURE_FLAGS: "-Dcloudproviders=true"
MESON_TEST_TIMEOUT_MULTIPLIER: 2
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v18"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19"
.only-default:
only:
@@ -27,14 +32,14 @@ variables:
style-check-diff:
extends: .only-default
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
image: $FEDORA_IMAGE
stage: .pre
allow_failure: true
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
image: $FEDORA_IMAGE
artifacts:
when: always
reports:
@@ -66,11 +71,7 @@ fedora-x86_64:
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
-Dprofiler=true
_build
- ninja -C _build
@@ -84,11 +85,7 @@ release-build:
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
@@ -117,7 +114,7 @@ msys2-mingw32:
CHERE_INVOKING: "yes"
.flatpak-defaults:
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
image: $FLATPAK_IMAGE
stage: flatpak
allow_failure: true
tags:
@@ -171,7 +168,7 @@ flatpak-master:icon-browser:
APPID: org.gtk.IconBrowser4
static-scan:
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v16
image: $FEDORA_IMAGE
stage: analysis
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug"
@@ -184,7 +181,7 @@ static-scan:
allow_failure: true
reference:
image: registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19
image: $DOCS_IMAGE
stage: docs
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
+1
View File
@@ -42,6 +42,7 @@ RUN dnf -y install \
json-glib-devel \
lcov \
libattr-devel \
libcloudproviders-devel \
libepoxy-devel \
libffi-devel \
libmount-devel \
+1 -1
View File
@@ -1,4 +1,4 @@
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v19
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v20
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
+89
View File
@@ -1,3 +1,92 @@
Overview of Changes in GTK 3.98.5
=================================
* Introduce new list widgets and supporting infrastructure.
The main APIs are:
- GtkListView
- GtkGridView
- GtkColumnView and GtkColumnViewColumn
- GtkDropDown
- GtkListItemFactory and implementations
- GtkExpression
- GtkFilter and subclasses, and GtkFilterListModel
- GtkSorter and subclasses, and GtkSortListModel
- GtkSelectionModel and subclasses
- GtkTreeListModel, GtkTreeExpander and GtkTreeListRowSorter
* GtkFileChooser:
- Add a tracker3-based search engine implementation
- Rate-limit updates from the trash monitor
* GtkWindow:
- Redo the css node setup. There is now a single 'window' node
- Fix rounded corners on tiled windows
* GtkApplication:
- Drop app menu support. Menubar support is still there
* GtkFixed:
- Change coordinate APIs to take doubles
* GtkOverlay:
- Make GtkOverlayLayout public
* GtkTooltips:
- Fix line wrapping of tooltips
* Shortcuts:
- Fix mnemonic cycling
- Fix using '0' as a mnemonic
* Menus:
- Differentiate keypad keys in accelerators
* GtkIMContext:
- Add gtk_im_context_filter_key to allow event reinjection
* Themes:
- Adwaita: Limit the scope of backdrop
* Accessibility:
- Clean up and reorganize the code to prepare for the
dropping of ATK
* GDK:
- Drop unused enum and struct definitions from headers
- Make keymap translation API public again. Still needed
- Frameclock: Always use compositor refresh rate info
- Frameclock: Use quadratic correction for frame time jitter
- Frameclock: Ensure monotonicity
- Frameclock: Track resason for paint
- X11: Improve sync when the Nvidia driver is used
* GSK:
- GL renderer: Fix blurred outset shadows
- GL renderer: handle nested transform nodes properly
- GL renderer: Optimize clip handling
* gtk-demo:
- Improve the Drag-and-Drop demo with proper drag icons
- Don't show the main window if --run is given
- Add demos for list widgets and GtkDropDrown
* Documentation:
- Convert freestanding sections to markdown
- Drop the glossary
- Expand and improve the migration guide
* Build:
- We require pandoc now, for building the documentation
- Require Pango 1.45
* Translation updates:
Polish
Romanian
Slovenian
Turkish
Ukrainian
Overview of Changes in GTK 3.98.4
=================================
+3
View File
@@ -123,6 +123,9 @@
/* Have the Xcursor library */
#mesondefine HAVE_XCURSOR
/* Have the XDAMAGE X extension */
#mesondefine HAVE_XDAMAGE
/* Have the XFIXES X extension */
#mesondefine HAVE_XFIXES
-247
View File
@@ -1,247 +0,0 @@
/*
* Copyright © 2018 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 "award.h"
struct _GtkAward
{
GObject parent;
char *explanation;
char *name;
char *title;
GDateTime *granted; /* or NULL if not granted */
};
enum {
PROP_0,
PROP_EXPLANATION,
PROP_NAME,
PROP_TITLE,
PROP_GRANTED,
N_PROPS,
};
static GParamSpec *properties[N_PROPS] = { NULL, };
G_DEFINE_TYPE (GtkAward, gtk_award, G_TYPE_OBJECT)
static void
gtk_award_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkAward *self = GTK_AWARD (object);
switch (prop_id)
{
case PROP_EXPLANATION:
self->explanation = g_value_dup_string (value);
break;
case PROP_NAME:
self->name = g_value_dup_string (value);
break;
case PROP_TITLE:
self->title = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_award_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkAward *self = GTK_AWARD (object);
switch (prop_id)
{
case PROP_EXPLANATION:
g_value_set_string (value, self->explanation);
break;
case PROP_NAME:
g_value_set_string (value, self->name);
break;
case PROP_TITLE:
g_value_set_string (value, self->title);
break;
case PROP_GRANTED:
g_value_set_boxed (value, self->granted);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_award_dispose (GObject *object)
{
GtkAward *self = GTK_AWARD (object);
g_clear_pointer (&self->name, g_free);
g_clear_pointer (&self->title, g_free);
g_clear_pointer (&self->granted, g_date_time_unref);
G_OBJECT_CLASS (gtk_award_parent_class)->dispose (object);
}
static void
gtk_award_class_init (GtkAwardClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
gobject_class->set_property = gtk_award_set_property;
gobject_class->get_property = gtk_award_get_property;
gobject_class->dispose = gtk_award_dispose;
properties[PROP_EXPLANATION] =
g_param_spec_string ("explanation",
"Explanation",
"How to get the title",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_NAME] =
g_param_spec_string ("name",
"Name",
"internal name of the award",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_TITLE] =
g_param_spec_string ("title",
"Title",
"user-visible title",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_GRANTED] =
g_param_spec_boxed ("granted",
"Granted",
"Timestamp the award was granted or NULL if not granted yet",
G_TYPE_DATE_TIME,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gtk_award_init (GtkAward *self)
{
}
GListModel *
gtk_award_get_list (void)
{
static GListModel *list = NULL;
if (list == NULL)
{
GtkBuilder *builder;
g_type_ensure (GTK_TYPE_AWARD);
builder = gtk_builder_new_from_resource ("/awards.ui");
list = G_LIST_MODEL (gtk_builder_get_object (builder, "list"));
g_object_ref (list);
g_object_unref (builder);
}
return g_object_ref (list);
}
const char *
gtk_award_get_name (GtkAward *award)
{
return award->name;
}
const char *
gtk_award_get_title (GtkAward *award)
{
return award->title;
}
GDateTime *
gtk_award_get_granted (GtkAward *award)
{
return award->granted;
}
GtkAward *
award_find (const char *name)
{
GListModel *list;
GtkAward *self;
guint i;
list = gtk_award_get_list ();
g_object_unref (list);
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
self = g_list_model_get_item (list, i);
g_object_unref (self);
if (g_ascii_strcasecmp (name, self->name) == 0)
return self;
}
return NULL;
}
void
award (const char *name)
{
GtkAward *self;
GNotification *notification;
self = award_find (name);
if (self == NULL)
{
g_warning ("Did not find award \"%s\"", name);
return;
}
if (self->granted)
return;
self->granted = g_date_time_new_now_utc ();
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_GRANTED]);
notification = g_notification_new ("You won an award!");
g_notification_set_body (notification, self->title);
g_application_send_notification (g_application_get_default (), NULL, notification);
g_object_unref (notification);
}
-18
View File
@@ -1,18 +0,0 @@
#ifndef __AWARD_H__
#define __AWARD_H__
#include <gtk/gtk.h>
#define GTK_TYPE_AWARD (gtk_award_get_type ())
G_DECLARE_FINAL_TYPE (GtkAward, gtk_award, GTK, AWARD, GObject)
GListModel * gtk_award_get_list (void);
const char * gtk_award_get_name (GtkAward *award);
const char * gtk_award_get_title (GtkAward *award);
GDateTime * gtk_award_get_granted (GtkAward *award);
void award (const char *name);
#endif /* __AWARD_H__ */
-18
View File
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="gtk40">
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<binding name="label">
<lookup name="title" type="GtkAward">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
</object>
</property>
</template>
</interface>
-89
View File
@@ -1,89 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GListStore" id="list">
<property name="item-type">GtkAward</property>
<child>
<object class="GtkAward">
<property name="name">demo-inspector</property>
<!-- Transformers -->
<property name="title" translatable="yes">You got a high-rise double-pump carburetor.</property>
<property name="explanation" translatable="yes">Launch the inspector</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">demo-start</property>
<!-- The Matrix -->
<property name="title" translatable="yes">After this, there is no turning back.</property>
<property name="explanation" translatable="yes">Start gtk-demo</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">listbox-reshare</property>
<!-- Mean Girls -->
<property name="title" translatable="yes">Trying to make fetch happen</property>
<property name="explanation" translatable="yes">Reshare a tweet</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">listbox-100th-row</property>
<!-- Aladdin -->
<property name="title" translatable="yes">The ever impressive, long contained, often imitated, but never duplicated Genie of the lamp.</property>
<property name="explanation" translatable="yes">Select a 100th row in a list</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">password-best</property>
<!-- Spaceballs -->
<property name="title" translatable="yes">I've got the same combination on my luggage!</property>
<property name="explanation" translatable="yes">Use "12345" as the password</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">password-correct</property>
<!-- Stanley Parable -->
<property name="title" translatable="yes">Night Shark 1-1-5</property>
<property name="explanation" translatable="yes">Correctly enter a password</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">puzzle-give-up</property>
<!-- Pretty Woman -->
<property name="title" translatable="yes">Big Mistake. Big. Huge!</property>
<property name="explanation" translatable="yes">Close the puzzle without finishing it</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">puzzle-solve</property>
<!-- The Incredibles -->
<property name="title" translatable="yes">That was totally wicked!</property>
<property name="explanation" translatable="yes">Solve a puzzle</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">puzzle-solve-animated</property>
<!-- The Phantom Menace -->
<property name="title" translatable="yes">A surprise to be sure but a welcome one.</property>
<property name="explanation" translatable="yes">Solve an animated puzzle</property>
</object>
</child>
<child>
<object class="GtkAward">
<property name="name">puzzle-solve-large</property>
<!-- Portal -->
<property name="title" translatable="yes">Science isn't about WHY. It's about WHY NOT?!</property>
<property name="explanation" translatable="yes">Solve a puzzle with at least 20 pieces</property>
</object>
</child>
</object>
</interface>
-48
View File
@@ -1,48 +0,0 @@
/* Awards
*
* This demo demonstrates how to use lists to show the awards you have collected
* while exploring this demo.
*
*/
#include <gtk/gtk.h>
/* Include the header for accessing the awards */
#include "award.h"
static GtkWidget *window = NULL;
GtkWidget *
do_awardview (GtkWidget *do_widget)
{
if (!window)
{
GtkWidget *sw, *listview;
GListModel *list;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Awards");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), sw);
listview = gtk_list_view_new_with_factory (
gtk_builder_list_item_factory_new_from_resource (NULL, "/awardview/awardlistitem.ui"));
list = gtk_award_get_list ();
gtk_list_view_set_model (GTK_LIST_VIEW (listview), list);
g_object_unref (list);
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+2 -2
View File
@@ -1,7 +1,7 @@
/* Constraints/Interactive
*
* Demonstrate how constraints can be updates during
* user interaction.
* Demonstrate how constraints can be updates during user interaction.
* The vertical edge between the buttons can be dragged with the mouse.
*/
#include <glib/gi18n.h>
+3 -4
View File
@@ -1,9 +1,8 @@
/* Cursors
*
* Demonstrates a useful set of available cursors. The cursors shown here are the ones
* defined by CSS, which we assume to be available.
*
* The example shows creating cursors by name or from an image, with or without a fallback.
* Demonstrates a useful set of available cursors. The cursors shown here are the
* ones defined by CSS, which we assume to be available. The example shows creating
* cursors by name or from an image, with or without a fallback.
*/
#include <gtk/gtk.h>
+3 -5
View File
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/">
<file>awards.ui</file>
</gresource>
<gresource prefix="/ui">
<file preprocess="xml-stripblanks">main.ui</file>
@@ -12,9 +11,6 @@
<file>application.ui</file>
<file>menus.ui</file>
</gresource>
<gresource prefix="/awardview">
<file>awardlistitem.ui</file>
</gresource>
<gresource prefix="/builder">
<file>demo.ui</file>
</gresource>
@@ -127,6 +123,7 @@
</gresource>
<gresource prefix="/listview_filebrowser">
<file>listview_filebrowser.ui</file>
<file>listview_filebrowser.css</file>
</gresource>
<gresource prefix="/listview_minesweeper">
<file>listview_minesweeper.ui</file>
@@ -177,7 +174,6 @@
</gresource>
<gresource prefix="/sources">
<file>application_demo.c</file>
<file>awardview.c</file>
<file>assistant.c</file>
<file>builder.c</file>
<file>clipboard.c</file>
@@ -194,6 +190,7 @@
<file>cursors.c</file>
<file>dialog.c</file>
<file>drawingarea.c</file>
<file>dropdown.c</file>
<file>dnd.c</file>
<file>editable_cells.c</file>
<file>entry_completion.c</file>
@@ -218,6 +215,7 @@
<file>infobar.c</file>
<file>links.c</file>
<file>listbox.c</file>
<file>listview_applauncher.c</file>
<file>listview_colors.c</file>
<file>listview_clocks.c</file>
<file>listview_filebrowser.c</file>
+305
View File
@@ -0,0 +1,305 @@
/* Drop Downs
*
* The GtkDropDown widget is a modern alternative to GtkComboBox.
* It uses list models instead of tree models, and the content is
* displayed using widgets instead of cell renderers.
*
* The examples here demonstrate how to use different kinds of
* list models with GtkDropDown, how to use search and how to
* display the selected item differently from the presentation
* in the popup.
*/
#include <gtk/gtk.h>
#define STRING_TYPE_HOLDER (string_holder_get_type ())
G_DECLARE_FINAL_TYPE (StringHolder, string_holder, STRING, HOLDER, GObject)
struct _StringHolder {
GObject parent_instance;
char *title;
char *icon;
char *description;
};
G_DEFINE_TYPE (StringHolder, string_holder, G_TYPE_OBJECT);
static void
string_holder_init (StringHolder *holder)
{
}
static void
string_holder_finalize (GObject *object)
{
StringHolder *holder = STRING_HOLDER (object);
g_free (holder->title);
g_free (holder->icon);
g_free (holder->description);
G_OBJECT_CLASS (string_holder_parent_class)->finalize (object);
}
static void
string_holder_class_init (StringHolderClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = string_holder_finalize;
}
static StringHolder *
string_holder_new (const char *title, const char *icon, const char *description)
{
StringHolder *holder = g_object_new (STRING_TYPE_HOLDER, NULL);
holder->title = g_strdup (title);
holder->icon = g_strdup (icon);
holder->description = g_strdup (description);
return holder;
}
static void
strings_setup_item_single_line (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *box, *image, *title;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
image = gtk_image_new ();
title = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
gtk_box_append (GTK_BOX (box), image);
gtk_box_append (GTK_BOX (box), title);
g_object_set_data (G_OBJECT (item), "title", title);
g_object_set_data (G_OBJECT (item), "image", image);
gtk_list_item_set_child (item, box);
}
static void
strings_setup_item_full (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *box, *box2, *image, *title, *description;
image = gtk_image_new ();
title = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
description = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (description), 0.0);
gtk_style_context_add_class (gtk_widget_get_style_context (description), "dim-label");
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_box_append (GTK_BOX (box), image);
gtk_box_append (GTK_BOX (box), box2);
gtk_box_append (GTK_BOX (box2), title);
gtk_box_append (GTK_BOX (box2), description);
g_object_set_data (G_OBJECT (item), "title", title);
g_object_set_data (G_OBJECT (item), "image", image);
g_object_set_data (G_OBJECT (item), "description", description);
gtk_list_item_set_child (item, box);
}
static void
strings_bind_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *image, *title, *description;
StringHolder *holder;
holder = gtk_list_item_get_item (item);
title = g_object_get_data (G_OBJECT (item), "title");
image = g_object_get_data (G_OBJECT (item), "image");
description = g_object_get_data (G_OBJECT (item), "description");
gtk_label_set_label (GTK_LABEL (title), holder->title);
if (image)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), holder->icon);
gtk_widget_set_visible (image, holder->icon != NULL);
}
if (description)
{
gtk_label_set_label (GTK_LABEL (description), holder->description);
gtk_widget_set_visible (description , holder->description != NULL);
}
}
static GtkListItemFactory *
strings_factory_new (gboolean full)
{
GtkListItemFactory *factory;
factory = gtk_signal_list_item_factory_new ();
if (full)
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_full), NULL);
else
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_single_line), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (strings_bind_item), NULL);
return factory;
}
static GListModel *
strings_model_new (const char *const *titles,
const char *const *icons,
const char *const *descriptions)
{
GListStore *store;
int i;
store = g_list_store_new (STRING_TYPE_HOLDER);
for (i = 0; titles[i]; i++)
{
StringHolder *holder = string_holder_new (titles[i],
icons ? icons[i] : NULL,
descriptions ? descriptions[i] : NULL);
g_list_store_append (store, holder);
g_object_unref (holder);
}
return G_LIST_MODEL (store);
}
static GtkWidget *
drop_down_new_from_strings (const char *const *titles,
const char *const *icons,
const char *const *descriptions)
{
GtkWidget *widget;
GListModel *model;
GtkListItemFactory *factory;
GtkListItemFactory *list_factory;
g_return_val_if_fail (titles != NULL, NULL);
g_return_val_if_fail (icons == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)titles), NULL);
g_return_val_if_fail (descriptions == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)descriptions), NULL);
model = strings_model_new (titles, icons, descriptions);
factory = strings_factory_new (FALSE);
if (icons != NULL || descriptions != NULL)
list_factory = strings_factory_new (TRUE);
else
list_factory = NULL;
widget = g_object_new (GTK_TYPE_DROP_DOWN,
"model", model,
"factory", factory,
"list-factory", list_factory,
NULL);
g_object_unref (model);
g_object_unref (factory);
if (list_factory)
g_object_unref (list_factory);
return widget;
}
static char *
get_family_name (gpointer item)
{
return g_strdup (pango_font_family_get_name (PANGO_FONT_FAMILY (item)));
}
static char *
get_title (gpointer item)
{
return g_strdup (STRING_HOLDER (item)->title);
}
GtkWidget *
do_dropdown (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *button, *box, *spin, *check;
GListModel *model;
GtkExpression *expression;
const char * const times[] = { "1 minute", "2 minutes", "5 minutes", "20 minutes", NULL };
const char * const many_times[] = {
"1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
"25 minutes", "30 minutes", "35 minutes", "40 minutes", "45 minutes", "50 minutes",
"55 minutes", "1 hour", "2 hours", "3 hours", "5 hours", "6 hours", "7 hours",
"8 hours", "9 hours", "10 hours", "11 hours", "12 hours", NULL
};
const char * const device_titles[] = { "Digital Output", "Headphones", "Digital Output", "Analog Output", NULL };
const char * const device_icons[] = { "audio-card-symbolic", "audio-headphones-symbolic", "audio-card-symbolic", "audio-card-symbolic", NULL };
const char * const device_descriptions[] = {
"Built-in Audio", "Built-in audio", "Thinkpad Tunderbolt 3 Dock USB Audio", "Thinkpad Tunderbolt 3 Dock USB Audio", NULL
};
if (!window)
{
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Drop Downs");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_widget_set_margin_start (box, 10);
gtk_widget_set_margin_end (box, 10);
gtk_widget_set_margin_top (box, 10);
gtk_widget_set_margin_bottom (box, 10);
gtk_window_set_child (GTK_WINDOW (window), box);
button = gtk_drop_down_new ();
model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
gtk_drop_down_set_selected (GTK_DROP_DOWN (button), 0);
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_family_name,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
gtk_expression_unref (expression);
gtk_box_append (GTK_BOX (box), button);
spin = gtk_spin_button_new_with_range (-1, g_list_model_get_n_items (G_LIST_MODEL (model)), 1);
gtk_widget_set_halign (spin, GTK_ALIGN_START);
g_object_bind_property (button, "selected", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), spin);
check = gtk_check_button_new_with_label ("Enable search");
g_object_bind_property (button, "enable-search", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), check);
g_object_unref (model);
button = drop_down_new_from_strings (times, NULL, NULL);
gtk_box_append (GTK_BOX (box), button);
button = drop_down_new_from_strings (many_times, NULL, NULL);
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_title,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
gtk_expression_unref (expression);
gtk_box_append (GTK_BOX (box), button);
button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
gtk_box_append (GTK_BOX (box), button);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+2 -2
View File
@@ -1,4 +1,4 @@
/* Fixed layout
/* Fixed Layout
*
* GtkFixed is a container that allows placing and transforming
* widgets manually.
@@ -126,7 +126,7 @@ create_demo_window (GtkWidget *do_widget)
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Fixed layout");
gtk_window_set_title (GTK_WINDOW (window), "Fixed Layout");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
+2 -3
View File
@@ -1,9 +1,8 @@
/* Flow Box
*
* GtkFlowBox allows flexible and responsive grids which reflow
* as needed and support sorting and filtering.
*
* The children of a GtkFlowBox are regular widgets
* as needed and support sorting and filtering. The children of
* a GtkFlowBox are regular widgets
*
* The dataset used here has 665 colors.
*/
+37 -30
View File
@@ -25,7 +25,7 @@ typedef struct _GtkFishbowlChild GtkFishbowlChild;
struct _GtkFishbowlPrivate
{
GtkFishCreationFunc creation_func;
GList *children;
GHashTable *children;
guint count;
gint64 last_frame_time;
@@ -67,6 +67,8 @@ gtk_fishbowl_init (GtkFishbowl *fishbowl)
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
priv->update_delay = G_USEC_PER_SEC;
priv->children = g_hash_table_new_full (NULL, NULL,
NULL, (GDestroyNotify) g_free);
}
/**
@@ -93,16 +95,18 @@ gtk_fishbowl_measure (GtkWidget *widget,
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GHashTableIter iter;
gpointer key, value;
GtkFishbowlChild *child;
GList *children;
gint child_min, child_nat;
*minimum = 0;
*natural = 0;
for (children = priv->children; children; children = children->next)
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
{
child = children->data;
child = value;
if (!gtk_widget_get_visible (child->widget))
continue;
@@ -136,11 +140,13 @@ gtk_fishbowl_size_allocate (GtkWidget *widget,
GtkFishbowlChild *child;
GtkAllocation child_allocation;
GtkRequisition child_requisition;
GList *children;
GHashTableIter iter;
gpointer key, value;
for (children = priv->children; children; children = children->next)
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
{
child = children->data;
child = value;
if (!gtk_widget_get_visible (child->widget))
continue;
@@ -181,7 +187,7 @@ gtk_fishbowl_add (GtkFishbowl *fishbowl,
gtk_widget_set_parent (widget, GTK_WIDGET (fishbowl));
priv->children = g_list_prepend (priv->children, child_info);
g_hash_table_insert (priv->children, widget, child_info);
priv->count++;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
}
@@ -191,34 +197,32 @@ gtk_fishbowl_remove (GtkFishbowl *fishbowl,
GtkWidget *widget)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GtkFishbowlChild *child;
GtkWidget *widget_bowl = GTK_WIDGET (fishbowl);
GList *children;
for (children = priv->children; children; children = children->next)
if (g_hash_table_remove (priv->children, widget))
{
child = children->data;
gboolean was_visible = gtk_widget_get_visible (widget);
if (child->widget == widget)
{
gboolean was_visible = gtk_widget_get_visible (widget);
gtk_widget_unparent (widget);
gtk_widget_unparent (widget);
if (was_visible && gtk_widget_get_visible (widget_bowl))
gtk_widget_queue_resize (widget_bowl);
priv->children = g_list_remove_link (priv->children, children);
g_list_free (children);
g_free (child);
if (was_visible && gtk_widget_get_visible (widget_bowl))
gtk_widget_queue_resize (widget_bowl);
priv->count--;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
break;
}
priv->count--;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
}
}
static void
gtk_fishbowl_finalize (GObject *object)
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (object);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
g_hash_table_destroy (priv->children);
priv->children = NULL;
}
static void
gtk_fishbowl_dispose (GObject *object)
{
@@ -304,6 +308,7 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = gtk_fishbowl_finalize;
object_class->dispose = gtk_fishbowl_dispose;
object_class->set_property = gtk_fishbowl_set_property;
object_class->get_property = gtk_fishbowl_get_property;
@@ -535,8 +540,9 @@ gtk_fishbowl_tick (GtkWidget *widget,
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GtkFishbowlChild *child;
GList *l;
gint64 frame_time, elapsed;
GHashTableIter iter;
gpointer key, value;
gboolean do_update;
frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
@@ -548,9 +554,10 @@ gtk_fishbowl_tick (GtkWidget *widget,
if (elapsed == frame_time)
return G_SOURCE_CONTINUE;
for (l = priv->children; l; l = l->next)
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
{
child = l->data;
child = value;
child->x += child->dx * ((double) elapsed / G_USEC_PER_SEC);
child->y += child->dy * ((double) elapsed / G_USEC_PER_SEC);
-4
View File
@@ -8,7 +8,6 @@
#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
#include "award.h"
static GdkPixbuf *avatar_pixbuf_other;
static GtkWidget *window = NULL;
@@ -235,7 +234,6 @@ reshare_clicked (GtkMessageRow *row,
{
GtkMessageRowPrivate *priv = row->priv;
award ("listbox-reshare");
priv->message->n_reshares++;
gtk_message_row_update (row);
}
@@ -262,8 +260,6 @@ gtk_message_row_state_flags_changed (GtkWidget *widget,
visible = flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED) ? TRUE : FALSE;
gtk_widget_set_visible (priv->extra_buttons_box, visible);
if (visible && gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (widget)) % 100 == 99)
award ("listbox-100th-row");
GTK_WIDGET_CLASS (gtk_message_row_parent_class)->state_flags_changed (widget, previous_state_flags);
}
+202
View File
@@ -0,0 +1,202 @@
/* Lists/Application launcher
*
* This demo uses the GtkListView widget as a fancy application launcher.
*
* It is also a very small introduction to listviews.
*/
#include <gtk/gtk.h>
/* This is the function that creates the #GListModel that we need.
* GTK list widgets need a #GListModel to display, as models support change
* notifications.
* Unfortunately various older APIs do not provide list models, so we create
* our own.
*/
static GListModel *
create_application_list (void)
{
GListStore *store;
GList *apps, *l;
/* We use a #GListStore here, which is a simple array-like list implementation
* for manual management.
* List models need to know what type of data they provide, so we need to
* provide the type here. As we want to do a list of applications, #GAppInfo
* is the object we provide.
*/
store = g_list_store_new (G_TYPE_APP_INFO);
apps = g_app_info_get_all ();
for (l = apps; l; l = l->next)
g_list_store_append (store, l->data);
g_list_free_full (apps, g_object_unref);
return G_LIST_MODEL (store);
}
/* This is the function we use for setting up new listitems to display.
* We add just an #GtkImage and a #GtkKabel here to display the application's
* icon and name, as this is just a simple demo.
*/
static void
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box;
GtkWidget *image;
GtkWidget *label;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
image = gtk_image_new ();
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_box_append (GTK_BOX (box), image);
label = gtk_label_new ("");
gtk_box_append (GTK_BOX (box), label);
gtk_list_item_set_child (list_item, box);
}
/* Here we need to prepare the listitem for displaying its item. We get the
* listitem already set up from the previous function, so we can reuse the
* #GtkImage widget we set up above.
* We get the item - which we know is a #GAppInfo because it comes out of
* the model we set up above, grab its icon and display it.
*/
static void
bind_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *image;
GtkWidget *label;
GAppInfo *app_info;
image = gtk_widget_get_first_child (gtk_list_item_get_child (list_item));
label = gtk_widget_get_next_sibling (image);
app_info = gtk_list_item_get_item (list_item);
gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info));
gtk_label_set_label (GTK_LABEL (label), g_app_info_get_display_name (app_info));
}
/* In more complex code, we would also need functions to unbind and teardown
* the listitem, but this is simple code, so the default implementations are
* enough. If we had connected signals, this step would have been necessary.
*
* The #GtkSignalListItemFactory documentation contains more information about
* this step.
*/
/* This function is called whenever an item in the list is activated. This is
* the simple way to allow reacting to the Enter key or double-clicking on a
* listitem.
* Of course, it is possible to use far more complex interactions by turning
* off activation and adding buttons or other widgets in the setup function
* above, but this is a simple demo, so we'll use the simple way.
*/
static void
activate_cb (GtkListView *list,
guint position,
gpointer unused)
{
GAppInfo *app_info;
GdkAppLaunchContext *context;
GError *error = NULL;
app_info = g_list_model_get_item (gtk_list_view_get_model (list), position);
/* Prepare the context for launching the application and launch it. This
* code is explained in detail in the documentation for #GdkAppLaunchContext
* and #GAppInfo.
*/
context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (list)));
if (!g_app_info_launch (app_info,
NULL,
G_APP_LAUNCH_CONTEXT (context),
&error))
{
GtkWidget *dialog;
/* And because error handling is important, even a simple demo has it:
* We display an error dialog that something went wrong.
*/
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (list))),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Could not launch %s", g_app_info_get_display_name (app_info));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
g_clear_error (&error);
gtk_widget_show (dialog);
}
g_object_unref (context);
g_object_unref (app_info);
}
static GtkWidget *window = NULL;
GtkWidget *
do_listview_applauncher (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *list, *sw;
GListModel *model;
GtkListItemFactory *factory;
/* Create a window and set a few defaults */
window = gtk_window_new ();
gtk_window_set_default_size (GTK_WINDOW (window), 640, 320);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Application Launcher");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
/* The #GtkListitemFactory is what is used to create #GtkListItems
* to display the data from the model. So it is absolutely necessary
* to create one.
* We will use a #GtkSignalListItemFactory because it is the simplest
* one to use. Different ones are available for different use cases.
* The most powerful one is #GtkBuilderListItemFactory which uses
* #GtkBuilder .ui files, so it requires little code.
*/
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
/* Create the list widget here.
*/
list = gtk_list_view_new_with_factory (factory);
/* We connect the activate signal here. It's the function we defined
* above for launching the selected application.
*/
g_signal_connect (list, "activate", G_CALLBACK (activate_cb), NULL);
/* And of course we need to set the data model. Here we call the function
* we wrote above that gives us the list of applications. Then we set
* it on the list widget.
* The list will now take items from the model and use the factory
* to create as many listitems as it needs to show itself to the user.
*/
model = create_application_list ();
gtk_list_view_set_model (GTK_LIST_VIEW (list), model);
g_object_unref (model);
/* List widgets should always be contained in a #GtkScrolledWindow,
* because otherwise they might get too large or they might not
* be scrollable.
*/
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+53 -36
View File
@@ -3,10 +3,9 @@
* This demo displays the time in different timezones.
*
* The goal is to show how to set up expressions that track changes
* in objects and make them update widgets.
*
* For that, we create a GtkClock object that updates its time every
* second and then use various ways to display that time.
* in objects and make them update widgets. For that, we create a
* GtkClock object that updates its time every second and then use
* various ways to display that time.
*
* Typically, this will be done using GtkBuilder .ui files with the
* help of the <binding> tag, but this demo shows the code that runs
@@ -41,7 +40,8 @@ enum {
/* This function returns the current time in the clock's timezone.
* Note that this returns a new object every time, so we need to
* remember to unref it after use. */
* remember to unref it after use.
*/
static GDateTime *
gtk_clock_get_time (GtkClock *clock)
{
@@ -51,10 +51,11 @@ gtk_clock_get_time (GtkClock *clock)
return g_date_time_new_now_local ();
}
/* Here, we implement the functionality required by the GdkPaintable interface.
* This way we have a trivial way to display an analog clock.
* It also allows demonstrating how to directly use objects in the listview
* later by making this object do something interesting. */
/* Here, we implement the functionality required by the GdkPaintable
* interface. This way we have a trivial way to display an analog clock.
* It also allows demonstrating how to directly use objects in the
* listview later by making this object do something interesting.
*/
static void
gtk_clock_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
@@ -68,26 +69,31 @@ gtk_clock_snapshot (GdkPaintable *paintable,
#define BLACK ((GdkRGBA) { 0, 0, 0, 1 })
/* save/restore() is necessary so we can undo the transforms we start
* out with. */
* out with.
*/
gtk_snapshot_save (snapshot);
/* First, we move the (0, 0) point to the center of the area so
* we can draw everything relative to it. */
* we can draw everything relative to it.
*/
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2, height / 2));
/* Next we scale it, so that we can pretend that the clock is
* 100px in size. That way, we don't need to do any complicated
* math later.
* We use MIN() here so that we use the smaller dimension for sizing.
* That way we don't overdraw but keep the aspect ratio. */
* math later. We use MIN() here so that we use the smaller
* dimension for sizing. That way we don't overdraw but keep
* the aspect ratio.
*/
gtk_snapshot_scale (snapshot, MIN (width, height) / 100.0, MIN (width, height) / 100.0);
/* Now we have a circle with diameter 100px (and radius 50px) that
* has its (0, 0) point at the center.
* Let's draw a simple clock into it. */
/* Now we have a circle with diameter 100px (and radius 50px) that
* has its (0, 0) point at the center. Let's draw a simple clock into it.
*/
time = gtk_clock_get_time (self);
/* First, draw a circle. This is a neat little trick to draw a circle
* without requiring Cairo. */
* without requiring Cairo.
*/
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-50, -50, 100, 100), 50);
gtk_snapshot_append_border (snapshot,
&outline,
@@ -95,9 +101,11 @@ gtk_clock_snapshot (GdkPaintable *paintable,
(GdkRGBA [4]) { BLACK, BLACK, BLACK, BLACK });
/* Next, draw the hour hand.
* We do this using tranforms again: Instead of computing where the angle points
* to, we just rotate everything and then draw the hand as if if was :00.
* We don't even need to care about am/pm here because rotations just work. */
* We do this using tranforms again: Instead of computing where the angle
* points to, we just rotate everything and then draw the hand as if it
* was :00. We don't even need to care about am/pm here because rotations
* just work.
*/
gtk_snapshot_save (snapshot);
gtk_snapshot_rotate (snapshot, 30 * g_date_time_get_hour (time) + 0.5 * g_date_time_get_minute (time));
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -23, 4, 25), 2);
@@ -107,7 +115,8 @@ gtk_clock_snapshot (GdkPaintable *paintable,
gtk_snapshot_restore (snapshot);
/* And the same as above for the minute hand. Just make this one longer
* so people can tell the hands apart. */
* so people can tell the hands apart.
*/
gtk_snapshot_save (snapshot);
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_minute (time));
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 45), 2);
@@ -125,8 +134,9 @@ gtk_clock_snapshot (GdkPaintable *paintable,
gtk_snapshot_pop (snapshot);
gtk_snapshot_restore (snapshot);
/* And finally, don't forget to restore the initial save() that we did for
* the initial transformations. */
/* And finally, don't forget to restore the initial save() that
* we did for the initial transformations.
*/
gtk_snapshot_restore (snapshot);
g_date_time_unref (time);
@@ -145,10 +155,9 @@ gtk_clock_get_intrinsic_height (GdkPaintable *paintable)
return 100;
}
/* Initialize the paintable interface. This way we turn our clock objects
* into objects that can be drawn.
* There are more functions to this interface to define desired size,
* but this is enough.
/* Initialize the paintable interface. This way we turn our clocks
* into objects that can be drawn. There are more functions to this
* interface to define desired size, but this is enough.
*/
static void
gtk_clock_paintable_init (GdkPaintableInterface *iface)
@@ -158,8 +167,9 @@ gtk_clock_paintable_init (GdkPaintableInterface *iface)
iface->get_intrinsic_height = gtk_clock_get_intrinsic_height;
}
/* Finally, we define the type. The important part is adding the paintable
* interface, so GTK knows that this object can indeed be drawm.
/* Finally, we define the type. The important part is adding the
* paintable interface, so GTK knows that this object can indeed
* be drawn.
*/
G_DEFINE_TYPE_WITH_CODE (GtkClock, gtk_clock, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
@@ -221,11 +231,14 @@ gtk_clock_set_property (GObject *object,
/* This is the list of all the ticking clocks */
static GSList *ticking_clocks = NULL;
/* This is the id of the timeout source that is updating all ticking clocks */
/* This is the ID of the timeout source that is updating all
* ticking clocks.
*/
static guint ticking_clock_id = 0;
/* Every second, this function is called to tell everybody that the
* clocks are ticking.
/* Every second, this function is called to tell everybody that
* the clocks are ticking.
*/
static gboolean
gtk_clock_tick (gpointer unused)
@@ -240,6 +253,7 @@ gtk_clock_tick (gpointer unused)
* so notify about that.
*/
g_object_notify_by_pspec (G_OBJECT (clock), properties[PROP_TIME]);
/* We will also draw the hands of the clock differently.
* So notify about that, too.
*/
@@ -309,16 +323,16 @@ gtk_clock_init (GtkClock *self)
static GtkClock *
gtk_clock_new (const char *location,
GTimeZone *timezone)
GTimeZone *_timezone)
{
GtkClock *result;
result = g_object_new (GTK_TYPE_CLOCK,
"location", location,
"timezone", timezone,
"timezone", _timezone,
NULL);
g_clear_pointer (&timezone, g_time_zone_unref);
g_clear_pointer (&_timezone, g_time_zone_unref);
return result;
}
@@ -343,6 +357,9 @@ create_clocks_model (void)
clock = gtk_clock_new ("San Francisco", g_time_zone_new ("America/Los_Angeles"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Xalapa", g_time_zone_new ("America/Mexico_City"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Boston", g_time_zone_new ("America/New_York"));
g_list_store_append (result, clock);
g_object_unref (clock);
+19 -4
View File
@@ -6,11 +6,13 @@
* and sort the data in various ways. The controls for
* this are implemented using GtkDropDown.
*
* The dataset used here has 9283 items.
* The dataset used here has 9283 items.
*/
#include <gtk/gtk.h>
#include <stdlib.h>
#define GTK_TYPE_COLOR (gtk_color_get_type ())
G_DECLARE_FINAL_TYPE (GtkColor, gtk_color, GTK, COLOR, GObject)
@@ -23,6 +25,7 @@ struct _GtkColor
char *name;
GdkRGBA *color;
int h, s, v;
gboolean selected;
};
enum {
@@ -35,6 +38,7 @@ enum {
PROP_HUE,
PROP_SATURATION,
PROP_VALUE,
PROP_SELECTED,
N_PROPS
};
@@ -122,6 +126,10 @@ gtk_color_get_property (GObject *object,
g_value_set_int (value, self->v);
break;
case PROP_SELECTED:
g_value_set_boolean (value, self->selected);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -158,6 +166,10 @@ gtk_color_set_property (GObject *object,
self->v = g_value_get_int (value);
break;
case PROP_SELECTED:
self->selected = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -200,6 +212,8 @@ gtk_color_class_init (GtkColorClass *klass)
g_param_spec_int ("saturation", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_VALUE] =
g_param_spec_int ("value", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_SELECTED] =
g_param_spec_boolean ("selected", NULL, NULL, FALSE, G_PARAM_READWRITE);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
@@ -259,7 +273,7 @@ create_colors_model (void)
h = atoi (fields[9]);
s = atoi (fields[10]);
v = atoi (fields[11]);
color = gtk_color_new (name, red / 255., green / 255., blue / 255., h, s, v);
g_list_store_append (result, color);
g_object_unref (color);
@@ -320,7 +334,7 @@ static void
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box, *picture, *name_label, *rgb_label, *hsv_label;;
GtkWidget *box, *picture, *name_label, *rgb_label, *hsv_label;
GtkExpression *color_expression, *expression;
GtkExpression *params[1];
@@ -422,9 +436,10 @@ create_color_grid (void)
g_object_unref (factory);
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (gridview), 24);
gtk_grid_view_set_enable_rubberband (GTK_GRID_VIEW (gridview), TRUE);
model = G_LIST_MODEL (gtk_sort_list_model_new (create_colors_model (), NULL));
selection = G_LIST_MODEL (gtk_no_selection_new (model));
selection = G_LIST_MODEL (gtk_property_selection_new (model, "selected"));
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
g_object_unref (selection);
g_object_unref (model);
+26
View File
@@ -18,6 +18,7 @@ struct _FileBrowserView
GtkListItemFactory *factory;
char *icon_name;
char *title;
GtkOrientation orientation;
};
@@ -25,6 +26,7 @@ enum {
PROP_0,
PROP_FACTORY,
PROP_ICON_NAME,
PROP_TITLE,
PROP_ORIENTATION,
N_PROPS
@@ -54,6 +56,10 @@ file_browser_view_get_property (GObject *object,
g_value_set_string (value, self->icon_name);
break;
case PROP_TITLE:
g_value_set_string (value, self->title);
break;
case PROP_ORIENTATION:
g_value_set_enum (value, self->orientation);
break;
@@ -83,6 +89,11 @@ file_browser_view_set_property (GObject *object,
self->icon_name = g_value_dup_string (value);
break;
case PROP_TITLE:
g_free (self->title);
self->title = g_value_dup_string (value);
break;
case PROP_ORIENTATION:
self->orientation = g_value_get_enum (value);
break;
@@ -100,6 +111,7 @@ file_browser_view_finalize (GObject *object)
g_object_unref (self->factory);
g_free (self->icon_name);
g_free (self->title);
G_OBJECT_CLASS (file_browser_view_parent_class)->dispose (object);
}
@@ -125,6 +137,12 @@ file_browser_view_class_init (FileBrowserViewClass *klass)
"icon to display for selecting this view",
NULL,
G_PARAM_READWRITE);
properties[PROP_TITLE] =
g_param_spec_string ("title",
"title",
"title to display for selecting this view",
NULL,
G_PARAM_READWRITE);
properties[PROP_ORIENTATION] =
g_param_spec_enum ("orientation",
"orientation",
@@ -224,6 +242,14 @@ do_listview_filebrowser (GtkWidget *do_widget)
GtkDirectoryList *dirlist;
GFile *file;
char *cwd;
GtkCssProvider *provider;
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/listview_filebrowser/listview_filebrowser.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
builder = gtk_builder_new_from_resource ("/listview_filebrowser/listview_filebrowser.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
+11
View File
@@ -0,0 +1,11 @@
list.viewswitcher {
border: 1px solid gray;
}
list.viewswitcher > row {
padding: 5px;
}
list.viewswitcher row:selected {
background: gray;
}
+10 -1
View File
@@ -39,12 +39,14 @@
</object>
</property>
<property name="icon-name">view-list-symbolic</property>
<property name="title" translatable="yes">List</property>
<property name="orientation">horizontal</property>
</object>
</child>
<child>
<object class="FileBrowserView">
<property name="icon-name">view-grid-symbolic</property>
<property name="title" translatable="yes">Grid</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
@@ -92,6 +94,7 @@
<child>
<object class="FileBrowserView">
<property name="icon-name">view-paged-symbolic</property>
<property name="title" translatable="yes">Paged</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
@@ -174,7 +177,7 @@
<property name="show-title-buttons">1</property>
<child>
<object class="GtkButton">
<property name="icon-name">go-up</property>
<property name="icon-name">go-up-symbolic</property>
<signal name="clicked" handler="filebrowser_up_clicked_cb" object="dirlist" swapped="no"/>
</object>
</child>
@@ -184,6 +187,7 @@
<property name="orientation">horizontal</property>
<style>
<class name="linked"/>
<class name="viewswitcher"/>
</style>
<property name="model">
<object class="GtkSingleSelection" id="selected-view">
@@ -203,6 +207,11 @@
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
<binding name="tooltip-text">
<lookup type="FileBrowserView" name="title">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
+79 -1
View File
@@ -9,6 +9,8 @@
#include <gtk/gtk.h>
#include <stdlib.h>
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
typedef struct _SettingsKey SettingsKey;
struct _SettingsKey
@@ -140,6 +142,43 @@ settings_key_new (GSettings *settings,
return result;
}
static void
item_value_changed (GtkListItem *item,
GtkEntry *entry)
{
SettingsKey *self;
const char *text;
const GVariantType *type;
GVariant *variant;
GError *error = NULL;
const char *name;
text = gtk_editable_get_text (GTK_EDITABLE (entry));
g_object_get (item, "item", &self, NULL);
g_object_unref (self);
type = g_settings_schema_key_get_value_type (self->key);
name = g_settings_schema_key_get_name (self->key);
variant = g_variant_parse (type, text, NULL, NULL, &error);
if (!variant)
{
g_warning ("%s", error->message);
g_clear_error (&error);
return;
}
if (!g_settings_schema_key_range_check (self->key, variant))
{
g_warning ("Not a valid value for %s", name);
return;
}
g_settings_set_value (self->settings, name, variant);
g_variant_unref (variant);
}
static int
strvcmp (gconstpointer p1,
gconstpointer p2)
@@ -165,6 +204,7 @@ transform_settings_to_keys (GBinding *binding,
GtkSortListModel *sort_model;
GtkFilterListModel *filter_model;
GtkFilter *filter;
GtkNoSelection *selection_model;
GtkExpression *expression;
char **keys;
guint i;
@@ -207,7 +247,10 @@ transform_settings_to_keys (GBinding *binding,
g_object_unref (filter);
g_value_take_object (to_value, filter_model);
selection_model = gtk_no_selection_new (G_LIST_MODEL (filter_model));
g_object_unref (filter_model);
g_value_take_object (to_value, selection_model);
return TRUE;
}
@@ -300,7 +343,13 @@ do_listview_settings (GtkWidget *do_widget)
GtkBuilderScope *scope;
GtkBuilder *builder;
GtkColumnViewColumn *name_column;
GtkColumnViewColumn *type_column;
GtkColumnViewColumn *default_column;
GtkColumnViewColumn *summary_column;
GtkColumnViewColumn *description_column;
GtkSorter *sorter;
GActionGroup *actions;
GAction *action;
g_type_ensure (SETTINGS_TYPE_KEY);
@@ -308,6 +357,7 @@ do_listview_settings (GtkWidget *do_widget)
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_enabled", (GCallback)search_enabled);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_changed", (GCallback)search_changed);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "stop_search", (GCallback)stop_search);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "item_value_changed", (GCallback)item_value_changed);
builder = gtk_builder_new ();
gtk_builder_set_scope (builder, scope);
@@ -320,6 +370,32 @@ do_listview_settings (GtkWidget *do_widget)
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
columnview = GTK_WIDGET (gtk_builder_get_object (builder, "columnview"));
type_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "type_column"));
default_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "default_column"));
summary_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "summary_column"));
description_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "description_column"));
actions = G_ACTION_GROUP (g_simple_action_group_new ());
action = G_ACTION (g_property_action_new ("show-type", type_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
action = G_ACTION (g_property_action_new ("show-default", default_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
action = G_ACTION (g_property_action_new ("show-summary", summary_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
action = G_ACTION (g_property_action_new ("show-description", description_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
gtk_widget_insert_action_group (columnview, "columnview", actions);
g_object_unref (actions);
model = create_settings_model (NULL, NULL);
treemodel = gtk_tree_list_model_new (FALSE,
model,
@@ -343,6 +419,8 @@ do_listview_settings (GtkWidget *do_widget)
sorter = gtk_string_sorter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
gtk_column_view_column_set_sorter (name_column, sorter);
g_object_unref (sorter);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
+95 -4
View File
@@ -77,6 +77,7 @@
<child>
<object class="GtkColumnViewColumn" id="name_column">
<property name="title">Name</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
@@ -103,6 +104,8 @@
<child>
<object class="GtkColumnViewColumn">
<property name="title">Value</property>
<property name="resizable">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
@@ -110,9 +113,10 @@
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<object class="GtkEntry">
<signal name="activate" handler="item_value_changed" object="GtkListItem" swapped="yes"/>
<property name="xalign">0</property>
<binding name="label">
<binding name="text">
<lookup name="value" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
@@ -127,8 +131,10 @@
</object>
</child>
<child>
<object class="GtkColumnViewColumn">
<object class="GtkColumnViewColumn" id="type_column">
<property name="title">Type</property>
<property name="resizable">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
@@ -153,8 +159,11 @@
</object>
</child>
<child>
<object class="GtkColumnViewColumn">
<object class="GtkColumnViewColumn" id="default_column">
<property name="title">Default</property>
<property name="resizable">1</property>
<property name="expand">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
@@ -172,6 +181,68 @@
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn" id="summary_column">
<property name="title">Summary</property>
<property name="resizable">1</property>
<property name="visible">0</property>
<property name="expand">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="wrap">1</property>
<binding name="label">
<lookup name="summary" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn" id="description_column">
<property name="title">Description</property>
<property name="resizable">1</property>
<property name="visible">0</property>
<property name="expand">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="wrap">1</property>
<binding name="label">
<lookup name="description" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
@@ -187,4 +258,24 @@
</object>
</child>
</object>
<menu id="header_menu">
<section>
<item>
<attribute name="label" translatable="yes">Type</attribute>
<attribute name="action">columnview.show-type</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Default value</attribute>
<attribute name="action">columnview.show-default</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Summary</attribute>
<attribute name="action">columnview.show-summary</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Description</attribute>
<attribute name="action">columnview.show-description</attribute>
</item>
</section>
</menu>
</interface>
+4 -4
View File
@@ -11,7 +11,7 @@
* A GtkNoSelectionModel is used to make sure no item in the list can be
* selected. All other interactions with the items is still possible.
*
* The dataset used here has 70000 items.
* The dataset used here has 70000 items.
*/
#include <gtk/gtk.h>
@@ -78,13 +78,13 @@ gtk_weather_info_new (GDateTime *timestamp,
static GDateTime *
parse_timestamp (const char *string,
GTimeZone *timezone)
GTimeZone *_timezone)
{
char *with_seconds;
GDateTime *result;
with_seconds = g_strconcat (string, ":00", NULL);
result = g_date_time_new_from_iso8601 (with_seconds, timezone);
result = g_date_time_new_from_iso8601 (with_seconds, _timezone);
g_free (with_seconds);
return result;
@@ -301,7 +301,7 @@ do_listview_weather (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *listview, *sw;;
GtkWidget *listview, *sw;
window = gtk_window_new ();
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+8 -10
View File
@@ -8,7 +8,6 @@
#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include "award.h"
#include "demos.h"
static GtkWidget *info_view;
@@ -213,7 +212,6 @@ activate_inspector (GSimpleAction *action,
gpointer user_data)
{
gtk_window_set_interactive_debugging (TRUE);
award ("demo-inspector");
}
static void
@@ -601,7 +599,7 @@ display_image (const char *resource)
{
GtkWidget *sw, *image;
image = gtk_image_new_from_resource (resource);
image = gtk_picture_new_for_resource (resource);
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
gtk_widget_set_valign (image, GTK_ALIGN_CENTER);
sw = gtk_scrolled_window_new (NULL, NULL);
@@ -1042,7 +1040,7 @@ activate (GApplication *app)
listmodel = create_demo_model ();
treemodel = gtk_tree_list_model_new (FALSE,
G_LIST_MODEL (listmodel),
FALSE,
TRUE,
get_child_model,
NULL,
NULL);
@@ -1051,10 +1049,6 @@ activate (GApplication *app)
gtk_list_view_set_model (GTK_LIST_VIEW (listview),
G_LIST_MODEL (selection));
award ("demo-start");
gtk_widget_show (GTK_WIDGET (window));
g_object_unref (builder);
}
@@ -1113,11 +1107,11 @@ command_line (GApplication *app,
return 0;
}
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
if (name == NULL)
goto out;
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
d = gtk_demos;
while (d->title)
@@ -1147,7 +1141,11 @@ out:
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
g_signal_connect_swapped (G_OBJECT (demo), "destroy", G_CALLBACK (g_application_quit), app);
}
else
gtk_widget_show (GTK_WIDGET (window));
if (autoquit)
g_timeout_add_seconds (1, auto_quit, app);
+1 -1
View File
@@ -5,7 +5,7 @@ Text <span color="gray">c<span color="green">o</span>l<span color="tomato">o</sp
Colorful <span underline="low" underline-color="blue"><span underline="double" underline-color="red">under</span>lines</span> and <span background="pink"><span underline="error">mo</span><span underline="error" underline-color="green">re</span></span>
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</span>
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</span> and <span overline="single" overline_color="green">overlines</span>
Superscripts and subscripts: 𝜀<span rise="-6000" size="x-small" font_desc="italic">0</span> = 𝜔<span rise="8000" size="smaller">𝜔<span rise="14000" size="smaller">𝜔<span rise="20000">.<span rise="23000">.<span rise="26000">.</span></span></span></span></span>
+2 -2
View File
@@ -3,7 +3,6 @@
demos = files([
'application_demo.c',
'assistant.c',
'awardview.c',
'builder.c',
'clipboard.c',
'combobox.c',
@@ -19,6 +18,7 @@ demos = files([
'cursors.c',
'dialog.c',
'drawingarea.c',
'dropdown.c',
'dnd.c',
'editable_cells.c',
'entry_completion.c',
@@ -42,6 +42,7 @@ demos = files([
'listbox.c',
'flowbox.c',
'list_store.c',
'listview_applauncher.c',
'listview_clocks.c',
'listview_colors.c',
'listview_filebrowser.c',
@@ -91,7 +92,6 @@ demos = files([
gtkdemo_deps = [ libgtk_dep, ]
extra_demo_sources = files(['main.c',
'award.c',
'gtkfishbowl.c',
'fontplane.c',
'gtkgears.c',
-6
View File
@@ -11,7 +11,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "award.h"
static GtkWidget *entry;
static GtkWidget *entry2;
@@ -27,17 +26,12 @@ update_button (GObject *object,
gtk_widget_set_sensitive (button,
text[0] != '\0' && g_str_equal (text, text2));
if (g_str_equal (text, text2) &&
g_ascii_strcasecmp (text, "12345") == 0)
award ("password-best");
}
static void
button_pressed (GtkButton *widget,
GtkWidget *window)
{
award ("password-correct");
gtk_window_destroy (GTK_WINDOW (window));
}
+1 -14
View File
@@ -1,4 +1,4 @@
/* Sliding puzzle
/* Sliding Puzzle
*
* This demo demonstrates how to use gestures and paintables to create a
* small sliding puzzle game.
@@ -11,8 +11,6 @@
#include "puzzlepiece.h"
#include "paintable.h"
/* Give out awards */
#include "award.h"
static GtkWidget *window = NULL;
static GtkWidget *frame = NULL;
@@ -159,14 +157,6 @@ check_solved (GtkWidget *grid)
picture = gtk_grid_get_child_at (GTK_GRID (grid), pos_x, pos_y);
gtk_picture_set_paintable (GTK_PICTURE (picture), piece);
/* Hand out a bunch of awards
*/
award ("puzzle-solve");
if ((gdk_paintable_get_flags (piece) & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
award ("puzzle-solve-animated");
if (height * width > 20)
award ("puzzle-solve-large");
return TRUE;
}
@@ -416,9 +406,6 @@ widget_destroyed (gpointer data,
{
if (data)
*(gpointer *) data = NULL;
if (!solved)
award ("puzzle-give-up");
}
+39 -10
View File
@@ -92,12 +92,11 @@ static Theme themes[] = {
static int theme;
static gboolean
change_theme (GtkWidget *widget,
change_theme (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer data)
gpointer data)
{
GtkBuilder *builder = data;
GtkWidget *label;
GtkWidget *label = data;
Theme next = themes[theme++ % G_N_ELEMENTS (themes)];
char *name;
@@ -110,7 +109,6 @@ change_theme (GtkWidget *widget,
gtk_window_set_title (GTK_WINDOW (widget), name);
g_free (name);
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
if (frame_clock)
{
char *fps;
@@ -127,10 +125,10 @@ change_theme (GtkWidget *widget,
static void
clicked (GtkGestureClick *gesture,
int n_press,
double x,
double y,
gpointer data)
int n_press,
double x,
double y,
gpointer data)
{
GtkWidget *window;
GdkEvent *event;
@@ -165,6 +163,29 @@ clicked (GtkGestureClick *gesture,
}
}
static void
toggle_cycle (GObject *button,
GParamSpec *pspec,
gpointer data)
{
gboolean active;
GtkWidget *window;
g_object_get (button, "active", &active, NULL);
window = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW);
if (active && !tick_cb)
{
tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL);
}
else if (!active && tick_cb)
{
gtk_widget_remove_tick_callback (window, tick_cb);
tick_cb = 0;
}
}
GtkWidget *
do_themes (GtkWidget *do_widget)
{
@@ -174,6 +195,8 @@ do_themes (GtkWidget *do_widget)
{
GtkBuilder *builder;
GtkWidget *header;
GtkWidget *button;
GtkWidget *label;
GtkGesture *gesture;
builder = gtk_builder_new_from_resource ("/themes/themes.ui");
@@ -183,11 +206,17 @@ do_themes (GtkWidget *do_widget)
gtk_widget_get_display (do_widget));
header = GTK_WIDGET (gtk_builder_get_object (builder, "header"));
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
gesture = gtk_gesture_click_new ();
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), builder);
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), label);
gtk_widget_add_controller (header, GTK_EVENT_CONTROLLER (gesture));
button = GTK_WIDGET (gtk_builder_get_object (builder, "toggle"));
g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), label);
gtk_widget_realize (window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
+5
View File
@@ -5,6 +5,11 @@
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="start">
<object class="GtkToggleButton" id="toggle">
<property name="label">Cycle</property>
</object>
</child>
<child type="end">
<object class="GtkLabel" id="fps"/>
</child>
+17 -3
View File
@@ -93,7 +93,6 @@ gdk_display_get_clipboard
gdk_display_get_primary_clipboard
gdk_display_get_setting
gdk_display_get_startup_notification_id
gdk_display_setup_window_visual
<SUBSECTION>
gdk_display_put_event
@@ -383,8 +382,6 @@ gdk_device_has_bidi_layouts
<SUBSECTION>
gdk_device_get_state
gdk_device_get_surface_at_position
gdk_device_get_history
gdk_device_free_history
GdkTimeCoord
gdk_device_get_axis
gdk_device_get_axis_names
@@ -502,6 +499,7 @@ gdk_event_get_position
gdk_event_get_axes
gdk_event_get_axis
gdk_event_get_pointer_emulated
gdk_event_triggers_context_menu
gdk_button_event_get_button
gdk_scroll_event_get_direction
gdk_scroll_event_get_deltas
@@ -520,6 +518,7 @@ gdk_crossing_event_get_mode
gdk_crossing_event_get_detail
gdk_crossing_event_get_focus
gdk_grab_broken_event_get_grab_surface
gdk_grab_broken_event_get_implicit
gdk_dnd_event_get_drop
gdk_configure_event_get_size
gdk_touchpad_event_get_gesture_phase
@@ -545,8 +544,23 @@ GDK_TYPE_CROSSING_MODE
GDK_TYPE_SCROLL_DIRECTION
GDK_TYPE_NOTIFY_TYPE
GDK_IS_EVENT
gdk_event_get_type
gdk_event_sequence_get_type
gdk_button_event_get_type
gdk_configure_event_get_type
gdk_crossing_event_get_type
gdk_delete_event_get_type
gdk_dnd_event_get_type
gdk_focus_event_get_type
gdk_grab_broken_event_get_type
gdk_key_event_get_type
gdk_motion_event_get_type
gdk_pad_event_get_type
gdk_proximity_event_get_type
gdk_scroll_event_get_type
gdk_touch_event_get_type
gdk_touchpad_event_get_type
</SECTION>
<SECTION>
+5 -1
View File
@@ -27,15 +27,19 @@ private_headers = [
'gdkmonitorprivate.h',
'gdkmemorytextureprivate.h',
'gdkpipeiostreamprivate.h',
'gdkpopupprivate.h',
'gdkprofilerprivate.h',
'gdkscreenprivate.h',
'gdkseatdefaultprivate.h',
'gdkseatprivate.h',
'gdksnapshotprivate.h',
'gdksurfaceimpl.h',
'gdksurfaceprivate.h',
'gdktextureprivate.h',
'gdktoplevelprivate.h',
'gdkvulkancontextprivate.h',
'keyname-table.h',
'gdkprivate-x11.h',
'x11/gdkprivate-x11.h',
'x11/gdkeventsource.h',
'gtk-primary-selection-client-protocol.h',
'gtk-shell-client-protocol.h',
-1
View File
@@ -236,7 +236,6 @@ 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
+2
View File
@@ -9,9 +9,11 @@ private_headers = [
'gskprofilerprivate.h',
'gskrendererprivate.h',
'gskrendernodeprivate.h',
'gskrendernodeparserprivate.h',
'gskroundedrectprivate.h',
'gskshaderbuilderprivate.h',
'gsktextureprivate.h',
'gsktransformprivate.h',
'gskvulkanblendpipelineprivate.h',
'gskvulkanborderpipelineprivate.h',
'gskvulkanboxshadowpipelineprivate.h',
+1 -1
View File
@@ -37,7 +37,7 @@ this range will trigger compiler warnings.
Here is how you would compile hello.c if you want to allow it
to use symbols that were not deprecated in 4.2:
```
$ cc `pkg-config --cflags gtk4` -DGDK_VERSION_MIN_REQIRED=GDK_VERSION_4_2 hello.c -o hello `pkg-config --libs gtk4`
$ cc `pkg-config --cflags gtk4` -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_4_2 hello.c -o hello `pkg-config --libs gtk4`
```
And here is how you would compile hello.c if you don't want
+11 -3
View File
@@ -68,8 +68,12 @@
<xi:include href="xml/gtkmultisorter.xml" />
</section>
<xi:include href="xml/gtkselectionmodel.xml" />
<xi:include href="xml/gtknoselection.xml" />
<xi:include href="xml/gtksingleselection.xml" />
<section>
<xi:include href="xml/gtknoselection.xml" />
<xi:include href="xml/gtksingleselection.xml" />
<xi:include href="xml/gtkmultiselection.xml" />
<xi:include href="xml/gtkpropertyselection.xml" />
</section>
<xi:include href="xml/gtkdirectorylist.xml" />
</chapter>
@@ -90,8 +94,11 @@
</chapter>
<chapter id="Trees">
<xi:include href="xml/gtktreelistrow.xml" />
<title>Tree support</title>
<xi:include href="xml/gtktreelistmodel.xml" />
<section>
<xi:include href="xml/gtktreelistrow.xml" />
</section>
<xi:include href="xml/gtktreelistrowsorter.xml" />
<xi:include href="xml/gtktreeexpander.xml" />
</chapter>
@@ -120,6 +127,7 @@
<xi:include href="xml/gtkaboutdialog.xml" />
<xi:include href="xml/gtkassistant.xml" />
<xi:include href="xml/gtkwindowgroup.xml" />
<xi:include href="xml/gtknativedialog.xml" />
</chapter>
<chapter id="LayoutContainers">
+56 -12
View File
@@ -350,6 +350,9 @@ gtk_selection_model_select_range
gtk_selection_model_unselect_range
gtk_selection_model_select_all
gtk_selection_model_unselect_all
GtkSelectionCallback
gtk_selection_model_select_callback
gtk_selection_model_unselect_callback
gtk_selection_model_query_range
<SUBSECTION>
gtk_selection_model_selection_changed
@@ -392,6 +395,24 @@ gtk_single_selection_set_can_unselect
gtk_single_selection_get_type
</SECTION>
<SECTION>
<FILE>gtkmultiselection</FILE>
<TITLE>GtkMultiSeledction</TITLE>
GtkMultiSelection
gtk_multi_selection_new
<SUBSECTION Private>
gtk_multi_selection_get_type
</SECTION>
<SECTION>
<FILE>gtkpropertyselection</FILE>
<TITLE>GtkPropertySelection</TITLE>
GtkPropertySelection
gtk_property_selection_new
<SUBSECTION Private>
gtk_property_selection_get_type
</SECTION>
<SECTION>
<FILE>gtklistitem</FILE>
<TITLE>GtkListItem</TITLE>
@@ -479,6 +500,8 @@ gtk_list_view_set_show_separators
gtk_list_view_get_show_separators
gtk_list_view_set_single_click_activate
gtk_list_view_get_single_click_activate
gtk_list_view_set_enable_rubberband
gtk_list_view_get_enable_rubberband
<SUBSECTION Standard>
GTK_LIST_VIEW
GTK_LIST_VIEW_CLASS
@@ -502,11 +525,17 @@ gtk_column_view_get_columns
gtk_column_view_get_model
gtk_column_view_set_model
gtk_column_view_get_sorter
gtk_column_view_get_show_separators
gtk_column_view_set_show_separators
gtk_column_view_get_show_row_separators
gtk_column_view_set_show_row_separators
gtk_column_view_get_show_column_separators
gtk_column_view_set_show_column_separators
gtk_column_view_sort_by_column
gtk_column_view_set_single_click_activate
gtk_column_view_get_single_click_activate
gtk_column_view_set_reorderable
gtk_column_view_get_reorderable
gtk_column_view_set_enable_rubberband
gtk_column_view_get_enable_rubberband
<SUBSECTION Standard>
GTK_COLUMN_VIEW
GTK_COLUMN_VIEW_CLASS
@@ -533,6 +562,15 @@ gtk_column_view_column_set_sorter
gtk_column_view_column_get_sorter
gtk_column_view_column_set_visible
gtk_column_view_column_get_visible
gtk_column_view_column_set_resizable
gtk_column_view_column_get_resizable
gtk_column_view_column_set_header_menu
gtk_column_view_column_get_header_menu
gtk_column_view_column_set_fixed_width
gtk_column_view_column_get_fixed_width
gtk_column_view_column_set_expand
gtk_column_view_column_get_expand
<SUBSECTION Standard>
GTK_COLUMN_VIEW_COLUMN
GTK_COLUMN_VIEW_COLUMN_CLASS
@@ -557,6 +595,8 @@ gtk_grid_view_set_min_columns
gtk_grid_view_get_min_columns
gtk_grid_view_set_single_click_activate
gtk_grid_view_get_single_click_activate
gtk_grid_view_set_enable_rubberband
gtk_grid_view_get_enable_rubberband
<SUBSECTION Standard>
GTK_GRID_VIEW
GTK_GRID_VIEW_CLASS
@@ -1426,7 +1466,6 @@ gtk_custom_filter_get_type
<FILE>gtkfilterlistmodel</FILE>
<TITLE>GtkFilterListModel</TITLE>
GtkFilterListModel
GtkFilterListModelFilterFunc
gtk_filter_list_model_new
gtk_filter_list_model_new_for_type
gtk_filter_list_model_set_model
@@ -2016,7 +2055,7 @@ gtk_info_bar_get_type
<SECTION>
<FILE>gtknativedialog</FILE>
<TITLE>GtkNativeDialog</TITLE>
GTK_TYPE_NATIVE_DIALOG
GtkNativeDialog
GtkNativeDialogClass
gtk_native_dialog_show
gtk_native_dialog_hide
@@ -2028,9 +2067,8 @@ gtk_native_dialog_set_title
gtk_native_dialog_get_title
gtk_native_dialog_set_transient_for
gtk_native_dialog_get_transient_for
<SUBSECTION Standard>
GtkNativeDialog
<SUBSECTION Private>
GTK_TYPE_NATIVE_DIALOG
gtk_native_dialog_get_type
</SECTION>
@@ -2104,12 +2142,18 @@ GtkNotebookPrivate
<TITLE>GtkPaned</TITLE>
GtkPaned
gtk_paned_new
gtk_paned_add1
gtk_paned_add2
gtk_paned_pack1
gtk_paned_pack2
gtk_paned_get_child1
gtk_paned_get_child2
gtk_paned_set_start_child
gtk_paned_get_start_child
gtk_paned_set_end_child
gtk_paned_get_end_child
gtk_paned_set_resize_start_child
gtk_paned_get_resize_start_child
gtk_paned_set_resize_end_child
gtk_paned_get_resize_end_child
gtk_paned_set_shrink_start_child
gtk_paned_get_shrink_start_child
gtk_paned_set_shrink_end_child
gtk_paned_get_shrink_end_child
gtk_paned_set_position
gtk_paned_get_position
gtk_paned_set_wide_handle
+2
View File
@@ -139,6 +139,7 @@ gtk_menu_button_get_type
gtk_message_dialog_get_type
gtk_mount_operation_get_type
gtk_multi_filter_get_type
gtk_multi_selection_get_type
gtk_multi_sorter_get_type
gtk_native_get_type
gtk_native_dialog_get_type
@@ -168,6 +169,7 @@ gtk_print_operation_preview_get_type
gtk_print_settings_get_type
@DISABLE_ON_W32@gtk_print_unix_dialog_get_type
gtk_progress_bar_get_type
gtk_property_selection_get_type
gtk_radio_button_get_type
gtk_range_get_type
gtk_recent_manager_get_type
-101
View File
@@ -1,101 +0,0 @@
# List widgets
GTK provides powerful widgets to display and edit lists of data. This document gives an overview over the concepts and how they work together to allow developers to implement lists.
Lists are intended to be used whenever developers want to display lists of objects in roughly the same way.
Lists are perfectly fine to be used for very short list of only 2 or 3 elements, but generally scale fine to millions of items. Of course, the larger the list grows, the more care needs to be taken to choose the right data structures to keep things running well.
Lists are meant to be used with changing data, both with the items itself changing as well as the list adding and removing items. Of course, they work just as well with static data.
## Terminology
These terms are used throughout the documentation when talking about lists and you should be aware of what they refer to. These are often generic terms that have a specific meaning in this context.
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists. Examples of thse widgets would be #GtkListView or #GtkGridView.
Views display data from a **_model_**. A model is a #GListModel and models can be provided in 3 ways or combinations thereof:
* Many list models implementations already exist. There are models that provide specific data, like #GtkDirectoryList. And there are models like #GListStore that allow building lists manually.
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel that modify or adapt or combine other models.
* Last but not least, developers are encouraged to create their own #GListModel implementations. The interface is kept deliberately small to make this easy.
The same model can be used in multiple different views and wrapped with multiple different models at once.
The elements in a model are called **_items_**. All items are #GObjects.
Every item in a model has a **_position_** which is the unsigned integer that describes where in the model the item is located. This position can of course change as items are added or removed from the model.
It is important to be aware of the difference between items and positions because the mapping from position to item is not permanent, so developers should think about whether they want to track items or positions when working with models. Oftentimes some things are really hard to do one way but very easy the other way.
The other important part of a view is a **_factory_**. Each factory is a #GtkListItemFactory implementation that takes care of mapping the items of the model to widgets that can be shown in the view.
The way factories do this is by creating a **_listitem_** for each item that is currently in use. Listitems are always #GtkListItem objects. They are only ever created by GTK and provide information about what item they are meant to display.
Different factory implementations use various different methods to allow developers to add the right widgets to listitems and to link those widgets with the item managed by the listitem. Finding a suitable factory implementation for the data displayed, the programming language and development environment is an important task that can simplify setting up the view tremendously.
Views support selections via a **_selection model_**. A selection model is an implementation of the #GtkSelectionModel interface on top of the #GListModel interface that allows marking each item in a model as either selected or not selected. Just like regular models, this can be implemented either by implementing #GtkSelectionModel directly or by wrapping a model with one of the GTK models provided for this purposes, such as #GtkNoSelection or #GtkSingleSelection. The behavior of selection models - ie which items they allow selecting and what effect this has on other items - is completely up to the selection model. As such, single-selections, multi-selections or sharing selection state between different selection models and/or views is possible. The selection state of an item is exposed in the listitem via the GtkListItem:selected property.
Views and listitems also support activation. Activation means that double clicking or pressing enter while inside a focused row will cause the view to emit and activation signal such as GtkListView::activate. This provides an easy way to set up lists, but can also be turned off on listitems if undesired.
Both selections and activation are supported among other things via widget actions (FIXME: Link docs). This allows developers to add widgets to their lists that cause selections to change or to trigger activation via the #GtkActionable interface. For a list of all supported actions see the relevant documentation. (FIXME: where do we document actions and how to I link that?)
## Behind the scenes
While for short lists it is not a problem to instantiate widgets for every item in the model, once lists grow to thousands or millions of elements, this gets less feasible. Because of this, the views only create a limited amount of listitems and recycle them by binding them to new items. In general, views try to keep listitems available only for the items that can actually be seen on screen.
While this behavior allows views to scale effortlessly to huge lists, it has a few implication on what can be done with views. For example, it is not possible to query a view for a listitem used for a certain position - there might not be one and even if there is, that listitem might soon be recycled for a new position.
It is also important that developers save state they care about in the item and do not rely on the widgets they created as those widgets can be recycled for a new position at any time causing any state to be lost.
Another important requirement for views is that they need to know which items are not visible so they can be recycled. Views achieve that by implementing the #GtkScrollable interface and expecting to be placed directly into a #GtkScrolledWindow.
Of course, if you are only using models with few items, this is not important and you can treat views like any other widget. But if you use large lists and your performance suffers, you should be aware of this. Views also allow tuning the number of listitems they create such as with gtk_grid_view_set_max_columns(), and developers running into performance problems should definitely study the tradeoffs of those and experiment with them.
## Displaying trees
While #GtkTreeView provided builtin support for trees, the list widgets, and in particular #GListModel do not. This was a design choice because the common use case is displaying lists and not trees and it greatly simplifies the API interface provided.
However, GTK provides functionality to make trees look and behave like lists for the people who still want to display lists. This is achieved by using the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander widget can then be used inside a listitem to allow users to expand and collapse rows and provide a similar experience to #GtkTreeView.
Developers should refer to those objects' API reference for more discussion on the topic.
## comparison to GtkTreeView
Developers familiar with #GtkTreeView may wonder how this way of doing lists compares to the way they know. This section will try to outline the similarities and differences between the two.
This new approach tries to provide roughly the same functionality as the old approach but often uses a very different approach to achieve these goals.
The main difference and one of the primary reasons for this new development is that items can be displayed using regular widgets and #GtkCellRenderer is no longer necessary. This allows all benefits that widgets provide, such as complex layout and animating widgets and not only makes cell renderers obsolete, but also #GtkCellArea.
The other big difference is the massive change to the data model. #GtkTreeModel was a rather complex interface for a tree data structure and #GListModel was deliberately designed to be a simple data structure for lists only. (See above (FIXME: link) for how to still do trees with this new model.) Another big change is that the new model allows for bulk changes via the #GListModel:items-changed signal while #GtkTreeModel only allows a single item to change at once. The goal here is of course to encourage implementation of custom list models.
Another consequence of the new model is that it is now easily possible to refer to the contents of a row in the model directly by keeping the item, while #GtkTreeRowReference was a very slow mechanism to achieve the same. And because the items are real objects, developers can make them emit change signals causing listitems and their children to update, which wasn't possible with #GtkTreeModel.
The selection handling is also different. While selections used to be managed via custom code in each widget, selection state is now meant to be managed by the selection models. In particular this allows for complex use cases with specialized requirements (FIXME: Can I add a shoutout to @mitch here because I vividly remember a huge discussion about GtkTreeView's selection behavior and the Gimp).
Finally here's a quick list of equivalent functionality to look for when transitioning code for easy lookup:
| old | new |
| ------------------- | ----------------------------------- |
| #GtkTreeModel | #GListModel |
| #GtkTreePath | #guint position, #GtkTreeListRow |
| #GtkTreeIter | #guint position |
| GtkTreeRowReference | #GObject item |
| #GtkListStore | #GListStore |
| #GtkTreeStore | #GtkTreeListModel, #GtkTreeExpander |
| #GtkTreeSelection | #GtkSelectionModel |
| #GtkTreeViewColumn | #GtkColumnView |
| #GtkTreeView | #GtkListView, #GtkColumnView |
| #GtkCellView | |
| #GtkComboBox | |
| #GtkIconView | #GtkGridView |
| #GtkTreeSortable | |
| #GtkTreeModelSort | #GtkSortListModel |
| #GtkTreeModelFilter | #GtkFilterListModel |
| #GtkCellLayout | #GtkListItemFactory |
| #GtkCellArea | #GtkWidget |
| #GtkCellRenderer | #GtkWidget |
+10 -1
View File
@@ -13,6 +13,7 @@ private_headers = [
'gtkappchooserprivate.h',
'gtkapplicationaccelsprivate.h',
'gtkapplicationprivate.h',
'gtkarrayimplprivate.h',
'gtkbindingsprivate.h',
'gtkbitmaskprivate.h',
'gtkbuilderprivate.h',
@@ -148,11 +149,14 @@ private_headers = [
'gtkmagnifierprivate.h',
'gtkmediafileprivate.h',
'gtkmenubuttonprivate.h',
'gtkmenusectionboxprivate.h',
'gtkmenutrackeritemprivate.h',
'gtkmenutrackerprivate.h',
'gtkmodulesprivate.h',
'gtkmountoperationprivate.h',
'gtknativedialogprivate.h',
'gtknomediafileprivate.h',
'gtkorientableprivate.h',
'gtkpango.h',
'gtkplacessidebarprivate.h',
'gtkplacesviewprivate.h',
'gtkplacesviewrowprivate.h',
@@ -162,6 +166,7 @@ private_headers = [
'gtkprintoperation-private.h',
'gtkprivate.h',
'gtkprogresstrackerprivate.h',
'gtkquery.h',
'gtkrangeprivate.h',
'gtkrbtreeprivate.h',
'gtkrenderbackgroundprivate.h',
@@ -171,7 +176,9 @@ private_headers = [
'gtkroundedboxprivate.h',
'gtkscalerprivate.h',
'gtksearchentryprivate.h',
'gtkset.h',
'gtksettingsprivate.h',
'gtkshortcutcontrollerprivate.h',
'gtkshortcutsshortcutprivate.h',
'gtkshortcutswindowprivate.h',
'gtksidebarrowprivate.h',
@@ -198,7 +205,9 @@ private_headers = [
'gtktoolbarprivate.h',
'gtktooltipprivate.h',
'gtktooltipwindowprivate.h',
'gtktreepopoverprivate.h',
'gtktreeprivate.h',
'gtktreerbtreeprivate.h',
'gtkutilsprivate.h',
'gtkwidgetpaintableprivate.h',
'gtkwidgetpathprivate.h',
+135 -39
View File
@@ -1,85 +1,181 @@
# List Widget Overview {#ListWidget}
GTK provides powerful widgets to display and edit lists of data. This document gives an overview over the concepts and how they work together to allow developers to implement lists.
GTK provides powerful widgets to display and edit lists of data. This document
gives an overview over the concepts and how they work together to allow
developers to implement lists.
Lists are intended to be used whenever developers want to display lists of objects in roughly the same way.
Lists are intended to be used whenever developers want to display lists of
objects in roughly the same way.
Lists are perfectly fine to be used for very short list of only 2 or 3 elements, but generally scale fine to millions of items. Of course, the larger the list grows, the more care needs to be taken to choose the right data structures to keep things running well.
Lists are perfectly fine to be used for very short list of only 2 or 3 elements,
but generally scale fine to millions of items. Of course, the larger the list
grows, the more care needs to be taken to choose the right data structures to
keep things running well.
Lists are meant to be used with changing data, both with the items itself changing as well as the list adding and removing items. Of course, they work just as well with static data.
Lists are meant to be used with changing data, both with the items itself changing
as well as the list adding and removing items. Of course, they work just as well
with static data.
## Terminology
These terms are used throughout the documentation when talking about lists and you should be aware of what they refer to. These are often generic terms that have a specific meaning in this context.
These terms are used throughout the documentation when talking about lists and
you should be aware of what they refer to. These are often generic terms that
have a specific meaning in this context.
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists. Examples of thse widgets would be #GtkListView or #GtkGridView.
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists.
Examples of these widgets would be #GtkListView or #GtkGridView.
Views display data from a **_model_**. A model is a #GListModel and models can be provided in 3 ways or combinations thereof:
Views display data from a **_model_**. A model is a #GListModel and models can
be provided in 3 ways or combinations thereof:
* Many list models implementations already exist. There are models that provide specific data, like #GtkDirectoryList. And there are models like #GListStore that allow building lists manually.
* Many list models implementations already exist. There are models that provide
specific data, like #GtkDirectoryList. And there are models like #GListStore
that allow building lists manually.
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel that modify or adapt or combine other models.
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel
that modify or adapt or combine other models.
* Last but not least, developers are encouraged to create their own #GListModel implementations. The interface is kept deliberately small to make this easy.
* Last but not least, developers are encouraged to create their own #GListModel
implementations. The interface is kept deliberately small to make this easy.
The same model can be used in multiple different views and wrapped with multiple different models at once.
The same model can be used in multiple different views and wrapped with
multiple different models at once.
The elements in a model are called **_items_**. All items are #GObjects.
Every item in a model has a **_position_** which is the unsigned integer that describes where in the model the item is located. This position can of course change as items are added or removed from the model.
Every item in a model has a **_position_** which is the unsigned integer that
describes where in the model the item is located. This position can of course
change as items are added or removed from the model.
It is important to be aware of the difference between items and positions because the mapping from position to item is not permanent, so developers should think about whether they want to track items or positions when working with models. Oftentimes some things are really hard to do one way but very easy the other way.
It is important to be aware of the difference between items and positions
because the mapping from position to item is not permanent, so developers
should think about whether they want to track items or positions when working
with models. Oftentimes some things are really hard to do one way but very easy
the other way.
The other important part of a view is a **_factory_**. Each factory is a #GtkListItemFactory implementation that takes care of mapping the items of the model to widgets that can be shown in the view.
The other important part of a view is a **_factory_**. Each factory is
a #GtkListItemFactory implementation that takes care of mapping the items
of the model to widgets that can be shown in the view.
The way factories do this is by creating a **_listitem_** for each item that is currently in use. Listitems are always #GtkListItem objects. They are only ever created by GTK and provide information about what item they are meant to display.
The way factories do this is by creating a **_listitem_** for each item that
is currently in use. Listitems are always #GtkListItem objects. They are only
ever created by GTK and provide information about what item they are meant
to display.
Different factory implementations use various different methods to allow developers to add the right widgets to listitems and to link those widgets with the item managed by the listitem. Finding a suitable factory implementation for the data displayed, the programming language and development environment is an important task that can simplify setting up the view tremendously.
Different factory implementations use various different methods to allow
developers to add the right widgets to listitems and to link those widgets
with the item managed by the listitem. Finding a suitable factory implementation
for the data displayed, the programming language and development environment
is an important task that can simplify setting up the view tremendously.
Views support selections via a **_selection model_**. A selection model is an implementation of the #GtkSelectionModel interface on top of the #GListModel interface that allows marking each item in a model as either selected or not selected. Just like regular models, this can be implemented either by implementing #GtkSelectionModel directly or by wrapping a model with one of the GTK models provided for this purposes, such as #GtkNoSelection or #GtkSingleSelection.
The behavior of selection models - ie which items they allow selecting and what effect this has on other items - is completely up to the selection model. As such, single-selections, multi-selections or sharing selection state between different selection models and/or views is possible.
The selection state of an item is exposed in the listitem via the GtkListItem:selected property.
Views support selections via a **_selection model_**. A selection model is an
implementation of the #GtkSelectionModel interface on top of the #GListModel
interface that allows marking each item in a model as either selected or not
selected. Just like regular models, this can be implemented either by
implementing #GtkSelectionModel directly or by wrapping a model with one of
the GTK models provided for this purposes, such as #GtkNoSelection
or #GtkSingleSelection.
Views and listitems also support activation. Activation means that double clicking or pressing enter while inside a focused row will cause the view to emit and activation signal such as GtkListView::activate. This provides an easy way to set up lists, but can also be turned off on listitems if undesired.
The behavior of selection models - ie which items they allow selecting and
what effect this has on other items - is completely up to the selection model.
As such, single-selections, multi-selections or sharing selection state between
different selection models and/or views is possible. The selection state of an
item is exposed in the listitem via the GtkListItem:selected property.
Both selections and activation are supported among other things via widget actions (FIXME: Link docs). This allows developers to add widgets to their lists that cause selections to change or to trigger activation via the #GtkActionable interface. For a list of all supported actions see the relevant documentation. (FIXME: where do we document actions and how to I link that?)
Views and listitems also support activation. Activation means that double
clicking or pressing enter while inside a focused row will cause the view
to emit and activation signal such as #GtkListView::activate. This provides
an easy way to set up lists, but can also be turned off on listitems if undesired.
Both selections and activation are supported among other things via widget
[actions](#actions-overview). This allows developers to add widgets to their
lists that cause selections to change or to trigger activation via
the #GtkActionable interface. For a list of all supported actions see the
relevant documentation.
## Behind the scenes
While for short lists it is not a problem to instantiate widgets for every item in the model, once lists grow to thousands or millions of elements, this gets less feasible. Because of this, the views only create a limited amount of listitems and recycle them by binding them to new items. In general, views try to keep listitems available only for the items that can actually be seen on screen.
While for short lists it is not a problem to instantiate widgets for every
item in the model, once lists grow to thousands or millions of elements, this
gets less feasible. Because of this, the views only create a limited amount of
listitems and recycle them by binding them to new items. In general, views try
to keep listitems available only for the items that can actually be seen on screen.
While this behavior allows views to scale effortlessly to huge lists, it has a few implication on what can be done with views. For example, it is not possible to query a view for a listitem used for a certain position - there might not be one and even if there is, that listitem might soon be recycled for a new position.
While this behavior allows views to scale effortlessly to huge lists, it has a
few implication on what can be done with views. For example, it is not possible
to query a view for a listitem used for a certain position - there might not be
one and even if there is, that listitem might soon be recycled for a new position.
It is also important that developers save state they care about in the item and do not rely on the widgets they created as those widgets can be recycled for a new position at any time causing any state to be lost.
It is also important that developers save state they care about in the item and
do not rely on the widgets they created as those widgets can be recycled for a
new position at any time causing any state to be lost.
Another important requirement for views is that they need to know which items are not visible so they can be recycled. Views achieve that by implementing the #GtkScrollable interface and expecting to be placed directly into a #GtkScrolledWindow.
Another important requirement for views is that they need to know which items
are not visible so they can be recycled. Views achieve that by implementing
the #GtkScrollable interface and expecting to be placed directly into
a #GtkScrolledWindow.
Of course, if you are only using models with few items, this is not important and you can treat views like any other widget. But if you use large lists and your performance suffers, you should be aware of this. Views also allow tuning the number of listitems they create such as with gtk_grid_view_set_max_columns(), and developers running into performance problems should definitely study the tradeoffs of those and experiment with them.
Of course, if you are only using models with few items, this is not important
and you can treat views like any other widget. But if you use large lists and
your performance suffers, you should be aware of this. Views also allow tuning
the number of listitems they create such as with gtk_grid_view_set_max_columns(),
and developers running into performance problems should definitely study the
tradeoffs of those and experiment with them.
## Displaying trees
## Displaying trees {#displaying-trees}
While #GtkTreeView provided builtin support for trees, the list widgets, and in particular #GListModel do not. This was a design choice because the common use case is displaying lists and not trees and it greatly simplifies the API interface provided.
While #GtkTreeView provided built-in support for trees, the list widgets, and
in particular #GListModel do not. This was a design choice because the common
use case is displaying lists and not trees and it greatly simplifies the API
interface provided.
However, GTK provides functionality to make trees look and behave like lists for the people who still want to display lists. This is achieved by using the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander widget can then be used inside a listitem to allow users to expand and collapse rows and provide a similar experience to #GtkTreeView.
However, GTK provides functionality to make trees look and behave like lists
for the people who still want to display lists. This is achieved by using
the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander
widget can then be used inside a listitem to allow users to expand and collapse
rows and provide a similar experience to #GtkTreeView.
Developers should refer to those objects' API reference for more discussion on the topic.
Developers should refer to those objects' API reference for more discussion
on the topic.
## comparison to GtkTreeView
## Comparison to GtkTreeView
Developers familiar with #GtkTreeView may wonder how this way of doing lists compares to the way they know. This section will try to outline the similarities and differences between the two.
Developers familiar with #GtkTreeView may wonder how this way of doing lists
compares to the way they know. This section will try to outline the similarities
and differences between the two.
This new approach tries to provide roughly the same functionality as the old approach but often uses a very different approach to achieve these goals.
This new approach tries to provide roughly the same functionality as the old
approach but often uses a very different approach to achieve these goals.
The main difference and one of the primary reasons for this new development is that items can be displayed using regular widgets and #GtkCellRenderer is no longer necessary. This allows all benefits that widgets provide, such as complex layout and animating widgets and not only makes cell renderers obsolete, but also #GtkCellArea.
The main difference and one of the primary reasons for this new development is
that items can be displayed using regular widgets and #GtkCellRenderer is no
longer necessary. This allows all benefits that widgets provide, such as complex
layout and animating widgets and not only makes cell renderers obsolete, but
also #GtkCellArea.
The other big difference is the massive change to the data model. #GtkTreeModel was a rather complex interface for a tree data structure and #GListModel was deliberately designed to be a simple data structure for lists only. (See above (FIXME: link) for how to still do trees with this new model.) Another big change is that the new model allows for bulk changes via the #GListModel:items-changed signal while #GtkTreeModel only allows a single item to change at once.
The goal here is of course to encourage implementation of custom list models.
The other big difference is the massive change to the data model. #GtkTreeModel
was a rather complex interface for a tree data structure and #GListModel was
deliberately designed to be a simple data structure for lists only. (See
[above](#displaying-trees)) for how to still do trees with this new model.)
Another big change is that the new model allows for bulk changes via
the #GListModel:items-changed signal while #GtkTreeModel only allows a single
item to change at once. The goal here is of course to encourage implementation
of custom list models.
Another consequence of the new model is that it is now easily possible to refer to the contents of a row in the model directly by keeping the item, while #GtkTreeRowReference was a very slow mechanism to achieve the same. And because the items are real objects, developers can make them emit change signals causing listitems and their children to update, which wasn't possible with #GtkTreeModel.
Another consequence of the new model is that it is now easily possible to
refer to the contents of a row in the model directly by keeping the item,
while #GtkTreeRowReference was a very slow mechanism to achieve the same.
And because the items are real objects, developers can make them emit change
signals causing listitems and their children to update, which wasn't possible
with #GtkTreeModel.
The selection handling is also different. While selections used to be managed via custom code in each widget, selection state is now meant to be managed by the selection models. In particular this allows for complex use cases with specialized requirements (FIXME: Can I add a shoutout to @mitch here because I vividly remember a huge discussion about GtkTreeView's selection behavior and the Gimp).
The selection handling is also different. While selections used to be managed
via custom code in each widget, selection state is now meant to be managed by
the selection models. In particular this allows for complex use cases with
specialized requirements.
Finally here's a quick list of equivalent functionality to look for when transitioning code for easy lookup:
Finally here's a quick list of equivalent functionality to look for when
transitioning code for easy lookup:
| Old | New |
| ------------------- | ----------------------------------- |
-18
View File
@@ -23,12 +23,6 @@
#include "gdksurfaceprivate.h"
#include "gdkprivate-broadway.h"
static gboolean gdk_broadway_device_get_history (GdkDevice *device,
GdkSurface *surface,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events);
static void gdk_broadway_device_get_state (GdkDevice *device,
GdkSurface *surface,
gdouble *axes,
@@ -64,7 +58,6 @@ gdk_broadway_device_class_init (GdkBroadwayDeviceClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_history = gdk_broadway_device_get_history;
device_class->get_state = gdk_broadway_device_get_state;
device_class->set_surface_cursor = gdk_broadway_device_set_surface_cursor;
device_class->query_state = gdk_broadway_device_query_state;
@@ -84,17 +77,6 @@ gdk_broadway_device_init (GdkBroadwayDevice *device_core)
_gdk_device_add_axis (device, NULL, GDK_AXIS_Y, 0, 0, 1);
}
static gboolean
gdk_broadway_device_get_history (GdkDevice *device,
GdkSurface *surface,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
return FALSE;
}
static void
gdk_broadway_device_get_state (GdkDevice *device,
GdkSurface *surface,
+61 -87
View File
@@ -635,93 +635,6 @@ gdk_device_get_surface_at_position (GdkDevice *device,
return surface;
}
/**
* gdk_device_get_history: (skip)
* @device: a #GdkDevice
* @surface: the surface with respect to which the event coordinates will be reported
* @start: starting timestamp for range of events to return
* @stop: ending timestamp for the range of events to return
* @events: (array length=n_events) (out) (transfer full) (optional):
* location to store a newly-allocated array of #GdkTimeCoord, or
* %NULL
* @n_events: (out) (optional): location to store the length of
* @events, or %NULL
*
* Obtains the motion history for a pointer device; given a starting and
* ending timestamp, return all events in the motion history for
* the device in the given range of time. Some windowing systems
* do not support motion history, in which case, %FALSE will
* be returned. (This is not distinguishable from the case where
* motion history is supported and no events were found.)
*
* Note that there is also gdk_surface_set_event_compression() to get
* more motion events delivered directly, independent of the windowing
* system.
*
* Returns: %TRUE if the windowing system supports motion history and
* at least one event was found.
**/
gboolean
gdk_device_get_history (GdkDevice *device,
GdkSurface *surface,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, FALSE);
g_return_val_if_fail (GDK_IS_SURFACE (surface), FALSE);
if (n_events)
*n_events = 0;
if (events)
*events = NULL;
if (GDK_SURFACE_DESTROYED (surface))
return FALSE;
if (!GDK_DEVICE_GET_CLASS (device)->get_history)
return FALSE;
return GDK_DEVICE_GET_CLASS (device)->get_history (device, surface,
start, stop,
events, n_events);
}
GdkTimeCoord **
_gdk_device_allocate_history (GdkDevice *device,
gint n_events)
{
GdkTimeCoord **result = g_new (GdkTimeCoord *, n_events);
gint i;
for (i = 0; i < n_events; i++)
result[i] = g_malloc (sizeof (GdkTimeCoord) -
sizeof (double) * (GDK_MAX_TIMECOORD_AXES - device->axes->len));
return result;
}
/**
* gdk_device_free_history: (skip)
* @events: (array length=n_events): an array of #GdkTimeCoord.
* @n_events: the length of the array.
*
* Frees an array of #GdkTimeCoord that was returned by gdk_device_get_history().
*/
void
gdk_device_free_history (GdkTimeCoord **events,
gint n_events)
{
gint i;
for (i = 0; i < n_events; i++)
g_free (events[i]);
g_free (events);
}
/**
* gdk_device_get_name:
* @device: a #GdkDevice
@@ -1775,6 +1688,15 @@ gdk_device_get_device_tool (GdkDevice *device)
return device->last_tool;
}
/**
* gdk_device_get_caps_lock_state:
* @device: a #GdkDevice
*
* Retrieves whether the Caps Lock modifier of the
* keyboard is locked, if @device is a keyboard device.
*
* Returns: %TRUE if Caps Lock is on for @device
*/
gboolean
gdk_device_get_caps_lock_state (GdkDevice *device)
{
@@ -1786,6 +1708,15 @@ gdk_device_get_caps_lock_state (GdkDevice *device)
return FALSE;
}
/**
* gdk_device_get_num_lock_state:
* @device: a #GdkDevice
*
* Retrieves whether the Num Lock modifier of the
* keyboard is locked, if @device is a keyboard device.
*
* Returns: %TRUE if Num Lock is on for @device
*/
gboolean
gdk_device_get_num_lock_state (GdkDevice *device)
{
@@ -1797,6 +1728,15 @@ gdk_device_get_num_lock_state (GdkDevice *device)
return FALSE;
}
/**
* gdk_device_get_scroll_lock_state:
* @device: a #GdkDevice
*
* Retrieves whether the Scroll Lock modifier of the
* keyboard is locked, if @device is a keyboard device.
*
* Returns: %TRUE if Scroll Lock is on for @device
*/
gboolean
gdk_device_get_scroll_lock_state (GdkDevice *device)
{
@@ -1808,6 +1748,15 @@ gdk_device_get_scroll_lock_state (GdkDevice *device)
return FALSE;
}
/**
* gdk_device_get_modifier_state:
* @device: a #GdkDevice
*
* Retrieves the current modifier state of the keyboard,
* if @device is a keyboard device.
*
* Returns: the current modifier state
*/
GdkModifierType
gdk_device_get_modifier_state (GdkDevice *device)
{
@@ -1819,6 +1768,20 @@ gdk_device_get_modifier_state (GdkDevice *device)
return 0;
}
/**
* gdk_device_get_direction:
* @device: a #GdkDevice
*
* Returns the direction of effective layout of the keyboard,
* if @device is a keyboard device.
*
* The direction of a layout is the direction of the majority
* of its symbols. See pango_unichar_direction().
*
* Returns: %PANGO_DIRECTION_LTR or %PANGO_DIRECTION_RTL
* if it can determine the direction. %PANGO_DIRECTION_NEUTRAL
* otherwise
*/
PangoDirection
gdk_device_get_direction (GdkDevice *device)
{
@@ -1830,6 +1793,17 @@ gdk_device_get_direction (GdkDevice *device)
return PANGO_DIRECTION_NEUTRAL;
}
/**
* gdk_device_has_bidi_layouts:
* @device: a #GdkDevice
*
* Determines if keyboard layouts for both right-to-left and
* left-to-right languages are in use on the keyboard, if
* @device is a keyboard device.
*
* Returns: %TRUE if there are layouts with both directions,
* %FALSE otherwise
*/
gboolean
gdk_device_has_bidi_layouts (GdkDevice *device)
{
-10
View File
@@ -146,16 +146,6 @@ GDK_AVAILABLE_IN_ALL
GdkSurface * gdk_device_get_surface_at_position (GdkDevice *device,
double *win_x,
double *win_y);
GDK_AVAILABLE_IN_ALL
gboolean gdk_device_get_history (GdkDevice *device,
GdkSurface *surface,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events);
GDK_AVAILABLE_IN_ALL
void gdk_device_free_history (GdkTimeCoord **events,
gint n_events);
GDK_AVAILABLE_IN_ALL
gint gdk_device_get_n_axes (GdkDevice *device);
-7
View File
@@ -70,13 +70,6 @@ struct _GdkDeviceClass
{
GObjectClass parent_class;
gboolean (* get_history) (GdkDevice *device,
GdkSurface *surface,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events);
void (* get_state) (GdkDevice *device,
GdkSurface *surface,
gdouble *axes,
+19 -18
View File
@@ -56,6 +56,7 @@ struct _GdkFrameClockIdlePrivate
GdkFrameClockPhase phase;
guint in_paint_idle : 1;
guint paint_is_thaw : 1;
#ifdef G_OS_WIN32
guint begin_period : 1;
#endif
@@ -162,7 +163,7 @@ gdk_frame_clock_idle_dispose (GObject *object)
static gint64
compute_smooth_frame_time (GdkFrameClock *clock,
gint64 new_frame_time,
gboolean new_frame_time_is_regular,
gboolean new_frame_time_is_vsync_related,
gint64 smoothed_frame_time_base,
gint64 frame_interval)
{
@@ -204,13 +205,13 @@ compute_smooth_frame_time (GdkFrameClock *clock,
* (current_error/frame_interval)*(current_error/frame_interval)*frame_interval
* But this can be simplified as below.
*
* Note: We only do this correction if we're regularly animating (no
* or low frame skip). If the last frame was a long time ago, or if
* we're not doing this in the frame cycle this call was likely
* triggered by an input event and new_frame_time is essentially
* random and not tied to the presentation time.
* Note: We only do this correction if the new frame is caused by a
* thaw of the frame clock, so that we know the time is actually
* related to the physical vblank. For frameclock cycles triggered
* by other events we always step up in whole frames from the last
* reported time.
*/
if (new_frame_time_is_regular)
if (new_frame_time_is_vsync_related)
{
current_error = new_smoothed_time - new_frame_time;
correction_magnitude = current_error * current_error / frame_interval; /* Note, this is always > 0 due to the square */
@@ -236,7 +237,8 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock)
/* can't change frame time during a paint */
if (priv->phase != GDK_FRAME_CLOCK_PHASE_NONE &&
priv->phase != GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS)
priv->phase != GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS &&
(priv->phase != GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT || priv->in_paint_idle))
return priv->smoothed_frame_time_base;
/* Outside a paint, pick something smoothed close to now */
@@ -274,7 +276,8 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock)
(priv)->updating_count > 0))
static void
maybe_start_idle (GdkFrameClockIdle *clock_idle)
maybe_start_idle (GdkFrameClockIdle *clock_idle,
gboolean caused_by_thaw)
{
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
@@ -302,6 +305,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle)
if (!priv->in_paint_idle &&
priv->paint_idle_id == 0 && RUN_PAINT_IDLE (priv))
{
priv->paint_is_thaw = caused_by_thaw;
priv->paint_idle_id = g_timeout_add_full (GDK_PRIORITY_REDRAW,
min_interval,
gdk_frame_clock_paint_idle,
@@ -408,7 +412,6 @@ gdk_frame_clock_paint_idle (void *data)
{
gint64 frame_interval = FRAME_INTERVAL;
GdkFrameTimings *prev_timings = gdk_frame_clock_get_current_timings (clock);
gint64 old_frame_time = priv->frame_time;
if (prev_timings && prev_timings->refresh_interval)
frame_interval = prev_timings->refresh_interval;
@@ -423,11 +426,9 @@ gdk_frame_clock_paint_idle (void *data)
}
else
{
/* For long delays, cycle was probably caused by input event rather than animation */
gboolean is_regular = priv->frame_time - old_frame_time < 4 * FRAME_INTERVAL;
priv->smoothed_frame_time_base =
compute_smooth_frame_time (clock, priv->frame_time,
is_regular,
priv->paint_is_thaw,
priv->smoothed_frame_time_base,
priv->smoothed_frame_time_period);
priv->smoothed_frame_time_period = frame_interval;
@@ -558,8 +559,8 @@ gdk_frame_clock_paint_idle (void *data)
if (priv->freeze_count == 0)
{
priv->min_next_frame_time = compute_min_next_frame_time (clock_idle,
priv->frame_time);
maybe_start_idle (clock_idle);
priv->smoothed_frame_time_base);
maybe_start_idle (clock_idle, FALSE);
}
if (priv->freeze_count == 0)
@@ -579,7 +580,7 @@ gdk_frame_clock_idle_request_phase (GdkFrameClock *clock,
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
priv->requested |= phase;
maybe_start_idle (clock_idle);
maybe_start_idle (clock_idle, FALSE);
}
static void
@@ -598,7 +599,7 @@ gdk_frame_clock_idle_begin_updating (GdkFrameClock *clock)
#endif
priv->updating_count++;
maybe_start_idle (clock_idle);
maybe_start_idle (clock_idle, FALSE);
}
static void
@@ -648,7 +649,7 @@ gdk_frame_clock_idle_thaw (GdkFrameClock *clock)
priv->freeze_count--;
if (priv->freeze_count == 0)
{
maybe_start_idle (clock_idle);
maybe_start_idle (clock_idle, TRUE);
/* If nothing is requested so we didn't start an idle, we need
* to skip to the end of the state chain, since the idle won't
* run and do it for us.
+2
View File
@@ -71,6 +71,8 @@ typedef enum
/**
* GdkPopupLayout:
*
* Struct containing information for gdk_popup_present()
*/
typedef struct _GdkPopupLayout GdkPopupLayout;
+2
View File
@@ -31,6 +31,8 @@ G_BEGIN_DECLS
/**
* GdkTopLevelLayout:
*
* Struct containing information for gdk_toplevel_present()
*/
typedef struct _GdkToplevelLayout GdkToplevelLayout;
-12
View File
@@ -309,17 +309,6 @@ static void deliver_key_event (GdkWaylandSeat *seat,
uint32_t state,
gboolean from_key_repeat);
static gboolean
gdk_wayland_device_get_history (GdkDevice *device,
GdkSurface *surface,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
return FALSE;
}
static void
gdk_wayland_device_get_state (GdkDevice *device,
GdkSurface *surface,
@@ -828,7 +817,6 @@ gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_history = gdk_wayland_device_get_history;
device_class->get_state = gdk_wayland_device_get_state;
device_class->set_surface_cursor = gdk_wayland_device_set_surface_cursor;
device_class->query_state = gdk_wayland_device_query_state;
-1
View File
@@ -31,7 +31,6 @@
#include <limits.h>
#include <errno.h>
#include <sys/mman.h>
#include <fribidi.h>
#include "gdk.h"
#include "gdkwayland.h"
-13
View File
@@ -63,18 +63,6 @@ _gdk_device_virtual_set_active (GdkDevice *device,
g_signal_emit_by_name (G_OBJECT (device), "changed");
}
static gboolean
gdk_device_virtual_get_history (GdkDevice *device,
GdkSurface *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
/* History is only per slave device */
return FALSE;
}
static void
gdk_device_virtual_get_state (GdkDevice *device,
GdkSurface *window,
@@ -188,7 +176,6 @@ gdk_device_virtual_class_init (GdkDeviceVirtualClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_history = gdk_device_virtual_get_history;
device_class->get_state = gdk_device_virtual_get_state;
device_class->set_surface_cursor = gdk_device_virtual_set_surface_cursor;
device_class->query_state = gdk_device_virtual_query_state;
-12
View File
@@ -29,17 +29,6 @@
G_DEFINE_TYPE (GdkDeviceWin32, gdk_device_win32, GDK_TYPE_DEVICE)
static gboolean
gdk_device_win32_get_history (GdkDevice *device,
GdkSurface *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
return FALSE;
}
static void
gdk_device_win32_get_state (GdkDevice *device,
GdkSurface *window,
@@ -235,7 +224,6 @@ gdk_device_win32_class_init (GdkDeviceWin32Class *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_history = gdk_device_win32_get_history;
device_class->get_state = gdk_device_win32_get_state;
device_class->set_surface_cursor = gdk_device_win32_set_surface_cursor;
device_class->query_state = gdk_device_win32_query_state;
-12
View File
@@ -28,17 +28,6 @@
G_DEFINE_TYPE (GdkDeviceWintab, gdk_device_wintab, GDK_TYPE_DEVICE)
static gboolean
gdk_device_wintab_get_history (GdkDevice *device,
GdkSurface *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
return FALSE;
}
static GdkModifierType
get_current_mask (void)
{
@@ -267,7 +256,6 @@ gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_history = gdk_device_wintab_get_history;
device_class->get_state = gdk_device_wintab_get_state;
device_class->set_surface_cursor = gdk_device_wintab_set_surface_cursor;
device_class->query_state = gdk_device_wintab_query_state;
+8
View File
@@ -1603,6 +1603,14 @@ gdk_x11_display_open (const gchar *display_name)
}
#endif
#ifdef HAVE_XDAMAGE
display_x11->have_damage = FALSE;
if (XDamageQueryExtension (display_x11->xdisplay,
&display_x11->damage_event_base,
&display_x11->damage_error_base))
display_x11->have_damage = TRUE;
#endif
display->clipboard = gdk_x11_clipboard_new (display, "CLIPBOARD");
display->primary_clipboard = gdk_x11_clipboard_new (display, "PRIMARY");
+7
View File
@@ -149,6 +149,13 @@ struct _GdkX11Display
guint has_glx_multisample : 1;
guint has_glx_visual_rating : 1;
guint has_glx_create_es2_context : 1;
guint has_async_glx_swap_buffers : 1;
#ifdef HAVE_XDAMAGE
gint damage_event_base;
gint damage_error_base;
guint have_damage;
#endif
};
struct _GdkX11DisplayClass
+128
View File
@@ -183,6 +183,22 @@ gdk_x11_gl_context_end_frame (GdkDrawContext *draw_context,
gdk_x11_surface_pre_damage (surface);
#ifdef HAVE_XDAMAGE
if (context_x11->xdamage != 0)
{
g_assert (context_x11->frame_fence == 0);
context_x11->frame_fence = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
/* We consider the frame still getting painted until the GL operation is
* finished, and the window gets damage reported from the X server.
* It's only at this point the compositor can be sure it has full
* access to the new updates.
*/
_gdk_x11_surface_set_frame_still_painting (surface, TRUE);
}
#endif
glXSwapBuffers (dpy, drawable);
if (context_x11->do_frame_sync && info != NULL && display_x11->has_glx_video_sync)
@@ -565,6 +581,81 @@ create_legacy_context (GdkDisplay *display,
return res;
}
#ifdef HAVE_XDAMAGE
static gboolean
on_gl_surface_xevent (GdkGLContext *context,
XEvent *xevent,
GdkX11Display *display_x11)
{
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
GdkSurface *surface = gdk_gl_context_get_surface (context);
XDamageNotifyEvent *damage_xevent;
if (!context_x11->is_attached)
return FALSE;
if (xevent->type != (display_x11->damage_event_base + XDamageNotify))
return FALSE;
damage_xevent = (XDamageNotifyEvent *) xevent;
if (damage_xevent->damage != context_x11->xdamage)
return FALSE;
if (context_x11->frame_fence)
{
GLenum wait_result;
wait_result = glClientWaitSync (context_x11->frame_fence, 0, 0);
switch (wait_result)
{
/* We assume that if the fence has been signaled, that this damage
* event is the damage event that was triggered by the GL drawing
* associated with the fence. That's, technically, not necessarly
* always true. The X server could have generated damage for
* an unrelated event (say the size of the window changing), at
* just the right moment such that we're picking it up instead.
*
* We're choosing not to handle this edge case, but if it does ever
* happen in the wild, it could lead to slight underdrawing by
* the compositor for one frame. In the future, if we find out
* this edge case is noticeable, we can compensate by copying the
* painted region from gdk_x11_gl_context_end_frame and subtracting
* damaged areas from the copy as they come in. Once the copied
* region goes empty, we know that there won't be any underdraw,
* and can mark painting has finished. It's not worth the added
* complexity and resource usage to do this bookkeeping, however,
* unless the problem is practically visible.
*/
case GL_ALREADY_SIGNALED:
case GL_CONDITION_SATISFIED:
case GL_WAIT_FAILED:
if (wait_result == GL_WAIT_FAILED)
g_warning ("failed to wait on GL fence associated with last swap buffers call");
glDeleteSync (context_x11->frame_fence);
context_x11->frame_fence = 0;
_gdk_x11_surface_set_frame_still_painting (surface, FALSE);
break;
/* We assume that if the fence hasn't been signaled, that this
* damage event is not the damage event that was triggered by the
* GL drawing associated with the fence. That's only true for
* the Nvidia vendor driver. When using open source drivers, damage
* is emitted immediately on swap buffers, before the fence ever
* has a chance to signal.
*/
case GL_TIMEOUT_EXPIRED:
break;
default:
g_assert_not_reached ();
}
}
return FALSE;
}
#endif
static gboolean
gdk_x11_gl_context_realize (GdkGLContext *context,
GError **error)
@@ -737,6 +828,24 @@ gdk_x11_gl_context_realize (GdkGLContext *context,
context_x11->attached_drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_surface_get_xid (surface);
context_x11->unattached_drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin;
#ifdef HAVE_XDAMAGE
if (display_x11->have_damage && display_x11->has_async_glx_swap_buffers)
{
gdk_x11_display_error_trap_push (display);
context_x11->xdamage = XDamageCreate (dpy,
gdk_x11_surface_get_xid (surface),
XDamageReportRawRectangles);
if (gdk_x11_display_error_trap_pop (display))
context_x11->xdamage = 0;
else
g_signal_connect_object (G_OBJECT (display),
"xevent",
G_CALLBACK (on_gl_surface_xevent),
context,
G_CONNECT_SWAPPED);
}
#endif
context_x11->is_direct = glXIsDirect (dpy, context_x11->glx_context);
GDK_DISPLAY_NOTE (display, OPENGL,
@@ -766,6 +875,10 @@ gdk_x11_gl_context_dispose (GObject *gobject)
context_x11->glx_context = NULL;
}
#ifdef HAVE_XDAMAGE
context_x11->xdamage = 0;
#endif
G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject);
}
@@ -841,6 +954,21 @@ gdk_x11_screen_init_gl (GdkX11Screen *screen)
display_x11->has_glx_visual_rating =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_visual_rating");
if (g_strcmp0 (glXGetClientString (dpy, GLX_VENDOR), "NVIDIA Corporation") == 0)
{
/* With the mesa based drivers, we can safely assume the compositor can
* access the updated surface texture immediately after glXSwapBuffers is
* run, because the kernel ensures there is an implicit synchronization
* operation upon texture access. This is not true with the Nvidia vendor
* driver. There is a window of time after glXSwapBuffers before other
* processes can see the updated drawing. We need to take special care,
* in that case, to defer telling the compositor our latest frame is
* ready until after the GPU has completed all issued commands related
* to the frame, and that the X server says the frame has been drawn.
*/
display_x11->has_async_glx_swap_buffers = TRUE;
}
GDK_DISPLAY_NOTE (display, OPENGL,
g_message ("GLX version %d.%d found\n"
" - Vendor: %s\n"
+9
View File
@@ -24,6 +24,10 @@
#include <X11/X.h>
#include <X11/Xlib.h>
#ifdef HAVE_XDAMAGE
#include <X11/extensions/Xdamage.h>
#endif
#include <epoxy/gl.h>
#include <epoxy/glx.h>
@@ -44,6 +48,11 @@ struct _GdkX11GLContext
GLXDrawable attached_drawable;
GLXDrawable unattached_drawable;
#ifdef HAVE_XDAMAGE
GLsync frame_fence;
Damage xdamage;
#endif
guint is_attached : 1;
guint is_direct : 1;
guint do_frame_sync : 1;
+5
View File
@@ -104,6 +104,11 @@ void _gdk_x11_surface_grab_check_unmap (GdkSurface *window,
gulong serial);
void _gdk_x11_surface_grab_check_destroy (GdkSurface *window);
#ifdef HAVE_XDAMAGE
void _gdk_x11_surface_set_frame_still_painting (GdkSurface *surface,
gboolean painting);
#endif
gboolean _gdk_x11_display_is_root_window (GdkDisplay *display,
Window xroot_window);
+73 -6
View File
@@ -360,6 +360,77 @@ gdk_x11_surface_begin_frame (GdkSurface *surface,
}
}
static gboolean
should_sync_frame_drawing (GdkSurface *surface)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
/* disabled client side */
if (!impl->frame_sync_enabled)
return FALSE;
/* disabled compositor side */
if (!gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (surface),
g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
return FALSE;
return TRUE;
}
static void
sync_counter_for_end_frame (GdkSurface *surface)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
g_assert (!impl->toplevel->in_frame);
g_assert (impl->toplevel->extended_update_counter != None);
g_assert ((impl->toplevel->current_counter_value % 2) == 0);
set_sync_counter (GDK_SURFACE_XDISPLAY (surface),
impl->toplevel->extended_update_counter,
impl->toplevel->current_counter_value);
}
static void
maybe_sync_counter_for_end_frame (GdkSurface *surface)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
gboolean frame_sync_negotiated = should_sync_frame_drawing (surface);
gboolean frame_done_painting = !impl->toplevel->frame_pending;
#ifdef HAVE_XDAMAGE
frame_done_painting = !impl->toplevel->frame_still_painting && frame_sync_negotiated;
#endif
if (!impl->toplevel->frame_pending)
{
if (!frame_sync_negotiated || frame_done_painting)
sync_counter_for_end_frame (surface);
}
else
{
if (frame_done_painting)
sync_counter_for_end_frame (surface);
}
}
#ifdef HAVE_XDAMAGE
void
_gdk_x11_surface_set_frame_still_painting (GdkSurface *surface,
gboolean painting)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
if (impl->toplevel->frame_still_painting == painting)
return;
impl->toplevel->frame_still_painting = painting;
if (!impl->toplevel->frame_still_painting)
maybe_sync_counter_for_end_frame (surface);
}
#endif
static void
gdk_x11_surface_end_frame (GdkSurface *surface)
{
@@ -405,13 +476,9 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
else
impl->toplevel->current_counter_value += 1;
set_sync_counter(GDK_SURFACE_XDISPLAY (surface),
impl->toplevel->extended_update_counter,
impl->toplevel->current_counter_value);
maybe_sync_counter_for_end_frame (surface);
if (impl->frame_sync_enabled &&
gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (surface),
g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
if (should_sync_frame_drawing (surface))
{
impl->toplevel->frame_pending = TRUE;
gdk_surface_freeze_updates (surface);
+3
View File
@@ -124,6 +124,9 @@ struct _GdkToplevelX11
guint in_frame : 1;
/* If we're waiting for damage from the X server after painting a frame */
guint frame_still_painting : 1;
/* If we're expecting a response from the compositor after painting a frame */
guint frame_pending : 1;
+1
View File
@@ -65,6 +65,7 @@ gdk_x11_deps = [
xext_dep,
x11_dep,
xcursor_dep,
xdamage_dep,
xfixes_dep,
xcomposite_dep,
xrandr_dep,
+35 -1
View File
@@ -370,7 +370,7 @@ gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node)
* @node: (type GskLinearGradientNode): a #GskRenderNode for a linear gradient
* @n_stops: (out) (optional): the number of color stops in the returned array
*
* Retrievs the color stops in the gradient.
* Retrieves the color stops in the gradient.
*
* Returns: (array length=n_stops): the color stops in the gradient
*/
@@ -555,6 +555,14 @@ gsk_border_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
/**
* gsk_border_node_peek_outline:
* @node: (type GskBorderNode): a #GskRenderNode for a border
*
* Retrieves the outline of the border.
*
* Returns: the outline of the border
*/
const GskRoundedRect *
gsk_border_node_peek_outline (GskRenderNode *node)
{
@@ -563,6 +571,15 @@ gsk_border_node_peek_outline (GskRenderNode *node)
return &self->outline;
}
/**
* gsk_border_node_peek_widths:
* @node: (type GskBorderNode): a #GskRenderNode for a border
*
* Retrieves the stroke widths of the border.
*
* Returns: (transfer none): an array of 4 floats for the top,
* right, bottom and left stroke width of the border
*/
const float *
gsk_border_node_peek_widths (GskRenderNode *node)
{
@@ -571,6 +588,15 @@ gsk_border_node_peek_widths (GskRenderNode *node)
return self->border_width;
}
/**
* gsk_border_node_peek_colors:
* @node: (type GskBorderNode): a #GskRenderNode for a border
*
* Retrieves the colors of the border.
*
* Returns: (transfer none): an array of 4 #GdkRGBA structs
* for the top, right, bottom and left color of the border
*/
const GdkRGBA *
gsk_border_node_peek_colors (GskRenderNode *node)
{
@@ -3626,6 +3652,14 @@ gsk_text_node_has_color_glyphs (GskRenderNode *node)
return self->has_color_glyphs;
}
/**
* gsk_text_node_get_num_glyphs:
* @node: (type GskTextNode): a text #GskRenderNode
*
* Retrieves the number of glyphs in the text node.
*
* Returns: the number of glyphs
*/
guint
gsk_text_node_get_num_glyphs (GskRenderNode *node)
{
+9 -16
View File
@@ -171,37 +171,30 @@ gtk_button_accessible_ref_state_set (AtkObject *obj)
return state_set;
}
static void
gtk_button_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
void
gtk_button_accessible_update_label (GtkButtonAccessible *self)
{
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *atk_obj = gtk_widget_get_accessible (widget);
g_return_if_fail (GTK_IS_BUTTON_ACCESSIBLE (self));
if (strcmp (pspec->name, "label") == 0)
{
if (atk_obj->name == NULL)
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
/* If we don't have an overridden name, we use the label as the
* accessible name
*/
if (atk_object_get_name (ATK_OBJECT (self)) == NULL)
g_object_notify (G_OBJECT (self), "accessible-name");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec);
g_signal_emit_by_name (self, "visible-data-changed");
}
static void
gtk_button_accessible_class_init (GtkButtonAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
class->get_name = gtk_button_accessible_get_name;
class->get_n_children = gtk_button_accessible_get_n_children;
class->ref_child = gtk_button_accessible_ref_child;
class->ref_state_set = gtk_button_accessible_ref_state_set;
class->initialize = gtk_button_accessible_initialize;
widget_class->notify_gtk = gtk_button_accessible_notify_gtk;
}
static void
+3
View File
@@ -52,6 +52,9 @@ struct _GtkButtonAccessibleClass
GDK_AVAILABLE_IN_ALL
GType gtk_button_accessible_get_type (void);
/*< private >*/
void gtk_button_accessible_update_label (GtkButtonAccessible *self);
G_END_DECLS
#endif /* __GTK_BUTTON_ACCESSIBLE_H__ */
+33 -30
View File
@@ -17,10 +17,10 @@
#include "config.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include "gtkcolorswatchprivate.h"
#include "gtkcolorswatchaccessibleprivate.h"
#include "gtkcolorswatchprivate.h"
#include <glib/gi18n-lib.h>
static void atk_action_interface_init (AtkActionIface *iface);
@@ -29,9 +29,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkColorSwatchAccessible, _gtk_color_swatch_accessible,
static void
state_changed_cb (GtkWidget *widget,
GtkStateFlags previous_flags)
GtkStateFlags previous_flags,
AtkObject *accessible)
{
AtkObject *accessible;
GtkStateFlags flags;
gboolean was_selected;
gboolean selected;
@@ -41,23 +41,46 @@ state_changed_cb (GtkWidget *widget,
was_selected = (previous_flags & GTK_STATE_FLAG_SELECTED) != 0;
selected = (flags & GTK_STATE_FLAG_SELECTED) != 0;
accessible = gtk_widget_get_accessible (widget);
if (selected && !was_selected)
atk_object_notify_state_change (accessible, ATK_STATE_CHECKED, TRUE);
else if (!selected && was_selected)
atk_object_notify_state_change (accessible, ATK_STATE_CHECKED, FALSE);
}
static void
on_selectable_changed_cb (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (gobject);
AtkRole role;
if (gtk_color_swatch_get_selectable (swatch))
role = ATK_ROLE_RADIO_BUTTON;
else
role = ATK_ROLE_PUSH_BUTTON;
atk_object_set_role (accessible, role);
}
static void
gtk_color_swatch_accessible_initialize (AtkObject *obj,
gpointer data)
{
GtkColorSwatch *swatch = data;
ATK_OBJECT_CLASS (_gtk_color_swatch_accessible_parent_class)->initialize (obj, data);
g_signal_connect (data, "state-flags-changed",
G_CALLBACK (state_changed_cb), NULL);
G_CALLBACK (state_changed_cb),
obj);
g_signal_connect (data, "notify::selectable",
G_CALLBACK (on_selectable_changed_cb),
obj);
atk_object_set_role (obj, ATK_ROLE_RADIO_BUTTON);
obj->role = gtk_color_swatch_get_selectable (swatch)
? ATK_ROLE_RADIO_BUTTON
: ATK_ROLE_PUSH_BUTTON;
}
static AtkStateSet *
@@ -78,39 +101,19 @@ gtk_color_swatch_accessible_ref_state_set (AtkObject *accessible)
return state_set;
}
static void
gtk_color_swatch_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *atk_obj = gtk_widget_get_accessible (widget);
if (strcmp (pspec->name, "selectable") == 0)
{
if (gtk_color_swatch_get_selectable (GTK_COLOR_SWATCH (widget)))
atk_object_set_role (atk_obj, ATK_ROLE_RADIO_BUTTON);
else
atk_object_set_role (atk_obj, ATK_ROLE_PUSH_BUTTON);
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_color_swatch_accessible_parent_class)->notify_gtk (obj, pspec);
}
static void
_gtk_color_swatch_accessible_class_init (GtkColorSwatchAccessibleClass *klass)
{
AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass *)klass;
atk_class->initialize = gtk_color_swatch_accessible_initialize;
atk_class->ref_state_set = gtk_color_swatch_accessible_ref_state_set;
widget_class->notify_gtk = gtk_color_swatch_accessible_notify_gtk;
}
static void
_gtk_color_swatch_accessible_init (GtkColorSwatchAccessible *scale)
_gtk_color_swatch_accessible_init (GtkColorSwatchAccessible *self)
{
ATK_OBJECT (self)->role = ATK_ROLE_RADIO_BUTTON;
}
static gint
+293 -334
View File
@@ -17,20 +17,21 @@
#include "config.h"
#include "gtkentryaccessible.h"
#include "gtkcomboboxaccessible.h"
#include "gtkentryprivate.h"
#include "gtklabel.h"
#include "gtkpango.h"
#include "gtkstylecontextprivate.h"
#include "gtktextprivate.h"
#include "gtkwidgetprivate.h"
#include "gdk/gdkeventsprivate.h"
#include <glib/gi18n-lib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "gtkpango.h"
#include "gtkentryaccessible.h"
#include "gtkentryprivate.h"
#include "gtksearchentryprivate.h"
#include "gtkpasswordentry.h"
#include "gtktextprivate.h"
#include "gtkcomboboxaccessible.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#define GTK_TYPE_ENTRY_ICON_ACCESSIBLE (gtk_entry_icon_accessible_get_type ())
#define GTK_ENTRY_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ENTRY_ICON_ACCESSIBLE, GtkEntryIconAccessible))
@@ -157,7 +158,7 @@ gtk_entry_icon_accessible_ref_state_set (AtkObject *accessible)
if (!entry_set || atk_state_set_contains_state (entry_set, ATK_STATE_DEFUNCT))
{
atk_state_set_add_state (set, ATK_STATE_DEFUNCT);
g_clear_object (&entry_set);
g_clear_object (&entry_set);
return set;
}
@@ -356,15 +357,6 @@ icon_atk_component_interface_init (AtkComponentIface *iface)
}
/* Callbacks */
static void insert_text_cb (GtkEditable *editable,
gchar *new_text,
gint new_text_length,
gint *position);
static void delete_text_cb (GtkEditable *editable,
gint start,
gint end);
static gboolean check_for_selection_change (GtkEntryAccessible *entry,
GtkEditable *editable);
@@ -380,6 +372,277 @@ G_DEFINE_TYPE_WITH_CODE (GtkEntryAccessible, gtk_entry_accessible, GTK_TYPE_WIDG
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
static GtkText *
get_text (AtkText *atk_text)
{
GtkWidget *widget;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
return NULL;
return gtk_entry_get_text_widget (GTK_ENTRY (widget));
}
static gboolean
check_for_selection_change (GtkEntryAccessible *accessible,
GtkEditable *editable)
{
gboolean ret_val = FALSE;
gint start, end;
if (gtk_editable_get_selection_bounds (editable, &start, &end))
{
if (end != accessible->priv->cursor_position ||
start != accessible->priv->selection_bound)
/*
* This check is here as this function can be called
* for notification of selection_bound and current_pos.
* The values of current_pos and selection_bound may be the same
* for both notifications and we only want to generate one
* text_selection_changed signal.
*/
ret_val = TRUE;
}
else
{
/* We had a selection */
ret_val = (accessible->priv->cursor_position != accessible->priv->selection_bound);
}
accessible->priv->cursor_position = end;
accessible->priv->selection_bound = start;
return ret_val;
}
static void
insert_text_cb (GtkEditable *editable,
gchar *new_text,
gint new_text_length,
gint *position,
GtkEntryAccessible *self)
{
int length;
if (new_text_length == 0)
return;
length = g_utf8_strlen (new_text, new_text_length);
g_signal_emit_by_name (self,
"text-changed::insert",
*position - length,
length);
}
/* We connect to GtkEditable::delete-text, since it carries
* the information we need. But we delay emitting our own
* text_changed::delete signal until the entry has update
* all its internal state and emits GtkEntry::changed.
*/
static void
delete_text_cb (GtkEditable *editable,
gint start,
gint end,
GtkEntryAccessible *self)
{
GtkText *textw;
textw = get_text (ATK_TEXT (self));
if (textw == NULL)
return;
if (end < 0)
{
gchar *text;
text = gtk_text_get_display_text (textw, 0, -1);
end = g_utf8_strlen (text, -1);
g_free (text);
}
if (end == start)
return;
g_signal_emit_by_name (self,
"text-changed::delete",
start,
end - start);
}
static void
on_notify (GObject *gobject,
GParamSpec *pspec,
GtkEntryAccessible *self)
{
GtkWidget *widget;
AtkObject* atk_obj;
GtkEntryAccessiblePrivate *priv;
widget = GTK_WIDGET (gobject);
atk_obj = gtk_widget_get_accessible (widget);
priv = gtk_entry_accessible_get_instance_private (self);
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
{
if (check_for_selection_change (self, GTK_EDITABLE (widget)))
g_signal_emit_by_name (atk_obj, "text-selection-changed");
/*
* The entry cursor position has moved so generate the signal.
*/
g_signal_emit_by_name (atk_obj, "text-caret-moved",
gtk_editable_get_position (GTK_EDITABLE (widget)));
}
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
{
if (check_for_selection_change (self, GTK_EDITABLE (widget)))
g_signal_emit_by_name (atk_obj, "text-selection-changed");
}
else if (g_strcmp0 (pspec->name, "editable") == 0)
{
gboolean value;
g_object_get (gobject, "editable", &value, NULL);
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value);
}
else if (g_strcmp0 (pspec->name, "visibility") == 0)
{
gboolean visibility;
AtkRole new_role;
visibility = gtk_entry_get_visibility (GTK_ENTRY (widget));
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (atk_obj, new_role);
}
else if (g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
{
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY &&
!priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (self, GTK_ENTRY_ICON_PRIMARY);
g_signal_emit_by_name (self, "children-changed::add", 0,
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
}
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY &&
priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY]));
g_signal_emit_by_name (self, "children-changed::remove", 0,
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
}
}
else if (g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
{
gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0);
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY &&
!priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (self, GTK_ENTRY_ICON_SECONDARY);
g_signal_emit_by_name (self, "children-changed::add", index,
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
}
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY &&
priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY]));
g_signal_emit_by_name (self, "children-changed::remove", index,
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
}
}
else if (g_strcmp0 (pspec->name, "primary-icon-name") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
const gchar *name;
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
if (name)
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name);
}
}
else if (g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
const gchar *name;
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
if (name)
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name);
}
}
else if (g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gchar *text;
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
if (text)
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], text);
g_free (text);
}
else
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], "");
}
}
}
else if (g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gchar *text;
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
if (text)
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], text);
g_free (text);
}
else
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], "");
}
}
}
else if (g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
ATK_STATE_ENABLED, on);
}
}
else if (g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
ATK_STATE_ENABLED, on);
}
}
else if (g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
ATK_STATE_SENSITIVE, on);
}
}
else if (g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
ATK_STATE_SENSITIVE, on);
}
}
}
static AtkStateSet *
gtk_entry_accessible_ref_state_set (AtkObject *accessible)
@@ -423,9 +686,7 @@ gtk_entry_accessible_get_attributes (AtkObject *accessible)
if (widget == NULL)
return attributes;
if (GTK_IS_ENTRY (widget) || GTK_IS_SEARCH_ENTRY (widget))
g_object_get (widget, "placeholder-text", &text, NULL);
g_object_get (widget, "placeholder-text", &text, NULL);
if (text == NULL)
return attributes;
@@ -456,197 +717,9 @@ gtk_entry_accessible_initialize (AtkObject *obj,
gtk_entry_accessible->priv->selection_bound = start_pos;
/* Set up signal callbacks */
g_signal_connect_after (widget, "insert-text", G_CALLBACK (insert_text_cb), NULL);
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), NULL);
if (GTK_IS_PASSWORD_ENTRY (widget))
obj->role = ATK_ROLE_PASSWORD_TEXT;
else
obj->role = ATK_ROLE_TEXT;
}
static void
gtk_entry_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget *widget;
AtkObject* atk_obj;
GtkEntryAccessible* entry;
GtkEntryAccessiblePrivate *priv;
widget = GTK_WIDGET (obj);
atk_obj = gtk_widget_get_accessible (widget);
entry = GTK_ENTRY_ACCESSIBLE (atk_obj);
priv = entry->priv;
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
{
if (check_for_selection_change (entry, GTK_EDITABLE (widget)))
g_signal_emit_by_name (atk_obj, "text-selection-changed");
/*
* The entry cursor position has moved so generate the signal.
*/
g_signal_emit_by_name (atk_obj, "text-caret-moved",
gtk_editable_get_position (GTK_EDITABLE (widget)));
}
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
{
if (check_for_selection_change (entry, GTK_EDITABLE (widget)))
g_signal_emit_by_name (atk_obj, "text-selection-changed");
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "editable") == 0)
{
gboolean value;
g_object_get (obj, "editable", &value, NULL);
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value);
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "visibility") == 0)
{
gboolean visibility;
AtkRole new_role;
visibility = gtk_entry_get_visibility (GTK_ENTRY (widget));
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (atk_obj, new_role);
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
{
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_PRIMARY);
g_signal_emit_by_name (entry, "children-changed::add", 0,
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
}
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY]));
g_signal_emit_by_name (entry, "children-changed::remove", 0,
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
{
gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0);
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_SECONDARY);
g_signal_emit_by_name (entry, "children-changed::add", index,
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
}
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY]));
g_signal_emit_by_name (entry, "children-changed::remove", index,
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "primary-icon-name") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
const gchar *name;
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
if (name)
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name);
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
const gchar *name;
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
if (name)
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name);
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gchar *text;
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
if (text)
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], text);
g_free (text);
}
else
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], "");
}
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gchar *text;
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
if (text)
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], text);
g_free (text);
}
else
{
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], "");
}
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
ATK_STATE_ENABLED, on);
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
ATK_STATE_ENABLED, on);
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
{
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
ATK_STATE_SENSITIVE, on);
}
}
else if (GTK_IS_ENTRY (widget) &&
g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
{
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
{
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
ATK_STATE_SENSITIVE, on);
}
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_entry_accessible_parent_class)->notify_gtk (obj, pspec);
g_signal_connect_after (widget, "insert-text", G_CALLBACK (insert_text_cb), obj);
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), obj);
g_signal_connect (widget, "notify", G_CALLBACK (on_notify), obj);
}
static gint
@@ -673,13 +746,10 @@ gtk_entry_accessible_get_n_children (AtkObject* obj)
if (widget == NULL)
return 0;
if (GTK_IS_ENTRY (widget))
{
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
count++;
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
count++;
}
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
count++;
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
count++;
return count;
}
@@ -697,9 +767,6 @@ gtk_entry_accessible_ref_child (AtkObject *obj,
if (widget == NULL)
return NULL;
if (!GTK_IS_ENTRY (widget))
return NULL;
switch (i)
{
case 0:
@@ -741,8 +808,7 @@ gtk_entry_accessible_finalize (GObject *object)
static void
gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
class->ref_state_set = gtk_entry_accessible_ref_state_set;
@@ -752,8 +818,6 @@ gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
class->get_n_children = gtk_entry_accessible_get_n_children;
class->ref_child = gtk_entry_accessible_ref_child;
widget_class->notify_gtk = gtk_entry_accessible_notify_gtk;
gobject_class->finalize = gtk_entry_accessible_finalize;
}
@@ -763,23 +827,8 @@ gtk_entry_accessible_init (GtkEntryAccessible *entry)
entry->priv = gtk_entry_accessible_get_instance_private (entry);
entry->priv->cursor_position = 0;
entry->priv->selection_bound = 0;
}
static GtkText *
get_text (AtkText *atk_text)
{
GtkWidget *widget;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
return NULL;
if (GTK_IS_ENTRY (widget))
return gtk_entry_get_text_widget (GTK_ENTRY (widget));
else if (GTK_IS_SEARCH_ENTRY (widget))
return gtk_search_entry_get_text_widget (GTK_SEARCH_ENTRY (widget));
else
return NULL; // FIXME;
ATK_OBJECT (entry)->role = ATK_ROLE_TEXT;
}
static gchar *
@@ -1377,96 +1426,6 @@ atk_editable_text_interface_init (AtkEditableTextIface *iface)
iface->set_run_attributes = NULL;
}
static void
insert_text_cb (GtkEditable *editable,
gchar *new_text,
gint new_text_length,
gint *position)
{
GtkEntryAccessible *accessible;
gint length;
if (new_text_length == 0)
return;
accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
length = g_utf8_strlen (new_text, new_text_length);
g_signal_emit_by_name (accessible,
"text-changed::insert",
*position - length,
length);
}
/* We connect to GtkEditable::delete-text, since it carries
* the information we need. But we delay emitting our own
* text_changed::delete signal until the entry has update
* all its internal state and emits GtkEntry::changed.
*/
static void
delete_text_cb (GtkEditable *editable,
gint start,
gint end)
{
GtkEntryAccessible *accessible;
GtkText *textw;
accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
textw = get_text (ATK_TEXT (accessible));
if (textw == NULL)
return;
if (end < 0)
{
gchar *text;
text = gtk_text_get_display_text (textw, 0, -1);
end = g_utf8_strlen (text, -1);
g_free (text);
}
if (end == start)
return;
g_signal_emit_by_name (accessible,
"text-changed::delete",
start,
end - start);
}
static gboolean
check_for_selection_change (GtkEntryAccessible *accessible,
GtkEditable *editable)
{
gboolean ret_val = FALSE;
gint start, end;
if (gtk_editable_get_selection_bounds (editable, &start, &end))
{
if (end != accessible->priv->cursor_position ||
start != accessible->priv->selection_bound)
/*
* This check is here as this function can be called
* for notification of selection_bound and current_pos.
* The values of current_pos and selection_bound may be the same
* for both notifications and we only want to generate one
* text_selection_changed signal.
*/
ret_val = TRUE;
}
else
{
/* We had a selection */
ret_val = (accessible->priv->cursor_position != accessible->priv->selection_bound);
}
accessible->priv->cursor_position = end;
accessible->priv->selection_bound = start;
return ret_val;
}
static gboolean
gtk_entry_accessible_do_action (AtkAction *action,
gint i)
+19 -36
View File
@@ -17,9 +17,10 @@
#include "config.h"
#include "gtkexpanderaccessibleprivate.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include "gtkexpanderaccessible.h"
static void atk_action_interface_init (AtkActionIface *iface);
@@ -91,41 +92,27 @@ gtk_expander_accessible_ref_child (AtkObject *obj,
return accessible;
}
static void
gtk_expander_accessible_initialize (AtkObject *obj,
gpointer data)
void
gtk_expander_accessible_update_label (GtkExpanderAccessible *self)
{
ATK_OBJECT_CLASS (gtk_expander_accessible_parent_class)->initialize (obj, data);
AtkObject *atk_obj = ATK_OBJECT (self);
obj->role = ATK_ROLE_TOGGLE_BUTTON;
if (atk_obj->name == NULL)
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
static void
gtk_expander_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
void
gtk_expander_accessible_update_state (GtkExpanderAccessible *self,
gboolean expanded)
{
AtkObject* atk_obj;
GtkExpander *expander;
AtkObject *atk_obj = ATK_OBJECT (self);
expander = GTK_EXPANDER (obj);
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (expander));
;
if (g_strcmp0 (pspec->name, "label") == 0)
{
if (atk_obj->name == NULL)
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
else if (g_strcmp0 (pspec->name, "expanded") == 0)
{
atk_object_notify_state_change (atk_obj, ATK_STATE_CHECKED,
gtk_expander_get_expanded (expander));
atk_object_notify_state_change (atk_obj, ATK_STATE_EXPANDED,
gtk_expander_get_expanded (expander));
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_expander_accessible_parent_class)->notify_gtk (obj, pspec);
atk_object_notify_state_change (atk_obj, ATK_STATE_CHECKED, expanded);
atk_object_notify_state_change (atk_obj, ATK_STATE_EXPANDED, expanded);
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
static AtkStateSet *
@@ -158,21 +145,17 @@ static void
gtk_expander_accessible_class_init (GtkExpanderAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
widget_class->notify_gtk = gtk_expander_accessible_notify_gtk;
class->get_name = gtk_expander_accessible_get_name;
class->get_n_children = gtk_expander_accessible_get_n_children;
class->ref_child = gtk_expander_accessible_ref_child;
class->ref_state_set = gtk_expander_accessible_ref_state_set;
class->initialize = gtk_expander_accessible_initialize;
}
static void
gtk_expander_accessible_init (GtkExpanderAccessible *expander)
gtk_expander_accessible_init (GtkExpanderAccessible *self)
{
ATK_OBJECT (self)->role = ATK_ROLE_TOGGLE_BUTTON;
}
static gboolean
+31
View File
@@ -0,0 +1,31 @@
/* gtkexpanderaccessibleprivate.h: GtkExpanderAccessible private API
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
#pragma once
#include "gtkexpanderaccessible.h"
G_BEGIN_DECLS
void gtk_expander_accessible_update_label (GtkExpanderAccessible *self);
void gtk_expander_accessible_update_state (GtkExpanderAccessible *self,
gboolean expanded);
G_END_DECLS
+202 -225
View File
@@ -32,11 +32,11 @@
#define GTK_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, GtkIconViewItemAccessible))
#define GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE))
struct _GtkIconViewAccessiblePrivate
typedef struct
{
GList *items;
GtkTreeModel *model;
};
} GtkIconViewAccessiblePrivate;
typedef struct
{
@@ -265,7 +265,8 @@ get_text (GtkIconView *icon_view,
_gtk_icon_view_set_cell_data (icon_view, item);
gtk_cell_area_foreach (icon_view->priv->cell_area,
(GtkCellCallback)get_text_foreach, &text);
(GtkCellCallback) get_text_foreach,
&text);
return text;
}
@@ -742,8 +743,9 @@ gtk_icon_view_item_accessible_set_visibility (GtkIconViewItemAccessible *item,
static void
_gtk_icon_view_item_accessible_init (GtkIconViewItemAccessible *item)
{
item->state_set = atk_state_set_new ();
atk_object_set_role (ATK_OBJECT (item), ATK_ROLE_ICON);
item->state_set = atk_state_set_new ();
atk_state_set_add_state (item->state_set, ATK_STATE_ENABLED);
atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSABLE);
atk_state_set_add_state (item->state_set, ATK_STATE_SENSITIVE);
@@ -860,25 +862,25 @@ G_DEFINE_TYPE_WITH_CODE (GtkIconViewAccessible, gtk_icon_view_accessible, GTK_TY
typedef struct
{
AtkObject *item;
gint index;
} GtkIconViewItemAccessibleInfo;
int index;
} ItemAccessibleInfo;
static void
gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
AtkObject *item,
gint index)
gtk_icon_view_item_accessible_info_new (GtkIconViewAccessible *self,
GtkIconViewItemAccessible *item,
int index)
{
GtkIconViewAccessible *view = (GtkIconViewAccessible *)accessible;
GtkIconViewItemAccessibleInfo *info;
GtkIconViewItemAccessibleInfo *tmp_info;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
ItemAccessibleInfo *info;
ItemAccessibleInfo *tmp_info;
GList *items;
info = g_new (GtkIconViewItemAccessibleInfo, 1);
info->item = item;
info = g_new (ItemAccessibleInfo, 1);
info->item = ATK_OBJECT (item);
info->index = index;
items = view->priv->items;
items = priv->items;
while (items)
{
tmp_info = items->data;
@@ -886,7 +888,8 @@ gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
break;
items = items->next;
}
view->priv->items = g_list_insert_before (view->priv->items, items, info);
priv->items = g_list_insert_before (priv->items, items, info);
}
static gint
@@ -904,22 +907,24 @@ gtk_icon_view_accessible_get_n_children (AtkObject *accessible)
return g_list_length (icon_view->priv->items);
}
static AtkObject *
gtk_icon_view_accessible_find_child (AtkObject *accessible,
gint index)
static GtkIconViewItemAccessible *
gtk_icon_view_accessible_find_child (GtkIconViewAccessible *self,
gint index)
{
GtkIconViewAccessible *view = (GtkIconViewAccessible*)accessible;
GtkIconViewItemAccessibleInfo *info;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GList *items;
items = view->priv->items;
items = priv->items;
while (items)
{
info = items->data;
ItemAccessibleInfo *info = items->data;
GList *next = items->next;
if (info->index == index)
return info->item;
items = items->next;
return GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
items = next;
}
return NULL;
@@ -929,31 +934,28 @@ static AtkObject *
gtk_icon_view_accessible_ref_child (AtkObject *accessible,
gint index)
{
GtkIconViewAccessible *self = GTK_ICON_VIEW_ACCESSIBLE (accessible);
GtkIconViewItemAccessible *a11y_item;
GtkIconView *icon_view;
GtkWidget *widget;
GList *icons;
AtkObject *obj;
GtkIconViewItemAccessible *a11y_item;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
if (!widget)
if (widget == NULL)
return NULL;
icon_view = GTK_ICON_VIEW (widget);
icons = g_list_nth (icon_view->priv->items, index);
obj = NULL;
if (icons)
{
GtkIconViewItem *item = icons->data;
g_return_val_if_fail (item->index == index, NULL);
obj = gtk_icon_view_accessible_find_child (accessible, index);
if (!obj)
a11y_item = gtk_icon_view_accessible_find_child (self, index);
if (a11y_item == NULL)
{
obj = g_object_new (GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, NULL);
gtk_icon_view_item_accessible_info_new (accessible, obj, index);
obj->role = ATK_ROLE_ICON;
a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
a11y_item = g_object_new (GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, NULL);
a11y_item->item = item;
a11y_item->widget = widget;
@@ -962,60 +964,62 @@ gtk_icon_view_accessible_ref_child (AtkObject *accessible,
gtk_icon_view_item_accessible_set_visibility (a11y_item, FALSE);
g_object_add_weak_pointer (G_OBJECT (widget), (gpointer) &(a11y_item->widget));
gtk_icon_view_item_accessible_info_new (self, a11y_item, index);
}
g_object_ref (obj);
g_object_ref (a11y_item);
return ATK_OBJECT (a11y_item);
}
else
{
return NULL;
}
return obj;
}
static void
gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view,
gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *self,
GList *list)
{
GtkIconViewItemAccessibleInfo *info;
GtkIconViewItemAccessible *item;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkWidget *widget;
gboolean act_on_item;
GList *items;
if (view->priv->items)
if (priv->items == NULL)
return;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
if (widget == NULL)
return;
items = priv->items;
act_on_item = (list == NULL);
while (items)
{
GtkWidget *widget;
gboolean act_on_item;
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item;
GList *next = items->next;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (view));
if (widget == NULL)
return;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
items = view->priv->items;
if (act_on_item == FALSE && list == items)
act_on_item = TRUE;
act_on_item = (list == NULL);
if (act_on_item)
gtk_icon_view_item_accessible_set_visibility (item, TRUE);
while (items)
{
info = (GtkIconViewItemAccessibleInfo *)items->data;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
if (act_on_item == FALSE && list == items)
act_on_item = TRUE;
if (act_on_item)
gtk_icon_view_item_accessible_set_visibility (item, TRUE);
items = items->next;
}
items = next;
}
}
void
_gtk_icon_view_accessible_adjustment_changed (GtkIconView *icon_view)
gtk_icon_view_accessible_adjustment_changed (GtkIconViewAccessible *self)
{
GtkIconViewAccessible *view;
view = GTK_ICON_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (icon_view)));
if (view == NULL)
return;
gtk_icon_view_accessible_traverse_items (view, NULL);
gtk_icon_view_accessible_traverse_items (self, NULL);
}
static void
@@ -1024,36 +1028,26 @@ gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
AtkObject *atk_obj;
gint index;
GtkWidget *widget;
GtkIconView *icon_view;
GtkIconViewItem *item;
GtkIconViewAccessible *self = user_data;
GtkIconViewItemAccessible *a11y_item;
const gchar *name;
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
index = gtk_tree_path_get_indices(path)[0];
a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (
gtk_icon_view_accessible_find_child (atk_obj, index));
int index;
index = gtk_tree_path_get_indices (path)[0];
a11y_item = gtk_icon_view_accessible_find_child (self, index);
if (a11y_item)
{
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj));
icon_view = GTK_ICON_VIEW (widget);
item = a11y_item->item;
GtkIconViewItem *item = a11y_item->item;
GtkIconView *icon_view = GTK_ICON_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (self)));
name = atk_object_get_name (ATK_OBJECT (a11y_item));
if (!name || strcmp (name, "") == 0)
const char *name = atk_object_get_name (ATK_OBJECT (a11y_item));
if (name == NULL || *name == '\0')
{
g_free (a11y_item->text);
a11y_item->text = get_text (icon_view, item);
}
}
g_signal_emit_by_name (atk_obj, "visible-data-changed");
return;
g_signal_emit_by_name (self, "visible-data-changed");
}
static void
@@ -1062,24 +1056,22 @@ gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
GtkIconViewItemAccessibleInfo *info;
GtkIconViewAccessible *view;
GtkIconViewItemAccessible *item;
GtkIconViewAccessible *self = user_data;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GList *items;
GList *tmp_list;
AtkObject *atk_obj;
gint index;
int index;
index = gtk_tree_path_get_indices(path)[0];
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
index = gtk_tree_path_get_indices (path)[0];
items = view->priv->items;
items = priv->items;
tmp_list = NULL;
while (items)
{
info = items->data;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
GList *next = items->next;
if (info->index != item->item->index)
{
if (info->index < index)
@@ -1091,40 +1083,36 @@ gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
info->index = item->item->index;
}
items = items->next;
items = next;
}
gtk_icon_view_accessible_traverse_items (view, tmp_list);
g_signal_emit_by_name (atk_obj, "children-changed::add",
gtk_icon_view_accessible_traverse_items (self, tmp_list);
g_signal_emit_by_name (self,
"children-changed::add",
index, NULL, NULL);
return;
}
static void
gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
GtkTreePath *path,
gpointer user_data)
gpointer user_data)
{
GtkIconViewItemAccessibleInfo *info;
GtkIconViewAccessible *view;
GtkIconViewItemAccessible *item;
GtkIconViewAccessible *self = user_data;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GList *items;
GList *tmp_list;
GList *deleted_item;
AtkObject *atk_obj;
gint index;
GList *tmp_list = NULL;
GList *deleted_item = NULL;
int index;
index = gtk_tree_path_get_indices(path)[0];
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
index = gtk_tree_path_get_indices (path)[0];
items = view->priv->items;
tmp_list = NULL;
deleted_item = NULL;
info = NULL;
items = priv->items;
while (items)
{
info = items->data;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
GList *next = items->next;
if (info->index == index)
{
deleted_item = items;
@@ -1137,26 +1125,32 @@ gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
info->index = item->item->index;
}
items = items->next;
items = next;
}
if (deleted_item)
{
info = deleted_item->data;
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item), ATK_STATE_DEFUNCT, TRUE);
g_signal_emit_by_name (atk_obj, "children-changed::remove",
ItemAccessibleInfo *info = deleted_item->data;
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item),
ATK_STATE_DEFUNCT,
TRUE);
g_signal_emit_by_name (self,
"children-changed::remove",
index, NULL, NULL);
view->priv->items = g_list_delete_link (view->priv->items, deleted_item);
priv->items = g_list_delete_link (priv->items, deleted_item);
g_object_unref (info->item);
g_free (info);
}
gtk_icon_view_accessible_traverse_items (view, tmp_list);
return;
gtk_icon_view_accessible_traverse_items (self, tmp_list);
}
static gint
gtk_icon_view_accessible_item_compare (GtkIconViewItemAccessibleInfo *i1,
GtkIconViewItemAccessibleInfo *i2)
gtk_icon_view_accessible_item_compare (ItemAccessibleInfo *i1,
ItemAccessibleInfo *i2)
{
return i1->index - i2->index;
}
@@ -1166,151 +1160,138 @@ gtk_icon_view_accessible_model_rows_reordered (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeIter *iter,
gint *new_order,
gpointer user_data)
gpointer user_data)
{
GtkIconViewAccessible *view;
GtkIconViewItemAccessibleInfo *info;
GtkIconViewAccessible *self = user_data;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconView *icon_view;
GtkIconViewItemAccessible *item;
GList *items;
AtkObject *atk_obj;
gint *order;
gint length, i;
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
icon_view = GTK_ICON_VIEW (user_data);
view = (GtkIconViewAccessible*)atk_obj;
int *order;
int length, i;
icon_view = GTK_ICON_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (self)));
length = gtk_tree_model_iter_n_children (tree_model, NULL);
order = g_new (gint, length);
order = g_new (int, length);
for (i = 0; i < length; i++)
order [new_order[i]] = i;
items = view->priv->items;
items = priv->items;
while (items)
{
info = items->data;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
GList *next = items->next;
info->index = order[info->index];
item->item = g_list_nth_data (icon_view->priv->items, info->index);
items = items->next;
items = next;
}
g_free (order);
view->priv->items = g_list_sort (view->priv->items,
(GCompareFunc)gtk_icon_view_accessible_item_compare);
return;
priv->items = g_list_sort (priv->items, (GCompareFunc) gtk_icon_view_accessible_item_compare);
}
static void
gtk_icon_view_accessible_disconnect_model_signals (GtkTreeModel *model,
GtkWidget *widget)
gtk_icon_view_accessible_disconnect_model_signals (GtkIconViewAccessible *self)
{
GObject *obj;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
obj = G_OBJECT (model);
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_changed, widget);
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_inserted, widget);
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_deleted, widget);
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_rows_reordered, widget);
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_row_changed, self);
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_row_inserted, self);
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_row_deleted, self);
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_rows_reordered, self);
}
static void
gtk_icon_view_accessible_connect_model_signals (GtkIconView *icon_view)
gtk_icon_view_accessible_connect_model_signals (GtkIconViewAccessible *self)
{
GObject *obj;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
obj = G_OBJECT (icon_view->priv->model);
g_signal_connect_object (obj, "row-changed",
g_signal_connect_object (priv->model, "row-changed",
G_CALLBACK (gtk_icon_view_accessible_model_row_changed),
icon_view, 0);
g_signal_connect_object (obj, "row-inserted",
self, 0);
g_signal_connect_object (priv->model, "row-inserted",
G_CALLBACK (gtk_icon_view_accessible_model_row_inserted),
icon_view, G_CONNECT_AFTER);
g_signal_connect_object (obj, "row-deleted",
self, G_CONNECT_AFTER);
g_signal_connect_object (priv->model, "row-deleted",
G_CALLBACK (gtk_icon_view_accessible_model_row_deleted),
icon_view, G_CONNECT_AFTER);
g_signal_connect_object (obj, "rows-reordered",
self, G_CONNECT_AFTER);
g_signal_connect_object (priv->model, "rows-reordered",
G_CALLBACK (gtk_icon_view_accessible_model_rows_reordered),
icon_view, G_CONNECT_AFTER);
self, G_CONNECT_AFTER);
}
static void
gtk_icon_view_accessible_clear_cache (GtkIconViewAccessible *view)
gtk_icon_view_accessible_clear_cache (GtkIconViewAccessible *self)
{
GtkIconViewItemAccessibleInfo *info;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GList *items;
items = view->priv->items;
while (items)
if (priv->items == NULL)
return;
items = priv->items;
while (items != NULL)
{
info = (GtkIconViewItemAccessibleInfo *) items->data;
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item), ATK_STATE_DEFUNCT, TRUE);
ItemAccessibleInfo *info = items->data;
GList *next = items->next;
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item),
ATK_STATE_DEFUNCT,
TRUE);
g_object_unref (info->item);
g_free (items->data);
items = items->next;
g_free (info);
items = next;
}
g_list_free (view->priv->items);
view->priv->items = NULL;
g_clear_pointer (&priv->items, g_list_free);
}
static void
gtk_icon_view_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
void
gtk_icon_view_accessible_update_model (GtkIconViewAccessible *self,
GtkTreeModel *model)
{
GtkIconView *icon_view;
GtkWidget *widget;
AtkObject *atk_obj;
GtkIconViewAccessible *view;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
if (strcmp (pspec->name, "model") == 0)
if (priv->model != NULL)
{
widget = GTK_WIDGET (obj);
atk_obj = gtk_widget_get_accessible (widget);
view = (GtkIconViewAccessible*)atk_obj;
if (view->priv->model)
{
g_object_remove_weak_pointer (G_OBJECT (view->priv->model),
(gpointer *)&view->priv->model);
gtk_icon_view_accessible_disconnect_model_signals (view->priv->model, widget);
}
gtk_icon_view_accessible_clear_cache (view);
icon_view = GTK_ICON_VIEW (obj);
view->priv->model = icon_view->priv->model;
/* If there is no model the GtkIconView is probably being destroyed */
if (view->priv->model)
{
g_object_add_weak_pointer (G_OBJECT (view->priv->model), (gpointer *)&view->priv->model);
gtk_icon_view_accessible_connect_model_signals (icon_view);
}
g_object_remove_weak_pointer (G_OBJECT (priv->model),
(gpointer *) &priv->model);
gtk_icon_view_accessible_disconnect_model_signals (self);
}
return;
gtk_icon_view_accessible_clear_cache (self);
priv->model = model;
/* If there is no model the GtkIconView is probably being destroyed */
if (priv->model != NULL)
{
g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *) &priv->model);
gtk_icon_view_accessible_connect_model_signals (self);
}
}
static void
gtk_icon_view_accessible_initialize (AtkObject *accessible,
gpointer data)
{
GtkIconViewAccessible *view;
GtkIconView *icon_view;
GtkIconViewAccessible *self = GTK_ICON_VIEW_ACCESSIBLE (accessible);
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconView *icon_view = data;
if (ATK_OBJECT_CLASS (gtk_icon_view_accessible_parent_class)->initialize)
ATK_OBJECT_CLASS (gtk_icon_view_accessible_parent_class)->initialize (accessible, data);
icon_view = (GtkIconView*)data;
view = (GtkIconViewAccessible*)accessible;
g_signal_connect (data, "notify",
G_CALLBACK (gtk_icon_view_accessible_notify_gtk), NULL);
view->priv->model = icon_view->priv->model;
if (view->priv->model)
priv->model = icon_view->priv->model;
if (priv->model)
{
g_object_add_weak_pointer (G_OBJECT (view->priv->model), (gpointer *)&view->priv->model);
gtk_icon_view_accessible_connect_model_signals (icon_view);
g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *) &priv->model);
gtk_icon_view_accessible_connect_model_signals (self);
}
accessible->role = ATK_ROLE_LAYERED_PANE;
@@ -1319,7 +1300,7 @@ gtk_icon_view_accessible_initialize (AtkObject *accessible,
static void
gtk_icon_view_accessible_finalize (GObject *object)
{
GtkIconViewAccessible *view = (GtkIconViewAccessible*)object;
GtkIconViewAccessible *view = GTK_ICON_VIEW_ACCESSIBLE (object);
gtk_icon_view_accessible_clear_cache (view);
@@ -1329,11 +1310,8 @@ gtk_icon_view_accessible_finalize (GObject *object)
static void
gtk_icon_view_accessible_class_init (GtkIconViewAccessibleClass *klass)
{
GObjectClass *gobject_class;
AtkObjectClass *atk_class;
gobject_class = (GObjectClass *)klass;
atk_class = (AtkObjectClass *)klass;
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
gobject_class->finalize = gtk_icon_view_accessible_finalize;
@@ -1345,7 +1323,6 @@ gtk_icon_view_accessible_class_init (GtkIconViewAccessibleClass *klass)
static void
gtk_icon_view_accessible_init (GtkIconViewAccessible *accessible)
{
accessible->priv = gtk_icon_view_accessible_get_instance_private (accessible);
}
static AtkObject*
-3
View File
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
typedef struct _GtkIconViewAccessible GtkIconViewAccessible;
typedef struct _GtkIconViewAccessibleClass GtkIconViewAccessibleClass;
typedef struct _GtkIconViewAccessiblePrivate GtkIconViewAccessiblePrivate;
struct _GtkIconViewAccessible
{
GtkWidgetAccessible parent;
GtkIconViewAccessiblePrivate *priv;
};
struct _GtkIconViewAccessibleClass
+4 -2
View File
@@ -19,12 +19,14 @@
#define __GTK_ICON_VIEW_ACCESSIBLE_PRIVATE_H__
#include <gtk/a11y/gtkiconviewaccessible.h>
#include <gtk/gtkiconview.h>
G_BEGIN_DECLS
void _gtk_icon_view_accessible_adjustment_changed (GtkIconView *icon_view);
void gtk_icon_view_accessible_adjustment_changed (GtkIconViewAccessible *self);
void gtk_icon_view_accessible_update_model (GtkIconViewAccessible *self,
GtkTreeModel *model);
G_END_DECLS
+16 -24
View File
@@ -18,10 +18,11 @@
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include "gtklevelbaraccessible.h"
#include "gtklevelbar.h"
#include <string.h>
static void atk_value_interface_init (AtkValueIface *iface);
@@ -29,45 +30,36 @@ G_DEFINE_TYPE_WITH_CODE (GtkLevelBarAccessible, gtk_level_bar_accessible, GTK_TY
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
static void
gtk_level_bar_accessible_initialize (AtkObject *obj,
gpointer data)
on_value_changed (GObject *gobject,
GParamSpec *pspec,
gpointer user_data)
{
ATK_OBJECT_CLASS (gtk_level_bar_accessible_parent_class)->initialize (obj, data);
GtkLevelBarAccessible *self = user_data;
obj->role = ATK_ROLE_LEVEL_BAR;
g_object_notify (G_OBJECT (self), "accessible-value");
}
static void
gtk_level_bar_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
gtk_level_bar_accessible_initialize (AtkObject *object,
gpointer data)
{
GtkWidget *widget = GTK_WIDGET (obj);
GtkLevelBarAccessible *level_bar = GTK_LEVEL_BAR_ACCESSIBLE (gtk_widget_get_accessible (widget));
GtkLevelBar *level_bar = data;
if (strcmp (pspec->name, "value") == 0)
{
g_object_notify (G_OBJECT (level_bar), "accessible-value");
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_level_bar_accessible_parent_class)->notify_gtk (obj, pspec);
g_signal_connect (level_bar, "notify::value", G_CALLBACK (on_value_changed), object);
}
static void
gtk_level_bar_accessible_class_init (GtkLevelBarAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
AtkObjectClass *object_class = ATK_OBJECT_CLASS (klass);
widget_class->notify_gtk = gtk_level_bar_accessible_notify_gtk;
class->initialize = gtk_level_bar_accessible_initialize;
object_class->initialize = gtk_level_bar_accessible_initialize;
}
static void
gtk_level_bar_accessible_init (GtkLevelBarAccessible *button)
gtk_level_bar_accessible_init (GtkLevelBarAccessible *self)
{
ATK_OBJECT (self)->role = ATK_ROLE_LEVEL_BAR;
}
static void
+29 -44
View File
@@ -17,10 +17,12 @@
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include "gtknotebookaccessible.h"
#include "gtknotebookaccessibleprivate.h"
#include "gtknotebookpageaccessible.h"
#include "gtknotebook.h"
#include <string.h>
struct _GtkNotebookAccessiblePrivate
{
@@ -153,55 +155,41 @@ gtk_notebook_accessible_ref_child (AtkObject *obj,
return child;
}
static void
gtk_notebook_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
void
gtk_notebook_accessible_update_page (GtkNotebookAccessible *self,
int page_num)
{
GtkWidget *widget;
AtkObject* atk_obj;
GtkNotebookAccessiblePrivate *priv = gtk_notebook_accessible_get_instance_private (self);
AtkObject *atk_obj = ATK_OBJECT (self);
int old_page_num = priv->selected_page;
widget = GTK_WIDGET (obj);
atk_obj = gtk_widget_get_accessible (widget);
priv->selected_page = page_num;
if (strcmp (pspec->name, "page") == 0)
/* Notify SELECTED state change for old and new page */
if (page_num != old_page_num)
{
gint page_num, old_page_num;
GtkNotebookAccessible *accessible;
GtkNotebook *notebook;
AtkObject *child;
accessible = GTK_NOTEBOOK_ACCESSIBLE (atk_obj);
notebook = GTK_NOTEBOOK (widget);
/* Notify SELECTED state change for old and new page */
old_page_num = accessible->priv->selected_page;
page_num = gtk_notebook_get_current_page (notebook);
accessible->priv->selected_page = page_num;
if (page_num != old_page_num)
if (old_page_num != -1)
{
AtkObject *child;
if (old_page_num != -1)
child = gtk_notebook_accessible_ref_child (atk_obj, old_page_num);
if (child != NULL)
{
child = gtk_notebook_accessible_ref_child (atk_obj, old_page_num);
if (child)
{
atk_object_notify_state_change (child, ATK_STATE_SELECTED, FALSE);
g_object_unref (child);
}
}
child = gtk_notebook_accessible_ref_child (atk_obj, page_num);
if (child)
{
atk_object_notify_state_change (child, ATK_STATE_SELECTED, TRUE);
atk_object_notify_state_change (child, ATK_STATE_SELECTED, FALSE);
g_object_unref (child);
}
g_signal_emit_by_name (atk_obj, "selection-changed");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
child = gtk_notebook_accessible_ref_child (atk_obj, page_num);
if (child != NULL)
{
atk_object_notify_state_change (child, ATK_STATE_SELECTED, TRUE);
g_object_unref (child);
}
g_signal_emit_by_name (atk_obj, "selection-changed");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_notebook_accessible_parent_class)->notify_gtk (obj, pspec);
}
/*
@@ -230,14 +218,11 @@ gtk_notebook_accessible_class_init (GtkNotebookAccessibleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
gobject_class->finalize = gtk_notebook_accessible_finalize;
class->ref_child = gtk_notebook_accessible_ref_child;
class->initialize = gtk_notebook_accessible_initialize;
widget_class->notify_gtk = gtk_notebook_accessible_notify_gtk;
}
static void
+30
View File
@@ -0,0 +1,30 @@
/* gtknotebookaccessibleprivate.h: GtkNotebookAccessible private API
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
#pragma once
#include "gtknotebookaccessible.h"
G_BEGIN_DECLS
void gtk_notebook_accessible_update_page (GtkNotebookAccessible *self,
int page_num);
G_END_DECLS
+654
View File
@@ -0,0 +1,654 @@
/* gtkpasswordentryaccessible.c: A GtkWidgetAccessible for GtkPasswordEntry
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
#include "config.h"
#include "gtkpasswordentryaccessibleprivate.h"
#include "gtkeditable.h"
#include "gtkimage.h"
#include "gtkintl.h"
#include "gtklabel.h"
#include "gtkpango.h"
#include "gtkpasswordentryprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtktextprivate.h"
struct _GtkPasswordEntryAccessible
{
GtkWidgetAccessible parent_instance;
int cursor_position;
int selection_bound;
};
static void atk_editable_text_interface_init (AtkEditableTextIface *iface);
static void atk_text_interface_init (AtkTextIface *iface);
static void atk_action_interface_init (AtkActionIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkPasswordEntryAccessible, gtk_password_entry_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
static inline GtkText *
get_text_widget (GtkAccessible *accessible)
{
GtkWidget *widget = gtk_accessible_get_widget (accessible);
if (widget == NULL)
return NULL;
GtkPasswordEntry *entry = GTK_PASSWORD_ENTRY (widget);
return gtk_password_entry_get_text_widget (entry);
}
static gunichar
gtk_password_entry_accessible_get_character_at_offset (AtkText *atk_text,
gint offset)
{
GtkText *text = get_text_widget (GTK_ACCESSIBLE (atk_text));
char *contents, *index;
gunichar result;
result = '\0';
text = get_text_widget (GTK_ACCESSIBLE (atk_text));
if (text == NULL)
return 0;
if (!gtk_text_get_visibility (text))
return result;
contents = gtk_text_get_display_text (text, 0, -1);
if (offset < g_utf8_strlen (contents, -1))
{
index = g_utf8_offset_to_pointer (contents, offset);
result = g_utf8_get_char (index);
g_free (contents);
}
return result;
}
static gint
gtk_password_entry_accessible_get_caret_offset (AtkText *atk_text)
{
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
return -1;
int cursor_position = 0;
gboolean result = gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), NULL, &cursor_position);
if (!result)
return -1;
return cursor_position;
}
static gboolean
gtk_password_entry_accessible_set_caret_offset (AtkText *atk_text,
gint offset)
{
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
return FALSE;
gtk_editable_set_position (GTK_EDITABLE (widget), offset);
return TRUE;
}
static gint
gtk_password_entry_accessible_get_character_count (AtkText *atk_text)
{
GtkText *text = get_text_widget (GTK_ACCESSIBLE (atk_text));
if (text == NULL)
return 0;
char *display_text = gtk_text_get_display_text (text, 0, -1);
int char_count = 0;
if (display_text)
{
char_count = g_utf8_strlen (display_text, -1);
g_free (display_text);
}
return char_count;
}
static gint
gtk_password_entry_accessible_get_offset_at_point (AtkText *atk_text,
gint x,
gint y,
AtkCoordType coords)
{
GtkText *text = get_text_widget (GTK_ACCESSIBLE (atk_text));
int index, x_layout, y_layout;
int x_local, y_local;
glong offset;
if (text == NULL)
return 1;
gtk_text_get_layout_offsets (text, &x_layout, &y_layout);
x_local = x - x_layout;
y_local = y - y_layout;
if (!pango_layout_xy_to_index (gtk_text_get_layout (text),
x_local * PANGO_SCALE,
y_local * PANGO_SCALE,
&index, NULL))
{
if (x_local < 0 || y_local < 0)
index = 0;
else
index = -1;
}
offset = -1;
if (index != -1)
{
char *entry_text = gtk_text_get_display_text (text, 0, -1);
offset = g_utf8_pointer_to_offset (entry_text, entry_text + index);
g_free (entry_text);
}
return offset;
}
static void
atk_text_interface_init (AtkTextIface *iface)
{
iface->get_character_at_offset = gtk_password_entry_accessible_get_character_at_offset;
iface->get_caret_offset = gtk_password_entry_accessible_get_caret_offset;
iface->set_caret_offset = gtk_password_entry_accessible_set_caret_offset;
iface->get_character_count = gtk_password_entry_accessible_get_character_count;
iface->get_offset_at_point = gtk_password_entry_accessible_get_offset_at_point;
}
static void
gtk_password_entry_accessible_set_text_contents (AtkEditableText *text,
const gchar *string)
{
GtkWidget *widget;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
return;
if (!gtk_editable_get_editable (GTK_EDITABLE (widget)))
return;
gtk_editable_set_text (GTK_EDITABLE (widget), string);
}
static void
gtk_password_entry_accessible_insert_text (AtkEditableText *text,
const gchar *string,
gint length,
gint *position)
{
GtkWidget *widget;
GtkEditable *editable;
int pos = 0;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
return;
editable = GTK_EDITABLE (widget);
if (!gtk_editable_get_editable (editable))
return;
if (position != NULL)
pos = *position;
gtk_editable_insert_text (editable, string, length, &pos);
gtk_editable_set_position (editable, pos);
if (position != NULL)
*position = pos;
}
static void
gtk_password_entry_accessible_delete_text (AtkEditableText *text,
gint start_pos,
gint end_pos)
{
GtkWidget *widget;
GtkEditable *editable;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
return;
editable = GTK_EDITABLE (widget);
if (!gtk_editable_get_editable (editable))
return;
gtk_editable_delete_text (editable, start_pos, end_pos);
}
typedef struct
{
GtkEditable *entry;
int position;
} PasteData;
static void
paste_received_cb (GObject *clipboard,
GAsyncResult *result,
gpointer data)
{
PasteData *paste = data;
char *text;
text = gdk_clipboard_read_text_finish (GDK_CLIPBOARD (clipboard), result, NULL);
if (text != NULL)
gtk_editable_insert_text (paste->entry,
text, -1,
&(paste->position));
g_object_unref (paste->entry);
g_free (paste);
g_free (text);
}
static void
gtk_password_entry_accessible_paste_text (AtkEditableText *text,
gint position)
{
GtkWidget *widget;
GtkEditable *editable;
PasteData *paste;
GdkClipboard *clipboard;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
return;
editable = GTK_EDITABLE (widget);
if (!gtk_editable_get_editable (editable))
return;
paste = g_new0 (PasteData, 1);
paste->entry = GTK_EDITABLE (widget);
paste->position = position;
g_object_ref (paste->entry);
clipboard = gtk_widget_get_clipboard (widget);
gdk_clipboard_read_text_async (clipboard, NULL, paste_received_cb, paste);
}
static void
atk_editable_text_interface_init (AtkEditableTextIface *iface)
{
iface->set_text_contents = gtk_password_entry_accessible_set_text_contents;
iface->insert_text = gtk_password_entry_accessible_insert_text;
iface->copy_text = NULL;
iface->cut_text = NULL;
iface->delete_text = gtk_password_entry_accessible_delete_text;
iface->paste_text = gtk_password_entry_accessible_paste_text;
iface->set_run_attributes = NULL;
}
static gboolean
gtk_password_entry_accessible_do_action (AtkAction *action,
gint i)
{
GtkWidget *widget;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
if (widget == NULL)
return FALSE;
if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
return FALSE;
if (i == 0)
{
gtk_widget_activate (widget);
return TRUE;
}
if (i == 1)
{
GtkText *text = get_text_widget (GTK_ACCESSIBLE (action));
gboolean visibility = gtk_text_get_visibility (text);
gtk_text_set_visibility (text, !visibility);
return TRUE;
}
return FALSE;
}
static gint
gtk_password_entry_accessible_get_n_actions (AtkAction *action)
{
GtkAccessible *accessible = GTK_ACCESSIBLE (action);
GtkWidget *widget = gtk_accessible_get_widget (accessible);
if (widget == NULL)
return 0;
int n_actions = 1;
if (gtk_password_entry_get_show_peek_icon (GTK_PASSWORD_ENTRY (widget)))
n_actions += 1;
return n_actions;
}
static const gchar *
gtk_password_entry_accessible_get_keybinding (AtkAction *action,
gint i)
{
GtkWidget *widget;
GtkWidget *label;
AtkRelationSet *set;
AtkRelation *relation;
GPtrArray *target;
gpointer target_object;
guint key_val;
if (i != 0)
return NULL;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
if (widget == NULL)
return NULL;
set = atk_object_ref_relation_set (ATK_OBJECT (action));
if (!set)
return NULL;
label = NULL;
relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
if (relation)
{
target = atk_relation_get_target (relation);
target_object = g_ptr_array_index (target, 0);
label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
}
g_object_unref (set);
if (GTK_IS_LABEL (label))
{
key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
if (key_val != GDK_KEY_VoidSymbol)
return gtk_accelerator_name (key_val, GDK_ALT_MASK);
}
return NULL;
}
static const gchar *
gtk_password_entry_accessible_action_get_name (AtkAction *action,
gint i)
{
switch (i)
{
case 0:
return "activate";
case 1:
return "peek";
default:
break;
}
return NULL;
}
static const gchar*
gtk_password_entry_accessible_action_get_localized_name (AtkAction *action,
gint i)
{
if (i == 0)
return C_("Action name", "Activate");
if (i == 1)
return C_("Action name", "Peek");
return NULL;
}
static const gchar *
gtk_password_entry_accessible_action_get_description (AtkAction *action,
gint i)
{
if (i == 0)
return C_("Action description", "Activates the entry");
if (i == 1)
return C_("Action description", "Reveals the contents the entry");
return NULL;
}
static void
atk_action_interface_init (AtkActionIface *iface)
{
iface->do_action = gtk_password_entry_accessible_do_action;
iface->get_n_actions = gtk_password_entry_accessible_get_n_actions;
iface->get_keybinding = gtk_password_entry_accessible_get_keybinding;
iface->get_name = gtk_password_entry_accessible_action_get_name;
iface->get_localized_name = gtk_password_entry_accessible_action_get_localized_name;
iface->get_description = gtk_password_entry_accessible_action_get_description;
}
static AtkAttributeSet *
gtk_password_entry_accessible_get_attributes (AtkObject *accessible)
{
GtkWidget *widget;
AtkAttributeSet *attributes;
AtkAttribute *placeholder_text;
char *text = NULL;
attributes = ATK_OBJECT_CLASS (gtk_password_entry_accessible_parent_class)->get_attributes (accessible);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
if (widget == NULL)
return attributes;
g_object_get (widget, "placeholder-text", &text, NULL);
if (text == NULL)
return attributes;
placeholder_text = g_malloc (sizeof (AtkAttribute));
placeholder_text->name = g_strdup ("placeholder-text");
placeholder_text->value = text;
attributes = g_slist_append (attributes, placeholder_text);
return attributes;
}
static gboolean
check_for_selection_change (GtkPasswordEntryAccessible *self,
GtkEditable *editable)
{
gboolean ret_val = FALSE;
gint start, end;
if (gtk_editable_get_selection_bounds (editable, &start, &end))
{
if (end != self->cursor_position ||
start != self->selection_bound)
/*
* This check is here as this function can be called
* for notification of selection_bound and current_pos.
* The values of current_pos and selection_bound may be the same
* for both notifications and we only want to generate one
* text_selection_changed signal.
*/
ret_val = TRUE;
}
else
{
/* We had a selection */
ret_val = (self->cursor_position != self->selection_bound);
}
self->cursor_position = end;
self->selection_bound = start;
return ret_val;
}
static void
on_cursor_position_changed (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
GtkPasswordEntryAccessible *self = data;
GtkEditable *editable = GTK_EDITABLE (gobject);
if (check_for_selection_change (self, editable))
g_signal_emit_by_name (self, "text-selection-changed");
// The entry cursor position has moved so generate the signal
g_signal_emit_by_name (self, "text-caret-moved",
gtk_editable_get_position (editable));
}
static void
on_selection_bound_changed (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
GtkPasswordEntryAccessible *self = data;
GtkEditable *editable = GTK_EDITABLE (gobject);
if (check_for_selection_change (self, editable))
g_signal_emit_by_name (self, "text-selection-changed");
}
static void
insert_text_cb (GtkEditable *editable,
gchar *new_text,
gint new_text_length,
gint *position,
GtkPasswordEntryAccessible *self)
{
int length;
if (new_text_length == 0)
return;
length = g_utf8_strlen (new_text, new_text_length);
g_signal_emit_by_name (self,
"text-changed::insert",
*position - length,
length);
}
static void
delete_text_cb (GtkEditable *editable,
gint start,
gint end,
GtkPasswordEntryAccessible *self)
{
GtkText *text;
text = get_text_widget (GTK_ACCESSIBLE (self));
if (text == NULL)
return;
if (end < 0)
{
char *contents;
contents = gtk_text_get_display_text (text, 0, -1);
end = g_utf8_strlen (contents, -1);
g_free (contents);
}
if (end == start)
return;
g_signal_emit_by_name (self,
"text-changed::delete",
start,
end - start);
}
static void
gtk_password_entry_accessible_initialize (AtkObject *atk_object,
gpointer data)
{
GtkPasswordEntryAccessible *self = GTK_PASSWORD_ENTRY_ACCESSIBLE (atk_object);
GtkEditable *editable = data;
GtkWidget *widget = data;
int start_pos, end_pos;
gtk_editable_get_selection_bounds (editable, &start_pos, &end_pos);
self->cursor_position = end_pos;
self->selection_bound = start_pos;
/* Set up signal callbacks */
g_signal_connect_after (widget, "insert-text", G_CALLBACK (insert_text_cb), self);
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), self);
g_signal_connect (widget, "notify::cursor-position",
G_CALLBACK (on_cursor_position_changed), self);
g_signal_connect (widget, "notify::selection-bound",
G_CALLBACK (on_selection_bound_changed), self);
}
static void
gtk_password_entry_accessible_class_init (GtkPasswordEntryAccessibleClass *klass)
{
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
atk_object_class->initialize = gtk_password_entry_accessible_initialize;
atk_object_class->get_attributes = gtk_password_entry_accessible_get_attributes;
}
static void
gtk_password_entry_accessible_init (GtkPasswordEntryAccessible *self)
{
AtkObject *atk_obj = ATK_OBJECT (self);
atk_obj->role = ATK_ROLE_PASSWORD_TEXT;
atk_object_set_name (atk_obj, _("Password"));
}
void
gtk_password_entry_accessible_update_visibility (GtkPasswordEntryAccessible *self)
{
GtkText *text = get_text_widget (GTK_ACCESSIBLE (self));
if (text == NULL)
return;
gboolean visibility = gtk_text_get_visibility (text);
AtkRole role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (ATK_OBJECT (self), role);
}
+48
View File
@@ -0,0 +1,48 @@
/* gtkpasswordentryaccessible.h: A GtkWidgetAccessible for GtkPasswordEntry
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
#pragma once
#if !defined (__GTK_A11Y_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk-a11y.h> can be included directly."
#endif
#include <gtk/a11y/gtkentryaccessible.h>
G_BEGIN_DECLS
#define GTK_TYPE_PASSWORD_ENTRY_ACCESSIBLE (gtk_password_entry_accessible_get_type())
#define GTK_PASSWORD_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PASSWORD_ENTRY_ACCESSIBLE, GtkPasswordEntryAccessible))
#define GTK_IS_PASSWORD_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PASSWORD_ENTRY_ACCESSIBLE))
typedef struct _GtkPasswordEntryAccessible GtkPasswordEntryAccessible;
typedef struct _GtkPasswordEntryAccessibleClass GtkPasswordEntryAccessibleClass;
struct _GtkPasswordEntryAccessibleClass
{
GtkWidgetAccessibleClass parent_class;
};
GDK_AVAILABLE_IN_ALL
GType gtk_password_entry_accessible_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkPasswordEntryAccessible, g_object_unref)
G_END_DECLS
@@ -0,0 +1,29 @@
/* gtkpasswordentryaccessibleprivate.h: Private API for GtkPasswordEntryAccessible
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
#pragma once
#include "gtkpasswordentryaccessible.h"
G_BEGIN_DECLS
void gtk_password_entry_accessible_update_visibility (GtkPasswordEntryAccessible *self);
G_END_DECLS
+6 -30
View File
@@ -21,52 +21,28 @@
#include <gtk/gtk.h>
#include "gtkprogressbaraccessible.h"
#include "gtkprogressbaraccessibleprivate.h"
static void atk_value_interface_init (AtkValueIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkProgressBarAccessible, gtk_progress_bar_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
static void
gtk_progress_bar_accessible_initialize (AtkObject *obj,
gpointer data)
void
gtk_progress_bar_accessible_update_value (GtkProgressBarAccessible *self)
{
ATK_OBJECT_CLASS (gtk_progress_bar_accessible_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_PROGRESS_BAR;
}
static void
gtk_progress_bar_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *accessible;
accessible = gtk_widget_get_accessible (widget);
if (strcmp (pspec->name, "fraction") == 0)
g_object_notify (G_OBJECT (accessible), "accessible-value");
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_progress_bar_accessible_parent_class)->notify_gtk (obj, pspec);
g_object_notify (G_OBJECT (self), "accessible-value");
}
static void
gtk_progress_bar_accessible_class_init (GtkProgressBarAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
widget_class->notify_gtk = gtk_progress_bar_accessible_notify_gtk;
class->initialize = gtk_progress_bar_accessible_initialize;
}
static void
gtk_progress_bar_accessible_init (GtkProgressBarAccessible *bar)
gtk_progress_bar_accessible_init (GtkProgressBarAccessible *self)
{
ATK_OBJECT (self)->role = ATK_ROLE_PROGRESS_BAR;
}
static void
@@ -1,10 +1,13 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2011 Red Hat, Inc.
/* gtkprogressbaraccessibleprivate.h: Private GtkProgressBarAccessible API
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* 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
@@ -12,18 +15,15 @@
* 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/>.
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_ORIENTABLE_PRIVATE_H__
#define __GTK_ORIENTABLE_PRIVATE_H__
#pragma once
#include "gtkorientable.h"
#include "gtkprogressbaraccessible.h"
G_BEGIN_DECLS
void _gtk_orientable_set_style_classes (GtkOrientable *orientable);
void gtk_progress_bar_accessible_update_value (GtkProgressBarAccessible *self);
G_END_DECLS
#endif /* __GTK_ORIENTABLE_H__ */
+42 -33
View File
@@ -21,10 +21,12 @@
#include <gtk/gtk.h>
#include "gtkrangeaccessible.h"
struct _GtkRangeAccessiblePrivate
typedef struct
{
GtkAdjustment *adjustment;
};
gulong value_changed_id;
} GtkRangeAccessiblePrivate;
static void atk_value_interface_init (AtkValueIface *iface);
@@ -42,35 +44,44 @@ gtk_range_accessible_value_changed (GtkAdjustment *adjustment,
static void
gtk_range_accessible_widget_set (GtkAccessible *accessible)
{
GtkRangeAccessiblePrivate *priv = GTK_RANGE_ACCESSIBLE (accessible)->priv;
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (accessible);
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
GtkWidget *range;
GtkAdjustment *adj;
range = gtk_accessible_get_widget (accessible);
adj = gtk_range_get_adjustment (GTK_RANGE (range));
if (adj)
if (adj != NULL)
{
priv->adjustment = adj;
g_object_ref (priv->adjustment);
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (gtk_range_accessible_value_changed),
accessible);
priv->adjustment = g_object_ref (adj);
priv->value_changed_id =
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (gtk_range_accessible_value_changed),
self);
}
}
static void
gtk_range_accessible_widget_unset (GtkAccessible *accessible)
{
GtkRangeAccessiblePrivate *priv = GTK_RANGE_ACCESSIBLE (accessible)->priv;
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (accessible);
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
if (priv->adjustment)
if (priv->adjustment != NULL &&
priv->value_changed_id != 0)
{
g_signal_handlers_disconnect_by_func (priv->adjustment,
G_CALLBACK (gtk_range_accessible_value_changed),
accessible);
g_object_unref (priv->adjustment);
priv->adjustment = NULL;
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
g_clear_object (&priv->adjustment);
}
void
gtk_range_accessible_update_adjustment (GtkRangeAccessible *self)
{
gtk_range_accessible_widget_unset (GTK_ACCESSIBLE (self));
gtk_range_accessible_widget_set (GTK_ACCESSIBLE (self));
}
static void
@@ -82,42 +93,40 @@ gtk_range_accessible_initialize (AtkObject *obj,
}
static void
gtk_range_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
gtk_range_accessible_dispose (GObject *gobject)
{
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *range;
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (gobject);
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
if (strcmp (pspec->name, "adjustment") == 0)
if (priv->adjustment != NULL && priv->value_changed_id != 0)
{
range = gtk_widget_get_accessible (widget);
gtk_range_accessible_widget_unset (GTK_ACCESSIBLE (range));
gtk_range_accessible_widget_set (GTK_ACCESSIBLE (range));
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_range_accessible_parent_class)->notify_gtk (obj, pspec);
}
g_clear_object (&priv->adjustment);
G_OBJECT_CLASS (gtk_range_accessible_parent_class)->dispose (gobject);
}
static void
gtk_range_accessible_class_init (GtkRangeAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *atkobject_class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
class->initialize = gtk_range_accessible_initialize;
gobject_class->dispose = gtk_range_accessible_dispose;
atkobject_class->initialize = gtk_range_accessible_initialize;
accessible_class->widget_set = gtk_range_accessible_widget_set;
accessible_class->widget_unset = gtk_range_accessible_widget_unset;
widget_class->notify_gtk = gtk_range_accessible_notify_gtk;
}
static void
gtk_range_accessible_init (GtkRangeAccessible *range)
{
range->priv = gtk_range_accessible_get_instance_private (range);
}
static void
+3 -3
View File
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
typedef struct _GtkRangeAccessible GtkRangeAccessible;
typedef struct _GtkRangeAccessibleClass GtkRangeAccessibleClass;
typedef struct _GtkRangeAccessiblePrivate GtkRangeAccessiblePrivate;
struct _GtkRangeAccessible
{
GtkWidgetAccessible parent;
GtkRangeAccessiblePrivate *priv;
};
struct _GtkRangeAccessibleClass
@@ -52,6 +49,9 @@ struct _GtkRangeAccessibleClass
GDK_AVAILABLE_IN_ALL
GType gtk_range_accessible_get_type (void);
/*< private >*/
void gtk_range_accessible_update_adjustment (GtkRangeAccessible *self);
G_END_DECLS
#endif /* __GTK_RANGE_ACCESSIBLE_H__ */
+63 -35
View File
@@ -23,79 +23,107 @@
#include <string.h>
typedef struct {
GtkAdjustment *adjustment;
gulong value_changed_id;
} GtkScaleButtonAccessiblePrivate;
static void atk_action_interface_init (AtkActionIface *iface);
static void atk_value_interface_init (AtkValueIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkScaleButtonAccessible, gtk_scale_button_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
G_ADD_PRIVATE (GtkScaleButtonAccessible)
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init));
static void
gtk_scale_button_accessible_value_changed (GtkAdjustment *adjustment,
gpointer data)
on_value_changed (GtkAdjustment *adjustment,
gpointer data)
{
g_object_notify (G_OBJECT (data), "accessible-value");
GtkScaleButtonAccessible *self = data;
g_object_notify (G_OBJECT (self), "accessible-value");
}
static void
on_adjustment_changed (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
GtkScaleButton *scale_button = GTK_SCALE_BUTTON (gobject);
GtkScaleButtonAccessible *self = data;
GtkScaleButtonAccessiblePrivate *priv =
gtk_scale_button_accessible_get_instance_private (self);
GtkAdjustment *adjustment =
gtk_scale_button_get_adjustment (scale_button);
if (priv->adjustment == adjustment)
return;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
{
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
g_clear_object (&priv->adjustment);
if (adjustment != NULL)
{
priv->adjustment = g_object_ref (adjustment);
priv->value_changed_id =
g_signal_connect (priv->adjustment, "notify::value-changed",
G_CALLBACK (on_value_changed),
self);
}
}
static void
gtk_scale_button_accessible_initialize (AtkObject *obj,
gpointer data)
{
GtkAdjustment *adjustment;
GtkScaleButton *scale_button = data;
ATK_OBJECT_CLASS (gtk_scale_button_accessible_parent_class)->initialize (obj, data);
adjustment = gtk_scale_button_get_adjustment (GTK_SCALE_BUTTON (data));
if (adjustment)
g_signal_connect (adjustment,
"value-changed",
G_CALLBACK (gtk_scale_button_accessible_value_changed),
obj);
obj->role = ATK_ROLE_SLIDER;
g_signal_connect (scale_button, "notify::adjustment",
G_CALLBACK (on_adjustment_changed),
obj);
}
static void
gtk_scale_button_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
gtk_scale_button_accessible_dispose (GObject *gobject)
{
GtkScaleButton *scale_button;
GtkScaleButtonAccessible *accessible;
GtkScaleButtonAccessible *self = GTK_SCALE_BUTTON_ACCESSIBLE (gobject);
GtkScaleButtonAccessiblePrivate *priv =
gtk_scale_button_accessible_get_instance_private (self);
scale_button = GTK_SCALE_BUTTON (obj);
accessible = GTK_SCALE_BUTTON_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (scale_button)));
if (strcmp (pspec->name, "adjustment") == 0)
if (priv->adjustment != NULL && priv->value_changed_id != 0)
{
GtkAdjustment* adjustment;
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
adjustment = gtk_scale_button_get_adjustment (scale_button);
g_signal_connect (adjustment,
"value-changed",
G_CALLBACK (gtk_scale_button_accessible_value_changed),
accessible);
}
else
{
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_scale_button_accessible_parent_class)->notify_gtk (obj, pspec);
}
g_clear_object (&priv->adjustment);
G_OBJECT_CLASS (gtk_scale_button_accessible_parent_class)->dispose (gobject);
}
static void
gtk_scale_button_accessible_class_init (GtkScaleButtonAccessibleClass *klass)
{
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = GTK_WIDGET_ACCESSIBLE_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gtk_scale_button_accessible_dispose;
atk_object_class->initialize = gtk_scale_button_accessible_initialize;
widget_class->notify_gtk = gtk_scale_button_accessible_notify_gtk;
}
static void
gtk_scale_button_accessible_init (GtkScaleButtonAccessible *button)
gtk_scale_button_accessible_init (GtkScaleButtonAccessible *self)
{
ATK_OBJECT (self)->role = ATK_ROLE_SLIDER;
}
static gboolean
-3
View File
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
typedef struct _GtkScaleButtonAccessible GtkScaleButtonAccessible;
typedef struct _GtkScaleButtonAccessibleClass GtkScaleButtonAccessibleClass;
typedef struct _GtkScaleButtonAccessiblePrivate GtkScaleButtonAccessiblePrivate;
struct _GtkScaleButtonAccessible
{
GtkWidgetAccessible parent;
GtkScaleButtonAccessiblePrivate *priv;
};
struct _GtkScaleButtonAccessibleClass
+57 -54
View File
@@ -21,10 +21,11 @@
#include <gtk/gtk.h>
#include "gtkscrollbaraccessible.h"
struct _GtkScrollbarAccessiblePrivate
typedef struct
{
GtkAdjustment *adjustment;
};
gulong value_changed_id;
} GtkScrollbarAccessiblePrivate;
static void atk_value_interface_init (AtkValueIface *iface);
@@ -33,91 +34,93 @@ G_DEFINE_TYPE_WITH_CODE (GtkScrollbarAccessible, gtk_scrollbar_accessible, GTK_T
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
static void
gtk_scrollbar_accessible_value_changed (GtkAdjustment *adjustment,
gpointer data)
on_value_changed (GtkAdjustment *adjustment,
gpointer data)
{
g_object_notify (G_OBJECT (data), "accessible-value");
GtkScrollbarAccessible *self = data;
g_object_notify (G_OBJECT (self), "accessible-value");
}
static void
gtk_scrollbar_accessible_widget_set (GtkAccessible *accessible)
on_adjustment_changed (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
GtkScrollbarAccessiblePrivate *priv = GTK_SCROLLBAR_ACCESSIBLE (accessible)->priv;
GtkWidget *scrollbar;
GtkAdjustment *adj;
GtkScrollbar *scrollbar = GTK_SCROLLBAR (gobject);
GtkScrollbarAccessible *self = data;
GtkScrollbarAccessiblePrivate *priv =
gtk_scrollbar_accessible_get_instance_private (self);
GtkAdjustment *adjustment =
gtk_scrollbar_get_adjustment (scrollbar);
scrollbar = gtk_accessible_get_widget (accessible);
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (scrollbar));
if (adj)
if (priv->adjustment == adjustment)
return;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
{
priv->adjustment = adj;
g_object_ref (priv->adjustment);
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (gtk_scrollbar_accessible_value_changed),
accessible);
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
g_clear_object (&priv->adjustment);
if (adjustment != NULL)
{
priv->adjustment = g_object_ref (adjustment);
priv->value_changed_id =
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (on_value_changed),
self);
}
}
static void
gtk_scrollbar_accessible_widget_unset (GtkAccessible *accessible)
gtk_scrollbar_accessible_dispose (GObject *gobject)
{
GtkScrollbarAccessiblePrivate *priv = GTK_SCROLLBAR_ACCESSIBLE (accessible)->priv;
GtkScrollbarAccessible *self = GTK_SCROLLBAR_ACCESSIBLE (gobject);
GtkScrollbarAccessiblePrivate *priv =
gtk_scrollbar_accessible_get_instance_private (self);
if (priv->adjustment)
if (priv->adjustment != NULL && priv->value_changed_id != 0)
{
g_signal_handlers_disconnect_by_func (priv->adjustment,
G_CALLBACK (gtk_scrollbar_accessible_value_changed),
accessible);
g_object_unref (priv->adjustment);
priv->adjustment = NULL;
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
g_clear_object (&priv->adjustment);
G_OBJECT_CLASS (gtk_scrollbar_accessible_parent_class)->dispose (gobject);
}
static void
gtk_scrollbar_accessible_initialize (AtkObject *obj,
gpointer data)
{
GtkScrollbar *scrollbar = data;
ATK_OBJECT_CLASS (gtk_scrollbar_accessible_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_SCROLL_BAR;
g_signal_connect (scrollbar, "notify::adjustment",
G_CALLBACK (on_adjustment_changed),
obj);
}
static void
gtk_scrollbar_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *scrollbar;
if (strcmp (pspec->name, "adjustment") == 0)
{
scrollbar = gtk_widget_get_accessible (widget);
gtk_scrollbar_accessible_widget_unset (GTK_ACCESSIBLE (scrollbar));
gtk_scrollbar_accessible_widget_set (GTK_ACCESSIBLE (scrollbar));
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_scrollbar_accessible_parent_class)->notify_gtk (obj, pspec);
}
static void
gtk_scrollbar_accessible_class_init (GtkScrollbarAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
class->initialize = gtk_scrollbar_accessible_initialize;
atk_object_class->initialize = gtk_scrollbar_accessible_initialize;
accessible_class->widget_set = gtk_scrollbar_accessible_widget_set;
accessible_class->widget_unset = gtk_scrollbar_accessible_widget_unset;
widget_class->notify_gtk = gtk_scrollbar_accessible_notify_gtk;
gobject_class->dispose = gtk_scrollbar_accessible_dispose;
}
static void
gtk_scrollbar_accessible_init (GtkScrollbarAccessible *scrollbar)
gtk_scrollbar_accessible_init (GtkScrollbarAccessible *self)
{
scrollbar->priv = gtk_scrollbar_accessible_get_instance_private (scrollbar);
ATK_OBJECT (self)->role = ATK_ROLE_SCROLL_BAR;
}
static void
-3
View File
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
typedef struct _GtkScrollbarAccessible GtkScrollbarAccessible;
typedef struct _GtkScrollbarAccessibleClass GtkScrollbarAccessibleClass;
typedef struct _GtkScrollbarAccessiblePrivate GtkScrollbarAccessiblePrivate;
struct _GtkScrollbarAccessible
{
GtkWidgetAccessible parent;
GtkScrollbarAccessiblePrivate *priv;
};
struct _GtkScrollbarAccessibleClass
File diff suppressed because it is too large Load Diff
+48
View File
@@ -0,0 +1,48 @@
/* gtksearchentryaccessible.h: A GtkWidgetAccessible for GtkSearchEntry
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
#pragma once
#if !defined (__GTK_A11Y_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk-a11y.h> can be included directly."
#endif
#include <gtk/a11y/gtkentryaccessible.h>
G_BEGIN_DECLS
#define GTK_TYPE_SEARCH_ENTRY_ACCESSIBLE (gtk_search_entry_accessible_get_type())
#define GTK_SEARCH_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SEARCH_ENTRY_ACCESSIBLE, GtkSearchEntryAccessible))
#define GTK_IS_SEARCH_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SEARCH_ENTRY_ACCESSIBLE))
typedef struct _GtkSearchEntryAccessible GtkSearchEntryAccessible;
typedef struct _GtkSearchEntryAccessibleClass GtkSearchEntryAccessibleClass;
struct _GtkSearchEntryAccessibleClass
{
GtkWidgetAccessibleClass parent_class;
};
GDK_AVAILABLE_IN_ALL
GType gtk_search_entry_accessible_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkSearchEntryAccessible, g_object_unref)
G_END_DECLS
+45 -51
View File
@@ -24,6 +24,7 @@
struct _GtkSpinButtonAccessiblePrivate
{
GtkAdjustment *adjustment;
gulong value_changed_id;
};
static void atk_value_interface_init (AtkValueIface *iface);
@@ -33,91 +34,84 @@ G_DEFINE_TYPE_WITH_CODE (GtkSpinButtonAccessible, gtk_spin_button_accessible, GT
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
static void
gtk_spin_button_accessible_value_changed (GtkAdjustment *adjustment,
gpointer data)
on_value_changed (GtkAdjustment *adjustment,
GtkSpinButtonAccessible *self)
{
g_object_notify (G_OBJECT (data), "accessible-value");
g_object_notify (G_OBJECT (self), "accessible-value");
}
static void
gtk_spin_button_accessible_widget_set (GtkAccessible *accessible)
on_adjustment_changed (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
GtkSpinButtonAccessiblePrivate *priv = GTK_SPIN_BUTTON_ACCESSIBLE (accessible)->priv;
GtkWidget *spin;
GtkAdjustment *adj;
GtkSpinButton *spin = GTK_SPIN_BUTTON (gobject);
GtkSpinButtonAccessible *self = data;
GtkSpinButtonAccessiblePrivate *priv = gtk_spin_button_accessible_get_instance_private (self);
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin);
spin = gtk_accessible_get_widget (accessible);
adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin));
if (adj)
if (priv->adjustment == adjustment)
return;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
{
priv->adjustment = adj;
g_object_ref (priv->adjustment);
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (gtk_spin_button_accessible_value_changed),
accessible);
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
}
static void
gtk_spin_button_accessible_widget_unset (GtkAccessible *accessible)
{
GtkSpinButtonAccessiblePrivate *priv = GTK_SPIN_BUTTON_ACCESSIBLE (accessible)->priv;
g_clear_object (&priv->adjustment);
if (priv->adjustment)
if (adjustment != NULL)
{
g_signal_handlers_disconnect_by_func (priv->adjustment,
G_CALLBACK (gtk_spin_button_accessible_value_changed),
accessible);
g_object_unref (priv->adjustment);
priv->adjustment = NULL;
priv->adjustment = g_object_ref (adjustment);
priv->value_changed_id = g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (on_value_changed),
self);
}
}
static void
gtk_spin_button_accessible_initialize (AtkObject *obj,
gpointer data)
gpointer data)
{
ATK_OBJECT_CLASS (gtk_spin_button_accessible_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_SPIN_BUTTON;
g_signal_connect (data, "notify::adjustment", G_CALLBACK (on_adjustment_changed), obj);
}
static void
gtk_spin_button_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
gtk_spin_button_accessible_dispose (GObject *gobject)
{
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *spin;
GtkSpinButtonAccessible *self = GTK_SPIN_BUTTON_ACCESSIBLE (gobject);
GtkSpinButtonAccessiblePrivate *priv =
gtk_spin_button_accessible_get_instance_private (self);
if (strcmp (pspec->name, "adjustment") == 0)
if (priv->adjustment != NULL && priv->value_changed_id != 0)
{
spin = gtk_widget_get_accessible (widget);
gtk_spin_button_accessible_widget_unset (GTK_ACCESSIBLE (spin));
gtk_spin_button_accessible_widget_set (GTK_ACCESSIBLE (spin));
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_spin_button_accessible_parent_class)->notify_gtk (obj, pspec);
g_clear_object (&priv->adjustment);
G_OBJECT_CLASS (gtk_spin_button_accessible_parent_class)->dispose (gobject);
}
static void
gtk_spin_button_accessible_class_init (GtkSpinButtonAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
class->initialize = gtk_spin_button_accessible_initialize;
atk_object_class->initialize = gtk_spin_button_accessible_initialize;
accessible_class->widget_set = gtk_spin_button_accessible_widget_set;
accessible_class->widget_unset = gtk_spin_button_accessible_widget_unset;
widget_class->notify_gtk = gtk_spin_button_accessible_notify_gtk;
gobject_class->dispose = gtk_spin_button_accessible_dispose;
}
static void
gtk_spin_button_accessible_init (GtkSpinButtonAccessible *button)
gtk_spin_button_accessible_init (GtkSpinButtonAccessible *self)
{
button->priv = gtk_spin_button_accessible_get_instance_private (button);
ATK_OBJECT (self)->role = ATK_ROLE_SPIN_BUTTON;
}
static void
@@ -207,8 +201,8 @@ gtk_spin_button_accessible_set_current_value (AtkValue *obj,
static void
gtk_spin_button_accessible_get_value_and_text (AtkValue *obj,
gdouble *value,
gchar **text)
gdouble *value,
gchar **text)
{
GtkWidget *widget;
GtkAdjustment *adjustment;
+64 -56
View File
@@ -109,9 +109,65 @@ gtk_text_accessible_get_attributes (AtkObject *accessible)
return attributes;
}
static void
on_cursor_position_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkTextAccessible *self = GTK_TEXT_ACCESSIBLE (accessible);
GtkTextAccessiblePrivate *priv = gtk_text_accessible_get_instance_private (self);
GtkText *text = GTK_TEXT (gobject);
if (check_for_selection_change (self, text))
g_signal_emit_by_name (accessible, "text-selection-changed");
/* The entry cursor position has moved so generate the signal */
g_signal_emit_by_name (accessible,
"text-caret-moved",
priv->cursor_position);
}
static void
on_selection_bound_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkTextAccessible *self = GTK_TEXT_ACCESSIBLE (accessible);
GtkText *text = GTK_TEXT (gobject);
if (check_for_selection_change (self, text))
g_signal_emit_by_name (accessible, "text-selection-changed");
}
static void
on_editable_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkEditable *editable = GTK_EDITABLE (gobject);
gboolean value = gtk_editable_get_editable (editable);
atk_object_notify_state_change (accessible, ATK_STATE_EDITABLE, value);
}
static void
on_visibility_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkText *text = GTK_TEXT (gobject);
AtkRole new_role;
new_role = gtk_text_get_visibility (text)
? ATK_ROLE_TEXT
: ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (accessible, new_role);
}
static void
gtk_text_accessible_initialize (AtkObject *obj,
gpointer data)
gpointer data)
{
GtkText *entry;
GtkTextAccessible *gtk_text_accessible;
@@ -130,66 +186,21 @@ gtk_text_accessible_initialize (AtkObject *obj,
g_signal_connect_after (entry, "insert-text", G_CALLBACK (insert_text_cb), NULL);
g_signal_connect (entry, "delete-text", G_CALLBACK (delete_text_cb), NULL);
g_signal_connect (entry, "notify::cursor-position", G_CALLBACK (on_cursor_position_changed), obj);
g_signal_connect (entry, "notify::selection-bound", G_CALLBACK (on_selection_bound_changed), obj);
g_signal_connect (entry, "notify::editable", G_CALLBACK (on_editable_changed), obj);
g_signal_connect (entry, "notify::visibility", G_CALLBACK (on_visibility_changed), obj);
if (gtk_text_get_visibility (entry))
obj->role = ATK_ROLE_TEXT;
else
obj->role = ATK_ROLE_PASSWORD_TEXT;
}
static void
gtk_text_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget *widget;
AtkObject* atk_obj;
GtkText* gtk_text;
GtkTextAccessible* entry;
widget = GTK_WIDGET (obj);
atk_obj = gtk_widget_get_accessible (widget);
gtk_text = GTK_TEXT (widget);
entry = GTK_TEXT_ACCESSIBLE (atk_obj);
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
{
if (check_for_selection_change (entry, gtk_text))
g_signal_emit_by_name (atk_obj, "text-selection-changed");
/*
* The entry cursor position has moved so generate the signal.
*/
g_signal_emit_by_name (atk_obj, "text-caret-moved",
entry->priv->cursor_position);
}
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
{
if (check_for_selection_change (entry, gtk_text))
g_signal_emit_by_name (atk_obj, "text-selection-changed");
}
else if (g_strcmp0 (pspec->name, "editable") == 0)
{
gboolean value;
g_object_get (obj, "editable", &value, NULL);
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value);
}
else if (g_strcmp0 (pspec->name, "visibility") == 0)
{
gboolean visibility;
AtkRole new_role;
visibility = gtk_text_get_visibility (gtk_text);
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (atk_obj, new_role);
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_text_accessible_parent_class)->notify_gtk (obj, pspec);
}
static gint
gtk_text_accessible_get_index_in_parent (AtkObject *accessible)
{
/*
* If the parent widget is a combo box then the index is 1
/* If the parent widget is a combo box then the index is 1
* otherwise do the normal thing.
*/
if (accessible->accessible_parent)
@@ -202,15 +213,12 @@ gtk_text_accessible_get_index_in_parent (AtkObject *accessible)
static void
gtk_text_accessible_class_init (GtkTextAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->ref_state_set = gtk_text_accessible_ref_state_set;
class->get_index_in_parent = gtk_text_accessible_get_index_in_parent;
class->initialize = gtk_text_accessible_initialize;
class->get_attributes = gtk_text_accessible_get_attributes;
widget_class->notify_gtk = gtk_text_accessible_notify_gtk;
}
static void
+15 -21
View File
@@ -67,6 +67,18 @@ G_DEFINE_TYPE_WITH_CODE (GtkTextViewAccessible, gtk_text_view_accessible, GTK_TY
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
static void
on_editable_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkTextView *text_view = GTK_TEXT_VIEW (gobject);
atk_object_notify_state_change (accessible,
ATK_STATE_EDITABLE,
gtk_text_view_get_editable (text_view));
}
static void
gtk_text_view_accessible_initialize (AtkObject *obj,
gpointer data)
@@ -74,25 +86,10 @@ gtk_text_view_accessible_initialize (AtkObject *obj,
ATK_OBJECT_CLASS (gtk_text_view_accessible_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_TEXT;
}
static void
gtk_text_view_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
AtkObject *atk_obj;
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (obj));
if (!strcmp (pspec->name, "editable"))
{
gboolean editable;
editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (obj));
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, editable);
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_text_view_accessible_parent_class)->notify_gtk (obj, pspec);
g_signal_connect (data, "notify::editable",
G_CALLBACK (on_editable_changed),
obj);
}
static AtkStateSet*
@@ -167,15 +164,12 @@ gtk_text_view_accessible_class_init (GtkTextViewAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
accessible_class->widget_set = gtk_text_view_accessible_widget_set;
accessible_class->widget_unset = gtk_text_view_accessible_widget_unset;
class->ref_state_set = gtk_text_view_accessible_ref_state_set;
class->initialize = gtk_text_view_accessible_initialize;
widget_class->notify_gtk = gtk_text_view_accessible_notify_gtk;
}
static void
-24
View File
@@ -49,27 +49,6 @@ gtk_toggle_button_accessible_initialize (AtkObject *obj,
obj->role = ATK_ROLE_TOGGLE_BUTTON;
}
static void
gtk_toggle_button_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (obj);
AtkObject *atk_obj;
gboolean sensitive;
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (toggle_button));
sensitive = gtk_widget_get_sensitive (GTK_WIDGET (toggle_button));
if (strcmp (pspec->name, "sensitive") == 0)
{
/* Need to override gailwidget behavior of notifying for ENABLED */
atk_object_notify_state_change (atk_obj, ATK_STATE_SENSITIVE, sensitive);
atk_object_notify_state_change (atk_obj, ATK_STATE_ENABLED, sensitive);
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_toggle_button_accessible_parent_class)->notify_gtk (obj, pspec);
}
static AtkStateSet*
gtk_toggle_button_accessible_ref_state_set (AtkObject *accessible)
{
@@ -94,9 +73,6 @@ static void
gtk_toggle_button_accessible_class_init (GtkToggleButtonAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
widget_class->notify_gtk = gtk_toggle_button_accessible_notify_gtk;
class->ref_state_set = gtk_toggle_button_accessible_ref_state_set;
class->initialize = gtk_toggle_button_accessible_initialize;
+58 -65
View File
@@ -32,10 +32,10 @@
#include "gtkcellaccessibleparent.h"
#include "gtkcellaccessibleprivate.h"
struct _GtkTreeViewAccessiblePrivate
typedef struct
{
GHashTable *cell_infos;
};
} GtkTreeViewAccessiblePrivate;
typedef struct _GtkTreeViewAccessibleCellInfo GtkTreeViewAccessibleCellInfo;
struct _GtkTreeViewAccessibleCellInfo
@@ -138,89 +138,80 @@ static void
gtk_tree_view_accessible_initialize (AtkObject *obj,
gpointer data)
{
GtkTreeViewAccessible *accessible;
GtkTreeView *tree_view;
GtkTreeViewAccessible *self = GTK_TREE_VIEW_ACCESSIBLE (obj);
GtkTreeViewAccessiblePrivate *priv = gtk_tree_view_accessible_get_instance_private (self);
GtkTreeView *tree_view = data;
GtkTreeModel *tree_model;
GtkWidget *widget;
ATK_OBJECT_CLASS (gtk_tree_view_accessible_parent_class)->initialize (obj, data);
accessible = GTK_TREE_VIEW_ACCESSIBLE (obj);
priv->cell_infos = g_hash_table_new_full (cell_info_hash, cell_info_equal,
NULL,
(GDestroyNotify) cell_info_free);
accessible->priv->cell_infos = g_hash_table_new_full (cell_info_hash,
cell_info_equal, NULL, (GDestroyNotify) cell_info_free);
widget = GTK_WIDGET (data);
tree_view = GTK_TREE_VIEW (widget);
tree_model = gtk_tree_view_get_model (tree_view);
if (tree_model)
if (tree_model != NULL)
{
if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
obj->role = ATK_ROLE_TABLE;
AtkRole role;
if ((gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY) != 0)
role = ATK_ROLE_TABLE;
else
obj->role = ATK_ROLE_TREE_TABLE;
role = ATK_ROLE_TREE_TABLE;
atk_object_set_role (obj, role);
}
}
static void
gtk_tree_view_accessible_finalize (GObject *object)
{
GtkTreeViewAccessible *accessible = GTK_TREE_VIEW_ACCESSIBLE (object);
GtkTreeViewAccessible *self = GTK_TREE_VIEW_ACCESSIBLE (object);
GtkTreeViewAccessiblePrivate *priv = gtk_tree_view_accessible_get_instance_private (self);
if (accessible->priv->cell_infos)
g_hash_table_destroy (accessible->priv->cell_infos);
g_clear_pointer (&priv->cell_infos, g_hash_table_unref);
G_OBJECT_CLASS (gtk_tree_view_accessible_parent_class)->finalize (object);
}
static void
gtk_tree_view_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
void
gtk_tree_view_accessible_update_model (GtkTreeViewAccessible *self,
GtkTreeModel *model)
{
GtkWidget *widget;
GtkTreeView *tree_view;
GtkTreeViewAccessible *accessible;
GtkTreeViewAccessiblePrivate *priv = gtk_tree_view_accessible_get_instance_private (self);
widget = GTK_WIDGET (obj);
accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
tree_view = GTK_TREE_VIEW (widget);
g_return_if_fail (GTK_IS_TREE_VIEW_ACCESSIBLE (self));
g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
if (g_strcmp0 (pspec->name, "model") == 0)
g_hash_table_remove_all (priv->cell_infos);
if (model != NULL)
{
GtkTreeModel *tree_model;
AtkObject *object = ATK_OBJECT (self);
AtkRole role;
tree_model = gtk_tree_view_get_model (tree_view);
g_hash_table_remove_all (accessible->priv->cell_infos);
if (tree_model)
{
if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
role = ATK_ROLE_TABLE;
else
role = ATK_ROLE_TREE_TABLE;
}
if ((gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY) != 0)
role = ATK_ROLE_TABLE;
else
{
role = ATK_ROLE_UNKNOWN;
}
atk_object_set_role (ATK_OBJECT (accessible), role);
g_object_freeze_notify (G_OBJECT (accessible));
g_signal_emit_by_name (accessible, "model-changed");
g_signal_emit_by_name (accessible, "visible-data-changed");
g_object_thaw_notify (G_OBJECT (accessible));
role = ATK_ROLE_TREE_TABLE;
atk_object_set_role (object, role);
g_object_freeze_notify (G_OBJECT (self));
g_signal_emit_by_name (self, "model-changed");
g_signal_emit_by_name (self, "visible-data-changed");
g_object_thaw_notify (G_OBJECT (self));
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_tree_view_accessible_parent_class)->notify_gtk (obj, pspec);
}
static void
gtk_tree_view_accessible_widget_unset (GtkAccessible *gtkaccessible)
{
GtkTreeViewAccessible *accessible = GTK_TREE_VIEW_ACCESSIBLE (gtkaccessible);
GtkTreeViewAccessible *self = GTK_TREE_VIEW_ACCESSIBLE (gtkaccessible);
GtkTreeViewAccessiblePrivate *priv = gtk_tree_view_accessible_get_instance_private (self);
g_hash_table_remove_all (accessible->priv->cell_infos);
g_hash_table_remove_all (priv->cell_infos);
GTK_ACCESSIBLE_CLASS (gtk_tree_view_accessible_parent_class)->widget_unset (gtkaccessible);
}
@@ -338,18 +329,19 @@ set_cell_data (GtkTreeView *treeview,
}
static GtkCellAccessible *
peek_cell (GtkTreeViewAccessible *accessible,
peek_cell (GtkTreeViewAccessible *self,
GtkTreeRBTree *tree,
GtkTreeRBNode *node,
GtkTreeViewColumn *column)
{
GtkTreeViewAccessiblePrivate *priv = gtk_tree_view_accessible_get_instance_private (self);
GtkTreeViewAccessibleCellInfo lookup, *cell_info;
lookup.tree = tree;
lookup.node = node;
lookup.cell_col_ref = column;
cell_info = g_hash_table_lookup (accessible->priv->cell_infos, &lookup);
cell_info = g_hash_table_lookup (priv->cell_infos, &lookup);
if (cell_info == NULL)
return NULL;
@@ -490,15 +482,12 @@ gtk_tree_view_accessible_class_init (GtkTreeViewAccessibleClass *klass)
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
class->get_n_children = gtk_tree_view_accessible_get_n_children;
class->ref_child = gtk_tree_view_accessible_ref_child;
class->ref_state_set = gtk_tree_view_accessible_ref_state_set;
class->initialize = gtk_tree_view_accessible_initialize;
widget_class->notify_gtk = gtk_tree_view_accessible_notify_gtk;
accessible_class->widget_unset = gtk_tree_view_accessible_widget_unset;
gobject_class->finalize = gtk_tree_view_accessible_finalize;
@@ -507,7 +496,6 @@ gtk_tree_view_accessible_class_init (GtkTreeViewAccessibleClass *klass)
static void
gtk_tree_view_accessible_init (GtkTreeViewAccessible *view)
{
view->priv = gtk_tree_view_accessible_get_instance_private (view);
}
/* atkcomponent.h */
@@ -1499,27 +1487,28 @@ cell_info_get_index (GtkTreeView *tree_view,
}
static void
cell_info_new (GtkTreeViewAccessible *accessible,
cell_info_new (GtkTreeViewAccessible *self,
GtkTreeRBTree *tree,
GtkTreeRBNode *node,
GtkTreeViewColumn *tv_col,
GtkCellAccessible *cell)
{
GtkTreeViewAccessiblePrivate *priv = gtk_tree_view_accessible_get_instance_private (self);
GtkTreeViewAccessibleCellInfo *cell_info;
cell_info = g_new (GtkTreeViewAccessibleCellInfo, 1);
cell_info->view = self;
cell_info->tree = tree;
cell_info->node = node;
cell_info->cell_col_ref = tv_col;
cell_info->cell = cell;
cell_info->view = accessible;
g_object_set_qdata (G_OBJECT (cell),
gtk_tree_view_accessible_get_data_quark (),
cell_info);
g_hash_table_replace (accessible->priv->cell_infos, cell_info, cell_info);
g_hash_table_replace (priv->cell_infos, cell_info, cell_info);
}
/* Returns the column number of the specified GtkTreeViewColumn
@@ -1668,12 +1657,15 @@ _gtk_tree_view_accessible_remove (GtkTreeView *treeview,
GtkTreeViewAccessibleCellInfo *cell_info;
GHashTableIter iter;
GtkTreeViewAccessible *accessible;
GtkTreeViewAccessiblePrivate *priv;
guint row, n_rows, n_cols, i;
accessible = GTK_TREE_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (treeview)));
if (accessible == NULL)
return;
priv = gtk_tree_view_accessible_get_instance_private (accessible);
/* if this shows up in profiles, special-case node->children == NULL */
if (node == NULL)
@@ -1700,7 +1692,7 @@ _gtk_tree_view_accessible_remove (GtkTreeView *treeview,
g_signal_emit_by_name (accessible, "children-changed::remove", i, NULL, NULL);
}
g_hash_table_iter_init (&iter, accessible->priv->cell_infos);
g_hash_table_iter_init (&iter, priv->cell_infos);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
{
if (node == cell_info->node ||
@@ -1805,18 +1797,19 @@ _gtk_tree_view_accessible_add_column (GtkTreeView *treeview,
}
static void
gtk_tree_view_accessible_do_remove_column (GtkTreeViewAccessible *accessible,
gtk_tree_view_accessible_do_remove_column (GtkTreeViewAccessible *self,
GtkTreeView *treeview,
GtkTreeViewColumn *column,
guint id)
{
GtkTreeViewAccessiblePrivate *priv = gtk_tree_view_accessible_get_instance_private (self);
GtkTreeViewAccessibleCellInfo *cell_info;
GHashTableIter iter;
gpointer value;
guint row, n_rows, n_cols;
/* Clean column from cache */
g_hash_table_iter_init (&iter, accessible->priv->cell_infos);
g_hash_table_iter_init (&iter, priv->cell_infos);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
cell_info = value;
@@ -1825,7 +1818,7 @@ gtk_tree_view_accessible_do_remove_column (GtkTreeViewAccessible *accessible,
}
/* Generate column-deleted signal */
g_signal_emit_by_name (accessible, "column-deleted", id, 1);
g_signal_emit_by_name (self, "column-deleted", id, 1);
n_rows = get_n_rows (treeview);
n_cols = get_n_columns (treeview);
@@ -1834,7 +1827,7 @@ gtk_tree_view_accessible_do_remove_column (GtkTreeViewAccessible *accessible,
for (row = 0; row <= n_rows; row++)
{
/* Pass NULL as the child object, 4th argument */
g_signal_emit_by_name (accessible, "children-changed::remove",
g_signal_emit_by_name (self, "children-changed::remove",
(row * n_cols) + id, NULL, NULL);
}
}
-3
View File
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
typedef struct _GtkTreeViewAccessible GtkTreeViewAccessible;
typedef struct _GtkTreeViewAccessibleClass GtkTreeViewAccessibleClass;
typedef struct _GtkTreeViewAccessiblePrivate GtkTreeViewAccessiblePrivate;
struct _GtkTreeViewAccessible
{
GtkWidgetAccessible parent;
GtkTreeViewAccessiblePrivate *priv;
};
struct _GtkTreeViewAccessibleClass
+3
View File
@@ -60,6 +60,9 @@ void _gtk_tree_view_accessible_remove_state (GtkTreeView *tree
GtkTreeRBNode *node,
GtkCellRendererState state);
void gtk_tree_view_accessible_update_model (GtkTreeViewAccessible *self,
GtkTreeModel *model);
G_END_DECLS
#endif /* __GTK_TREE_VIEW_ACCESSIBLE_PRIVATE_H__ */
+133 -125
View File
@@ -17,20 +17,43 @@
#include "config.h"
#include <gtk/gtk.h>
#include "gtkwidgetaccessibleprivate.h"
#include "gtknotebookpageaccessible.h"
struct _GtkWidgetAccessiblePrivate
#include "gtkaccellabel.h"
#include "gtkadjustment.h"
#include "gtkbox.h"
#include "gtkbutton.h"
#include "gtkcombobox.h"
#include "gtkdragicon.h"
#include "gtkdrawingarea.h"
#include "gtkglarea.h"
#include "gtkimage.h"
#include "gtklevelbar.h"
#include "gtkmediacontrols.h"
#include "gtknotebookpageaccessible.h"
#include "gtknotebook.h"
#include "gtkorientable.h"
#include "gtkpicture.h"
#include "gtkprogressbar.h"
#include "gtkscrollable.h"
#include "gtkscrollbar.h"
#include "gtkseparator.h"
#include "gtkshortcutlabel.h"
#include "gtkshortcutsshortcut.h"
#include "gtkspinner.h"
#include "gtkstacksidebar.h"
#include "gtkstatusbar.h"
#include "gtkvideo.h"
#include "gtkviewport.h"
#include "gtkwidgetprivate.h"
typedef struct
{
AtkLayer layer;
};
#define TOOLTIP_KEY "tooltip"
} GtkWidgetAccessiblePrivate;
extern GtkWidget *_focus_widget;
static gboolean gtk_widget_accessible_on_screen (GtkWidget *widget);
static gboolean gtk_widget_accessible_all_parents_visible (GtkWidget *widget);
@@ -40,20 +63,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkWidgetAccessible, gtk_widget_accessible, GTK_TYPE_AC
G_ADD_PRIVATE (GtkWidgetAccessible)
G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
/* Translate GtkWidget property change notification to the notify_gtk vfunc */
static void
notify_cb (GObject *obj,
GParamSpec *pspec)
{
GtkWidgetAccessible *widget;
GtkWidgetAccessibleClass *klass;
widget = GTK_WIDGET_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (obj)));
klass = GTK_WIDGET_ACCESSIBLE_GET_CLASS (widget);
if (klass->notify_gtk)
klass->notify_gtk (obj, pspec);
}
/*< private >
* gtk_widget_accessible_update_bounds:
* @self: a #GtkWidgetAccessible
@@ -78,47 +87,111 @@ gtk_widget_accessible_update_bounds (GtkWidgetAccessible *self)
g_signal_emit_by_name (self, "bounds-changed", &rect);
}
/* Translate GtkWidget mapped state into AtkObject showing */
static gint
map_cb (GtkWidget *widget)
/*< private >
* gtk_widget_accessible_notify_showing:
* @self: a #GtkWidgetAccessible
*
* Translates the #GtkWidget mapped state into the #AtkObject
* showing state.
*/
void
gtk_widget_accessible_notify_showing (GtkWidgetAccessible *self)
{
AtkObject *accessible;
g_return_if_fail (GTK_IS_WIDGET_ACCESSIBLE (self));
accessible = gtk_widget_get_accessible (widget);
atk_object_notify_state_change (accessible, ATK_STATE_SHOWING,
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_SHOWING,
gtk_widget_get_mapped (widget));
return 1;
}
static void
gtk_widget_accessible_update_tooltip (GtkWidgetAccessible *accessible,
GtkWidget *widget)
void
gtk_widget_accessible_notify_tooltip (GtkWidgetAccessible *self)
{
g_object_set_data_full (G_OBJECT (accessible),
TOOLTIP_KEY,
gtk_widget_get_tooltip_text (widget),
g_free);
g_return_if_fail (GTK_IS_WIDGET_ACCESSIBLE (self));
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_HAS_TOOLTIP,
gtk_widget_get_has_tooltip (widget));
}
void
gtk_widget_accessible_notify_visible (GtkWidgetAccessible *self)
{
g_return_if_fail (GTK_IS_WIDGET_ACCESSIBLE (self));
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_VISIBLE,
gtk_widget_get_visible (widget));
}
void
gtk_widget_accessible_notify_sensitive (GtkWidgetAccessible *self)
{
g_return_if_fail (GTK_IS_WIDGET_ACCESSIBLE (self));
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
gboolean is_sensitive = gtk_widget_get_sensitive (widget);
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_SENSITIVE,
is_sensitive);
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_ENABLED,
is_sensitive);
}
void
gtk_widget_accessible_notify_focus (GtkWidgetAccessible *self)
{
g_return_if_fail (GTK_IS_WIDGET_ACCESSIBLE (self));
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_FOCUSED,
gtk_widget_has_focus (widget));
}
void
gtk_widget_accessible_notify_orientation (GtkWidgetAccessible *self)
{
g_return_if_fail (GTK_IS_WIDGET_ACCESSIBLE (self));
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
if (GTK_IS_ORIENTABLE (widget))
{
GtkOrientable *orientable = GTK_ORIENTABLE (widget);
GtkOrientation orientation = gtk_orientable_get_orientation (orientable);
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_HORIZONTAL,
orientation == GTK_ORIENTATION_HORIZONTAL);
atk_object_notify_state_change (ATK_OBJECT (self),
ATK_STATE_VERTICAL,
orientation == GTK_ORIENTATION_VERTICAL);
}
}
static void
gtk_widget_accessible_initialize (AtkObject *obj,
gtk_widget_accessible_initialize (AtkObject *object,
gpointer data)
{
GtkWidget *widget;
GtkWidgetAccessible *self = GTK_WIDGET_ACCESSIBLE (object);
GtkWidgetAccessiblePrivate *priv = gtk_widget_accessible_get_instance_private (self);
widget = GTK_WIDGET (data);
priv->layer = ATK_LAYER_WIDGET;
g_signal_connect (widget, "notify", G_CALLBACK (notify_cb), NULL);
g_signal_connect (widget, "map", G_CALLBACK (map_cb), NULL);
g_signal_connect (widget, "unmap", G_CALLBACK (map_cb), NULL);
GTK_WIDGET_ACCESSIBLE (obj)->priv->layer = ATK_LAYER_WIDGET;
obj->role = ATK_ROLE_UNKNOWN;
gtk_widget_accessible_update_tooltip (GTK_WIDGET_ACCESSIBLE (obj), widget);
atk_object_set_role (object, ATK_ROLE_UNKNOWN);
}
static const gchar *
static const char *
gtk_widget_accessible_get_description (AtkObject *accessible)
{
GtkWidget *widget;
@@ -127,10 +200,10 @@ gtk_widget_accessible_get_description (AtkObject *accessible)
if (widget == NULL)
return NULL;
if (accessible->description)
if (accessible->description != NULL)
return accessible->description;
return g_object_get_data (G_OBJECT (accessible), TOOLTIP_KEY);
return gtk_widget_get_tooltip_text (widget);
}
static AtkObject *
@@ -446,72 +519,6 @@ gtk_widget_accessible_get_index_in_parent (AtkObject *accessible)
return index;
}
/* This function is the default implementation for the notify_gtk
* vfunc which gets called when a property changes value on the
* GtkWidget associated with a GtkWidgetAccessible. It constructs
* an AtkPropertyValues structure and emits a property_changed
* signal which causes the user specified AtkPropertyChangeHandler
* to be called.
*/
static void
gtk_widget_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget* widget = GTK_WIDGET (obj);
AtkObject* atk_obj = gtk_widget_get_accessible (widget);
AtkState state;
gboolean value;
if (g_strcmp0 (pspec->name, "has-focus") == 0)
{
state = ATK_STATE_FOCUSED;
value = gtk_widget_has_focus (widget);
}
else if (g_strcmp0 (pspec->name, "tooltip-text") == 0)
{
gtk_widget_accessible_update_tooltip (GTK_WIDGET_ACCESSIBLE (atk_obj),
widget);
if (atk_obj->description == NULL)
g_object_notify (G_OBJECT (atk_obj), "accessible-description");
return;
}
else if (g_strcmp0 (pspec->name, "visible") == 0)
{
state = ATK_STATE_VISIBLE;
value = gtk_widget_get_visible (widget);
}
else if (g_strcmp0 (pspec->name, "sensitive") == 0)
{
state = ATK_STATE_SENSITIVE;
value = gtk_widget_get_sensitive (widget);
}
else if (g_strcmp0 (pspec->name, "orientation") == 0 &&
GTK_IS_ORIENTABLE (widget))
{
GtkOrientable *orientable;
orientable = GTK_ORIENTABLE (widget);
state = ATK_STATE_HORIZONTAL;
value = (gtk_orientable_get_orientation (orientable) == GTK_ORIENTATION_HORIZONTAL);
}
else if (g_strcmp0 (pspec->name, "has-tooltip") == 0)
{
state = ATK_STATE_HAS_TOOLTIP;
value = gtk_widget_get_has_tooltip (widget);
}
else
return;
atk_object_notify_state_change (atk_obj, state, value);
if (state == ATK_STATE_SENSITIVE)
atk_object_notify_state_change (atk_obj, ATK_STATE_ENABLED, value);
if (state == ATK_STATE_HORIZONTAL)
atk_object_notify_state_change (atk_obj, ATK_STATE_VERTICAL, !value);
}
static AtkAttributeSet *
gtk_widget_accessible_get_attributes (AtkObject *obj)
{
@@ -567,8 +574,6 @@ gtk_widget_accessible_class_init (GtkWidgetAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
klass->notify_gtk = gtk_widget_accessible_notify_gtk;
class->get_description = gtk_widget_accessible_get_description;
class->get_parent = gtk_widget_accessible_get_parent;
class->ref_relation_set = gtk_widget_accessible_ref_relation_set;
@@ -583,7 +588,6 @@ gtk_widget_accessible_class_init (GtkWidgetAccessibleClass *klass)
static void
gtk_widget_accessible_init (GtkWidgetAccessible *accessible)
{
accessible->priv = gtk_widget_accessible_get_instance_private (accessible);
}
static void
@@ -626,9 +630,10 @@ gtk_widget_accessible_get_extents (AtkComponent *component,
static AtkLayer
gtk_widget_accessible_get_layer (AtkComponent *component)
{
GtkWidgetAccessible *accessible = GTK_WIDGET_ACCESSIBLE (component);
GtkWidgetAccessible *self = GTK_WIDGET_ACCESSIBLE (component);
GtkWidgetAccessiblePrivate *priv = gtk_widget_accessible_get_instance_private (self);
return accessible->priv->layer;
return priv->layer;
}
static gboolean
@@ -760,10 +765,11 @@ gtk_widget_accessible_all_parents_visible (GtkWidget *widget)
GtkWidget *iter_parent = NULL;
gboolean result = TRUE;
for (iter_parent = gtk_widget_get_parent (widget); iter_parent;
iter_parent = gtk_widget_get_parent (iter_parent))
for (iter_parent = _gtk_widget_get_parent (widget);
iter_parent != NULL;
iter_parent = _gtk_widget_get_parent (iter_parent))
{
if (!gtk_widget_get_visible (iter_parent))
if (!_gtk_widget_get_visible (iter_parent))
{
result = FALSE;
break;
@@ -774,8 +780,10 @@ gtk_widget_accessible_all_parents_visible (GtkWidget *widget)
}
void
_gtk_widget_accessible_set_layer (GtkWidgetAccessible *accessible,
_gtk_widget_accessible_set_layer (GtkWidgetAccessible *self,
AtkLayer layer)
{
accessible->priv->layer = layer;
GtkWidgetAccessiblePrivate *priv = gtk_widget_accessible_get_instance_private (self);
priv->layer = layer;
}
+3 -28
View File
@@ -26,41 +26,16 @@
G_BEGIN_DECLS
#define GTK_TYPE_WIDGET_ACCESSIBLE (gtk_widget_accessible_get_type ())
#define GTK_WIDGET_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WIDGET_ACCESSIBLE, GtkWidgetAccessible))
#define GTK_WIDGET_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WIDGET_ACCESSIBLE, GtkWidgetAccessibleClass))
#define GTK_IS_WIDGET_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WIDGET_ACCESSIBLE))
#define GTK_IS_WIDGET_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WIDGET_ACCESSIBLE))
#define GTK_WIDGET_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WIDGET_ACCESSIBLE, GtkWidgetAccessibleClass))
#define GTK_TYPE_WIDGET_ACCESSIBLE (gtk_widget_accessible_get_type())
typedef struct _GtkWidgetAccessible GtkWidgetAccessible;
typedef struct _GtkWidgetAccessibleClass GtkWidgetAccessibleClass;
typedef struct _GtkWidgetAccessiblePrivate GtkWidgetAccessiblePrivate;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkWidgetAccessible, g_object_unref)
struct _GtkWidgetAccessible
{
GtkAccessible parent;
GtkWidgetAccessiblePrivate *priv;
};
GDK_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (GtkWidgetAccessible, gtk_widget_accessible, GTK, WIDGET_ACCESSIBLE, GtkAccessible)
struct _GtkWidgetAccessibleClass
{
GtkAccessibleClass parent_class;
/*
* Signal handler for notify signal on GTK widget
*/
void (*notify_gtk) (GObject *object,
GParamSpec *pspec);
};
GDK_AVAILABLE_IN_ALL
GType gtk_widget_accessible_get_type (void);
G_END_DECLS
#endif /* __GTK_WIDGET_ACCESSIBLE_H__ */

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