Compare commits

..

264 Commits

Author SHA1 Message Date
Matthias Clasen aa4af4c946 Add a quick demo for a range selector
This is a widget that looks like a GtkScale,
except that it has two sliders instead of one.
It lets you select a subrange of a given range.

Only horizontal for now, and reusing the GtkScale
styling.
2020-07-18 20:16:05 -04:00
Matthias Clasen 7b76be5360 button: Add explicit key bindings for activation
We should not rely on GtkWindow to have global
"activate-default" key bindings that happen to
fall back to activating the focus widget. This is
unreliable, since the bubbling up from the button
to the toplevel may run across other widgets that
may want to use Enter for their own purpose, and
then the button loses out. By adding our own
key bindings, the button gets to handle it before
its ancestors.

This fixes check buttons in the inspector property
list not reacting to Enter despite having focus.
2020-07-18 12:53:10 -04:00
Matthias Clasen 2e2336ffce text: Claim clicks when grabbing focus
If we don't, an ancestor (such a GtkListItemWidget)
may interpret the click as "I should grab focus!",
and still our focus away. This was causing hard-to-focus
entries in the property list in the inspector.
2020-07-18 12:47:47 -04:00
Matthias Clasen 76d80ef516 inspector: Add focus handling to the property editor
We want to focus the actual control here.
2020-07-18 11:55:19 -04:00
Matthias Clasen 287d80bd36 editablelabel: Stop editing on focus-out
This is the expected behavior for the main use case,
treeview-like 'edit one cell at a time'.
2020-07-18 10:45:27 -04:00
Matthias Clasen 77072b3eaa fixup editing style class 2020-07-18 10:10:28 -04:00
Matthias Clasen c7833bb090 editablelabel: Document css nodes
Just the usual.
2020-07-18 09:55:46 -04:00
Matthias Clasen 899024cef7 editablelabel: Add a style class while editing
Add the .editing style class to the editable label
while it is editing. The idea is that themes can
show a frame around the entry.
2020-07-18 09:54:55 -04:00
Matthias Clasen 7c02ae00c2 inspector: Clean up GtkInspectorGeneral
Drop the Private struct.
2020-07-18 00:31:04 -04:00
Matthias Clasen 80e29a3627 inspector: Clean up GtkInspectorMiscInfo
Drop the Private struct.
2020-07-18 00:25:46 -04:00
Matthias Clasen 26163a4f30 inspector: Clean up GtkInspectorVisual
Drop the Private struct, and do all cleanup in dispose.
2020-07-18 00:17:42 -04:00
Matthias Clasen dbd88fc210 inspector: Clean up GtkInspectorActions
Drop the Private struct, dispose properly,
and don't derive from GtkBox.
2020-07-17 23:59:49 -04:00
Matthias Clasen 2de31e4cac inspector: Clean up GtkInspectorActionEditor
Drop the Private struct, dispose properly,
and don't derive from GtkBox.
2020-07-17 23:36:05 -04:00
Matthias Clasen 1bff328895 inspector: Clean up GtkInspectorLogs
Drop the Private struct, dispose properly,
and don't derive from GtkBox.
2020-07-17 23:24:14 -04:00
Matthias Clasen facf78a5b6 inspector: Allow disposing the inspector
We were hiding the inspector when the window
is closed, but that has the side-effect of
keeping references to application windows,
so we would keep them artificially alive,
which can have side-effects.

So, make the inspector go away when closed.
2020-07-17 23:15:42 -04:00
Matthias Clasen 6b19fcd859 inspector: Properly dispose GtkInspectorWindow 2020-07-17 23:15:25 -04:00
Matthias Clasen ca784e3e1a inspector: Properly dispose GtkInspectorShortcuts 2020-07-17 23:13:29 -04:00
Matthias Clasen 314c8558d7 inspector: Properly dispose GtkInspectorListData 2020-07-17 23:13:07 -04:00
Matthias Clasen af30a7fe06 inspector: Dispose tree data properly
Another place where we were leaking children.
2020-07-17 22:54:19 -04:00
Matthias Clasen 9ffd7d1970 inspector: Dispose the recorder properly
We were leaking children here.
2020-07-17 22:54:10 -04:00
Matthias Clasen cb906c80eb inspector: Drop the recorder Private struct 2020-07-17 22:37:24 -04:00
Matthias Clasen 96ce0eb600 Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Don't use GtkColorSwatch

See merge request GNOME/gtk!2262
2020-07-18 01:17:43 +00:00
Matthias Clasen 0e476c1f28 gtk-demo: Don't use GtkColorSwatch
Making our own is 80 lines of code, so just do it.
2020-07-17 20:44:06 -04:00
Matthias Clasen f2924988db Merge branch 'ebassi/for-master' into 'master'
Fix typo in the GtkStrinFilter constructor declaration

See merge request GNOME/gtk!2261
2020-07-17 13:18:59 +00:00
Emmanuele Bassi 671435e07f Fix typo in the GtkStrinFilter constructor declaration 2020-07-17 14:16:46 +01:00
Emmanuele Bassi b17cfb9b65 Merge branch 'ebassi/for-master' into 'master'
Fix typo in the gtk-doc stanza for gtk_string_filter_new()

See merge request GNOME/gtk!2259
2020-07-17 13:09:55 +00:00
Emmanuele Bassi 0385f1aaf4 Fix typo in the gtk-doc stanza for gtk_string_filter_new() 2020-07-17 12:03:17 +01:00
Matthias Clasen 8611faf338 Merge branch 'wip/baedert/for-master' into 'master'
Wip/baedert/for master

Closes #2776

See merge request GNOME/gtk!2258
2020-07-17 10:56:16 +00:00
Timm Bäder 7e19911d3f testwidgettransforms: Fix GtkBox casts 2020-07-17 07:14:50 +02:00
Timm Bäder c1f5153f6d boxlayout: Remove unnecessary checks
The pointers passed to GtkLayoutManager::measure() are never NULL. The
ones passed to gtk_layout_manager_measure() can be, however.
2020-07-17 06:31:57 +02:00
Timm Bäder 2bd87ce771 boxlayout: Remove unused include 2020-07-17 06:27:50 +02:00
Timm Bäder de0547ede7 migration guide: Remove a stray html tag 2020-07-17 06:27:23 +02:00
Timm Bäder 14589c2a59 widget: Save a gtk_css_node_get_style call 2020-07-17 05:49:12 +02:00
Timm Bäder f678b3804d widget: Remove useless if statement
filter_value is never NULL anyway.
2020-07-17 05:49:12 +02:00
Timm Bäder 720c298786 snapshot: Use collect_default directoy in push_debug()
Instead of going through collect_debug and then doing a collect_default
anyway if the message is NULL.
2020-07-17 05:49:12 +02:00
Timm Bäder f721d2de15 debug: Remove resize highlighting
This has been broken ever since the debug highlighting moved to
inspector overlays.
2020-07-17 05:49:12 +02:00
Timm Bäder 11f07cb5ad GdkRGBA: Fix typo in documentation 2020-07-17 05:49:11 +02:00
Timm Bäder 37d7ab88dc gl renderer: Avoid 9-slicing things that can't be
The outline needs to be large enough so changing the size of the outline
does not affect the resulting blurred texture.

Fixes #2776
2020-07-17 05:49:11 +02:00
Timm Bäder 6cde64072d gl renderer: Remove outdated comment 2020-07-17 05:49:11 +02:00
Timm Bäder 6a60b0f591 gl renderer: Try to intersect rounded clips more often 2020-07-17 05:49:11 +02:00
Timm Bäder 339d9f05e4 gl renderer: Remove unused flag 2020-07-17 05:49:11 +02:00
Timm Bäder 4e4207457f adwaita: Remove header bar border radius
We get this from the window node these days.
2020-07-17 05:49:11 +02:00
Timm Bäder 46bb3e3046 icontheme: Indentation 2020-07-17 05:49:11 +02:00
Timm Bäder 34008e6aab gl renderer: Ignore rounded clip that only increase the clip
This fixes the widget factory rendering too much.

In the widget-factory, we generally have a pretty small update area (two
spinners and a progressbar). We take the extents of that as a update
area and inital clip.

However, the first clip node we see is from the toplevel window, which
essentially increases the clip again to almost the entire window.

Fix that by ignoring such cases.
2020-07-17 05:49:11 +02:00
Timm Bäder d6b3ac850d testsuite: Fix test case indentation 2020-07-17 05:49:11 +02:00
Matthias Clasen 9742200ff6 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2257
2020-07-17 03:20:20 +00:00
Matthias Clasen ec10857b84 docs: Move columns below columnview 2020-07-16 22:14:39 -04:00
Matthias Clasen 353d4d161c Cosmetic docs change 2020-07-16 22:08:15 -04:00
Matthias Clasen bcd650f169 docs: Revise the filter docs a bit 2020-07-16 21:48:08 -04:00
Matthias Clasen 72d66dfcdd docs: Revise sorter docs a bit 2020-07-16 21:45:11 -04:00
Matthias Clasen 5e97df5058 bitset: try again 2020-07-16 21:44:31 -04:00
Matthias Clasen 059d131e2b Merge branch 'wip/chergert/subclass-treeview' into 'master'
treeview: allow subclassing GtkTreeView

Closes #2936

See merge request GNOME/gtk!2256
2020-07-17 01:05:07 +00:00
Matthias Clasen 8f7c207c7c docs: Add more GtkExpression
Make GtkExpression show up in the object
hierarchy, and add the param spec and GValue
support to the docs.
2020-07-16 21:02:33 -04:00
Matthias Clasen b9e8935037 docs: Document GtkBitsetIter 2020-07-16 20:28:21 -04:00
Matthias Clasen 5f33f4ae8e docs: Add an example
Add a small example for setting up columnview sorting.
2020-07-16 20:21:21 -04:00
Matthias Clasen adf0e8b1e6 docs: Fix examples
The formatting for examples in the GtkExpression
long description was messed up.
2020-07-16 20:21:21 -04:00
Christian Hergert 7500f9b255 treeview: allow subclassing GtkTreeView
Porting code from GTK 3 without the ability to subclass GtkTreeView
directly can cause an extreme amount of pain on application developers.
It can also complicate performance when it comes to dealing with
encapsulation as the outer widget would also encapsulate the GtkScrollable
implementation from GtkTreeView, typically through GtkViewport.

Fixes #2936
2020-07-16 17:06:15 -07:00
Matthias Clasen a8d433dd26 docs: Link to GtkTreeRowReference
The list overview cross-reference table links
to all objects, except for this one.
2020-07-16 19:53:47 -04:00
Matthias Clasen ecaf6fced0 docs: Add GtkTreeExpander
We want to link to it from various places, so it needs
to be present in the docs.
2020-07-16 19:53:47 -04:00
Matthias Clasen 31a7cac4a6 Merge branch 'matthiasc/arrays' into 'master'
Matthiasc/arrays

See merge request GNOME/gtk!2253
2020-07-16 23:31:31 +00:00
Matthias Clasen 5eec736b07 multifilter: Use GdkArray for the filters 2020-07-16 18:44:25 -04:00
Matthias Clasen cf4a8e2152 multisorter: Use GdkArray for the sorters 2020-07-16 18:44:25 -04:00
Matthias Clasen 31bb969cce Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Use better api

See merge request GNOME/gtk!2254
2020-07-16 21:03:21 +00:00
Matthias Clasen f4a7c7f6bf gtk-demo: Use better api
We have a getter for the model, lets use it.
2020-07-16 16:26:41 -04:00
Benjamin Otte 495069c868 Merge branch 'wip/otte/for-master' into 'master'
Wip/otte/for master

See merge request GNOME/gtk!2251
2020-07-16 19:43:45 +00:00
Matthias Clasen dfe470475b Merge branch 'missing-exports' into 'master'
Add missing exports for GtkColumnView methods.

See merge request GNOME/gtk!2252
2020-07-16 18:52:22 +00:00
Benjamin Otte de56e892aa listitemmanager: Do a better job on double items
Previously, we would unparent the existing item that we were about
to reuse, and not the duplicate one.

Change that.
2020-07-16 20:43:16 +02:00
Benjamin Otte e518c1f2f3 stringfilter: Make the constructor take an expression
An expression is critically important for a string filter and people
should be made aware of it when constructing the filter.
2020-07-16 20:43:16 +02:00
Benjamin Otte c5ea59d7d1 gtk-demo: Don't make demos modal
That way, demo windows can be maximized and multiple demos can run at
once.

It's especially useful when using --run because the main window is
invisible then.
2020-07-16 20:43:16 +02:00
Benjamin Otte 22eccbdbb6 testsuite: Don't be too exhaustive
The test was taking over 60s on CI, that's a but much.
2020-07-16 20:43:16 +02:00
Benjamin Otte 58e85c85e4 testsuite: Add a case with escaped Latin-1 code
This came up in recent g_uri_escape() discussions.
2020-07-16 20:43:11 +02:00
Matthias Clasen 6b89148487 Merge branch 'wip/otte/vector' into 'master'
Arrays

See merge request GNOME/gtk!2197
2020-07-16 18:05:43 +00:00
Matthias Clasen ddb9e428ec Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2250
2020-07-16 17:39:16 +00:00
Andreas Persson b7fa353db2 Add missing exports for GtkColumnView methods.
GDK_AVAILABLE_IN_ALL was missing for one method in GtkColumnView and one
in GtkColumnViewColumn.
2020-07-16 18:58:41 +02:00
Matthias Clasen 87b5eadb7c treesorter tests: Add a comment
This looks like a leak, but isn't one.
Add a comment to that effect.
2020-07-16 12:14:28 -04:00
Benjamin Otte 60a09e59e8 stringlist: Convert to array
Stringlists are usually built and then never modified, and accessing
items through an array is faster.
2020-07-16 18:09:58 +02:00
Benjamin Otte 6f8e9bf3a9 snapshot: Use GdkArray for the state stack 2020-07-16 18:09:58 +02:00
Benjamin Otte 90b7b84337 array: Add a bunch of new features
* GDK_ARRAY_BY_VALUE
  #define this to get GArray-like behavior
* gdk_array_splice (v, 0, 0, NULL, 25)
  Adding items but passing NULL as the items will zero() them.
* gdk_array_set_size()
  A nicer way to call gdk_array_splice()
* constify getters
2020-07-16 18:09:58 +02:00
Benjamin Otte 088b5fc57f icontheme: Use GdkArray 2020-07-16 18:09:58 +02:00
Benjamin Otte a4cd974912 array: Add null-termination 2020-07-16 18:09:57 +02:00
Benjamin Otte 65359dcc59 snapshot: Port node list to GdkArray 2020-07-16 18:09:57 +02:00
Benjamin Otte ac8b398c50 snapshot: Move structs into .c file
They aren't used anywhere else.
2020-07-16 18:09:57 +02:00
Benjamin Otte aac2417893 Remove preallocated array code
Now with GdkArray, we can use that one instead.
2020-07-16 18:09:57 +02:00
Benjamin Otte ad8892df10 main: Use a GdkArray 2020-07-16 18:09:57 +02:00
Benjamin Otte edc7977c4e cssselector: Use GdkArray 2020-07-16 18:09:57 +02:00
Benjamin Otte 8bf8ac5076 Add GdkArray
This is a scary idea where you #define a bunch of preprocessor values
and then #include "gdkarrayimpl.c" and end up with a dynamic array for
that data type.

See https://en.wikipedia.org/wiki/X_Macro for what's going on.

What are the advantages over using GArray or GPtrArray?

 * It's typesafe
   Because it works like C++ templates, we can use the actual type of
   the object instead of having to use gpointer.

 * It's one less indirection
   instead of 2 indirections via self->array->data, this array is
   embedded, so self->array is the actual data, and just one indirection
   away. This is pretty irrelevant in general, but can be very noticable
   in tight loops.

 * It's all inline
   Because the whole API is defined as static inline functions, the
   compiler has full access to everything and can (and does) optimize
   out unnecessary calls, thereby speeding up some operations quite
   significantly, when full optimizations are enabled.

 * It has more features
   In particular preallocation allows for avoiding malloc() calls, which
   can again speed up tight loops a lot.
   But there's also splice(), which is very useful when used with
   listmodels.
2020-07-16 18:09:57 +02:00
Benjamin Otte c36cbd5140 sortlistmodel: Remove forgotten G_PARAM_CONSTRUCT_ONLY 2020-07-16 17:33:29 +02:00
Matthias Clasen ee96bc7185 multiselection tests: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen f94f325636 filterlistmodel tests: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen 6c1217dd93 filter tests: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen edb792503b printunixdialog: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen 3a43859286 Cosmetics 2020-07-16 08:54:36 -04:00
Matthias Clasen c55dd104d4 placessidebar: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen 497d137fb8 filechoosernativewin32: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen df01c5c7a4 columnlistitemfactory: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen 2d1135fba6 applicationaccels: Plug a leak
g_list_model_get_item is transfer full.
2020-07-16 08:54:36 -04:00
Matthias Clasen f54ed6f7dc columviewsorter: Add an assertion 2020-07-16 08:54:36 -04:00
Matthias Clasen b7efd896b6 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2249
2020-07-16 12:52:46 +00:00
Matthias Clasen 46eb51bc30 inspector: Avoid losing a reference
This was copying the example in the treelistrowsorter
docs that the previous commit fixed, so we apply
the same fix here.
2020-07-16 07:14:01 -04:00
Matthias Clasen 500dbaabc3 treelistrowsorter: Fix a faulty example
gtk_tree_list_row_sorter_new() consumes the
sorter, so we can't pass gtk_column_view_get_sorter(),
since that is transfer none.
2020-07-16 07:14:01 -04:00
Matthias Clasen 594ec3d822 inspector: Don't derive from GtkBox
We don't do that anymore. A bin layout
is sufficient here.
2020-07-16 07:14:01 -04:00
Matthias Clasen f280508209 inspector: Drop a Private struct
These are really not needed in the inspector.
2020-07-16 07:14:01 -04:00
Matthias Clasen 480b88c776 inspector: Drop an unused field 2020-07-16 07:14:01 -04:00
Efstathios Iosifidis a4e63905b1 Update Greek translation 2020-07-15 18:12:26 +00:00
Matthias Clasen 5666127dbc Merge branch 'matthiasc/for-master' into 'master'
inspector: Use substring matching in the property list

See merge request GNOME/gtk!2247
2020-07-15 16:52:05 +00:00
Matthias Clasen c1c110ba65 inspector: Use substring matching in the property list
This is convenient for things like "set both hexpand and
vexpand", since you can then search for "expand"
2020-07-15 11:29:06 -04:00
Florentina Mușat eb2a839892 Update Romanian translation 2020-07-15 08:58:58 +00:00
Matthias Clasen 1c537a6d2e Merge branch 'wip/jimmac/file-dialog-sidebar-color' into 'master'
Adwaita: sidebar color for file picker

See merge request GNOME/gtk!2242
2020-07-15 01:41:35 +00:00
Matthias Clasen c12261a6ec Merge branch 'wip/fix-picom-crasher' into 'master'
x11: Don't set up frame sync fence on unsupported compositors

Closes #2927

See merge request GNOME/gtk!2245
2020-07-15 01:40:49 +00:00
Matthias Clasen 5af7d6bff3 Merge branch 'idle-inhibit' into 'master'
Add support for idle inhibition on Wayland

Closes #2202

See merge request GNOME/gtk!2226
2020-07-15 01:38:55 +00:00
Matthias Clasen de0f4b0f5b Merge branch 'shortcuts-section-reflow-fix' into 'master'
Fix shortcuts section reflow

Closes #2928

See merge request GNOME/gtk!2246
2020-07-15 01:38:38 +00:00
Emmanuel Gil Peyrot 966ab1152d gtk/wayland: Add support for idle inhibition in GtkApplication
This feature was previously only supported on DBus compositors, such as
Mutter, this adds support for other compositors such as all of those
based on wlroots.

This implementation prefers the idle-inhibit Wayland protocol to the
DBus version if it is available, since the inhibitor is per-surface
instead of global it allows a finer control over which displays get
dimmed for instance.  For every case not supported by this protocol, a
fallback to the DBus version is used.

It can’t do anything if the GtkWindow isn’t passed, which might warrant
some documentation change to encourage users to not use NULL for this
argument.

This has been tested on Sway.

Fixes #2202.
2020-07-14 21:47:22 +02:00
Emmanuel Gil Peyrot 74a4432688 gdk/wayland: Add an API to inhibit and uninhibit idle
This uses the idle-inhibit protocol from wayland-protocols, to attach an
inhibitor to the GdkSurface.  The inhibit function can be called as many
times as the user wants, but the uninhibit function MUST be called as
many times to unset the idle inhibition.

This has been tested on Sway.
2020-07-14 21:47:22 +02:00
Matthias Clasen 115d0cdc07 Fix shortcuts section reflow
When this code was ported from gtk_container_get_children
to the dom api, we inadvertendly inverted the order of the
list in one place. With the dom api, we can just avoid
reversing lists altogether, so do that.

Fixes: #2928
2020-07-14 14:48:32 -04:00
Ray Strode d0ec616fba x11: Don't set up frame sync fence on unsupported compositors
Not all compositors support _NET_WM_FRAME_DRAWN.  In cases
where the compositor doesn't support _NET_WM_FRAME_DRAWN we don't
need to do all the fancy damage tracking and fence watching.

Furthermore, if the compositor doesn't support _NET_WM_FRAME_DRAWN,
it's possible that one frame will start before the previous frame has
made it through the pipeline, leading to a blown assertion.

This commit side-steps the unnecessary code and associated assertion
when _NET_WM_FRAME_DRAWN isn't supported.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/2927
2020-07-14 14:33:12 -04:00
Florentina Mușat 38cce2bb18 Update Romanian translation 2020-07-14 14:52:19 +00:00
Matthias Clasen 9cb7002b98 Merge branch 'wip/jimmac/large-title-letterspacing' into 'master'
Adwaita: revert letter-spacing for large-title

Closes #2932

See merge request GNOME/gtk!2243
2020-07-14 11:47:36 +00:00
Yuri Chornoivan eb9c91c0a9 Update Ukrainian translation 2020-07-14 10:33:34 +00:00
Jakub Steiner be07153efa Adwaita: revert letter-spacing for large-title
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/2932
2020-07-14 12:24:25 +02:00
Jakub Steiner 627ec82e60 Adwaita: sidebar color for file picker
- use menu like hovers and desaturated selected_bg_color

Partially addresses https://gitlab.gnome.org/GNOME/gtk/-/issues/1586
2020-07-14 11:37:29 +02:00
Matthias Clasen ccc34ca06c Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2241
2020-07-14 02:43:25 +00:00
Matthias Clasen 2b5dd0082d inspector: Show some information about expressions
This is not too useful, but better than nothing.
2020-07-13 20:49:56 -04:00
Matthias Clasen 7b36b339aa expression: Add some introspection
Add a few apis to peek inside expressions, mainly
for the benefit of GtkInspector and similar uses.
2020-07-13 20:19:07 -04:00
Matthias Clasen b7eb663b82 gtk-demo: Make the words demo expand
We want to fill the window here.
2020-07-13 17:54:27 -04:00
Matthias Clasen 1b28353be5 inspector: Ellipsize in the object tree
We don't want a long label to blow up the width
of the inspector window.
2020-07-13 17:32:52 -04:00
Matthias Clasen a07c030d02 inspector: Fix up input enum names
We've recently added and removed a few values in these
enumerations. Keep the names in sync, so we don't show
nonsense.
2020-07-13 17:13:43 -04:00
Matthias Clasen 339cccdf53 NEWS: Updates and fixes 2020-07-13 17:10:22 -04:00
Matthias Clasen 577126e99c Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2240
2020-07-13 20:48:08 +00:00
Matthias Clasen 125ea5ee4a treeexpander: Be focusable
We need to be focusable so that we can take focus
if the child doesn't.
2020-07-13 15:06:35 -04:00
Matthias Clasen 3c5afc06d1 searchbar: Set a focus vfunc
We don't want to take focus ourselves here.
2020-07-13 15:06:08 -04:00
Matthias Clasen f87c15f4f9 Merge branch 'wip/jimmac/file-dialog-sidebar-color' into 'master'
Adwaita: sidebar color for file picker

Closes #1586

See merge request GNOME/gtk!2238
2020-07-13 16:31:07 +00:00
Jakub Steiner fe5c0e2fe3 Adwaita: sidebar color for file picker
- avoid using the selected blue for the sidebar

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/1586
2020-07-13 17:03:55 +02:00
Matthias Clasen c8421cfd82 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2236
2020-07-13 14:38:03 +00:00
Matthias Clasen fbf99b8d65 Merge branch 'wip/carlosg/windowhandle-gesture-state' into 'master'
gtkwindowhandle: Only claim gesture on action

See merge request GNOME/gtk!2237
2020-07-13 14:32:06 +00:00
Yuri Chornoivan 57312c9b79 Update Ukrainian translation 2020-07-13 14:18:40 +00:00
Carlos Garnacho 35d2539ef8 gtkwindowhandle: Only claim gesture on action
The press gesture does not need to set claimed state just for n-press
tracking, it will however reset all other click gestures on each press
if the event gets propagated all the way up.

Fixes tracking of multi-press in gestures in widgets that are children
of the window handle. E.g. the headerbar listview in the "File browser"
gtk4-demo demo.
2020-07-13 15:48:12 +02:00
Matthias Clasen 08a4f4552c Give the inspector a devel header too
Lets clearly communicate that we're unstable.
2020-07-13 08:28:02 -04:00
Matthias Clasen 6502d3669f print-editor: Set the devel style class
Lets clearly communicate that we're unstable.
2020-07-13 08:27:51 -04:00
Matthias Clasen 53831e67a7 Integrate the new icons
Install and use the node-editor and print-editor icons.
2020-07-13 07:30:46 -04:00
Jakub Steiner e742fc1206 demos: icons for Print and Node Editors
- probably needs meson build hooks
2020-07-13 07:30:46 -04:00
Piotr Drąg 4ef5ee23e6 Update POTFILES.in 2020-07-13 13:17:37 +02:00
Matthias Clasen 4a8330fda0 Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Work harder to filter the tree

See merge request GNOME/gtk!2234
2020-07-12 23:16:35 +00:00
Matthias Clasen b4096cee64 gtk-demo: Work harder to filter the tree
Arrange for an item to be visible if it either
matches the filter or has children that do.
2020-07-12 18:26:56 -04:00
Matthias Clasen 032302c358 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2233
2020-07-12 21:23:07 +00:00
Matthias Clasen a888e1cb65 demo: Clear filter when search is stopped
When the search entry disappears on Escape,
reset the search string to "", so we don't
end up with a filtered list and no obvious
way to remove the filtering.
2020-07-12 16:47:51 -04:00
Matthias Clasen c80b33b2ad gtk-demo: Make the search bar appear for typing
Having the search bar present from the start is
a bit jarring. Make it appear when called for.
2020-07-12 16:26:17 -04:00
Matthias Clasen f32239df1f searchbar: Add a key-capture-widget property
This is handy to set up this relationship in ui files,
and also makes it accessible in the inspector.
2020-07-12 16:25:48 -04:00
Matthias Clasen 22c1b541df Merge branch 'wip/sadiq/demo-filter' into 'master'
demo: Add a search filter

See merge request GNOME/gtk!2232
2020-07-12 19:04:00 +00:00
Matthias Clasen 78a59c95fe Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2231
2020-07-12 16:59:10 +00:00
Mohammed Sadiq 7583d48266 demo: Add a search filter 2020-07-12 22:19:40 +05:30
Matthias Clasen f1188aaeac Fix gtk_file_chooser_error_stack_set_custom_error
This never worked, due to a typo.
2020-07-12 12:15:08 -04:00
Matthias Clasen 4dac5c222f Drop GtkFileChooserEmbed
This private interface is no longer used.
2020-07-12 12:15:08 -04:00
Matthias Clasen 0145809a94 filechooserdialog: Stop using ::response-requested
Replace the ::response-requested signal by an action.
2020-07-12 12:15:08 -04:00
Matthias Clasen 2e6b8810c0 filechooserdialog: Stop using the embed interface
Just call private GtkFileChooserWidget api. There
is no real justification for diverting this through
an extra interface.
2020-07-12 10:59:49 -04:00
Matthias Clasen d8abcdb5a1 Remove unused includes
Only GtkFileChooserWidget and GtkFileChooserDialog
use the GtkFileChooserEmbed interface.
2020-07-12 10:59:31 -04:00
Matthias Clasen 65ecfa20dd filechooserwidget: Use dropdown api better
We now have GtkStringList, so we can implement
the choice api a little cleaner with it.
2020-07-12 10:58:33 -04:00
Matthias Clasen aa5ab02166 filechooserwidget: Remove homegrown profiling
We have sysprof support now, so we no longer have
to use this homegrown profiler.
2020-07-12 10:58:33 -04:00
Matthias Clasen 7ddbbb50ff Merge branch 'drop-file-system' into 'master'
Drop file system

See merge request GNOME/gtk!2229
2020-07-12 14:41:01 +00:00
Matthias Clasen f2eb036119 Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Make style apply in the file browser

See merge request GNOME/gtk!2230
2020-07-12 13:58:30 +00:00
Matthias Clasen 8a8b96bf4b Drop GtkFileSystem
It is no longer used.
2020-07-12 09:49:31 -04:00
Matthias Clasen bdcda2d8f0 filechooserwidget: Stop using GtkFileSystem
Just use gio directly.
2020-07-12 09:49:31 -04:00
Matthias Clasen ef3f997d55 filechooser: Drop get_file_system from the interface
This is no longer used.
2020-07-12 09:49:31 -04:00
Matthias Clasen b41d380230 filechooserbutton: Stop using GtkFileSystem
Just use gio directly.
2020-07-12 09:49:31 -04:00
Matthias Clasen 0210850e86 Reduce includes of gtkfilesystem.h
Move a few non-filesystem helpers to gtkfileutils.h,
and drop the include in all the places where it isn't needed.
2020-07-12 09:12:43 -04:00
Matthias Clasen 053223bf65 pathbar: Stop using GtkFileSystem
This is just a thin wrapper around some gio functionality
these days, and we want to get rid of it.
2020-07-12 09:12:43 -04:00
Matthias Clasen 746b84cc0f gtk-demo: Make style apply in the file browser
Commit 5afe6f7825 claims to make this demo
'look good', but it failed to actually make its
css apply. Now it really looks good.
2020-07-12 08:11:42 -04:00
Matthias Clasen f1ad883e00 pathbar: Drop the Private struct 2020-07-11 17:23:55 -04:00
Matthias Clasen 191e0e8d5e Merge branch 'matthiasc/for-master' into 'master'
Fix the build with clang

See merge request GNOME/gtk!2225
2020-07-10 19:29:18 +00:00
Matthias Clasen 55217e2181 Fix the build with clang
clang doesn't allow G_GNUC_FALLBACK in dead code.
Seems silly, but what can we do.
2020-07-10 13:21:23 -04:00
Emmanuele Bassi 7c8cd23c5f Merge branch 'ebassi/ci-timeout' into 'master'
Ebassi/ci timeout

See merge request GNOME/gtk!2223
2020-07-10 17:01:56 +00:00
Matthias Clasen 6aafb81702 Merge branch 'ci-tweaks' into 'master'
ci: Use lsan again

See merge request GNOME/gtk!2224
2020-07-10 16:13:48 +00:00
Emmanuele Bassi 0578422612 build: Restructure the tests to use dictionaries
Instead of an array of arrays, let's use an array of dictionaries; it's
easier to add optional keys without requiring to remember where to put
empty arrays.
2020-07-10 16:32:15 +01:00
Emmanuele Bassi ad04da84c9 Add the filtermodel-exhaustive test to the slow suite
This increases the default timeout.
2020-07-10 16:16:15 +01:00
Emmanuele Bassi 333b013f7f Increase the default timeout for slow tests
If a test is part of the 'slow' test suite, we should increment the
default timeout to compensate.
2020-07-10 16:13:37 +01:00
Matthias Clasen b3dc517565 ci: Use lsan again
Turning it off didn't fix the crashes; and we allow
the asan build to fail anyway now. And the leak reports
are useful whenever it doesn't crash.
2020-07-10 11:11:42 -04:00
Emmanuele Bassi 70e4dabe89 ci: Increase the timeout multiplier
We do have some slow tests.
2020-07-10 16:08:59 +01:00
Emmanuele Bassi d3443d6f2a ci: Use the timeout multiplier from the environment
When running our test suite on our CI infrastructure.
2020-07-10 16:08:14 +01:00
Matthias Clasen a508f68044 Merge branch 'asan-ci' into 'master'
Asan ci

See merge request GNOME/gtk!2214
2020-07-10 13:04:34 +00:00
Matthias Clasen f191b64bbc Disable lsan for now
The leak sanitizer causes on average 3-4 tests
to segfault during a testsuite run. Disable it
for now to see if we can get a successful
testsuite run with asan alone.
2020-07-10 07:32:48 -04:00
Matthias Clasen e9efe77839 Merge branch 'wip/Jehan/gio-querymodules-pkg-config-master' into 'master'
build-aux: search various Glib/GIO utilities in .pc file.

See merge request GNOME/gtk!2129
2020-07-09 23:53:25 +00:00
Matthias Clasen d98c0d32f2 ci: Add a build with asan
Run our testsuite under asan. We do this in a
separate build, since we need to turn off
introspection to make the build succeed.

As Michael Catanzaro pointed out, this requires a
privileged runner in order to use kernel apis.
2020-07-09 19:43:06 -04:00
Matthias Clasen dfa2dcceb8 Merge branch 'matthiasc/for-master' into 'master'
x11: Plug a memory leak

See merge request GNOME/gtk!2222
2020-07-09 23:06:37 +00:00
Matthias Clasen d441e7106b x11: Plug a memory leak
Don't leak atoms when we're storing the clipboard.
2020-07-09 18:19:32 -04:00
Benjamin Otte 4cd92f979c Merge branch 'wip/otte/for-master' into 'master'
Wip/otte/for master

See merge request GNOME/gtk!2221
2020-07-09 21:34:02 +00:00
Benjamin Otte d1a068e5b1 sorter: Remove a return_if_fail()
It's too expsensive.
2020-07-09 22:29:36 +02:00
Benjamin Otte 4d90846182 testsuite: Be more exhaustive
Create larger source models in tests, so that we hit the incremental
batch size more often and have a higher chance to expose bugs there.
2020-07-09 22:29:36 +02:00
Benjamin Otte 986f721938 filterlistmodel: Don't filter out every 513th element
Incremental filtering would skip every 513th element due to an
off-by-one error.

Test included
2020-07-09 22:29:36 +02:00
Matthias Clasen 7903246355 Ignore more leaks in asan
These showed up in ci. The atk-bridge will
be gone before too long anyway. Since we
may not have debug symbols in ci, just at
the so's.
2020-07-09 16:18:07 -04:00
Matthias Clasen 0252ae2be3 Merge branch 'wip/carlosg/range-autoscroll' into 'master'
gtkrange: group gestures the right way around

See merge request GNOME/gtk!2220
2020-07-09 20:05:07 +00:00
Matthias Clasen fa90e42a38 ci: Set LSAN_OPTIONS for tests
When running the testsuite with the address sanitizer,
many of our dependencies cause it to report cause it
to report memory leaks, causing tests to fail.
Therefore, point the leak sanitizer at a list of
suppressions. The list is kept in the lsan.supp
file in git.
2020-07-09 15:07:50 -04:00
Matthias Clasen 2d36109565 ci: Use the fedora:v20 image
This image includes libasan and libubsan.
2020-07-09 15:07:50 -04:00
Matthias Clasen de8258171a ci: Mention image layering in the README 2020-07-09 15:07:50 -04:00
Matthias Clasen 2ed6224778 ci: Add libasan and libubsan to the image
Add libasan and libubsan to fedora-base:v20,
and build fedora:20 on top of it.

This is so we can build and run the tests with
the address and undefined behavior sanitizers.
2020-07-09 15:07:50 -04:00
Carlos Garnacho e1a0171094 gtkrange: group gestures the right way around
The gtk_gesture_group() call is not a commutative operation, it
takes two gestures, maybe detaches the first one from its current
group, and adds it to the same group than the second gesture.

With the flipped argument order here, GtkRange was actually detaching
the same gesture in order to group it with a second one two times, so
the desired effect to group all 3 gestures was not achieved.

Fixes autoscroll as the drag gesture is now actually grouped with the
click one, so drag offsets can be accessed from the autoscroll
timeout.
2020-07-09 20:49:25 +02:00
Matthias Clasen 395521f3d3 x11: Plug a memory leak
Don't leak atoms when we're storing the clipboard.
2020-07-09 13:52:53 -04:00
Matthias Clasen 8c95a84ea4 Merge branch 'matthiasc/for-master' into 'master'
css: Plug a memory leak

Closes #2921

See merge request GNOME/gtk!2219
2020-07-09 17:19:57 +00:00
Matthias Clasen 75db19c789 css: Plug a memory leak
When a rule has no styles, we don't add it
to our ruleset. Since we are not adopting
the selectors in this case, we must free them.

Fixes: #2921
2020-07-09 12:14:18 -04:00
Matthias Clasen f00d2b30bb Merge branch 'wip/carlosg/scrollbar-fixes' into 'master'
Scrollbar fixes

Closes #2879

See merge request GNOME/gtk!2216
2020-07-09 15:56:13 +00:00
Carlos Garnacho c0c5ce2f9b gdk/x11: Ignore regular crossing events while in implicit grabs
If we create an implicit grab on a surface, leave the surface, and
release the button, we would get 2 XI_Leave events, one with mode
XINotifyNormal when the pointer leaves the surface, and another with
mode XINotifyUngrab when the button is released.

Meanwhile, the upper layers rely on crossing events being paired,
and particularly in no crossing event being sent until the implicit
grab is dismissed (either by releasing it, or via more pervasive
grabs).

Ignoring the set of XINotifyNormal events while an implicit grab
is active adapts the X11 backend to this behavior. If the grab were
released or taken away by another grab, a crossing event with one
of the other XINotify*Grab/XINotify*Ungrab will be generated.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/2879
2020-07-09 17:02:07 +02:00
Matthias Clasen ee9f9ae05e Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2212
2020-07-09 14:49:42 +00:00
Matthias Clasen 387649ded4 Merge branch 'ebassi/subprojects-depth' into 'master'
Use depth=1 for cloning sub-projects

See merge request GNOME/gtk!2215
2020-07-09 14:39:01 +00:00
Matthias Clasen be12131d74 Merge branch 'file-chooser-api-cleanup-2' into 'master'
File chooser api cleanup 2

See merge request GNOME/gtk!2213
2020-07-09 14:31:14 +00:00
Carlos Garnacho 896ebdc9d7 gtkscrolledwindow: Look up correctly target in captured motion events
Check correctly that the captured motion events are emitted towards the
content or one of the scrollbars, in order to have it set the expected
"over" state depending on whether the drag begins from the scrolledwindow
content or one of the scrollbars.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/2879
2020-07-09 16:10:55 +02:00
Matthias Clasen bc58bd0b83 NEWS: Updates 2020-07-09 09:29:09 -04:00
Matthias Clasen 8d4c87876b Add a suppression file for asan
This can be used similar to valgrind suppressions:

LSAN_OPTIONS=suppressions=`pwd`/lsan.supp meson  tests -Cbuild
2020-07-09 09:29:09 -04:00
Matthias Clasen cebc99ddc7 tests: Plug some more memory leaks
These showed up under asan.
2020-07-09 09:29:09 -04:00
Matthias Clasen 1b62203f18 cups: Plug a memory leak
This showed up under asan.
2020-07-09 09:29:09 -04:00
Matthias Clasen 06dd8c2cfd Merge branch 'wayland_surface_app_id_changing' into 'master'
add a way to change the application_id of a toplevel wayland GdkSurface

See merge request GNOME/gtk!2205
2020-07-09 13:28:07 +00:00
Emmanuele Bassi 5da21ca4dc Use depth=1 for cloning sub-projects
We don't really need the full history and branches when building
sub-projects.

This should shave some bandwidth and time in our CI pipeline as well.
2020-07-09 14:07:14 +01:00
Matthias Clasen 3e16ef33b0 Merge branch 'fix-levelbar-layout' into 'master'
levelbar: Chainup to parent buildable when handling custom tags

See merge request GNOME/gtk!2200
2020-07-09 11:42:33 +00:00
Matthias Clasen 2746a2d929 filechooser: Drop the ::selection-changed signal
This signal does not work on native file choosers,
and it exposes internals of the widget that should
not be public. And it is just not very interesting.
2020-07-09 02:06:31 -04:00
Matthias Clasen e31bacf7be filechooser: Drop the ::current-folder-changed signal
This signal does not work on native file choosers,
and it exposes internals of the widget that should
not be public. And it is just not very interesting.
2020-07-09 01:48:33 -04:00
Matthias Clasen 911ae64931 filechoosernative: Update docs
Remove mention of things that are no longer
in the filechooser api.
2020-07-09 01:44:09 -04:00
Matthias Clasen 99a0b35705 filechooser: Drop the ::file-activated signal
This signal does not work on native file choosers,
and it exposes internals of the widget that should
not be public. And it is just not very interesting.
2020-07-09 01:40:08 -04:00
Matthias Clasen 89bf8af878 filechooser: Make get_files return a list model
Like the other list getters in this interface,
make gtk_file_chooser_get_files() return a
list model.
2020-07-09 01:29:20 -04:00
Matthias Clasen f3744c991a Cosmetics 2020-07-09 01:02:21 -04:00
Matthias Clasen dcee15c0f1 filechooser: Drop gtk_file_chooser_[un]select_file
Most use cases for these apis can be handled with
gtk_file_chooser_set_file and/or
gtk_file_chooser_set_current_folder.
2020-07-09 00:50:03 -04:00
Matthias Clasen 2321e9de05 filechooser: Drop gtk_file_chooser_[un]_select_all
For now, we just remove them as public api, they are
still used internally.
2020-07-09 00:50:03 -04:00
Matthias Clasen 73dcda460f tests: Stop using file chooser apis that are going away
gtk_file_chooser_[un]select_all are going away, stop
using them.
2020-07-09 00:50:03 -04:00
Matthias Clasen 0f8bc67a98 docs: Add gtk_file_chooser_get_shortcut_folders 2020-07-09 00:50:03 -04:00
Matthias Clasen 379d830123 Merge branch 'printing-portal-fix-master' into 'master'
Remember to call print_cb even if print operation is cancelled.

Closes #2917

See merge request GNOME/gtk!2211
2020-07-09 04:40:34 +00:00
Matthias Clasen bc8bc68b80 Add a suppression file for asan
This can be used similar to valgrind suppressions:

LSAN_OPTIONS=suppressions=`pwd`/lsan.supp meson  tests -Cbuild
2020-07-09 00:33:35 -04:00
Matthias Clasen 8c4df51a14 tests: Plug some more memory leaks
These showed up under asan.
2020-07-09 00:33:14 -04:00
Matthias Clasen 06d67d2384 cups: Plug a memory leak
This showed up under asan.
2020-07-09 00:32:17 -04:00
Casey Jao cc8bb5fc54 Remember to call print_cb even if print operation is cancelled.
Closes #2917.
2020-07-08 23:32:43 -04:00
Matthias Clasen 8fb1e33d0f Merge branch 'matthiasc/for-master' into 'master'
directorylist: Fix file monitoring implementation

See merge request GNOME/gtk!2209
2020-07-09 02:08:53 +00:00
Matthias Clasen 0dc946da63 testsuite: Assorted leak fixes
All found by asan.
2020-07-08 17:44:49 -04:00
Matthias Clasen 26a23d3e56 shortcuttrigger: Fix some leaks in error paths
Found while running the testsuite under asan.
2020-07-08 17:44:42 -04:00
Matthias Clasen 766f4bc8fe css: Fix some memory leaks in error paths
Found while running the testsuite under asan.
2020-07-08 17:44:36 -04:00
Matthias Clasen 3d008d5929 picture: Don't leak alternative-test
This leak showed up while running the testsuite
under asan.
2020-07-08 17:44:29 -04:00
Matthias Clasen 0546e26434 bookmarklist: Don't leak uris
This leak showed up in multiple places while
running the testsuite under asan.
2020-07-08 17:44:23 -04:00
Matthias Clasen e6d8eedc00 testsuite: Fix a memory leak in the bitmask tests
This was showing up when running under asan.
2020-07-08 17:44:16 -04:00
Matthias Clasen 13b37b0ba4 gsk: Fix a transform leak
This was found by running our testsuite under asan.
2020-07-08 17:44:08 -04:00
Matthias Clasen 779c71b66d testsuite: Fix some memory leaks reported by asan 2020-07-08 15:09:13 -04:00
Matthias Clasen 8e73d007f5 testsuite: Fix an asan error
asan complains that some of the memorytexture tests
read past limits. Avoid that.
2020-07-08 15:09:08 -04:00
Matthias Clasen e376d638fb directorylist: Fix file monitoring implementation
The while loops were never advancing the iterator.
Oops.
2020-07-08 15:08:53 -04:00
Yuri Chornoivan 52982a88aa Update Ukrainian translation 2020-07-08 18:28:01 +00:00
Baurzhan Muftakhidinov 422c1d9c0d Update Kazakh translation 2020-07-08 17:44:28 +00:00
Daniel Șerbănescu ccc8ad8700 Update Romanian translation 2020-07-08 16:22:30 +00:00
Florentina Mușat 6b0eb970d8 Update Romanian translation 2020-07-08 16:17:12 +00:00
Florentina Mușat 775e35865c Update Romanian translation 2020-07-08 08:33:20 +00:00
Matthias Clasen 49ce680d53 Merge branch 'directorylist-monitor' into 'master'
directorylist: Add monitoring

See merge request GNOME/gtk!2207
2020-07-08 02:25:46 +00:00
Matthias Clasen 463f3d3a52 directorylist: Add monitoring
Add a GtkDirectoryList:monitored property, and
keep a file monitor if it is set to TRUE. To ensure
that the list reflects reality, we reload the directory
when monitoring is turned on after the fact. This means
that turning monitoring is expensive, while turning it
off is cheap, so we default to monitoring being on.
2020-07-07 21:21:41 -04:00
Jordi Mas f6347f18b0 Fixes to Catalan translations 2020-07-07 20:24:24 +02:00
Yuri Chornoivan 2e959fe300 Update Ukrainian translation 2020-07-07 18:03:32 +00:00
Yuri Chornoivan 56f771ba29 Update Ukrainian translation 2020-07-07 17:55:52 +00:00
Baurzhan Muftakhidinov 32e96215b4 Update Kazakh translation 2020-07-07 17:21:22 +00:00
Matthias Clasen 86f800e11d Merge branch 'inspector-navigation' into 'master'
Inspector navigation

See merge request GNOME/gtk!2201
2020-07-07 17:04:51 +00:00
Matthias Clasen 4d371b2b16 inspector: Fix property list styling
We use dropdowns here now, so style them.

Also, avoid the swoosh when switching to the
property list, when everything shrinks.
2020-07-07 11:21:42 -04:00
Caolán McNamara 7e97c2513f gtk#767 add a way to change the application_id of a toplevel wayland GdkSurface
so LibreOffice can reuse toplevels and get the right task icons

references;
 https://gitlab.gnome.org/GNOME/gtk/-/issues/767
 https://lists.freedesktop.org/archives/wayland-devel/2019-July/040704.html
 https://gitlab.freedesktop.org/wayland/wayland-protocols/commit/e0d6ad1d5e7e80321285a9b14ca3329289eb02e6
 https://bugs.documentfoundation.org/show_bug.cgi?id=125934
 https://bugzilla.redhat.com/show_bug.cgi?id=1334915
 https://bugreports.qt.io/browse/QTBUG-77182
2020-07-07 15:56:12 +01:00
Emmanuele Bassi 2bf5a150e6 Merge branch 'issue-2915' into 'master'
Issue 2915

Closes #2915

See merge request GNOME/gtk!2204
2020-07-07 11:48:07 +00:00
Emmanuele Bassi 18c87faaa5 Annotate string array
Fixes: #2915
2020-07-07 12:06:28 +01:00
Emmanuele Bassi fdeda388bf Fix "not nullable" annotation 2020-07-07 12:03:44 +01:00
Stefano Facchini ea2c27c640 levelbar: Chainup to parent buildable when handling custom tags
This is necessary to handle <layout> tags.
2020-07-07 09:34:00 +02:00
Matthias Clasen dfc04a590d inspector: Reshuffle the sidebar
Move the sidebar in the object page below the
object header, for a more logical hierarchy.
2020-07-07 02:05:18 -04:00
Matthias Clasen fe5b364675 inspector: Drop unused properties
The individual pages no longer need the object tree
to show object details, this works with the window
now.
2020-07-07 01:25:21 -04:00
Matthias Clasen 9b73c55559 Merge branch 'patch-1' into 'master'
Fix typo: Filer -> Filter

See merge request GNOME/gtk!2203
2020-07-07 05:08:19 +00:00
Matthias Clasen 0b38a0663d inspector: Add dom-like navigation controls
Maintain a stack of objects, and add ˂˅˄˃ buttons
that navigate this stack, as well as the widget
tree and list models.
2020-07-07 00:51:18 -04:00
Matthias Clasen e5c0716293 inspector: Remove an unused field 2020-07-07 00:48:43 -04:00
Matthias Clasen 54a3293cad stack: Fix handling of GtkStackPage:visible
The stack wasn't updating its visible-child when
the stack pages visible property changes. This
showed up in the inspector, when showing the details
for a list model item.
2020-07-07 00:48:43 -04:00
Yuri Chornoivan 818287a7ce Update Ukrainian translation 2020-07-07 04:45:03 +00:00
Yuri Chornoivan 59119cd898 Fix typo: Filer -> Filter 2020-07-07 04:41:44 +00:00
Jehan 2fb755e0c9 build-aux: fallback to default glib-compile-schemas & gio-querymodules.
The pkg-config variables have been added in GLib 2.62.0. Let's fallback
to default names for these tools in such case (`pkg-config` still
returns a 0 return value, but with empty output for absent variables).
2020-06-28 12:48:27 +02:00
Jehan cd096819d8 build-aux: search various Glib/GIO utilities in .pc file.
Some distributions are renaming Glib/GIO utilities for multi-arch
reasons so pkg-config variables have been added to find the correct name
of a tool. GTK+ should use these variables instead of searching in PATH.
See glib#1796.
2020-06-28 12:46:32 +02:00
223 changed files with 11810 additions and 11900 deletions
+18 -2
View File
@@ -19,8 +19,8 @@ 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:v17"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v20"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19"
@@ -180,6 +180,22 @@ static-scan:
- _scan_build/meson-logs
allow_failure: true
# Run tests with the address sanitizer. We need to turn off introspection,
# since it is incompatible with asan
asan-build:
image: $FEDORA_IMAGE
tags: [ privileged ]
stage: analysis
variables:
script:
- CC=clang meson --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=false _build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build wayland
artifacts:
paths:
- _build/meson-logs
allow_failure: true
reference:
image: $DOCS_IMAGE
stage: docs
View File
+9
View File
@@ -35,4 +35,13 @@ branch, as well as their available versions.
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
- [ ] Open a merge request with your changes and let it run
### Checklist for Adding a new dependency to a CI image
Our images are layered, and the base (called fedora-base) contains
all the rpm payload. Therefore, adding a new dependency is a 2-step
process:
1. [ ] Build and upload fedora-base:$version+1
1. [ ] Build and upload fedora:$version+1 based on fedora-base:version+1
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry
+2
View File
@@ -41,12 +41,14 @@ RUN dnf -y install \
itstool \
json-glib-devel \
lcov \
libasan \
libattr-devel \
libepoxy-devel \
libffi-devel \
libmount-devel \
librsvg2 \
libselinux-devel \
libubsan \
libXcomposite-devel \
libXcursor-devel \
libXcursor-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}
+6
View File
@@ -7,10 +7,14 @@ srcdir=$( pwd )
builddir=$1
backend=$2
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
case "${backend}" in
x11)
xvfb-run -a -s "-screen 0 1024x768x24" \
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
@@ -30,6 +34,7 @@ case "${backend}" in
export WAYLAND_DISPLAY=wayland-5
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
@@ -48,6 +53,7 @@ case "${backend}" in
export BROADWAY_DISPLAY=:5
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
+77
View File
@@ -1,3 +1,80 @@
Overview of Changes in GTK 3.99.0
=================================
* Add GtkEditableLabel
* Add GtkBookmarkList, a list model for bookmarks
* Add GtkStringList, a list model for strings
* Add GtkBitset, and use it for representing selections
* GtkTreeView:
- Make cell editing work again
* GtkSpinButton:
- Make autosizing work again
* Printing:
- Use GtkDropDown in the print dialog
* GtkApplication
- Support opening files on OS X
* GtkFileChooser:
- Fix libcloudproviders support
- Turn GtkFileFilter into a GtkFilter
- Simplify the api
* GtkGridView, GtkListView:
- Improve scrolling behavior
- Autoscroll and autoexpand during DND
* GtkScrolledWindow:
- Make autoscrolling work again
* GtkFilterListModel:
- Add incremental filtering
* GtkEntry:
- Make entry completion work again
- Drop action support from GtkEntryCompletion
* Inspector:
- Improve list model support
- Add direct navigation between objects
* GDK:
- Compress scroll events
- Keep a scroll history
- Clean up GdkDevice api
- Improve frame clock accuracy
* GSK:
- Use GL_ARB_framebuffer_object
* gtk-demo:
- Add incremental refill to the color grid
- Improve performance of the color grid
- Add an incrementally filtering word list
- Improve the sidebar
* Install print-editor as another demo
* Translation updates
Basque
Catalan
Chinese
Japanese
Kazakh
Lithuanian
Polish
Romanian
Spanish
Turkish
Ukrainian
Overview of Changes in GTK 3.98.5
=================================
+45 -31
View File
@@ -1,29 +1,38 @@
{
"app-id": "org.gtk.WidgetFactory4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-widget-factory",
"tags": ["devel", "development", "nightly"],
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
"app-id" : "org.gtk.WidgetFactory4",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-widget-factory",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
"--talk-name=org.gtk.vfs",
"--talk-name=org.gtk.vfs.*"
],
"cleanup": [
"cleanup" : [
"/include",
"/lib/pkgconfig", "/share/pkgconfig",
"/lib/pkgconfig",
"/share/pkgconfig",
"/share/aclocal",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules": [
"modules" : [
{
"name" : "wayland",
"buildsystem" : "autotools",
@@ -39,18 +48,18 @@
]
},
{
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources": [
"sources" : [
{
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
}
]
},
@@ -58,7 +67,7 @@
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
@@ -73,7 +82,7 @@
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
@@ -85,18 +94,23 @@
]
},
{
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"name" : "gtk",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources": [
"sources" : [
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
]
],
"build-options" : {
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''"
}
}
}
+15 -3
View File
@@ -15,7 +15,13 @@ if 'DESTDIR' not in os.environ:
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
print('Compiling GSettings schemas...')
subprocess.call(['glib-compile-schemas',
glib_compile_schemas = subprocess.check_output(['pkg-config',
'--variable=glib_compile_schemas',
'gio-2.0']).strip()
if not os.path.exists(glib_compile_schemas):
# pkg-config variables only available since GLib 2.62.0.
glib_compile_schemas = 'glib-compile-schemas'
subprocess.call([glib_compile_schemas,
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
print('Updating icon cache...')
@@ -24,8 +30,14 @@ if 'DESTDIR' not in os.environ:
print('Updating module cache for print backends...')
os.makedirs(gtk_printmodule_dir, exist_ok=True)
subprocess.call(['gio-querymodules', gtk_printmodule_dir])
gio_querymodules = subprocess.check_output(['pkg-config',
'--variable=gio_querymodules',
'gio-2.0']).strip()
if not os.path.exists(gio_querymodules):
# pkg-config variables only available since GLib 2.62.0.
gio_querymodules = 'gio-querymodules'
subprocess.call([gio_querymodules, gtk_printmodule_dir])
print('Updating module cache for input methods...')
os.makedirs(gtk_immodule_dir, exist_ok=True)
subprocess.call(['gio-querymodules', gtk_immodule_dir])
subprocess.call([gio_querymodules, gtk_immodule_dir])
+78 -12
View File
@@ -597,6 +597,83 @@ css_button_new (const char *class)
return button;
}
typedef struct
{
GtkWidget parent_instance;
GdkRGBA color;
} ColorSwatch;
typedef struct
{
GtkWidgetClass parent_class;
} ColorSwatchClass;
G_DEFINE_TYPE (ColorSwatch, color_swatch, GTK_TYPE_WIDGET)
static GdkContentProvider *
color_swatch_drag_prepare (GtkDragSource *source,
double x,
double y,
ColorSwatch *swatch)
{
return gdk_content_provider_new_typed (GDK_TYPE_RGBA, &swatch->color);
}
static void
color_swatch_init (ColorSwatch *swatch)
{
GtkDragSource *source = gtk_drag_source_new ();
g_signal_connect (source, "prepare", G_CALLBACK (color_swatch_drag_prepare), swatch);
gtk_widget_add_controller (GTK_WIDGET (swatch), GTK_EVENT_CONTROLLER (source));
}
static void
color_swatch_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
ColorSwatch *swatch = (ColorSwatch *)widget;
float w = gtk_widget_get_width (widget);
float h = gtk_widget_get_height (widget);
gtk_snapshot_append_color (snapshot, &swatch->color,
&GRAPHENE_RECT_INIT(0, 0, w, h));
}
void
color_swatch_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum_size,
int *natural_size,
int *minimum_baseline,
int *natural_baseline)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum_size = *natural_size = 48;
else
*minimum_size = *natural_size = 32;
}
static void
color_swatch_class_init (ColorSwatchClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
widget_class->snapshot = color_swatch_snapshot;
widget_class->measure = color_swatch_measure;
gtk_widget_class_set_css_name (widget_class, "colorswatch");
}
static GtkWidget *
color_swatch_new (const char *color)
{
ColorSwatch *swatch = g_object_new (color_swatch_get_type (), NULL);
gdk_rgba_parse (&swatch->color, color);
return GTK_WIDGET (swatch);
}
static GtkWidget *window = NULL;
GtkWidget *
@@ -670,18 +747,7 @@ do_dnd (GtkWidget *do_widget)
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), box3);
for (i = 0; colors[i]; i++)
{
GdkRGBA rgba;
GtkWidget *swatch;
gdk_rgba_parse (&rgba, colors[i]);
swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
"rgba", &rgba,
"selectable", FALSE,
NULL);
gtk_box_append (GTK_BOX (box3), swatch);
}
gtk_box_append (GTK_BOX (box3), color_swatch_new (colors[i]));
gtk_box_append (GTK_BOX (box3), css_button_new ("rainbow1"));
gtk_box_append (GTK_BOX (box3), css_button_new ("rainbow2"));
+5 -64
View File
@@ -676,7 +676,7 @@ create_color_grid (void)
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_sor3_list_model_new (gtk_color_list_new (0), NULL));
model = G_LIST_MODEL (gtk_sort_list_model_new (gtk_color_list_new (0), NULL));
selection = G_LIST_MODEL (gtk_multi_selection_new (model));
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
@@ -835,54 +835,6 @@ update_selection_average (GListModel *model,
g_object_unref (color);
}
static int
compare_red (gconstpointer a,
gconstpointer b,
gpointer unused)
{
GtkColor *colora = (GtkColor *) a;
GtkColor *colorb = (GtkColor *) b;
if (colora->color.red < colorb->color.red)
return GTK_ORDERING_LARGER;
else if (colora->color.red > colorb->color.red)
return GTK_ORDERING_SMALLER;
else
return GTK_ORDERING_EQUAL;
}
static int
compare_green (gconstpointer a,
gconstpointer b,
gpointer unused)
{
GtkColor *colora = (GtkColor *) a;
GtkColor *colorb = (GtkColor *) b;
if (colora->color.green < colorb->color.green)
return GTK_ORDERING_LARGER;
else if (colora->color.green > colorb->color.green)
return GTK_ORDERING_SMALLER;
else
return GTK_ORDERING_EQUAL;
}
static int
compare_blue (gconstpointer a,
gconstpointer b,
gpointer unused)
{
GtkColor *colora = (GtkColor *) a;
GtkColor *colorb = (GtkColor *) b;
if (colora->color.blue < colorb->color.blue)
return GTK_ORDERING_LARGER;
else if (colora->color.blue > colorb->color.blue)
return GTK_ORDERING_SMALLER;
else
return GTK_ORDERING_EQUAL;
}
static GtkWidget *window = NULL;
GtkWidget *
@@ -998,7 +950,8 @@ do_listview_colors (GtkWidget *do_widget)
g_object_unref (selection_filter);
g_object_unref (no_selection);
g_object_get (model, "model", &model, NULL);
model = gtk_multi_selection_get_model (GTK_MULTI_SELECTION (model));
g_object_ref (model);
selection_info_toggle = gtk_toggle_button_new ();
gtk_button_set_icon_name (GTK_BUTTON (selection_info_toggle), "emblem-important-symbolic");
@@ -1012,7 +965,7 @@ do_listview_colors (GtkWidget *do_widget)
button = gtk_button_new_with_mnemonic ("_Refill");
g_signal_connect (button, "clicked",
G_CALLBACK (refill),
gtk_sor3_list_model_get_model (GTK_SOR3_LIST_MODEL (model)));
gtk_sort_list_model_get_model (GTK_SORT_LIST_MODEL (model)));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
@@ -1035,7 +988,7 @@ do_listview_colors (GtkWidget *do_widget)
gtk_drop_down_set_from_strings (GTK_DROP_DOWN (dropdown), (const char *[]) { "8", "64", "512", "4096", "32768", "262144", "2097152", "16777216", NULL });
g_signal_connect (dropdown, "notify::selected",
G_CALLBACK (limit_changed_cb),
gtk_sor3_list_model_get_model (GTK_SOR3_LIST_MODEL (model)));
gtk_sort_list_model_get_model (GTK_SORT_LIST_MODEL (model)));
g_signal_connect (dropdown, "notify::selected",
G_CALLBACK (limit_changed_cb2),
label);
@@ -1070,30 +1023,18 @@ do_listview_colors (GtkWidget *do_widget)
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_custom_sorter_new (compare_red, NULL, NULL);
set_title (sorter, "Red (fast)");
g_list_store_append (sorters, sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "green"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Green");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_custom_sorter_new (compare_green, NULL, NULL);
set_title (sorter, "Green (fast)");
g_list_store_append (sorters, sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "blue"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Blue");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_custom_sorter_new (compare_blue, NULL, NULL);
set_title (sorter, "Blue (fast)");
g_list_store_append (sorters, sorter);
set_title (multi_sorter, "RGB");
g_list_store_append (sorters, multi_sorter);
g_object_unref (multi_sorter);
+3 -3
View File
@@ -1,11 +1,11 @@
list.viewswitcher {
listview.viewswitcher {
border: 1px solid gray;
}
list.viewswitcher > row {
listview.viewswitcher > row {
padding: 5px;
}
list.viewswitcher row:selected {
listview.viewswitcher row:selected {
background: gray;
}
+1 -5
View File
@@ -215,7 +215,6 @@ transform_settings_to_keys (GBinding *binding,
GtkFilterListModel *filter_model;
GtkFilter *filter;
GtkNoSelection *selection_model;
GtkExpression *expression;
char **keys;
guint i;
@@ -246,11 +245,8 @@ transform_settings_to_keys (GBinding *binding,
gtk_column_view_get_sorter (GTK_COLUMN_VIEW (data)));
g_object_unref (store);
expression = gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name");
filter = gtk_string_filter_new ();
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), expression);
filter = gtk_string_filter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), filter);
gtk_expression_unref (expression);
g_object_unref (sort_model);
g_set_object (&current_filter, filter);
+2 -5
View File
@@ -160,7 +160,6 @@ do_listview_words (GtkWidget *do_widget)
GtkNoSelection *selection;
GtkStringList *stringlist;
GtkFilter *filter;
GtkExpression *expression;
GFile *file;
file = g_file_new_for_path ("/usr/share/dict/words");
@@ -177,10 +176,7 @@ do_listview_words (GtkWidget *do_widget)
g_strfreev (words);
}
filter = gtk_string_filter_new ();
expression = gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string");
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), expression);
gtk_expression_unref (expression);
filter = gtk_string_filter_new (gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string"));
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (stringlist), filter);
gtk_filter_list_model_set_incremental (filter_model, TRUE);
@@ -215,6 +211,7 @@ do_listview_words (GtkWidget *do_widget)
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), progress);
sw = gtk_scrolled_window_new ();
gtk_widget_set_vexpand (sw, TRUE);
gtk_overlay_set_child (GTK_OVERLAY (overlay), sw);
listview = gtk_list_view_new_with_factory (
+113 -4
View File
@@ -18,6 +18,7 @@ static gchar *current_file = NULL;
static GtkWidget *notebook;
static GtkSingleSelection *selection;
static GtkWidget *toplevel;
static char **search_needle;
typedef struct _GtkDemo GtkDemo;
struct _GtkDemo
@@ -945,7 +946,18 @@ selection_cb (GtkSingleSelection *sel,
gpointer user_data)
{
GtkTreeListRow *row = gtk_single_selection_get_selected_item (sel);
GtkDemo *demo = gtk_tree_list_row_get_item (row);
GtkDemo *demo;
gtk_widget_set_sensitive (GTK_WIDGET (notebook), !!row);
if (!row)
{
gtk_window_set_title (GTK_WINDOW (toplevel), "No match");
return;
}
demo = gtk_tree_list_row_get_item (row);
if (demo->filename)
load_file (demo->name, demo->filename);
@@ -953,6 +965,84 @@ selection_cb (GtkSingleSelection *sel,
gtk_window_set_title (GTK_WINDOW (toplevel), demo->title);
}
static gboolean
filter_demo (GtkDemo *demo)
{
int i;
/* Show only if the name maches every needle */
for (i = 0; search_needle[i]; i++)
{
if (!demo->title)
return FALSE;
if (g_str_match_string (search_needle[i], demo->title, TRUE))
continue;
return FALSE;
}
return TRUE;
}
static gboolean
demo_filter_by_name (GtkTreeListRow *row,
GtkFilterListModel *model)
{
GListModel *children;
GtkDemo *demo;
guint i, n;
/* Show all items if search is empty */
if (!search_needle || !search_needle[0] || !*search_needle[0])
return TRUE;
g_assert (GTK_IS_TREE_LIST_ROW (row));
g_assert (GTK_IS_FILTER_LIST_MODEL (model));
children = gtk_tree_list_row_get_children (row);
if (children)
{
n = g_list_model_get_n_items (children);
for (i = 0; i < n; i++)
{
demo = g_list_model_get_item (children, i);
g_assert (GTK_IS_DEMO (demo));
if (filter_demo (demo))
{
g_object_unref (demo);
return TRUE;
}
g_object_unref (demo);
}
}
demo = gtk_tree_list_row_get_item (row);
g_assert (GTK_IS_DEMO (demo));
return filter_demo (demo);
}
static void
demo_search_changed_cb (GtkSearchEntry *entry,
GtkFilter *filter)
{
const char *text;
g_assert (GTK_IS_SEARCH_ENTRY (entry));
g_assert (GTK_IS_FILTER (filter));
text = gtk_editable_get_text (GTK_EDITABLE (entry));
g_clear_pointer (&search_needle, g_strfreev);
if (text && *text)
search_needle = g_strsplit (text, " ", 0);
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static GListModel *
create_demo_model (void)
{
@@ -1007,13 +1097,25 @@ get_child_model (gpointer item,
return NULL;
}
static void
clear_search (GtkSearchBar *bar)
{
if (!gtk_search_bar_get_search_mode (bar))
{
GtkWidget *entry = gtk_search_bar_get_child (GTK_SEARCH_BAR (bar));
gtk_editable_set_text (GTK_EDITABLE (entry), "");
}
}
static void
activate (GApplication *app)
{
GtkBuilder *builder;
GListModel *listmodel;
GtkTreeListModel *treemodel;
GtkWidget *window, *listview;
GtkWidget *window, *listview, *search_entry, *search_bar;
GtkFilterListModel *filter_model;
GtkFilter *filter;
static GActionEntry win_entries[] = {
{ "run", activate_run, NULL, NULL, NULL }
@@ -1034,6 +1136,8 @@ activate (GApplication *app)
toplevel = GTK_WIDGET (window);
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
g_signal_connect (listview, "activate", G_CALLBACK (activate_cb), window);
search_bar = GTK_WIDGET (gtk_builder_get_object (builder, "searchbar"));
g_signal_connect (search_bar, "notify::search-mode-enabled", G_CALLBACK (clear_search), NULL);
listmodel = create_demo_model ();
treemodel = gtk_tree_list_model_new (FALSE,
@@ -1042,7 +1146,13 @@ activate (GApplication *app)
get_child_model,
NULL,
NULL);
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (treemodel), NULL);
filter = gtk_custom_filter_new ((GtkCustomFilterFunc)demo_filter_by_name, filter_model, NULL);
gtk_filter_list_model_set_filter (filter_model, filter);
search_entry = GTK_WIDGET (gtk_builder_get_object (builder, "search-entry"));
g_signal_connect (search_entry, "search-changed", G_CALLBACK (demo_search_changed_cb), filter);
selection = gtk_single_selection_new (G_LIST_MODEL (filter_model));
g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
@@ -1139,7 +1249,6 @@ out:
demo = (func) (window);
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);
}
+22 -5
View File
@@ -55,12 +55,29 @@
<property name="hscrollbar-policy">never</property>
<property name="min-content-width">150</property>
<child>
<object class="GtkListView" id="listview">
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/ui/main-listitem.ui</property>
<object class="GtkBox">
<property name="width-request">220</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchBar" id="searchbar">
<property name="key-capture-widget">window</property>
<child>
<object class="GtkSearchEntry" id="search-entry"/>
</child>
</object>
</property>
</child>
<child>
<object class="GtkListView" id="listview">
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/ui/main-listitem.ui</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="43.000351" x2="85.000351" y1="39.000164" y2="39.000164">
<stop offset="0" stop-color="#26a269"/>
<stop offset="0.0934161" stop-color="#84e3b7"/>
<stop offset="0.330831" stop-color="#26a269"/>
<stop offset="0.686952" stop-color="#26a269"/>
<stop offset="0.89736" stop-color="#175e3c"/>
<stop offset="1" stop-color="#26a269"/>
</linearGradient>
<linearGradient id="b" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#c0bfbc"/>
<stop offset="0.154754" stop-color="#ffffff"/>
<stop offset="0.433722" stop-color="#bdbbb5"/>
<stop offset="0.650505" stop-color="#c1c0ba"/>
<stop offset="0.825253" stop-color="#ffffff"/>
<stop offset="1" stop-color="#c0bfbc"/>
</linearGradient>
<linearGradient id="c" gradientTransform="matrix(0.0811899 -0.046875 0.069079 0.119648 307.03142 127.069456)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
<linearGradient id="d" gradientTransform="matrix(-0.0811899 -0.046875 -0.069079 0.119648 -177.242852 127.069447)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
<linearGradient id="e" gradientUnits="userSpaceOnUse" x1="14" x2="56" y1="94.999964" y2="94.999964">
<stop offset="0" stop-color="#813d9c"/>
<stop offset="0.109119" stop-color="#b378ca"/>
<stop offset="0.241583" stop-color="#813d9c"/>
<stop offset="0.731841" stop-color="#813d9c"/>
<stop offset="0.872163" stop-color="#4d255d"/>
<stop offset="1" stop-color="#813d9c"/>
</linearGradient>
<linearGradient id="f" gradientUnits="userSpaceOnUse" x1="72" x2="114" y1="94.999964" y2="94.999964">
<stop offset="0" stop-color="#e66100"/>
<stop offset="0.0678478" stop-color="#ff903e"/>
<stop offset="0.168852" stop-color="#e66100"/>
<stop offset="0.886626" stop-color="#e66100"/>
<stop offset="1" stop-color="#9d4200"/>
</linearGradient>
<clipPath id="g">
<rect height="128" width="128"/>
</clipPath>
<clipPath id="h">
<rect height="128" width="128"/>
</clipPath>
<filter id="i" height="100%" width="100%" x="0%" y="0%">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="j">
<g clip-path="url(#h)" filter="url(#i)">
<g clip-path="url(#g)">
<path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/>
<path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/>
<path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/>
<path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/>
<path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/>
<path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/>
<path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/>
</g>
</g>
</mask>
<mask id="k">
<g filter="url(#i)">
<rect fill-opacity="0.8" height="128" width="128"/>
</g>
</mask>
<linearGradient id="l" gradientTransform="matrix(0 0.37 -0.98462 0 295.38501 -30.360001)" gradientUnits="userSpaceOnUse" x1="300" x2="428" y1="235" y2="235">
<stop offset="0" stop-color="#f9f06b"/>
<stop offset="1" stop-color="#f5c211"/>
</linearGradient>
<clipPath id="m">
<rect height="128" width="128"/>
</clipPath>
<clipPath id="n">
<rect height="128" width="128"/>
</clipPath>
<path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/>
<path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/>
<path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/>
<path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/>
<path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/>
<path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/>
<path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/>
<g clip-path="url(#n)" mask="url(#j)">
<g clip-path="url(#m)" mask="url(#k)">
<path d="m 128 80.640625 v 47.359375 h -128 v -47.359375 z m 0 0" fill="url(#l)"/>
<path d="m 13.308594 80.640625 l 47.355468 47.359375 h 21.214844 l -47.359375 -47.359375 z m 42.421875 0 l 47.363281 47.359375 h 21.214844 l -47.363282 -47.359375 z m 42.429687 0 l 29.839844 29.839844 v -21.210938 l -8.628906 -8.628906 z m -98.160156 7.90625 v 21.214844 l 18.238281 18.238281 h 21.214844 z m 0 0"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.4 KiB

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="43.000351" x2="85.000351" y1="39.000164" y2="39.000164">
<stop offset="0" stop-color="#26a269"/>
<stop offset="0.0934161" stop-color="#84e3b7"/>
<stop offset="0.330831" stop-color="#26a269"/>
<stop offset="0.686952" stop-color="#26a269"/>
<stop offset="0.89736" stop-color="#175e3c"/>
<stop offset="1" stop-color="#26a269"/>
</linearGradient>
<linearGradient id="b" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#c0bfbc"/>
<stop offset="0.154754" stop-color="#ffffff"/>
<stop offset="0.433722" stop-color="#bdbbb5"/>
<stop offset="0.650505" stop-color="#c1c0ba"/>
<stop offset="0.825253" stop-color="#ffffff"/>
<stop offset="1" stop-color="#c0bfbc"/>
</linearGradient>
<linearGradient id="c" gradientTransform="matrix(0.0811899 -0.046875 0.069079 0.119648 307.03142 127.069456)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
<linearGradient id="d" gradientTransform="matrix(-0.0811899 -0.046875 -0.069079 0.119648 -177.242852 127.069447)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
<linearGradient id="e" gradientUnits="userSpaceOnUse" x1="14" x2="56" y1="94.999964" y2="94.999964">
<stop offset="0" stop-color="#813d9c"/>
<stop offset="0.109119" stop-color="#b378ca"/>
<stop offset="0.241583" stop-color="#813d9c"/>
<stop offset="0.731841" stop-color="#813d9c"/>
<stop offset="0.872163" stop-color="#4d255d"/>
<stop offset="1" stop-color="#813d9c"/>
</linearGradient>
<linearGradient id="f" gradientUnits="userSpaceOnUse" x1="72" x2="114" y1="94.999964" y2="94.999964">
<stop offset="0" stop-color="#e66100"/>
<stop offset="0.0678478" stop-color="#ff903e"/>
<stop offset="0.168852" stop-color="#e66100"/>
<stop offset="0.886626" stop-color="#e66100"/>
<stop offset="1" stop-color="#9d4200"/>
</linearGradient>
<path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/>
<path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/>
<path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/>
<path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/>
<path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/>
<path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/>
<path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 5.75 1 c -0.414062 0 -0.75 0.335938 -0.75 0.75 v 4.5 c 0 0.414062 0.335938 0.75 0.75 0.75 h 0.191406 l -1 2 h -3.191406 c -0.414062 0 -0.75 0.335938 -0.75 0.75 v 4.5 c 0 0.414062 0.335938 0.75 0.75 0.75 h 4.5 c 0.414062 0 0.75 -0.335938 0.75 -0.75 v -4.5 c 0 -0.414062 -0.335938 -0.75 -0.75 -0.75 h -0.191406 l 1 -2 h 1.882812 l 1 2 h -0.191406 c -0.414062 0 -0.75 0.335938 -0.75 0.75 v 4.5 c 0 0.414062 0.335938 0.75 0.75 0.75 h 4.5 c 0.414062 0 0.75 -0.335938 0.75 -0.75 v -4.5 c 0 -0.414062 -0.335938 -0.75 -0.75 -0.75 h -3.191406 l -1 -2 h 0.191406 c 0.414062 0 0.75 -0.335938 0.75 -0.75 v -4.5 c 0 -0.414062 -0.335938 -0.75 -0.75 -0.75 z m 0 0"/>
</svg>

After

Width:  |  Height:  |  Size: 801 B

+9
View File
@@ -19,3 +19,12 @@ executable('gtk4-node-editor',
gui_app: true,
link_args: extra_demo_ldflags,
install: false)
# icons
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
foreach size: ['scalable', 'symbolic']
install_subdir('data/' + size,
install_dir: icontheme_dir
)
endforeach
+1 -1
View File
@@ -101,7 +101,7 @@ activate_about (GSimpleAction *action,
"website", "http://www.gtk.org",
"comments", "Program to test GTK rendering",
"authors", (const char *[]){ "Benjamin Otte", "Timm Bäder", NULL},
"logo-icon-name", "text-editor-symbolic",
"logo-icon-name", "org.gtk.gtk4.NodeEditor.Devel",
"title", "About GTK Node Editor",
"system-information", s->str,
NULL);
@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="a" gradientTransform="matrix(0.232143 0 0 0.328947 -7.567033 263.82666)" gradientUnits="userSpaceOnUse" x1="88.595886" x2="536.595886" y1="-449.394012" y2="-449.394012">
<stop offset="0" stop-color="#acabae"/>
<stop offset="0.0384615" stop-color="#deddda"/>
<stop offset="0.0768555" stop-color="#c0bfbc"/>
<stop offset="0.923077" stop-color="#c0bfbc"/>
<stop offset="0.961538" stop-color="#deddda"/>
<stop offset="1" stop-color="#9a9996"/>
</linearGradient>
<linearGradient id="b" gradientUnits="userSpaceOnUse" x1="26.999876" x2="100.999876" y1="32.999688" y2="32.999688">
<stop offset="0" stop-color="#7e7c77"/>
<stop offset="0.3" stop-color="#9a9996"/>
<stop offset="1" stop-color="#9a9996"/>
</linearGradient>
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="67.467916" x2="67.467916" y1="83.999688" y2="36.782906">
<stop offset="0" stop-color="#deddda"/>
<stop offset="1" stop-color="#c0bfbc"/>
</linearGradient>
<clipPath id="d">
<path d="m 79 72 h 15 v 16 h -15 z m 0 0"/>
</clipPath>
<clipPath id="e">
<path d="m 93.21875 72.921875 l -14.21875 14.21875 h -4.0625 v -18.28125 h 18.28125 z m 0 0"/>
</clipPath>
<linearGradient id="f" gradientTransform="matrix(0 0.126951 0.126951 0 76.460862 36.359884)" gradientUnits="userSpaceOnUse" x1="344" x2="340" y1="76" y2="72">
<stop offset="0" stop-color="#d5d3cf"/>
<stop offset="1" stop-color="#ffffff"/>
</linearGradient>
<filter id="g" height="100%" width="100%" x="0%" y="0%">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="h">
<g filter="url(#g)">
<rect fill-opacity="0.396" height="128" width="128"/>
</g>
</mask>
<linearGradient id="i" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#1c71d8"/>
<stop offset="0.323117" stop-color="#62a0ea"/>
<stop offset="0.59387" stop-color="#1b5aa6"/>
<stop offset="1" stop-color="#1c71d8"/>
</linearGradient>
<linearGradient id="j" gradientTransform="matrix(1.597748 1.597748 -1.06066 1.06066 -56.853041 -543.720139)" x1="224.504562" x2="231.453873" xlink:href="#i" y1="282.5" y2="282.5"/>
<radialGradient id="k" cx="227.599915" cy="201.029724" gradientTransform="matrix(4.072817 4.073078 -5.940048 5.939073 373.883117 -2098.049112)" gradientUnits="userSpaceOnUse" r="2.5">
<stop offset="0" stop-color="#93bdf1"/>
<stop offset="1" stop-color="#1a5fb4"/>
</radialGradient>
<linearGradient id="l" gradientTransform="matrix(2.121328 2.121328 -2.174353 2.174353 181.766074 -1021.145947)" gradientUnits="userSpaceOnUse" x1="226.90625" x2="228.86203" y1="288.75" y2="288.767151">
<stop offset="0" stop-color="#77767b"/>
<stop offset="0.443872" stop-color="#f6f5f4"/>
<stop offset="1" stop-color="#5e5c64"/>
</linearGradient>
<linearGradient id="m" gradientTransform="matrix(1.258421 1.258421 -1.06066 1.06066 57.381892 -503.024312)" gradientUnits="userSpaceOnUse" x1="223.1875" x2="233.0625" y1="278" y2="278">
<stop offset="0" stop-color="#ffa348"/>
<stop offset="0.265823" stop-color="#ffd7af"/>
<stop offset="0.734177" stop-color="#ff8d1c"/>
<stop offset="1" stop-color="#ffa348"/>
</linearGradient>
<linearGradient id="n" gradientTransform="matrix(1.573027 1.573027 -1.06066 1.06066 -14.348129 -574.754333)" x1="224.504562" x2="231.453873" xlink:href="#i" y1="282.5" y2="282.5"/>
<clipPath id="o">
<path d="m 79 72 h 15 v 16 h -15 z m 0 0"/>
</clipPath>
<clipPath id="p">
<path d="m 93.21875 72.921875 l -14.21875 14.21875 h -4.0625 v -18.28125 h 18.28125 z m 0 0"/>
</clipPath>
<mask id="q">
<g filter="url(#g)">
<rect fill-opacity="0.396" height="128" width="128"/>
</g>
</mask>
<clipPath id="r">
<rect height="152" width="192"/>
</clipPath>
<g id="s" clip-path="url(#r)">
<path d="m 29 112 c -4.433594 0 -8 -3.566406 -8 -8 v -2 c 0 4.433594 3.566406 8 8 8 h 88 c 4.433594 0 8 -3.566406 8 -8 v 2 c 0 4.433594 -3.566406 8 -8 8 z m 0 0" fill="#f6f5f4"/>
</g>
<clipPath id="t">
<rect height="128" width="128"/>
</clipPath>
<clipPath id="u">
<rect height="128" width="128"/>
</clipPath>
<mask id="v">
<g clip-path="url(#u)" filter="url(#g)">
<g clip-path="url(#t)">
<path d="m 21 16 c -4.433594 0 -8 3.566406 -8 8 v 84 c 0 4.433594 3.566406 8 8 8 h 4 v -4 h 80 v 4 h 4 c 4.433594 0 8 -3.566406 8 -8 v -84 c 0 -4.433594 -3.566406 -8 -8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 21 12 h 88 c 4.417969 0 8 3.582031 8 8 v 68 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -68 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#deddda"/>
<path d="m 27 28 h 74 v 10 h -74 z m 0 0" fill="url(#b)"/>
<path d="m 27 38 h 74 v 46 h -74 z m 0 0" fill="url(#c)"/>
<path d="m 24 33 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#bf5f00" fill-opacity="0.964567"/>
<path d="m 18 40 h 6 v 12 h -6 z m 0 0" fill="#acacac" fill-opacity="0.984252"/>
<path d="m 18 40 h 6 v 10 h -6 z m 0 0" fill="#d1d1d1" fill-opacity="0.984252"/>
<path d="m 37 36 h 56 v 44 h -56 z m 0 0" fill="#deddda" fill-opacity="0.984252"/>
<path d="m 37 34 h 56 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 h -56 c -1.105469 0 -2 -0.894531 -2 -2 s 0.894531 -2 2 -2 z m 0 0" fill-opacity="0.940945"/>
<path d="m 37 36.859375 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#9a9996" fill-opacity="0.984252"/>
<path d="m 37 36 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#f6f5f4" fill-opacity="0.984252"/>
<g clip-path="url(#o)">
<g clip-path="url(#p)">
<path d="m 79 77.386719 v 9.351562 c 0 2.464844 2 4.464844 4.464844 4.464844 h 9.351562 c 2.464844 0 4.464844 -2 4.464844 -4.464844 v -9.351562 c 0 -2.464844 -2 -4.464844 -4.464844 -4.464844 h -9.351562 c -2.464844 0 -4.464844 2 -4.464844 4.464844 z m 0 0" fill="url(#f)"/>
</g>
</g>
<path d="m 27 100 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#5e5c64" fill-opacity="0.940945"/>
<path d="m 27 102 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#9a9996"/>
<path d="m 13 106 v 2 c 0 4.433594 3.566406 8 8 8 h 4 v -2 h -4 c -4.433594 0 -8 -3.566406 -8 -8 z m 104 0 c 0 4.433594 -3.566406 8 -8 8 h -4 v 2 h 4 c 4.433594 0 8 -3.566406 8 -8 z m -92 6 v 2 h 80 v -2 z m 0 0" fill="#9e9c99" fill-opacity="0.366142"/>
<path d="m 27 38 v 46 l 6 -46 z m 0 0" fill="#7e7c77" fill-opacity="0.11811"/>
<path d="m 24 32 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#ffa348" fill-opacity="0.964567"/>
<use mask="url(#q)" transform="matrix(1 0 0 1 -8 -16)" xlink:href="#s"/>
<path d="m 89.503906 31.144531 l 10.066406 10.066407 l -41.71875 41.71875 l -10.066406 -10.066407 z m 0 0" fill="#ffa348"/>
<path d="m 88.246094 29.886719 l 7.550781 7.550781 l -41.71875 41.71875 l -7.550781 -7.550781 z m 0 0" fill="#ff7800"/>
<path d="m 86.789062 28.429688 l 2.515626 2.515624 l -41.71875 41.71875 l -2.515626 -2.515624 z m 0 0" fill="#ffbe6f"/>
<path d="m 121.898438 -0.101562 c -4.855469 0.921874 -11.730469 5.152343 -18.140626 11.558593 l -16.96875 16.972657 l 12.78125 12.78125 l 16.972657 -16.972657 c 6.40625 -6.40625 10.636719 -13.28125 11.558593 -18.136719 z m 0 0" fill="url(#j)"/>
<path d="m 110.011719 13.882812 c -2.1875 -0.398437 -5.421875 0.988282 -8.167969 3.730469 l -11.871094 11.875 l -6.6875 6.6875 c -4.800781 4.800781 -9.234375 12.007813 -9.648437 13.042969 c -0.484375 1.207031 -0.449219 2.730469 0.953125 4.136719 c 1.40625 1.40625 2.917968 1.441406 4.136718 0.953125 c 1.035157 -0.414063 8.292969 -4.984375 13.042969 -9.648438 l 2.402344 -2.398437 l 16.160156 -16.160157 c 2.742188 -2.746093 4.128907 -5.976562 3.730469 -8.167968 c -0.742188 1.390625 -1.859375 2.902344 -3.308594 4.347656 l -13.996094 13.996094 l -5.089843 -5.089844 l 13.996093 -13.996094 c 1.445313 -1.445312 2.960938 -2.566406 4.347657 -3.308594 z m 0 0" fill="url(#k)"/>
<path d="m 95.273438 36.914062 l -2.960938 2.960938 l -2.398438 2.402344 c -4.90625 5.101562 -11.855468 10.828125 -11.855468 10.828125 c 1.011718 -0.433594 8.167968 -5.101563 12.914062 -9.769531 l 2.402344 -2.402344 l 2.960938 -2.957032 z m 0 0" fill="#62a0ea"/>
<path d="m 87.320312 26.835938 l 13.789063 13.789062 c 0.292969 0.292969 0.292969 0.769531 0 1.0625 s -0.769531 0.292969 -1.0625 0 l -13.789063 -13.789062 c -0.292968 -0.292969 -0.292968 -0.769532 0 -1.0625 c 0.292969 -0.289063 0.769532 -0.289063 1.0625 0 z m 0 0" fill="#3584e4"/>
<path d="m 42.421875 89.765625 c -3 3 -6.382813 4.484375 -7.554687 3.3125 c -1.171876 -1.171875 0.3125 -4.554687 3.3125 -7.554687 c 3.003906 -3.003907 6.386718 -4.488282 7.558593 -3.316407 s -0.3125 4.554688 -3.316406 7.558594 z m 0 0" fill="url(#l)"/>
<path d="m 45.269531 70.347656 l -7.851562 12.511719 l 7.835937 7.925781 l 12.597656 -7.855468 z m -6.039062 13.171875 l 5.449219 5.449219 c 0.347656 0.347656 0.449218 0.933594 0.097656 1.160156 c -0.886719 0.570313 -2.9375 1.539063 -2.9375 1.539063 c -0.25 0.128906 -0.539063 0.164062 -0.773438 -0.066407 l -4.546875 -4.550781 c -0.234375 -0.230469 -0.207031 -0.527343 -0.066406 -0.773437 l 1.617187 -2.859375 c 0.207032 -0.363281 0.8125 -0.25 1.160157 0.101562 z m 0 0" fill="url(#m)"/>
<path d="m 43.332031 74.777344 l 9.867188 9.867187 c 0.394531 0.390625 0.476562 0.871094 0.128906 1.066407 l -7.710937 5.253906 c -0.308594 0.210937 -0.785157 0.160156 -1.171876 -0.226563 l -6.984374 -6.988281 c -0.386719 -0.386719 -0.4375 -0.859375 -0.230469 -1.167969 l 5.234375 -7.8125 c 0.125 -0.285156 0.558594 -0.304687 0.867187 0.007813 z m 0 0" fill="url(#n)"/>
</g>
</g>
</mask>
<mask id="w">
<g filter="url(#g)">
<rect fill-opacity="0.8" height="128" width="128"/>
</g>
</mask>
<linearGradient id="x" gradientTransform="matrix(0 0.37 -0.98462 0 295.38501 -30.360001)" gradientUnits="userSpaceOnUse" x1="300" x2="428" y1="235" y2="235">
<stop offset="0" stop-color="#f9f06b"/>
<stop offset="1" stop-color="#f5c211"/>
</linearGradient>
<clipPath id="y">
<rect height="128" width="128"/>
</clipPath>
<clipPath id="z">
<rect height="128" width="128"/>
</clipPath>
</defs>
<path d="m 21 16 c -4.433594 0 -8 3.566406 -8 8 v 84 c 0 4.433594 3.566406 8 8 8 h 4 v -4 h 80 v 4 h 4 c 4.433594 0 8 -3.566406 8 -8 v -84 c 0 -4.433594 -3.566406 -8 -8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 21 12 h 88 c 4.417969 0 8 3.582031 8 8 v 68 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -68 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#deddda"/>
<path d="m 27 28 h 74 v 10 h -74 z m 0 0" fill="url(#b)"/>
<path d="m 27 38 h 74 v 46 h -74 z m 0 0" fill="url(#c)"/>
<path d="m 24 33 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#bf5f00" fill-opacity="0.964567"/>
<g fill-opacity="0.984252">
<path d="m 18 40 h 6 v 12 h -6 z m 0 0" fill="#acacac"/>
<path d="m 18 40 h 6 v 10 h -6 z m 0 0" fill="#d1d1d1"/>
<path d="m 37 36 h 56 v 44 h -56 z m 0 0" fill="#deddda"/>
</g>
<path d="m 37 34 h 56 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 h -56 c -1.105469 0 -2 -0.894531 -2 -2 s 0.894531 -2 2 -2 z m 0 0" fill-opacity="0.940945"/>
<path d="m 37 36.859375 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#9a9996" fill-opacity="0.984252"/>
<path d="m 37 36 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#f6f5f4" fill-opacity="0.984252"/>
<g clip-path="url(#d)">
<g clip-path="url(#e)">
<path d="m 79 77.386719 v 9.351562 c 0 2.464844 2 4.464844 4.464844 4.464844 h 9.351562 c 2.464844 0 4.464844 -2 4.464844 -4.464844 v -9.351562 c 0 -2.464844 -2 -4.464844 -4.464844 -4.464844 h -9.351562 c -2.464844 0 -4.464844 2 -4.464844 4.464844 z m 0 0" fill="url(#f)"/>
</g>
</g>
<path d="m 27 100 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#5e5c64" fill-opacity="0.940945"/>
<path d="m 27 102 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#9a9996"/>
<path d="m 13 106 v 2 c 0 4.433594 3.566406 8 8 8 h 4 v -2 h -4 c -4.433594 0 -8 -3.566406 -8 -8 z m 104 0 c 0 4.433594 -3.566406 8 -8 8 h -4 v 2 h 4 c 4.433594 0 8 -3.566406 8 -8 z m -92 6 v 2 h 80 v -2 z m 0 0" fill="#9e9c99" fill-opacity="0.366142"/>
<path d="m 27 38 v 46 l 6 -46 z m 0 0" fill="#7e7c77" fill-opacity="0.11811"/>
<path d="m 24 32 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#ffa348" fill-opacity="0.964567"/>
<use mask="url(#h)" transform="matrix(1 0 0 1 -8 -16)" xlink:href="#s"/>
<path d="m 89.503906 31.144531 l 10.066406 10.066407 l -41.71875 41.71875 l -10.066406 -10.066407 z m 0 0" fill="#ffa348"/>
<path d="m 88.246094 29.886719 l 7.550781 7.550781 l -41.71875 41.71875 l -7.550781 -7.550781 z m 0 0" fill="#ff7800"/>
<path d="m 86.789062 28.429688 l 2.515626 2.515624 l -41.71875 41.71875 l -2.515626 -2.515624 z m 0 0" fill="#ffbe6f"/>
<path d="m 121.898438 -0.101562 c -4.855469 0.921874 -11.730469 5.152343 -18.140626 11.558593 l -16.96875 16.972657 l 12.78125 12.78125 l 16.972657 -16.972657 c 6.40625 -6.40625 10.636719 -13.28125 11.558593 -18.136719 z m 0 0" fill="url(#j)"/>
<path d="m 110.011719 13.882812 c -2.1875 -0.398437 -5.421875 0.988282 -8.167969 3.730469 l -11.871094 11.875 l -6.6875 6.6875 c -4.800781 4.800781 -9.234375 12.007813 -9.648437 13.042969 c -0.484375 1.207031 -0.449219 2.730469 0.953125 4.136719 c 1.40625 1.40625 2.917968 1.441406 4.136718 0.953125 c 1.035157 -0.414063 8.292969 -4.984375 13.042969 -9.648438 l 2.402344 -2.398437 l 16.160156 -16.160157 c 2.742188 -2.746093 4.128907 -5.976562 3.730469 -8.167968 c -0.742188 1.390625 -1.859375 2.902344 -3.308594 4.347656 l -13.996094 13.996094 l -5.089843 -5.089844 l 13.996093 -13.996094 c 1.445313 -1.445312 2.960938 -2.566406 4.347657 -3.308594 z m 0 0" fill="url(#k)"/>
<path d="m 95.273438 36.914062 l -2.960938 2.960938 l -2.398438 2.402344 c -4.90625 5.101562 -11.855468 10.828125 -11.855468 10.828125 c 1.011718 -0.433594 8.167968 -5.101563 12.914062 -9.769531 l 2.402344 -2.402344 l 2.960938 -2.957032 z m 0 0" fill="#62a0ea"/>
<path d="m 87.320312 26.835938 l 13.789063 13.789062 c 0.292969 0.292969 0.292969 0.769531 0 1.0625 s -0.769531 0.292969 -1.0625 0 l -13.789063 -13.789062 c -0.292968 -0.292969 -0.292968 -0.769532 0 -1.0625 c 0.292969 -0.289063 0.769532 -0.289063 1.0625 0 z m 0 0" fill="#3584e4"/>
<path d="m 42.421875 89.765625 c -3 3 -6.382813 4.484375 -7.554687 3.3125 c -1.171876 -1.171875 0.3125 -4.554687 3.3125 -7.554687 c 3.003906 -3.003907 6.386718 -4.488282 7.558593 -3.316407 s -0.3125 4.554688 -3.316406 7.558594 z m 0 0" fill="url(#l)"/>
<path d="m 45.269531 70.347656 l -7.851562 12.511719 l 7.835937 7.925781 l 12.597656 -7.855468 z m -6.039062 13.171875 l 5.449219 5.449219 c 0.347656 0.347656 0.449218 0.933594 0.097656 1.160156 c -0.886719 0.570313 -2.9375 1.539063 -2.9375 1.539063 c -0.25 0.128906 -0.539063 0.164062 -0.773438 -0.066407 l -4.546875 -4.550781 c -0.234375 -0.230469 -0.207031 -0.527343 -0.066406 -0.773437 l 1.617187 -2.859375 c 0.207032 -0.363281 0.8125 -0.25 1.160157 0.101562 z m 0 0" fill="url(#m)"/>
<path d="m 43.332031 74.777344 l 9.867188 9.867187 c 0.394531 0.390625 0.476562 0.871094 0.128906 1.066407 l -7.710937 5.253906 c -0.308594 0.210937 -0.785157 0.160156 -1.171876 -0.226563 l -6.984374 -6.988281 c -0.386719 -0.386719 -0.4375 -0.859375 -0.230469 -1.167969 l 5.234375 -7.8125 c 0.125 -0.285156 0.558594 -0.304687 0.867187 0.007813 z m 0 0" fill="url(#n)"/>
<g clip-path="url(#z)" mask="url(#v)">
<g clip-path="url(#y)" mask="url(#w)">
<path d="m 128 80.640625 v 47.359375 h -128 v -47.359375 z m 0 0" fill="url(#x)"/>
<path d="m 13.308594 80.640625 l 47.355468 47.359375 h 21.214844 l -47.359375 -47.359375 z m 42.421875 0 l 47.363281 47.359375 h 21.214844 l -47.363282 -47.359375 z m 42.429687 0 l 29.839844 29.839844 v -21.210938 l -8.628906 -8.628906 z m -98.160156 7.90625 v 21.214844 l 18.238281 18.238281 h 21.214844 z m 0 0"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="a" gradientTransform="matrix(0.232143 0 0 0.328947 -7.567033 263.82666)" gradientUnits="userSpaceOnUse" x1="88.595886" x2="536.595886" y1="-449.394012" y2="-449.394012">
<stop offset="0" stop-color="#acabae"/>
<stop offset="0.0384615" stop-color="#deddda"/>
<stop offset="0.0768555" stop-color="#c0bfbc"/>
<stop offset="0.923077" stop-color="#c0bfbc"/>
<stop offset="0.961538" stop-color="#deddda"/>
<stop offset="1" stop-color="#9a9996"/>
</linearGradient>
<linearGradient id="b" gradientUnits="userSpaceOnUse" x1="26.999876" x2="100.999876" y1="32.999688" y2="32.999688">
<stop offset="0" stop-color="#7e7c77"/>
<stop offset="0.3" stop-color="#9a9996"/>
<stop offset="1" stop-color="#9a9996"/>
</linearGradient>
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="67.467916" x2="67.467916" y1="83.999688" y2="36.782906">
<stop offset="0" stop-color="#deddda"/>
<stop offset="1" stop-color="#c0bfbc"/>
</linearGradient>
<clipPath id="d">
<path d="m 79 72 h 15 v 16 h -15 z m 0 0"/>
</clipPath>
<clipPath id="e">
<path d="m 93.21875 72.921875 l -14.21875 14.21875 h -4.0625 v -18.28125 h 18.28125 z m 0 0"/>
</clipPath>
<linearGradient id="f" gradientTransform="matrix(0 0.126951 0.126951 0 76.460862 36.359884)" gradientUnits="userSpaceOnUse" x1="344" x2="340" y1="76" y2="72">
<stop offset="0" stop-color="#d5d3cf"/>
<stop offset="1" stop-color="#ffffff"/>
</linearGradient>
<filter id="g" height="100%" width="100%" x="0%" y="0%">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="h">
<g filter="url(#g)">
<rect fill-opacity="0.396" height="128" width="128"/>
</g>
</mask>
<clipPath id="i">
<rect height="152" width="192"/>
</clipPath>
<linearGradient id="j" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#1c71d8"/>
<stop offset="0.323117" stop-color="#62a0ea"/>
<stop offset="0.59387" stop-color="#1b5aa6"/>
<stop offset="1" stop-color="#1c71d8"/>
</linearGradient>
<linearGradient id="k" gradientTransform="matrix(1.597748 1.597748 -1.06066 1.06066 -56.853041 -543.720139)" x1="224.504562" x2="231.453873" xlink:href="#j" y1="282.5" y2="282.5"/>
<radialGradient id="l" cx="227.599915" cy="201.029724" gradientTransform="matrix(4.072817 4.073078 -5.940048 5.939073 373.883117 -2098.049112)" gradientUnits="userSpaceOnUse" r="2.5">
<stop offset="0" stop-color="#93bdf1"/>
<stop offset="1" stop-color="#1a5fb4"/>
</radialGradient>
<linearGradient id="m" gradientTransform="matrix(2.121328 2.121328 -2.174353 2.174353 181.766074 -1021.145947)" gradientUnits="userSpaceOnUse" x1="226.90625" x2="228.86203" y1="288.75" y2="288.767151">
<stop offset="0" stop-color="#77767b"/>
<stop offset="0.443872" stop-color="#f6f5f4"/>
<stop offset="1" stop-color="#5e5c64"/>
</linearGradient>
<linearGradient id="n" gradientTransform="matrix(1.258421 1.258421 -1.06066 1.06066 57.381892 -503.024312)" gradientUnits="userSpaceOnUse" x1="223.1875" x2="233.0625" y1="278" y2="278">
<stop offset="0" stop-color="#ffa348"/>
<stop offset="0.265823" stop-color="#ffd7af"/>
<stop offset="0.734177" stop-color="#ff8d1c"/>
<stop offset="1" stop-color="#ffa348"/>
</linearGradient>
<linearGradient id="o" gradientTransform="matrix(1.573027 1.573027 -1.06066 1.06066 -14.348129 -574.754333)" x1="224.504562" x2="231.453873" xlink:href="#j" y1="282.5" y2="282.5"/>
<path d="m 21 16 c -4.433594 0 -8 3.566406 -8 8 v 84 c 0 4.433594 3.566406 8 8 8 h 4 v -4 h 80 v 4 h 4 c 4.433594 0 8 -3.566406 8 -8 v -84 c 0 -4.433594 -3.566406 -8 -8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 21 12 h 88 c 4.417969 0 8 3.582031 8 8 v 68 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -68 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#deddda"/>
<path d="m 27 28 h 74 v 10 h -74 z m 0 0" fill="url(#b)"/>
<path d="m 27 38 h 74 v 46 h -74 z m 0 0" fill="url(#c)"/>
<path d="m 24 33 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#bf5f00" fill-opacity="0.964567"/>
<g fill-opacity="0.984252">
<path d="m 18 40 h 6 v 12 h -6 z m 0 0" fill="#acacac"/>
<path d="m 18 40 h 6 v 10 h -6 z m 0 0" fill="#d1d1d1"/>
<path d="m 37 36 h 56 v 44 h -56 z m 0 0" fill="#deddda"/>
</g>
<path d="m 37 34 h 56 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 h -56 c -1.105469 0 -2 -0.894531 -2 -2 s 0.894531 -2 2 -2 z m 0 0" fill-opacity="0.940945"/>
<path d="m 37 36.859375 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#9a9996" fill-opacity="0.984252"/>
<path d="m 37 36 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#f6f5f4" fill-opacity="0.984252"/>
<g clip-path="url(#d)">
<g clip-path="url(#e)">
<path d="m 79 77.386719 v 9.351562 c 0 2.464844 2 4.464844 4.464844 4.464844 h 9.351562 c 2.464844 0 4.464844 -2 4.464844 -4.464844 v -9.351562 c 0 -2.464844 -2 -4.464844 -4.464844 -4.464844 h -9.351562 c -2.464844 0 -4.464844 2 -4.464844 4.464844 z m 0 0" fill="url(#f)"/>
</g>
</g>
<path d="m 27 100 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#5e5c64" fill-opacity="0.940945"/>
<path d="m 27 102 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#9a9996"/>
<path d="m 13 106 v 2 c 0 4.433594 3.566406 8 8 8 h 4 v -2 h -4 c -4.433594 0 -8 -3.566406 -8 -8 z m 104 0 c 0 4.433594 -3.566406 8 -8 8 h -4 v 2 h 4 c 4.433594 0 8 -3.566406 8 -8 z m -92 6 v 2 h 80 v -2 z m 0 0" fill="#9e9c99" fill-opacity="0.366142"/>
<path d="m 27 38 v 46 l 6 -46 z m 0 0" fill="#7e7c77" fill-opacity="0.11811"/>
<path d="m 24 32 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#ffa348" fill-opacity="0.964567"/>
<g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -8 -16)">
<path d="m 29 112 c -4.433594 0 -8 -3.566406 -8 -8 v -2 c 0 4.433594 3.566406 8 8 8 h 88 c 4.433594 0 8 -3.566406 8 -8 v 2 c 0 4.433594 -3.566406 8 -8 8 z m 0 0" fill="#f6f5f4"/>
</g>
<path d="m 89.503906 31.144531 l 10.066406 10.066407 l -41.71875 41.71875 l -10.066406 -10.066407 z m 0 0" fill="#ffa348"/>
<path d="m 88.246094 29.886719 l 7.550781 7.550781 l -41.71875 41.71875 l -7.550781 -7.550781 z m 0 0" fill="#ff7800"/>
<path d="m 86.789062 28.429688 l 2.515626 2.515624 l -41.71875 41.71875 l -2.515626 -2.515624 z m 0 0" fill="#ffbe6f"/>
<path d="m 121.898438 -0.101562 c -4.855469 0.921874 -11.730469 5.152343 -18.140626 11.558593 l -16.96875 16.972657 l 12.78125 12.78125 l 16.972657 -16.972657 c 6.40625 -6.40625 10.636719 -13.28125 11.558593 -18.136719 z m 0 0" fill="url(#k)"/>
<path d="m 110.011719 13.882812 c -2.1875 -0.398437 -5.421875 0.988282 -8.167969 3.730469 l -11.871094 11.875 l -6.6875 6.6875 c -4.800781 4.800781 -9.234375 12.007813 -9.648437 13.042969 c -0.484375 1.207031 -0.449219 2.730469 0.953125 4.136719 c 1.40625 1.40625 2.917968 1.441406 4.136718 0.953125 c 1.035157 -0.414063 8.292969 -4.984375 13.042969 -9.648438 l 2.402344 -2.398437 l 16.160156 -16.160157 c 2.742188 -2.746093 4.128907 -5.976562 3.730469 -8.167968 c -0.742188 1.390625 -1.859375 2.902344 -3.308594 4.347656 l -13.996094 13.996094 l -5.089843 -5.089844 l 13.996093 -13.996094 c 1.445313 -1.445312 2.960938 -2.566406 4.347657 -3.308594 z m 0 0" fill="url(#l)"/>
<path d="m 95.273438 36.914062 l -2.960938 2.960938 l -2.398438 2.402344 c -4.90625 5.101562 -11.855468 10.828125 -11.855468 10.828125 c 1.011718 -0.433594 8.167968 -5.101563 12.914062 -9.769531 l 2.402344 -2.402344 l 2.960938 -2.957032 z m 0 0" fill="#62a0ea"/>
<path d="m 87.320312 26.835938 l 13.789063 13.789062 c 0.292969 0.292969 0.292969 0.769531 0 1.0625 s -0.769531 0.292969 -1.0625 0 l -13.789063 -13.789062 c -0.292968 -0.292969 -0.292968 -0.769532 0 -1.0625 c 0.292969 -0.289063 0.769532 -0.289063 1.0625 0 z m 0 0" fill="#3584e4"/>
<path d="m 42.421875 89.765625 c -3 3 -6.382813 4.484375 -7.554687 3.3125 c -1.171876 -1.171875 0.3125 -4.554687 3.3125 -7.554687 c 3.003906 -3.003907 6.386718 -4.488282 7.558593 -3.316407 s -0.3125 4.554688 -3.316406 7.558594 z m 0 0" fill="url(#m)"/>
<path d="m 45.269531 70.347656 l -7.851562 12.511719 l 7.835937 7.925781 l 12.597656 -7.855468 z m -6.039062 13.171875 l 5.449219 5.449219 c 0.347656 0.347656 0.449218 0.933594 0.097656 1.160156 c -0.886719 0.570313 -2.9375 1.539063 -2.9375 1.539063 c -0.25 0.128906 -0.539063 0.164062 -0.773438 -0.066407 l -4.546875 -4.550781 c -0.234375 -0.230469 -0.207031 -0.527343 -0.066406 -0.773437 l 1.617187 -2.859375 c 0.207032 -0.363281 0.8125 -0.25 1.160157 0.101562 z m 0 0" fill="url(#n)"/>
<path d="m 43.332031 74.777344 l 9.867188 9.867187 c 0.394531 0.390625 0.476562 0.871094 0.128906 1.066407 l -7.710937 5.253906 c -0.308594 0.210937 -0.785157 0.160156 -1.171876 -0.226563 l -6.984374 -6.988281 c -0.386719 -0.386719 -0.4375 -0.859375 -0.230469 -1.167969 l 5.234375 -7.8125 c 0.125 -0.285156 0.558594 -0.304687 0.867187 0.007813 z m 0 0" fill="url(#o)"/>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<filter id="a" height="100%" width="100%" x="0%" y="0%">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="b">
<g filter="url(#a)">
<rect fill-opacity="0.396" height="16" width="16"/>
</g>
</mask>
<clipPath id="c">
<rect height="152" width="192"/>
</clipPath>
<g clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -168 -16)">
<path d="m 29 112 c -4.433594 0 -8 -3.566406 -8 -8 v -2 c 0 4.433594 3.566406 8 8 8 h 88 c 4.433594 0 8 -3.566406 8 -8 v 2 c 0 4.433594 -3.566406 8 -8 8 z m 0 0" fill="#f6f5f4"/>
</g>
<g fill="#2e3436">
<path d="m 4 2 v 2 h 5.585938 l 2 -2 z m -2 3 c -0.5 0 -1 0.5 -1 1 v 4 c 0 0.5 0.5 1 1 1 h 1 v -2 h 2 c 0 -0.265625 0.105469 -0.519531 0.292969 -0.707031 l 3.292969 -3.292969 z m 11.414062 0 l -4 4 h 3.585938 v 2 h 1 c 0.5 0 1 -0.5 1 -1 v -4 c 0 -0.5 -0.5 -1 -1 -1 z m -9.414062 5 v 5 h 8 v -5 h -3.585938 l -0.707031 0.707031 c -0.1875 0.1875 -0.441406 0.292969 -0.707031 0.292969 h -1 c -0.550781 0 -1 -0.449219 -1 -1 z m 0 0"/>
<path d="m 6 10 h 1 l 9 -9 l -1 -1 l -9 9 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+9
View File
@@ -12,3 +12,12 @@ install_data('org.gtk.PrintEditor4.desktop', install_dir: gtk_applicationsdir)
# appdata
install_data('org.gtk.PrintEditor4.appdata.xml', install_dir: gtk_appdatadir)
# icons
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
foreach size: ['scalable', 'symbolic']
install_subdir('data/' + size,
install_dir: icontheme_dir
)
endforeach
@@ -2,7 +2,7 @@
Name=Print Editor
Comment=A simple editor demonstrating GTK printing
Exec=gtk4-print-editor %f
Icon=text-editor-symbolic
Icon=org.gtk.PrintEditor4.Devel
Terminal=false
Type=Application
StartupNotify=true
+3 -1
View File
@@ -633,7 +633,7 @@ activate_about (GSimpleAction *action,
"website", "http://www.gtk.org",
"comments", "Program to demonstrate GTK printing",
"authors", (const char *[]){ "Alexander Larsson", NULL },
"logo-icon-name", "text-editor-symbolic",
"logo-icon-name", "org.gtk.PrintEditor4.Devel",
"title", "About GTK Print Editor",
"system-information", sysinfo->str,
NULL);
@@ -781,6 +781,8 @@ activate (GApplication *app)
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (main_window), TRUE);
update_title (GTK_WINDOW (main_window));
gtk_widget_add_css_class (main_window, "devel");
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (main_window), box);
+4 -2
View File
@@ -65,9 +65,9 @@
<section>
<xi:include href="xml/gtksorter.xml" />
<xi:include href="xml/gtkcustomsorter.xml" />
<xi:include href="xml/gtkmultisorter.xml" />
<xi:include href="xml/gtkstringsorter.xml" />
<xi:include href="xml/gtknumericsorter.xml" />
<xi:include href="xml/gtkmultisorter.xml" />
</section>
<xi:include href="xml/gtkselectionmodel.xml" />
<section>
@@ -93,7 +93,9 @@
<xi:include href="xml/gtklistview.xml" />
<xi:include href="xml/gtkgridview.xml" />
<xi:include href="xml/gtkcolumnview.xml" />
<xi:include href="xml/gtkcolumnviewcolumn.xml" />
<section>
<xi:include href="xml/gtkcolumnviewcolumn.xml" />
</section>
<xi:include href="xml/gtkdropdown.xml" />
</chapter>
+19 -5
View File
@@ -1300,10 +1300,6 @@ gtk_file_chooser_get_current_name
<SUBSECTION>
gtk_file_chooser_get_file
gtk_file_chooser_set_file
gtk_file_chooser_select_file
gtk_file_chooser_unselect_file
gtk_file_chooser_select_all
gtk_file_chooser_unselect_all
gtk_file_chooser_get_files
gtk_file_chooser_set_current_folder
gtk_file_chooser_get_current_folder
@@ -1316,7 +1312,7 @@ gtk_file_chooser_get_filter
<SUBSECTION>
gtk_file_chooser_add_shortcut_folder
gtk_file_chooser_remove_shortcut_folder
gtk_file_chooser_list_shortcut_folders
gtk_file_chooser_get_shortcut_folders
<SUBSECTION>
gtk_file_chooser_add_choice
gtk_file_chooser_remove_choice
@@ -1444,6 +1440,8 @@ gtk_directory_list_get_file
gtk_directory_list_set_file
gtk_directory_list_get_io_priority
gtk_directory_list_set_io_priority
gtk_directory_list_get_monitored
gtk_directory_list_set_monitored
gtk_directory_list_is_loading
gtk_directory_list_get_error
<SUBSECTION Standard>
@@ -3422,6 +3420,7 @@ gtk_tree_list_row_get_type
<SECTION>
<FILE>gtktreeexpander</FILE>
<TITLE>GtkTreeExpander</TITLE>
GtkTreeExpander
gtk_tree_expander_new
gtk_tree_expander_get_child
gtk_tree_expander_set_child
@@ -7543,12 +7542,27 @@ gtk_expression_watch_unwatch
<SUBSECTION>
gtk_property_expression_new
gtk_property_expression_new_for_pspec
gtk_property_expression_get_expression
gtk_property_expression_get_pspec
gtk_constant_expression_new
gtk_constant_expression_new_for_value
gtk_constant_expression_get_value
gtk_object_expression_new
gtk_object_expression_get_object
gtk_closure_expression_new
gtk_cclosure_expression_new
<SUBSECTION>
GTK_VALUE_HOLDS_EXPRESSION
gtk_value_set_expression
gtk_value_take_expression
gtk_value_get_expression
gtk_value_dup_expression
<SUBSECTION>
GtkParamSpecExpression
gtk_param_spec_expression
<SUBSECTION Standard>
GTK_IS_EXPRESSION
GTK_TYPE_EXPRESSION
+7
View File
@@ -19,6 +19,7 @@ gtk_assistant_get_type
gtk_assistant_page_get_type
gtk_bin_layout_get_type
gtk_bitset_get_type
gtk_expression_get_type
gtk_bookmark_list_get_type
gtk_box_get_type
gtk_box_layout_get_type
@@ -29,6 +30,7 @@ gtk_builder_list_item_factory_get_type
gtk_builder_scope_get_type
gtk_button_get_type
gtk_calendar_get_type
gtk_cclosure_expression_get_type
gtk_cell_area_get_type
gtk_cell_area_box_get_type
gtk_cell_area_context_get_type
@@ -46,6 +48,7 @@ gtk_cell_renderer_toggle_get_type
gtk_cell_view_get_type
gtk_center_layout_get_type
gtk_check_button_get_type
gtk_closure_expression_get_type
gtk_color_button_get_type
gtk_color_chooser_get_type
gtk_color_chooser_dialog_get_type
@@ -54,6 +57,7 @@ gtk_column_view_get_type
gtk_column_view_column_get_type
gtk_combo_box_get_type
gtk_combo_box_text_get_type
gtk_constant_expression_get_type
gtk_constraint_get_type
gtk_constraint_guide_get_type
gtk_constraint_layout_get_type
@@ -150,6 +154,7 @@ gtk_no_selection_get_type
gtk_notebook_get_type
gtk_notebook_page_get_type
gtk_numeric_sorter_get_type
gtk_object_expression_get_type
gtk_orientable_get_type
gtk_overlay_get_type
gtk_overlay_layout_get_type
@@ -172,6 +177,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_expression_get_type
gtk_radio_button_get_type
gtk_range_get_type
gtk_recent_manager_get_type
@@ -229,6 +235,7 @@ gtk_text_view_get_type
gtk_toggle_button_get_type
gtk_tree_drag_dest_get_type
gtk_tree_drag_source_get_type
gtk_tree_expander_get_type
gtk_tree_list_model_get_type
gtk_tree_list_row_get_type
gtk_tree_list_row_sorter_get_type
+1 -1
View File
@@ -170,7 +170,7 @@ in GTK 3, you can prepare for the switch by using gtk_widget_destroy()
only on toplevel windows, and replace all other uses with
gtk_container_remove() or g_object_unref().
### Reduce the use of generic container APIs</title>
### Reduce the use of generic container APIs
GTK 4 removes gtk_container_add() and gtk_container_remove(). While there
is not always a replacement for gtk_container_remove() in GTK 3, you can
+1 -1
View File
@@ -183,7 +183,7 @@ transitioning code for easy lookup:
| #GtkTreeModel | #GListModel |
| #GtkTreePath | #guint position, #GtkTreeListRow |
| #GtkTreeIter | #guint position |
| GtkTreeRowReference | #GObject item |
| #GtkTreeRowReference | #GObject item |
| #GtkListStore | #GListStore |
| #GtkTreeStore | #GtkTreeListModel, #GtkTreeExpander |
| #GtkTreeSelection | #GtkSelectionModel |
+283
View File
@@ -0,0 +1,283 @@
/*
* Copyright © 2020 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 <glib.h>
G_BEGIN_DECLS
#ifndef GDK_ARRAY_TYPE_NAME
#define GDK_ARRAY_TYPE_NAME GdkArray
#endif
#ifndef GDK_ARRAY_NAME
#define GDK_ARRAY_NAME gdk_array
#endif
#ifndef GDK_ARRAY_ELEMENT_TYPE
#define GDK_ARRAY_ELEMENT_TYPE gpointer
#endif
#ifdef GDK_ARRAY_PREALLOC
#if GDK_ARRAY_PREALLOC == 0
#undef GDK_ARRAY_PREALLOC
#endif
#endif
#ifdef GDK_ARRAY_NULL_TERMINATED
#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
#else
#define GDK_ARRAY_REAL_SIZE(_size) (_size)
#endif
/* make this readable */
#define _T_ GDK_ARRAY_ELEMENT_TYPE
#define GdkArray GDK_ARRAY_TYPE_NAME
#define gdk_array_paste_more(GDK_ARRAY_NAME, func_name) GDK_ARRAY_NAME ## _ ## func_name
#define gdk_array_paste(GDK_ARRAY_NAME, func_name) gdk_array_paste_more (GDK_ARRAY_NAME, func_name)
#define gdk_array(func_name) gdk_array_paste (GDK_ARRAY_NAME, func_name)
typedef struct GdkArray GdkArray;
struct GdkArray
{
_T_ *start;
_T_ *end;
_T_ *end_allocation;
#ifdef GDK_ARRAY_PREALLOC
_T_ preallocated[GDK_ARRAY_REAL_SIZE(GDK_ARRAY_PREALLOC)];
#endif
};
/* no G_GNUC_UNUSED here, if you don't use an array type, remove it. */
static inline void
gdk_array(init) (GdkArray *self)
{
#ifdef GDK_ARRAY_PREALLOC
self->start = self->preallocated;
self->end = self->start;
self->end_allocation = self->start + GDK_ARRAY_PREALLOC;
#ifdef GDK_ARRAY_NULL_TERMINATED
*self->start = *(_T_[1]) {};
#endif
#else
self->start = NULL;
self->end = NULL;
self->end_allocation = NULL;
#endif
}
static inline void
gdk_array(free_elements) (_T_ *start,
_T_ *end)
{
#ifdef GDK_ARRAY_FREE_FUNC
_T_ *e;
for (e = start; e < end; e++)
#ifdef GDK_ARRAY_BY_VALUE
GDK_ARRAY_FREE_FUNC (e);
#else
GDK_ARRAY_FREE_FUNC (*e);
#endif
#endif
}
/* no G_GNUC_UNUSED here */
static inline void
gdk_array(clear) (GdkArray *self)
{
gdk_array(free_elements) (self->start, self->end);
#ifdef GDK_ARRAY_PREALLOC
if (self->start != self->preallocated)
#endif
g_free (self->start);
gdk_array(init) (self);
}
G_GNUC_UNUSED static inline _T_ *
gdk_array(get_data) (const GdkArray *self)
{
return self->start;
}
G_GNUC_UNUSED static inline _T_ *
gdk_array(index) (const GdkArray *self,
gsize pos)
{
return self->start + pos;
}
G_GNUC_UNUSED static inline gsize
gdk_array(get_capacity) (const GdkArray *self)
{
return self->end_allocation - self->start;
}
G_GNUC_UNUSED static inline gsize
gdk_array(get_size) (const GdkArray *self)
{
return self->end - self->start;
}
G_GNUC_UNUSED static inline gboolean
gdk_array(is_empty) (const GdkArray *self)
{
return self->end == self->start;
}
G_GNUC_UNUSED static void
gdk_array(reserve) (GdkArray *self,
gsize n)
{
gsize new_size, size;
if (n <= gdk_array(get_capacity) (self))
return;
size = gdk_array(get_size) (self);
new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
#ifdef GDK_ARRAY_PREALLOC
if (self->start == self->preallocated)
{
self->start = g_new (_T_, new_size);
memcpy (self->start, self->preallocated, sizeof (_T_) * GDK_ARRAY_REAL_SIZE (size));
}
else
#endif
#ifdef GDK_ARRAY_NULL_TERMINATED
if (self->start == NULL)
{
self->start = g_new (_T_, new_size);
*self->start = *(_T_[1]) {};
}
else
#endif
self->start = g_renew (_T_, self->start, new_size);
self->end = self->start + size;
self->end_allocation = self->start + new_size;
#ifdef GDK_ARRAY_NULL_TERMINATED
self->end_allocation--;
#endif
}
G_GNUC_UNUSED static void
gdk_array(splice) (GdkArray *self,
gsize pos,
gsize removed,
_T_ *additions,
gsize added)
{
gsize size;
gsize remaining;
size = gdk_array(get_size) (self);
g_assert (pos + removed <= size);
remaining = size - pos - removed;
gdk_array(free_elements) (gdk_array(index) (self, pos),
gdk_array(index) (self, pos + removed));
gdk_array(reserve) (self, size - removed + added);
if (GDK_ARRAY_REAL_SIZE (remaining) && removed != added)
memmove (gdk_array(index) (self, pos + added),
gdk_array(index) (self, pos + removed),
GDK_ARRAY_REAL_SIZE (remaining) * sizeof (_T_));
if (added)
{
if (additions)
memcpy (gdk_array(index) (self, pos),
additions,
added * sizeof (_T_));
else
memset (gdk_array(index) (self, pos), 0, added * sizeof (_T_));
}
/* might overflow, but does the right thing */
self->end += added - removed;
}
G_GNUC_UNUSED static void
gdk_array(set_size) (GdkArray *self,
gsize new_size)
{
gsize old_size = gdk_array(get_size) (self);
if (new_size > old_size)
gdk_array(splice) (self, old_size, 0, NULL, new_size - old_size);
else
gdk_array(splice) (self, new_size, old_size - new_size, NULL, 0);
}
G_GNUC_UNUSED static void
gdk_array(append) (GdkArray *self,
#ifdef GDK_ARRAY_BY_VALUE
_T_ *value)
#else
_T_ value)
#endif
{
gdk_array(splice) (self,
gdk_array(get_size) (self),
0,
#ifdef GDK_ARRAY_BY_VALUE
value,
#else
&value,
#endif
1);
}
#ifdef GDK_ARRAY_BY_VALUE
G_GNUC_UNUSED static _T_ *
gdk_array(get) (const GdkArray *self,
gsize pos)
{
return gdk_array(index) (self, pos);
}
#else
G_GNUC_UNUSED static _T_
gdk_array(get) (const GdkArray *self,
gsize pos)
{
return *gdk_array(index) (self, pos);
}
#endif
#ifndef GDK_ARRAY_NO_UNDEF
#undef _T_
#undef GdkArray
#undef gdk_array_paste_more
#undef gdk_array_paste
#undef gdk_array
#undef GDK_ARRAY_REAL_SIZE
#undef GDK_ARRAY_BY_VALUE
#undef GDK_ARRAY_ELEMENT_TYPE
#undef GDK_ARRAY_FREE_FUNC
#undef GDK_ARRAY_NAME
#undef GDK_ARRAY_NULL_TERMINATED
#undef GDK_ARRAY_PREALLOC
#undef GDK_ARRAY_TYPE_NAME
#endif
+1 -1
View File
@@ -354,7 +354,7 @@ gdk_rgba_equal (gconstpointer p1,
*
* Returns a textual specification of @rgba in the form
* `rgb(r,g,b)` or
* `rgba(r g,b,a)`,
* `rgba(r,g,b,a)`,
* where “r”, “g”, “b” and “a” represent the red, green,
* blue and alpha values respectively. “r”, “g”, and “b” are
* represented as integers in the range 0 to 255, and “a”
+6
View File
@@ -544,6 +544,12 @@ gdk_registry_handle_global (void *data,
gdk_wayland_display_init_xdg_output (display_wayland);
_gdk_wayland_display_async_roundtrip (display_wayland);
}
else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
{
display_wayland->idle_inhibit_manager =
wl_registry_bind (display_wayland->wl_registry, id,
&zwp_idle_inhibit_manager_v1_interface, 1);
}
g_hash_table_insert (display_wayland->known_globals,
GUINT_TO_POINTER (id), g_strdup (interface));
+2
View File
@@ -35,6 +35,7 @@
#include <gdk/wayland/keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h>
#include <gdk/wayland/server-decoration-client-protocol.h>
#include <gdk/wayland/xdg-output-unstable-v1-client-protocol.h>
#include <gdk/wayland/idle-inhibit-unstable-v1-client-protocol.h>
#include <glib.h>
#include <gdk/gdkkeys.h>
@@ -109,6 +110,7 @@ struct _GdkWaylandDisplay
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
struct org_kde_kwin_server_decoration_manager *server_decoration_manager;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
GList *async_roundtrips;
+69 -13
View File
@@ -191,6 +191,9 @@ struct _GdkWaylandSurface
struct zxdg_imported_v1 *imported_transient_for;
GHashTable *shortcuts_inhibitors;
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
size_t idle_inhibitor_refcount;
};
struct _GdkWaylandSurfaceClass
@@ -1648,6 +1651,38 @@ create_zxdg_toplevel_v6_resources (GdkSurface *surface)
surface);
}
void
gdk_wayland_surface_set_application_id (GdkSurface *surface, const char* application_id)
{
GdkWaylandSurface *impl;
GdkWaylandDisplay *display_wayland;
g_return_if_fail (application_id != NULL);
if (GDK_SURFACE_DESTROYED (surface))
return;
if (!is_realized_toplevel (surface))
return;
display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
impl = GDK_WAYLAND_SURFACE (surface);
switch (display_wayland->shell_variant)
{
case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
xdg_toplevel_set_app_id (impl->display_server.xdg_toplevel,
application_id);
break;
case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
zxdg_toplevel_v6_set_app_id (impl->display_server.zxdg_toplevel_v6,
application_id);
break;
default:
g_assert_not_reached ();
}
}
static void
gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
{
@@ -1702,19 +1737,7 @@ gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
if (app_id == NULL)
app_id = "GTK+ Application";
switch (display_wayland->shell_variant)
{
case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
xdg_toplevel_set_app_id (impl->display_server.xdg_toplevel,
app_id);
break;
case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
zxdg_toplevel_v6_set_app_id (impl->display_server.zxdg_toplevel_v6,
app_id);
break;
default:
g_assert_not_reached ();
}
gdk_wayland_surface_set_application_id (surface, app_id);
maybe_set_gtk_surface_dbus_properties (surface);
maybe_set_gtk_surface_modal (surface);
@@ -1964,6 +1987,39 @@ gdk_wayland_surface_announce_csd (GdkSurface *surface)
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
}
gboolean
gdk_wayland_surface_inhibit_idle (GdkSurface *surface)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
if (!display_wayland->idle_inhibit_manager)
return false;
if (!impl->idle_inhibitor)
{
g_assert (impl->idle_inhibitor_refcount == 0);
impl->idle_inhibitor =
zwp_idle_inhibit_manager_v1_create_inhibitor (display_wayland->idle_inhibit_manager,
impl->display_server.wl_surface);
}
++impl->idle_inhibitor_refcount;
return true;
}
void
gdk_wayland_surface_uninhibit_idle (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
g_assert (impl->idle_inhibitor && impl->idle_inhibitor_refcount > 0);
if (--impl->idle_inhibitor_refcount == 0)
{
zwp_idle_inhibitor_v1_destroy (impl->idle_inhibitor);
impl->idle_inhibitor = NULL;
}
}
static void
calculate_popup_rect (GdkSurface *surface,
GdkPopupLayout *layout,
+7
View File
@@ -74,8 +74,15 @@ GDK_AVAILABLE_IN_ALL
gboolean gdk_wayland_surface_set_transient_for_exported (GdkSurface *surface,
char *parent_handle_str);
GDK_AVAILABLE_IN_ALL
void gdk_wayland_surface_set_application_id (GdkSurface *surface,
const char *application_id);
void gdk_wayland_surface_announce_csd (GdkSurface *surface);
gboolean gdk_wayland_surface_inhibit_idle (GdkSurface *surface);
void gdk_wayland_surface_uninhibit_idle (GdkSurface *surface);
G_END_DECLS
#endif /* __GDK_WAYLAND_SURFACE_H__ */
+1
View File
@@ -54,6 +54,7 @@ proto_sources = [
['keyboard-shortcuts-inhibit', 'unstable', 'v1', ],
['server-decoration', 'private' ],
['xdg-output', 'unstable', 'v1', ],
['idle-inhibit', 'unstable', 'v1', ],
]
gdk_wayland_gen_headers = []
+2
View File
@@ -653,6 +653,8 @@ gdk_x11_clipboard_store_async (GdkClipboard *clipboard,
GDK_DISPLAY_NOTE (display, CLIPBOARD,
g_printerr ("%s: X error during ConvertSelection() while storing selection: %d\n", cb->selection, error));
}
g_free (atoms);
}
static gboolean
+14 -2
View File
@@ -1874,6 +1874,7 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
case XI_Leave:
{
XIEnterEvent *xev = (XIEnterEvent *) ev;
GdkModifierType state;
GDK_DISPLAY_NOTE (display, EVENTS,
g_message ("%s notify:\twindow %ld\n\tsubwindow:%ld\n"
@@ -1890,6 +1891,18 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
source_device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (xev->sourceid));
state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
/* Ignore normal crossing events while there is an implicit grab.
* We will receive a crossing event with one of the other details if
* the implicit grab were finished (eg. releasing the button outside
* the window triggers a XINotifyUngrab leave).
*/
if (xev->mode == XINotifyNormal &&
(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)))
break;
if (ev->evtype == XI_Enter &&
xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab &&
GDK_IS_TOPLEVEL (surface))
@@ -1916,12 +1929,11 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
device,
source_device,
xev->time,
_gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
state,
(double) xev->event_x / scale,
(double) xev->event_y / scale,
translate_crossing_mode (xev->mode),
translate_notify_type (xev->detail));
}
break;
case XI_FocusIn:
+1 -1
View File
@@ -184,7 +184,7 @@ gdk_x11_gl_context_end_frame (GdkDrawContext *draw_context,
gdk_x11_surface_pre_damage (surface);
#ifdef HAVE_XDAMAGE
if (context_x11->xdamage != 0)
if (context_x11->xdamage != 0 && _gdk_x11_surface_syncs_frames (surface))
{
g_assert (context_x11->frame_fence == 0);
+4 -4
View File
@@ -360,8 +360,8 @@ gdk_x11_surface_begin_frame (GdkSurface *surface,
}
}
static gboolean
should_sync_frame_drawing (GdkSurface *surface)
gboolean
_gdk_x11_surface_syncs_frames (GdkSurface *surface)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
@@ -395,7 +395,7 @@ 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_sync_negotiated = _gdk_x11_surface_syncs_frames (surface);
gboolean frame_done_painting = !impl->toplevel->frame_pending;
#ifdef HAVE_XDAMAGE
@@ -478,7 +478,7 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
maybe_sync_counter_for_end_frame (surface);
if (should_sync_frame_drawing (surface))
if (_gdk_x11_surface_syncs_frames (surface))
{
impl->toplevel->frame_pending = TRUE;
gdk_surface_freeze_updates (surface);
+2
View File
@@ -179,6 +179,7 @@ GdkCursor *_gdk_x11_surface_get_cursor (GdkSurface *window);
void _gdk_x11_surface_update_size (GdkX11Surface *impl);
void _gdk_x11_surface_set_surface_scale (GdkSurface *window,
int scale);
gboolean _gdk_x11_surface_syncs_frames (GdkSurface *surface);
void gdk_x11_surface_pre_damage (GdkSurface *surface);
@@ -188,6 +189,7 @@ void gdk_x11_surface_move (GdkSurface *surface,
void gdk_x11_surface_check_monitor (GdkSurface *surface,
GdkMonitor *monitor);
G_END_DECLS
#endif /* __GDK_X11_SURFACE__ */
+180 -120
View File
@@ -70,7 +70,6 @@ typedef enum
RESET_CLIP = 1 << 1,
RESET_OPACITY = 1 << 2,
DUMP_FRAMEBUFFER = 1 << 3,
CENTER_CHILD = 1 << 4,
NO_CACHE_PLZ = 1 << 5,
} OffscreenFlags;
@@ -906,6 +905,7 @@ upload_texture (GskGLRenderer *self,
}
else
{
out_region->texture_id =
gsk_gl_driver_get_texture_for_texture (self->gl_driver,
texture,
@@ -1152,6 +1152,59 @@ rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
return graphene_rect_contains_rect (&inner, rect);
}
/* Current clip is NOT rounded but new one is definitely! */
static inline bool
intersect_rounded_rectilinear (const graphene_rect_t *non_rounded,
const GskRoundedRect *rounded,
GskRoundedRect *result)
{
int n_corners = 0;
bool corners[4];
/* Intersects with top left corner? */
n_corners += corners[0] = rounded_rect_has_corner (rounded, 0) &&
graphene_rect_intersection (non_rounded,
&rounded_rect_corner (rounded, 0), NULL);
/* top right? */
n_corners += corners[1] = rounded_rect_has_corner (rounded, 1) &&
graphene_rect_intersection (non_rounded,
&rounded_rect_corner (rounded, 1), NULL);
/* bottom right? */
n_corners += corners[2] = rounded_rect_has_corner (rounded, 2) &&
graphene_rect_intersection (non_rounded,
&rounded_rect_corner (rounded, 2), NULL);
/* bottom left */
n_corners += corners[3] = rounded_rect_has_corner (rounded, 3) &&
graphene_rect_intersection (non_rounded,
&rounded_rect_corner (rounded, 3), NULL);
if (corners[0] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 0)))
return false;
if (corners[1] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 1)))
return false;
if (corners[2] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 2)))
return false;
if (corners[3] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 3)))
return false;
/* We do intersect with at least one of the corners, but in such a way that the
* intersection between the two clips can still be represented by a single rounded
* rect in a trivial way. do that. */
graphene_rect_intersection (non_rounded, &rounded->bounds, &result->bounds);
for (int i = 0; i < 4; i++)
{
if (corners[i])
result->corner[i] = rounded->corner[i];
else
result->corner[i].width = result->corner[i].height = 0;
}
return true;
}
/* This code intersects the current (maybe rounded) clip with the new
* non-rounded clip */
static inline void
render_clipped_child (GskGLRenderer *self,
RenderOpBuilder *builder,
@@ -1159,112 +1212,57 @@ render_clipped_child (GskGLRenderer *self,
GskRenderNode *child)
{
graphene_rect_t transformed_clip;
GskRoundedRect child_clip;
GskRoundedRect intersection;
ops_transform_bounds_modelview (builder, clip, &transformed_clip);
if (builder->clip_is_rectilinear)
goto trivial;
{
const GskRoundedRect *cur_clip = builder->current_clip;
int n_corners = 0;
bool corners[4];
/* Intersects with top left corner? */
n_corners += corners[0] = rounded_rect_has_corner (cur_clip, 0) &&
graphene_rect_intersection (&transformed_clip,
&rounded_rect_corner (cur_clip, 0), NULL);
/* top right? */
n_corners += corners[1] = rounded_rect_has_corner (cur_clip, 1) &&
graphene_rect_intersection (&transformed_clip,
&rounded_rect_corner (cur_clip, 1), NULL);
/* bottom right? */
n_corners += corners[2] = rounded_rect_has_corner (cur_clip, 2) &&
graphene_rect_intersection (&transformed_clip,
&rounded_rect_corner (cur_clip, 2), NULL);
/* bottom left */
n_corners += corners[3] = rounded_rect_has_corner (cur_clip, 3) &&
graphene_rect_intersection (&transformed_clip,
&rounded_rect_corner (cur_clip, 3), NULL);
if (n_corners == 0)
goto trivial;
if (corners[0] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 0)))
goto rtt;
if (corners[1] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 1)))
goto rtt;
if (corners[2] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 2)))
goto rtt;
if (corners[3] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 3)))
goto rtt;
/* We do intersect with at least one of the corners, but in such a way that the
* intersection between the two clips can still be represented by a single rounded
* rect in a trivial way. do that. */
{
GskRoundedRect real_intersection;
memset (&intersection, 0, sizeof (GskRoundedRect));
graphene_rect_intersection (&transformed_clip,
&builder->current_clip->bounds,
&intersection.bounds);
graphene_rect_intersection (&transformed_clip, &cur_clip->bounds, &real_intersection.bounds);
for (int i = 0; i < 4; i++)
{
if (corners[i])
real_intersection.corner[i] = cur_clip->corner[i];
else
real_intersection.corner[i].width = real_intersection.corner[i].height = 0;
}
/* Draw with that new clip */
ops_push_clip (builder, &real_intersection);
ops_push_clip (builder, &intersection);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_clip (builder);
}
return;
}
else if (intersect_rounded_rectilinear (&transformed_clip,
builder->current_clip,
&intersection))
{
ops_push_clip (builder, &intersection);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_clip (builder);
}
else
{
/* well fuck */
const float scale = ops_get_scale (builder);
gboolean is_offscreen;
TextureRegion region;
GskRoundedRect scaled_clip;
rtt:
{
/* well fuck */
const float scale = ops_get_scale (builder);
gboolean is_offscreen;
TextureRegion region;
GskRoundedRect scaled_clip;
memset (&scaled_clip, 0, sizeof (GskRoundedRect));
memset (&scaled_clip, 0, sizeof (GskRoundedRect));
scaled_clip.bounds.origin.x = clip->origin.x * scale;
scaled_clip.bounds.origin.y = clip->origin.y * scale;
scaled_clip.bounds.size.width = clip->size.width * scale;
scaled_clip.bounds.size.height = clip->size.height * scale;
scaled_clip.bounds.origin.x = clip->origin.x * scale;
scaled_clip.bounds.origin.y = clip->origin.y * scale;
scaled_clip.bounds.size.width = clip->size.width * scale;
scaled_clip.bounds.size.height = clip->size.height * scale;
ops_push_clip (builder, &scaled_clip);
if (!add_offscreen_ops (self, builder, &child->bounds,
child,
&region, &is_offscreen,
RESET_OPACITY | FORCE_OFFSCREEN))
g_assert_not_reached ();
ops_pop_clip (builder);
ops_push_clip (builder, &scaled_clip);
if (!add_offscreen_ops (self, builder, &child->bounds,
child,
&region, &is_offscreen,
RESET_OPACITY | FORCE_OFFSCREEN))
g_assert_not_reached ();
ops_pop_clip (builder);
ops_set_program (builder, &self->programs->blit_program);
ops_set_texture (builder, region.texture_id);
ops_set_program (builder, &self->programs->blit_program);
ops_set_texture (builder, region.texture_id);
load_offscreen_vertex_data (ops_draw (builder, NULL), child, builder);
return;
}
trivial:
memset (&child_clip, 0, sizeof (GskRoundedRect));
graphene_rect_intersection (&transformed_clip,
&builder->current_clip->bounds,
&child_clip.bounds);
ops_push_clip (builder, &child_clip);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_clip (builder);
return;
load_offscreen_vertex_data (ops_draw (builder, NULL), child, builder);
}
}
static inline void
@@ -1294,6 +1292,29 @@ render_rounded_clip_node (GskGLRenderer *self,
return;
ops_transform_bounds_modelview (builder, &clip->bounds, &transformed_clip.bounds);
for (i = 0; i < 4; i ++)
{
transformed_clip.corner[i].width = clip->corner[i].width * scale;
transformed_clip.corner[i].height = clip->corner[i].height * scale;
}
if (builder->clip_is_rectilinear)
{
GskRoundedRect intersected_clip;
if (intersect_rounded_rectilinear (&builder->current_clip->bounds,
&transformed_clip,
&intersected_clip))
{
ops_push_clip (builder, &intersected_clip);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_clip (builder);
return;
}
}
/* After this point we are really working with a new and a current clip
* which both have rounded corners. */
if (!ops_has_clip (builder))
need_offscreen = FALSE;
@@ -1307,12 +1328,16 @@ render_rounded_clip_node (GskGLRenderer *self,
{
/* If they don't intersect at all, we can simply set
* the new clip and add the render ops */
for (i = 0; i < 4; i ++)
/* If the new clip entirely contains the current clip, the intersection is simply
* the current clip, so we can ignore the new one */
if (rounded_inner_rect_contains_rect (&transformed_clip, &builder->current_clip->bounds))
{
transformed_clip.corner[i].width = clip->corner[i].width * scale;
transformed_clip.corner[i].height = clip->corner[i].height * scale;
gsk_gl_renderer_add_render_ops (self, child, builder);
return;
}
/* TODO: Intersect current and new clip */
ops_push_clip (builder, &transformed_clip);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_clip (builder);
@@ -1354,7 +1379,6 @@ render_rounded_clip_node (GskGLRenderer *self,
load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder);
}
/* Else this node is entirely out of the current clip node and we don't draw it anyway. */
}
static inline void
@@ -1762,7 +1786,6 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
}
static GdkRGBA COLOR_WHITE = { 1, 1, 1, 1 };
static inline void
render_outset_shadow_node (GskGLRenderer *self,
@@ -1783,19 +1806,32 @@ render_outset_shadow_node (GskGLRenderer *self,
OpShadow *shadow;
int blurred_texture_id;
int cached_tid;
bool do_slicing;
/* scaled_outline is the minimal outline we need to draw the given drop shadow,
* enlarged by the spread and offset by the blur radius. */
scaled_outline = *outline;
/* Shrink our outline to the minimum size that can still hold all the border radii */
gsk_rounded_rect_shrink_to_minimum (&scaled_outline);
/* Increase by the spread */
gsk_rounded_rect_shrink (&scaled_outline, -spread, -spread, -spread, -spread);
/* Grow bounds but don't grow corners */
graphene_rect_inset (&scaled_outline.bounds, - extra_blur_pixels, - extra_blur_pixels);
/* For the center part, we add a few pixels */
scaled_outline.bounds.size.width += SHADOW_EXTRA_SIZE;
scaled_outline.bounds.size.height += SHADOW_EXTRA_SIZE;
if (outline->bounds.size.width < blur_extra ||
outline->bounds.size.height < blur_extra)
{
do_slicing = false;
gsk_rounded_rect_shrink (&scaled_outline, -spread, -spread, -spread, -spread);
}
else
{
/* Shrink our outline to the minimum size that can still hold all the border radii */
gsk_rounded_rect_shrink_to_minimum (&scaled_outline);
/* Increase by the spread */
gsk_rounded_rect_shrink (&scaled_outline, -spread, -spread, -spread, -spread);
/* Grow bounds but don't grow corners */
graphene_rect_inset (&scaled_outline.bounds, - blur_extra / 2.0, - blur_extra / 2.0);
/* For the center part, we add a few pixels */
scaled_outline.bounds.size.width += SHADOW_EXTRA_SIZE;
scaled_outline.bounds.size.height += SHADOW_EXTRA_SIZE;
do_slicing = true;
}
texture_width = (int)ceil ((scaled_outline.bounds.size.width + blur_extra) * scale);
texture_height = (int)ceil ((scaled_outline.bounds.size.height + blur_extra) * scale);
@@ -1880,6 +1916,41 @@ render_outset_shadow_node (GskGLRenderer *self,
blurred_texture_id = cached_tid;
}
if (!do_slicing)
{
const float min_x = floorf (builder->dx + outline->bounds.origin.x - spread - (blur_extra / 2.0) + dx);
const float min_y = floorf (builder->dy + outline->bounds.origin.y - spread - (blur_extra / 2.0) + dy);
float x1, x2, y1, y2, tx1, tx2, ty1, ty2;
ops_set_program (builder, &self->programs->outset_shadow_program);
ops_set_color (builder, color);
ops_set_texture (builder, blurred_texture_id);
shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
shadow->outline = transform_rect (self, builder, outline);
tx1 = 0; tx2 = 1;
ty1 = 0; ty2 = 1;
x1 = min_x;
x2 = min_x + texture_width / scale;
y1 = min_y;
y2 = min_y + texture_height / scale;
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { x1, y1 }, { tx1, ty2 }, },
{ { x1, y2 }, { tx1, ty1 }, },
{ { x2, y1 }, { tx2, ty2 }, },
{ { x2, y2 }, { tx2, ty1 }, },
{ { x1, y2 }, { tx1, ty1 }, },
{ { x2, y1 }, { tx2, ty2 }, },
});
return;
}
ops_set_program (builder, &self->programs->outset_shadow_program);
ops_set_color (builder, color);
ops_set_texture (builder, blurred_texture_id);
@@ -3317,19 +3388,8 @@ add_offscreen_ops (GskGLRenderer *self,
bounds->origin.y * scale,
width, height));
if (flags & CENTER_CHILD)
{
ops_offset (builder,
(bounds->size.width - child_node->bounds.size.width) / 2.0 -
child_node->bounds.origin.x,
(bounds->size.height - child_node->bounds.size.height) / 2.0 -
child_node->bounds.origin.y);
}
else
{
builder->dx = 0;
builder->dy = 0;
}
builder->dx = 0;
builder->dy = 0;
if (flags & RESET_OPACITY)
prev_opacity = ops_set_opacity (builder, 1.0);
+2 -1
View File
@@ -123,7 +123,8 @@ gsk_transform_alloc (const GskTransformClass *transform_class,
self->transform_class = transform_class;
self->category = next ? MIN (category, next->category) : category;
self->next = gsk_transform_is_identity (next) ? NULL : next;
self->next = gsk_transform_is_identity (next) ? NULL : gsk_transform_ref (next);
g_clear_pointer (&next, gsk_transform_unref);
return self;
}
-2
View File
@@ -233,8 +233,6 @@
#include <gtk/gtkslicelistmodel.h>
#include <gtk/gtksnapshot.h>
#include <gtk/gtksorter.h>
#include <gtk/gtksor2listmodel.h>
#include <gtk/gtksor3listmodel.h>
#include <gtk/gtksortlistmodel.h>
#include <gtk/gtkstacksidebar.h>
#include <gtk/gtksizegroup.h>
+103 -1
View File
@@ -1,6 +1,7 @@
/*
* Copyright © 2010 Codethink Limited
* Copyright © 2013 Canonical Limited
* Copyright © 2020 Emmanuel Gil Peyrot
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,12 +25,42 @@
#include "gtknative.h"
#include <gdk/wayland/gdkwayland.h>
#include <gdk/wayland/gdkdisplay-wayland.h>
#include <gdk/wayland/idle-inhibit-unstable-v1-client-protocol.h>
typedef GtkApplicationImplDBusClass GtkApplicationImplWaylandClass;
typedef struct
{
GtkApplicationImplDBusClass parent_class;
/* stores the dbus version of the overriden methods */
guint (*dbus_inhibit) (GtkApplicationImpl *impl,
GtkWindow *window,
GtkApplicationInhibitFlags flags,
const gchar *reason);
void (*dbus_uninhibit) (GtkApplicationImpl *impl,
guint cookie);
} GtkApplicationImplWaylandClass;
typedef struct
{
guint cookie;
guint dbus_cookie;
GtkApplicationInhibitFlags flags;
GdkSurface *surface;
} GtkApplicationWaylandInhibitor;
static void
gtk_application_wayland_inhibitor_free (GtkApplicationWaylandInhibitor *inhibitor)
{
g_slice_free (GtkApplicationWaylandInhibitor, inhibitor);
}
typedef struct
{
GtkApplicationImplDBus dbus;
GSList *inhibitors;
guint next_cookie;
} GtkApplicationImplWayland;
@@ -72,6 +103,70 @@ gtk_application_impl_wayland_before_emit (GtkApplicationImpl *impl,
gdk_wayland_display_set_startup_notification_id (gdk_display_get_default (), startup_notification_id);
}
static guint
gtk_application_impl_wayland_inhibit (GtkApplicationImpl *impl,
GtkWindow *window,
GtkApplicationInhibitFlags flags,
const gchar *reason)
{
GtkApplicationImplWayland *wayland = (GtkApplicationImplWayland *) impl;
GdkSurface *surface;
GtkApplicationWaylandInhibitor *inhibitor;
gboolean success;
if (!flags)
return 0;
inhibitor = g_slice_new (GtkApplicationWaylandInhibitor);
inhibitor->cookie = ++wayland->next_cookie;
inhibitor->flags = flags;
wayland->inhibitors = g_slist_prepend (wayland->inhibitors, inhibitor);
if (flags & GTK_APPLICATION_INHIBIT_IDLE)
{
surface = gtk_native_get_surface (GTK_NATIVE (window));
if (GDK_IS_WAYLAND_SURFACE (surface))
{
success = gdk_wayland_surface_inhibit_idle (surface);
if (success)
{
flags &= ~GTK_APPLICATION_INHIBIT_IDLE;
inhibitor->surface = surface;
}
}
}
inhibitor->dbus_cookie = ((GtkApplicationImplWaylandClass *) G_OBJECT_GET_CLASS (wayland))->dbus_inhibit (impl, window, flags, reason);
return inhibitor->cookie;
}
static void
gtk_application_impl_wayland_uninhibit (GtkApplicationImpl *impl,
guint cookie)
{
GtkApplicationImplWayland *wayland = (GtkApplicationImplWayland *) impl;
GSList *iter;
for (iter = wayland->inhibitors; iter; iter = iter->next)
{
GtkApplicationWaylandInhibitor *inhibitor = iter->data;
if (inhibitor->cookie == cookie)
{
if (inhibitor->dbus_cookie)
((GtkApplicationImplWaylandClass *) G_OBJECT_GET_CLASS (wayland))->dbus_uninhibit (impl, inhibitor->dbus_cookie);
if (inhibitor->surface)
gdk_wayland_surface_uninhibit_idle (inhibitor->surface);
gtk_application_wayland_inhibitor_free (inhibitor);
wayland->inhibitors = g_slist_delete_link (wayland->inhibitors, iter);
return;
}
}
g_warning ("Invalid inhibitor cookie");
}
static void
gtk_application_impl_wayland_init (GtkApplicationImplWayland *wayland)
{
@@ -82,8 +177,15 @@ gtk_application_impl_wayland_class_init (GtkApplicationImplWaylandClass *class)
{
GtkApplicationImplClass *impl_class = GTK_APPLICATION_IMPL_CLASS (class);
class->dbus_inhibit = impl_class->inhibit;
class->dbus_uninhibit = impl_class->uninhibit;
impl_class->handle_window_realize =
gtk_application_impl_wayland_handle_window_realize;
impl_class->before_emit =
gtk_application_impl_wayland_before_emit;
impl_class->inhibit =
gtk_application_impl_wayland_inhibit;
impl_class->uninhibit =
gtk_application_impl_wayland_uninhibit;
}
+1
View File
@@ -109,6 +109,7 @@ gtk_application_accels_set_accels_for_action (GtkApplicationAccels *accels,
}
g_list_store_remove (G_LIST_STORE (accels->shortcuts), i);
g_object_unref (shortcut_i);
break;
}
+3 -4
View File
@@ -27,20 +27,19 @@
* SECTION:gtkbitset
* @title: GtkBitset
* @short_description: Sets of integers
* @see_also: GtkSelectionModel
* @see_also: #GtkSelectionModel
*
* #GtkBitset is a data structure for representing a set of unsigned integers.
* Another name for this data structure is "bitmap".
*
* This version is based on [roaring bitmaps](https://roaringbitmap.org/).
* The current implemenation is based on [roaring bitmaps](https://roaringbitmap.org/).
*
* A bitset allows adding a set of integers and provides support for set operations
* like unions, intersections and checks for equality or if a value is contained
* in the set. #GtkBitset also contains various functions to query metadata about
* the bitset, such as the minimum or maximum values or its size.
*
* The fastest way to iterate values in a bitset is #GtkBitsetIter which allows
* quick iteration of all the values in a bitset.
* The fastest way to iterate values in a bitset is #GtkBitsetIter.
*
* The main use case for #GtkBitset is implementing complex selections for
* #GtkSelectionModel.
+15 -1
View File
@@ -130,7 +130,21 @@ void gtk_bitset_splice (GtkBitset
guint removed,
guint added);
typedef struct {gpointer private_data[10]; } GtkBitsetIter;
/**
* GtkBitsetIter:
*
* An opaque, stack-allocated struct for iterating
* over the elements of a #GtkBitset. Before a GtkBitsetIter
* can be used, it needs to be initialized with
* gtk_bitset_iter_init_first(), gtk_bitset_iter_init_last()
* or gtk_bitset_iter_init_at().
*/
typedef struct _GtkBitsetIter GtkBitsetIter;
struct _GtkBitsetIter
{
gpointer private_data[10];
};
GDK_AVAILABLE_IN_ALL
gboolean gtk_bitset_iter_init_first (GtkBitsetIter *iter,
+2
View File
@@ -369,6 +369,8 @@ gtk_bookmark_list_start_loading (GtkBookmarkList *self)
self);
g_object_unref (file);
}
g_strfreev (uris);
}
else
{
+6 -14
View File
@@ -28,7 +28,6 @@
#include "gtkstylecontextprivate.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gtknative.h"
/**
* SECTION:gtkboxlayout
@@ -250,10 +249,8 @@ gtk_box_layout_compute_size (GtkBoxLayout *self,
required_nat += (n_visible_children - 1) * spacing;
}
if (minimum != NULL)
*minimum = required_min;
if (natural != NULL)
*natural = required_nat;
*minimum = required_min;
*natural = required_nat;
}
static void
@@ -420,15 +417,10 @@ gtk_box_layout_compute_opposite_size (GtkBoxLayout *self,
}
}
if (minimum != NULL)
*minimum = computed_minimum;
if (natural != NULL)
*natural = MAX (computed_natural, computed_natural_below + computed_natural_above);
if (min_baseline != NULL)
*min_baseline = computed_minimum_baseline;
if (nat_baseline != NULL)
*nat_baseline = computed_natural_baseline;
*minimum = computed_minimum;
*natural = MAX (computed_natural, computed_natural_below + computed_natural_above);
*min_baseline = computed_minimum_baseline;
*nat_baseline = computed_natural_baseline;
}
static void
+11
View File
@@ -294,6 +294,17 @@ gtk_button_class_init (GtkButtonClass *klass)
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_BUTTON_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("button"));
gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0,
"activate", NULL);
gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0,
"activate", NULL);
gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
"activate", NULL);
gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
"activate", NULL);
gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
"activate", NULL);
}
static void
+3 -1
View File
@@ -62,10 +62,12 @@ gtk_column_list_item_factory_setup (GtkListItemFactory *factory,
{
GtkColumnViewColumn *column = g_list_model_get_item (columns, i);
gtk_column_list_item_factory_add_column (self,
gtk_column_list_item_factory_add_column (self,
list_item->owner,
column,
FALSE);
g_object_unref (column);
}
}
+19 -10
View File
@@ -60,7 +60,7 @@
* GtkColumnView allows the user to select items according to the selection
* characteristics of the model. If the provided model is not a #GtkSelectionModel,
* GtkColumnView will wrap it in a #GtkSingleSelection. For models that allow
* multiple selected items, it is possible to turn on _rubberband selection_,
* multiple selected items, it is possible to turn on *rubberband selection*,
* using #GtkColumnView:enable-rubberband.
*
* The column view supports sorting that can be customized by the user by
@@ -1241,7 +1241,7 @@ gtk_column_view_set_model (GtkColumnView *self,
*
* Gets the list of columns in this column view. This list is constant over
* the lifetime of @self and can be used to monitor changes to the columns
* of @self by connecting to the GListModel:items-changed signal.
* of @self by connecting to the #GListModel:items-changed signal.
*
* Returns: (transfer none): The list managing the columns
**/
@@ -1263,7 +1263,7 @@ gtk_column_view_get_columns (GtkColumnView *self)
*/
void
gtk_column_view_set_show_row_separators (GtkColumnView *self,
gboolean show_row_separators)
gboolean show_row_separators)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
@@ -1302,7 +1302,7 @@ gtk_column_view_get_show_row_separators (GtkColumnView *self)
*/
void
gtk_column_view_set_show_column_separators (GtkColumnView *self,
gboolean show_column_separators)
gboolean show_column_separators)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
@@ -1486,17 +1486,26 @@ gtk_column_view_get_list_view (GtkColumnView *self)
* gtk_column_view_get_sorter:
* @self: a #GtkColumnView
*
* Returns the sorter associated with users sorting choices in
* the column view.
* Returns a special sorter that reflects the users sorting
* choices in the column view.
*
* To allow users to customizable sorting by clicking on column
* headers, this sorter needs to be set on the sort
* model(s) underneath the model that is displayed
* by the view.
* headers, this sorter needs to be set on the sort model underneath
* the model that is displayed by the view.
*
* See gtk_column_view_column_get_sorter() for setting up
* See gtk_column_view_column_set_sorter() for setting up
* per-column sorting.
*
* Here is an example:
* |[
* gtk_column_view_column_set_sorter (column, sorter);
* gtk_column_view_append_column (view, column);
* model = gtk_sort_list_model_new (store,
* gtk_column_view_get_sorter (view));
* selection = gtk_no_selection_new (model);
* gtk_column_view_set_model (view, selection);
* ]|
*
* Returns: (transfer none): the #GtkSorter of @self
*/
GtkSorter *
+1
View File
@@ -105,6 +105,7 @@ void gtk_column_view_set_reorderable (GtkColumnView
GDK_AVAILABLE_IN_ALL
gboolean gtk_column_view_get_reorderable (GtkColumnView *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_set_enable_rubberband (GtkColumnView *self,
gboolean enable_rubberband);
GDK_AVAILABLE_IN_ALL
+1
View File
@@ -85,6 +85,7 @@ void gtk_column_view_column_set_header_menu (GtkColu
GDK_AVAILABLE_IN_ALL
GMenuModel * gtk_column_view_column_get_header_menu (GtkColumnViewColumn *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self,
int fixed_width);
GDK_AVAILABLE_IN_ALL
+8
View File
@@ -115,6 +115,14 @@ gtk_column_view_sorter_dispose (GObject *object)
{
GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (object);
/* The sorter is owned by the columview and is unreffed
* after the columns, so the sequence must be empty at
* this point.
* The sorter can outlive the columview it comes from
* (the model might still have a ref), but that does
* not change the fact that all columns will be gone.
*/
g_assert (g_sequence_is_empty (self->sorters));
g_clear_pointer (&self->sorters, g_sequence_free);
G_OBJECT_CLASS (gtk_column_view_sorter_parent_class)->dispose (object);
+17 -18
View File
@@ -560,10 +560,12 @@ css_provider_commit (GtkCssProvider *css_provider,
if (ruleset->styles == NULL)
{
for (i = 0; i < n_selectors; i++)
_gtk_css_selector_free (selectors[i]);
return;
}
for (i = 0; i < n_selectors; i ++)
for (i = 0; i < n_selectors; i++)
{
GtkCssRuleset *new;
@@ -766,7 +768,11 @@ parse_selector_list (GtkCssScanner *scanner,
GtkCssSelector *select = _gtk_css_selector_parse (scanner->parser);
if (select == NULL)
return 0;
{
for (int i = 0; i < n_selectors; i++)
g_clear_pointer (&out_selectors[i], _gtk_css_selector_free);
return 0;
}
out_selectors[n_selectors] = select;
n_selectors++;
@@ -776,6 +782,8 @@ parse_selector_list (GtkCssScanner *scanner,
gtk_css_parser_error_syntax (scanner->parser,
"Only %u selectors per ruleset allowed",
MAX_SELECTOR_LIST_LENGTH);
for (int i = 0; i < MAX_SELECTOR_LIST_LENGTH; i++)
g_clear_pointer (&out_selectors[i], _gtk_css_selector_free);
return 0;
}
}
@@ -804,10 +812,7 @@ parse_declaration (GtkCssScanner *scanner,
name = gtk_css_parser_consume_ident (scanner->parser);
if (name == NULL)
{
gtk_css_parser_end_block (scanner->parser);
return;
}
goto out;
property = _gtk_style_property_lookup (name);
@@ -819,25 +824,18 @@ parse_declaration (GtkCssScanner *scanner,
if (!gtk_css_parser_try_token (scanner->parser, GTK_CSS_TOKEN_COLON))
{
gtk_css_parser_error_syntax (scanner->parser, "Expected ':'");
g_free (name);
gtk_css_parser_end_block (scanner->parser);
return;
goto out;
}
value = _gtk_style_property_parse_value (property,
scanner->parser);
value = _gtk_style_property_parse_value (property, scanner->parser);
if (value == NULL)
{
gtk_css_parser_end_block (scanner->parser);
return;
}
goto out;
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_error_syntax (scanner->parser, "Junk at end of value for %s", property->name);
gtk_css_parser_end_block (scanner->parser);
return;
goto out;
}
if (gtk_keep_css_sections)
@@ -882,6 +880,7 @@ parse_declaration (GtkCssScanner *scanner,
gtk_css_parser_error_value (scanner->parser, "No property named \"%s\"", name);
}
out:
g_free (name);
gtk_css_parser_end_block (scanner->parser);
@@ -916,7 +915,7 @@ parse_ruleset (GtkCssScanner *scanner)
{
guint i;
gtk_css_parser_error_syntax (scanner->parser, "Expected '{' after selectors");
for (i = 0; i < n_selectors; i ++)
for (i = 0; i < n_selectors; i++)
_gtk_css_selector_free (selectors[i]);
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (scanner->parser);
+5 -5
View File
@@ -22,11 +22,11 @@
#include "gtk/gtkcsstypesprivate.h"
#include "gtk/gtkcssparserprivate.h"
#define GTK_VECTOR_ELEMENT_TYPE gpointer
#define GTK_VECTOR_TYPE_NAME GtkCssSelectorMatches
#define GTK_VECTOR_NAME gtk_css_selector_matches
#define GTK_VECTOR_PREALLOC 32
#include "gtk/gtkvectorimpl.c"
#define GDK_ARRAY_ELEMENT_TYPE gpointer
#define GDK_ARRAY_TYPE_NAME GtkCssSelectorMatches
#define GDK_ARRAY_NAME gtk_css_selector_matches
#define GDK_ARRAY_PREALLOC 32
#include "gdk/gdkarrayimpl.c"
G_BEGIN_DECLS
+9 -5
View File
@@ -29,8 +29,8 @@
* @Title: GtkCustomFilter
* @Short_description: Filtering with callbacks
*
* #GtkCustomFilter is a #GtkFilter that uses a callback to determine whether
* to include an item or not.
* #GtkCustomFilter is a #GtkFilter that uses a callback to determine
* whether to include an item or not.
*/
struct _GtkCustomFilter
{
@@ -98,11 +98,13 @@ gtk_custom_filter_init (GtkCustomFilter *self)
* gtk_custom_filter_new:
* @match_func: (nullable): function to filter items
* @user_data: (nullable): user data to pass to @match_func
* @user_destroy: destory notify
* @user_destroy: destroy notify for @user_data
*
* Creates a new filter using the given @match_func to filter
* items.
*
* If @match_func is %NULL, the filter matches all items.
*
* If the filter func changes its filtering behavior,
* gtk_filter_changed() needs to be called.
*
@@ -127,10 +129,12 @@ gtk_custom_filter_new (GtkCustomFilterFunc match_func,
* @self: a #GtkCustomFilter
* @match_func: (nullable): function to filter items
* @user_data: (nullable): user data to pass to @match_func
* @user_destroy: destory notify
* @user_destroy: destroy notify for @user_data
*
* Sets (or unsets) the function used for filtering items.
*
*
* If @match_func is %NULL, the filter matches all items.
*
* If the filter func changes its filtering behavior,
* gtk_filter_changed() needs to be called.
*
+9 -5
View File
@@ -27,7 +27,7 @@
/**
* SECTION:gtkcustomsorter
* @Title: GtkCustomSorter
* @Short_description: Sorting with a callback
* @Short_description: Sorting with a callbacks
*
* GtkCustomSorter is a #GtkSorter implementation that sorts
* via a traditional #GCompareDataFunc callback.
@@ -108,8 +108,10 @@ gtk_custom_sorter_init (GtkCustomSorter *self)
* Creates a new #GtkSorter that works by calling
* @sort_func to compare items.
*
* Returns: a new #GTkSorter
*/
* If @sort_func is %NULL, all items are considered equal.
*
* Returns: a new #GtkSorter
*/
GtkSorter *
gtk_custom_sorter_new (GCompareDataFunc sort_func,
gpointer user_data,
@@ -129,10 +131,12 @@ gtk_custom_sorter_new (GCompareDataFunc sort_func,
* @self: a #GtkCustomSorter
* @sort_func: (nullable): function to sort items
* @user_data: (nullable): user data to pass to @match_func
* @user_destroy: destory notify
* @user_destroy: destroy notify for @user_data
*
* Sets (or unsets) the function used for sorting items.
*
*
* If @sort_func is %NULL, all items are considered equal.
*
* If the sort func changes its sorting behavior,
* gtk_sorter_changed() needs to be called.
*
+4 -5
View File
@@ -48,11 +48,10 @@ typedef enum {
GTK_DEBUG_INTERACTIVE = 1 << 10,
GTK_DEBUG_TOUCHSCREEN = 1 << 11,
GTK_DEBUG_ACTIONS = 1 << 12,
GTK_DEBUG_RESIZE = 1 << 13,
GTK_DEBUG_LAYOUT = 1 << 14,
GTK_DEBUG_SNAPSHOT = 1 << 15,
GTK_DEBUG_CONSTRAINTS = 1 << 16,
GTK_DEBUG_BUILDER_OBJECTS = 1 << 17,
GTK_DEBUG_LAYOUT = 1 << 13,
GTK_DEBUG_SNAPSHOT = 1 << 14,
GTK_DEBUG_CONSTRAINTS = 1 << 15,
GTK_DEBUG_BUILDER_OBJECTS = 1 << 16,
} GtkDebugFlag;
#ifdef G_ENABLE_DEBUG
+229 -4
View File
@@ -62,6 +62,7 @@ enum {
PROP_IO_PRIORITY,
PROP_ITEM_TYPE,
PROP_LOADING,
PROP_MONITORED,
NUM_PROPERTIES
};
@@ -70,8 +71,10 @@ struct _GtkDirectoryList
GObject parent_instance;
char *attributes;
int io_priority;
GFile *file;
GFileMonitor *monitor;
gboolean monitored;
int io_priority;
GCancellable *cancellable;
GError *error; /* Error while loading */
@@ -147,13 +150,17 @@ gtk_directory_list_set_property (GObject *object,
gtk_directory_list_set_io_priority (self, g_value_get_int (value));
break;
case PROP_MONITORED:
gtk_directory_list_set_monitored (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
static void
gtk_directory_list_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -187,6 +194,10 @@ gtk_directory_list_get_property (GObject *object,
g_value_set_boolean (value, gtk_directory_list_is_loading (self));
break;
case PROP_MONITORED:
g_value_set_boolean (value, gtk_directory_list_get_monitored (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -204,12 +215,27 @@ gtk_directory_list_stop_loading (GtkDirectoryList *self)
return TRUE;
}
static void directory_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event,
gpointer data);
static void
gtk_directory_list_stop_monitoring (GtkDirectoryList *self)
{
if (self->monitor)
g_signal_handlers_disconnect_by_func (self->monitor, directory_changed, self);
g_clear_object (&self->monitor);
}
static void
gtk_directory_list_dispose (GObject *object)
{
GtkDirectoryList *self = GTK_DIRECTORY_LIST (object);
gtk_directory_list_stop_loading (self);
gtk_directory_list_stop_monitoring (self);
g_clear_object (&self->file);
g_clear_pointer (&self->attributes, g_free);
@@ -301,6 +327,18 @@ gtk_directory_list_class_init (GtkDirectoryListClass *class)
FALSE,
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkDirectoryList:monitored:
*
* %TRUE if the directory is monitored for changed
*/
properties[PROP_MONITORED] =
g_param_spec_boolean ("monitored",
P_("monitored"),
P_("TRUE if the directory is monitored for changes"),
TRUE,
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
}
@@ -309,6 +347,7 @@ gtk_directory_list_init (GtkDirectoryList *self)
{
self->items = g_sequence_new (g_object_unref);
self->io_priority = G_PRIORITY_DEFAULT;
self->monitored = TRUE;
}
/**
@@ -324,7 +363,6 @@ gtk_directory_list_init (GtkDirectoryList *self)
GtkDirectoryList *
gtk_directory_list_new (const char *attributes,
GFile *file)
{
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
@@ -410,7 +448,7 @@ gtk_directory_list_got_files_cb (GObject *source,
{
GFileInfo *info;
GFile *file;
info = l->data;
file = g_file_enumerator_get_child (enumerator, info);
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
@@ -496,6 +534,143 @@ gtk_directory_list_start_loading (GtkDirectoryList *self)
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
}
static void
got_new_file_info_cb (GObject *source,
GAsyncResult *res,
gpointer data)
{
GFile *file = G_FILE (source);
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
GFileInfo *info;
guint position;
info = g_file_query_info_finish (file, res, NULL);
if (!info)
return;
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
position = g_sequence_get_length (self->items);
g_sequence_append (self->items, info);
g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
}
static void
got_existing_file_info_cb (GObject *source,
GAsyncResult *res,
gpointer data)
{
GFile *file = G_FILE (source);
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
GFileInfo *info;
GSequenceIter *iter;
info = g_file_query_info_finish (file, res, NULL);
if (!info)
return;
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
for (iter = g_sequence_get_begin_iter (self->items);
!g_sequence_iter_is_end (iter);
iter = g_sequence_iter_next (iter))
{
GFileInfo *item = g_sequence_get (iter);
GFile *f = G_FILE (g_file_info_get_attribute_object (item, "standard::file"));
if (g_file_equal (f, file))
{
guint position = g_sequence_iter_get_position (iter);
g_sequence_set (iter, g_object_ref (info));
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 1);
break;
}
}
}
static void
gtk_directory_list_remove_file (GtkDirectoryList *self,
GFile *file)
{
GSequenceIter *iter;
for (iter = g_sequence_get_begin_iter (self->items);
!g_sequence_iter_is_end (iter);
iter = g_sequence_iter_next (iter))
{
GFileInfo *item = g_sequence_get (iter);
GFile *f = G_FILE (g_file_info_get_attribute_object (item, "standard::file"));
if (g_file_equal (f, file))
{
guint position = g_sequence_iter_get_position (iter);
g_sequence_remove (iter);
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
break;
}
}
}
static void
directory_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event,
gpointer data)
{
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
switch (event)
{
case G_FILE_MONITOR_EVENT_CREATED:
g_file_query_info_async (file,
self->attributes,
G_FILE_QUERY_INFO_NONE,
self->io_priority,
self->cancellable,
got_new_file_info_cb,
self);
break;
case G_FILE_MONITOR_EVENT_DELETED:
gtk_directory_list_remove_file (self, file);
break;
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
g_file_query_info_async (file,
self->attributes,
G_FILE_QUERY_INFO_NONE,
self->io_priority,
self->cancellable,
got_existing_file_info_cb,
self);
break;
case G_FILE_MONITOR_EVENT_CHANGED:
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
case G_FILE_MONITOR_EVENT_UNMOUNTED:
case G_FILE_MONITOR_EVENT_MOVED:
case G_FILE_MONITOR_EVENT_RENAMED:
case G_FILE_MONITOR_EVENT_MOVED_IN:
case G_FILE_MONITOR_EVENT_MOVED_OUT:
default:
break;
}
}
static void
gtk_directory_list_start_monitoring (GtkDirectoryList *self)
{
g_assert (self->monitor == NULL);
self->monitor = g_file_monitor_directory (self->file, G_FILE_MONITOR_NONE, NULL, NULL);
g_signal_connect (self->monitor, "changed", G_CALLBACK (directory_changed), self);
}
static void
gtk_directory_list_update_monitoring (GtkDirectoryList *self)
{
gtk_directory_list_stop_monitoring (self);
if (self->file && self->monitored)
gtk_directory_list_start_monitoring (self);
}
/**
* gtk_directory_list_set_file:
* @self: a #GtkDirectoryList
@@ -520,6 +695,7 @@ gtk_directory_list_set_file (GtkDirectoryList *self,
g_set_object (&self->file, file);
gtk_directory_list_update_monitoring (self);
gtk_directory_list_start_loading (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
@@ -679,3 +855,52 @@ gtk_directory_list_get_error (GtkDirectoryList *self)
return self->error;
}
/**
* gtk_directory_list_set_monitored:
* @self: a #GtkDirectoryList
* @monitored: %TRUE to monitor the directory for changes
*
* Sets whether the directory list will monitor the directory
* for changes. If monitoring is enabled, the
* #GListModel::items-changed signal will be emitted when the
* directory contents change.
*
* When monitoring is turned on after the initial creation
* of the directory list, the directory is reloaded to avoid
* missing files that appeared between the initial loading
* and when monitoring was turned on.
*/
void
gtk_directory_list_set_monitored (GtkDirectoryList *self,
gboolean monitored)
{
g_return_if_fail (GTK_IS_DIRECTORY_LIST (self));
if (self->monitored == monitored)
return;
self->monitored = monitored;
gtk_directory_list_update_monitoring (self);
if (monitored)
gtk_directory_list_start_loading (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MONITORED]);
}
/**
* gtk_directory_list_get_monitored:
* @self: a #GtkDirectoryList
*
* Returns whether the directory list is monitoring
* the directory for changes.
*
* Returns: %TRUE if the directory is monitored
*/
gboolean
gtk_directory_list_get_monitored (GtkDirectoryList *self)
{
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), TRUE);
return self->monitored;
}
+6
View File
@@ -62,6 +62,12 @@ gboolean gtk_directory_list_is_loading (GtkDirectoryLis
GDK_AVAILABLE_IN_ALL
const GError * gtk_directory_list_get_error (GtkDirectoryList *self);
GDK_AVAILABLE_IN_ALL
void gtk_directory_list_set_monitored (GtkDirectoryList *self,
gboolean monitored);
GDK_AVAILABLE_IN_ALL
gboolean gtk_directory_list_get_monitored (GtkDirectoryList *self);
G_END_DECLS
#endif /* __GTK_DIRECTORY_LIST_H__ */
+3 -4
View File
@@ -70,7 +70,7 @@
* useful if the list of options is long. To enable the search entry,
* use gtk_drop_down_set_enable_search().
*
* * # CSS nodes
* # CSS nodes
*
* GtkDropDown has a single CSS node with name dropdown,
* with the button and popover nodes as children.
@@ -205,9 +205,8 @@ update_filter (GtkDropDown *self)
if (self->expression)
{
filter = gtk_string_filter_new ();
filter = gtk_string_filter_new (gtk_expression_ref (self->expression));
gtk_string_filter_set_match_mode (GTK_STRING_FILTER (filter), GTK_STRING_FILTER_MATCH_MODE_PREFIX);
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), self->expression);
}
else
filter = gtk_every_filter_new ();
@@ -927,7 +926,7 @@ gtk_drop_down_get_expression (GtkDropDown *self)
/**
* gtk_drop_down_set_from_strings:
* @self: a #GtkDropDown
* @texts: a %NULL-terminated string array
* @texts: (array zero-terminated=1) (element-type utf8): a %NULL-terminated string array
*
* Populates @self with the strings in @text,
* by creating a suitable model and factory.
+34
View File
@@ -30,6 +30,7 @@
#include "gtkshortcut.h"
#include "gtkshortcuttrigger.h"
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerfocus.h"
#include "gtkintl.h"
/**
@@ -48,6 +49,22 @@
* to click or press the Enter key. The default bindings
* for leaving the edit mode are the Enter key (to save
* the results) or the Escape key (to cancel the editing).
*
* # CSS nodes
*
* |[<!-- language="plain" -->
* editablelabel[.editing]
* stack
* label
* text
* ]|
*
* GtkEditableLabel has a main node with the name editablelabel.
* When the entry is in editing mode, it gets the .editing style
* class.
*
* For all the subnodes added to the text node in various situations,
* see #GtkText.
*/
struct _GtkEditableLabel
@@ -177,12 +194,20 @@ gtk_editable_label_prepare_drag (GtkDragSource *source,
gtk_label_get_label (GTK_LABEL (self->label)));
}
static void
gtk_editable_label_focus_out (GtkEventController *controller,
GtkEditableLabel *self)
{
gtk_editable_label_stop_editing (self, TRUE);
}
static void
gtk_editable_label_init (GtkEditableLabel *self)
{
GtkGesture *gesture;
GtkDropTarget *target;
GtkDragSource *source;
GtkEventController *controller;
gtk_widget_set_focusable (GTK_WIDGET (self), TRUE);
@@ -212,6 +237,10 @@ gtk_editable_label_init (GtkEditableLabel *self)
g_signal_connect (source, "prepare", G_CALLBACK (gtk_editable_label_prepare_drag), self);
gtk_widget_add_controller (self->label, GTK_EVENT_CONTROLLER (source));
controller = gtk_event_controller_focus_new ();
g_signal_connect (controller, "leave", G_CALLBACK (gtk_editable_label_focus_out), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
gtk_editable_init_delegate (GTK_EDITABLE (self));
}
@@ -444,6 +473,8 @@ gtk_editable_label_start_editing (GtkEditableLabel *self)
gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "entry");
gtk_widget_grab_focus (self->entry);
gtk_widget_add_css_class (GTK_WIDGET (self), "editing");
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EDITING]);
}
@@ -480,5 +511,8 @@ gtk_editable_label_stop_editing (GtkEditableLabel *self,
}
gtk_widget_grab_focus (GTK_WIDGET (self));
gtk_widget_remove_css_class (GTK_WIDGET (self), "editing");
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EDITING]);
}
+83 -9
View File
@@ -53,26 +53,26 @@
*
* Here is an example of a complex expression:
* |[
* color_expr = gtk_property_expression_new (GTK_TYPE_LIST_ITEM,
* NULL, "item");
* expression = gtk_property_expression_new (GTK_TYPE_COLOR,
* color_expr,
* "name");
* color_expr = gtk_property_expression_new (GTK_TYPE_LIST_ITEM,
* NULL, "item");
* expression = gtk_property_expression_new (GTK_TYPE_COLOR,
* color_expr, "name");
* ]|
*
* when evaluated with `this` being a GtkListItem, it will obtain the
* "item" property from the GtkListItem, and then obtain the "name" property
* from the resulting object (which is assumed to be of type GTK_TYPE_COLOR).
*
* A more concise way to describe this would be
* |[
* this->item->name
* this->item->name
* ]|
*
* The most likely place where you will encounter expressions is in the context
* of list models and list widgets using them. For example, #GtkDropDown is
* evaluating a GtkExpression to obtain strings from the items in its model
* that it can then use to match against the contents of its search entry.
* #GtkStringFilter is using a GtkExpression for a similar reason.
* #GtkStringFilter is using a GtkExpression for similar reasons.
*
* By default, expressions are not paying attention to changes and evaluation is
* just a snapshot of the current state at a given time. To get informed about
@@ -127,11 +127,11 @@
* attribute to specify the object type, and a `name` attribute to specify the property
* to look up. The content of <lookup> can either be an element specfiying the expression
* to use the object, or a string that specifies the name of the object to use.
*
*
* Example:
* |[
* <lookup name='search'>string_filter</lookup>
* |]
* ]|
*
* To create a constant expression, use the <constant> element. If the type attribute
* is specified, the element content is interpreted as a value of that type. Otherwise,
@@ -855,6 +855,24 @@ gtk_constant_expression_new_for_value (const GValue *value)
return result;
}
/**
* gtk_constant_expression_get_value:
* @expression: a constant #GtkExpression
*
* Gets the value that a constant expression evaluates to.
*
* Returns: (transfer none): the value
*/
const GValue *
gtk_constant_expression_get_value (GtkExpression *expression)
{
GtkConstantExpression *self = (GtkConstantExpression *) expression;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (expression, GTK_TYPE_CONSTANT_EXPRESSION), NULL);
return &self->value;
}
/* }}} */
/* {{{ GtkObjectExpression */
@@ -1002,6 +1020,24 @@ gtk_object_expression_new (GObject *object)
return result;
}
/**
* gtk_object_expression_get_object:
* @expression: an object #GtkExpression
*
* Gets the object that the expression evaluates to.
*
* Returns: (transfer none): the object, or %NULL
*/
GObject *
gtk_object_expression_get_object (GtkExpression *expression)
{
GtkObjectExpression *self = (GtkObjectExpression *) expression;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (expression, GTK_TYPE_OBJECT_EXPRESSION), NULL);
return self->object;
}
/* }}} */
/* {{{ GtkPropertyExpression */
@@ -1307,6 +1343,44 @@ gtk_property_expression_new_for_pspec (GtkExpression *expression,
return result;
}
/**
* gtk_property_expression_get_expression:
* @expression: a property #GtkExpression
*
* Gets the expression specifying the object of
* a property expression.
*
* Returns: (transfer none): the object expression
*/
GtkExpression *
gtk_property_expression_get_expression (GtkExpression *expression)
{
GtkPropertyExpression *self = (GtkPropertyExpression *) expression;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (expression, GTK_TYPE_PROPERTY_EXPRESSION), NULL);
return self->expr;
}
/**
* gtk_property_expression_get_pspec:
* @expression: a property #GtkExpression
*
* Gets the #GParamSpec specifying the property of
* a property expression.
*
* Returns: (transfer none): the #GParamSpec
*/
GParamSpec *
gtk_property_expression_get_pspec (GtkExpression *expression)
{
GtkPropertyExpression *self = (GtkPropertyExpression *) expression;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (expression, GTK_TYPE_PROPERTY_EXPRESSION), NULL);
return self->pspec;
}
/* }}} */
/* {{{ GtkClosureExpression */
+11
View File
@@ -93,6 +93,11 @@ GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_property_expression_new_for_pspec (GtkExpression *expression,
GParamSpec *pspec);
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_property_expression_get_expression (GtkExpression *expression);
GDK_AVAILABLE_IN_ALL
GParamSpec * gtk_property_expression_get_pspec (GtkExpression *expression);
#define GTK_TYPE_CONSTANT_EXPRESSION (gtk_constant_expression_get_type())
typedef struct _GtkConstantExpression GtkConstantExpression;
@@ -105,6 +110,9 @@ GtkExpression * gtk_constant_expression_new (GType
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_constant_expression_new_for_value (const GValue *value);
GDK_AVAILABLE_IN_ALL
const GValue * gtk_constant_expression_get_value (GtkExpression *expression);
#define GTK_TYPE_OBJECT_EXPRESSION (gtk_object_expression_get_type())
typedef struct _GtkObjectExpression GtkObjectExpression;
@@ -114,6 +122,9 @@ GType gtk_object_expression_get_type (void) G_GNUC_CO
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_object_expression_new (GObject *object);
GDK_AVAILABLE_IN_ALL
GObject * gtk_object_expression_get_object (GtkExpression *expression);
#define GTK_TYPE_CLOSURE_EXPRESSION (gtk_closure_expression_get_type())
typedef struct _GtkClosureExpression GtkClosureExpression;
+13 -105
View File
@@ -79,75 +79,6 @@ G_DEFINE_INTERFACE (GtkFileChooser, gtk_file_chooser, G_TYPE_OBJECT);
static void
gtk_file_chooser_default_init (GtkFileChooserInterface *iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (iface);
/**
* GtkFileChooser::current-folder-changed:
* @chooser: the object which received the signal.
*
* This signal is emitted when the current folder in a #GtkFileChooser
* changes. This can happen due to the user performing some action that
* changes folders, such as selecting a bookmark or visiting a folder on the
* file list. It can also happen as a result of calling a function to
* explicitly change the current folder in a file chooser.
*
* Normally you do not need to connect to this signal, unless you need to keep
* track of which folder a file chooser is showing.
*
* See also: gtk_file_chooser_set_current_folder(),
* gtk_file_chooser_get_current_folder(),
*/
g_signal_new (I_("current-folder-changed"),
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkFileChooserIface, current_folder_changed),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
/**
* GtkFileChooser::selection-changed:
* @chooser: the object which received the signal.
*
* This signal is emitted when there is a change in the set of selected files
* in a #GtkFileChooser. This can happen when the user modifies the selection
* with the mouse or the keyboard, or when explicitly calling functions to
* change the selection.
*
* Normally you do not need to connect to this signal, as it is easier to wait
* for the file chooser to finish running, and then to get the list of
* selected files using the functions mentioned below.
*/
g_signal_new (I_("selection-changed"),
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkFileChooserIface, selection_changed),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
/**
* GtkFileChooser::file-activated:
* @chooser: the object which received the signal.
*
* This signal is emitted when the user "activates" a file in the file
* chooser. This can happen by double-clicking on a file in the file list, or
* by pressing `Enter`.
*
* Normally you do not need to connect to this signal. It is used internally
* by #GtkFileChooserDialog to know when to activate the default button in the
* dialog.
*
* See also: gtk_file_chooser_get_file(), gtk_file_chooser_get_files()
*/
g_signal_new (I_("file-activated"),
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkFileChooserIface, file_activated),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
g_object_interface_install_property (iface,
g_param_spec_enum ("action",
P_("Action"),
@@ -508,16 +439,15 @@ gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
/**
* gtk_file_chooser_get_files:
* @chooser: a #GtkFileChooser
*
* Lists all the selected files and subfolders in the current folder of @chooser
* as #GFile.
*
* Returns: (element-type GFile) (transfer full): a list
* containing a #GFile for each selected file and subfolder in the
* current folder. Free the returned list with g_slist_free(), and
* the files with g_object_unref().
**/
GSList *
* Lists all the selected files and subfolders in the current folder
* of @chooser as #GFile.
*
* Returns: (transfer full): a list model containing a #GFile for each
* selected file and subfolder in the current folder. Free the returned
* list with g_object_unref().
*/
GListModel *
gtk_file_chooser_get_files (GtkFileChooser *chooser)
{
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
@@ -597,41 +527,19 @@ gtk_file_chooser_set_file (GtkFileChooser *chooser,
GFile *
gtk_file_chooser_get_file (GtkFileChooser *chooser)
{
GSList *list;
GListModel *list;
GFile *result = NULL;
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
list = gtk_file_chooser_get_files (chooser);
if (list)
{
result = list->data;
list = g_slist_delete_link (list, list);
g_slist_free_full (list, g_object_unref);
}
if (g_list_model_get_n_items (list) > 0)
result = g_list_model_get_item (list, 0);
g_object_unref (list);
return result;
}
/*< private >
* _gtk_file_chooser_get_file_system:
* @chooser: a #GtkFileChooser
*
* Gets the #GtkFileSystem of @chooser; this is an internal
* implementation detail, used for conversion between paths
* and filenames and URIs.
*
* Returns: the file system for @chooser.
**/
GtkFileSystem *
_gtk_file_chooser_get_file_system (GtkFileChooser *chooser)
{
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_file_system (chooser);
}
/**
* gtk_file_chooser_add_shortcut_folder:
* @chooser: a #GtkFileChooser
+61 -68
View File
@@ -72,7 +72,8 @@ GType gtk_file_chooser_get_type (void) G_GNUC_CONST;
* @GTK_FILE_CHOOSER_ERROR_BAD_FILENAME: Indicates a malformed filename.
* @GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS: Indicates a duplicate path (e.g. when
* adding a bookmark).
* @GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME: Indicates an incomplete hostname (e.g. "http://foo" without a slash after that).
* @GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME: Indicates an incomplete hostname
* (e.g. "http://foo" without a slash after that).
*
* These identify the various errors that can occur while calling
* #GtkFileChooser functions.
@@ -87,108 +88,100 @@ typedef enum {
GDK_AVAILABLE_IN_ALL
GQuark gtk_file_chooser_error_quark (void);
/* Configuration
*/
/* Configuration */
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_set_action (GtkFileChooser *chooser,
GtkFileChooserAction action);
GtkFileChooserAction action);
GDK_AVAILABLE_IN_ALL
GtkFileChooserAction gtk_file_chooser_get_action (GtkFileChooser *chooser);
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_set_select_multiple (GtkFileChooser *chooser,
gboolean select_multiple);
gboolean select_multiple);
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_get_select_multiple (GtkFileChooser *chooser);
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_set_create_folders (GtkFileChooser *chooser,
gboolean create_folders);
gboolean create_folders);
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_get_create_folders (GtkFileChooser *chooser);
gboolean gtk_file_chooser_get_create_folders (GtkFileChooser *chooser);
/* Suggested name for the Save-type actions
*/
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_set_current_name (GtkFileChooser *chooser,
const gchar *name);
GDK_AVAILABLE_IN_ALL
gchar *gtk_file_chooser_get_current_name (GtkFileChooser *chooser);
/* Suggested name for the Save-type actions */
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_select_all (GtkFileChooser *chooser);
void gtk_file_chooser_set_current_name (GtkFileChooser *chooser,
const char *name);
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_unselect_all (GtkFileChooser *chooser);
char * gtk_file_chooser_get_current_name (GtkFileChooser *chooser);
/* GFile manipulation */
GDK_AVAILABLE_IN_ALL
GFile * gtk_file_chooser_get_file (GtkFileChooser *chooser);
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_set_file (GtkFileChooser *chooser,
GFile *file,
GError **error);
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_select_file (GtkFileChooser *chooser,
GFile *file,
GError **error);
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
GFile *file);
GDK_AVAILABLE_IN_ALL
GSList * gtk_file_chooser_get_files (GtkFileChooser *chooser);
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_set_current_folder (GtkFileChooser *chooser,
GFile *file,
GError **error);
GDK_AVAILABLE_IN_ALL
GFile * gtk_file_chooser_get_current_folder (GtkFileChooser *chooser);
/* List of user selectable filters
*/
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_add_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
GFile * gtk_file_chooser_get_file (GtkFileChooser *chooser);
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
gboolean gtk_file_chooser_set_file (GtkFileChooser *chooser,
GFile *file,
GError **error);
GDK_AVAILABLE_IN_ALL
GListModel *gtk_file_chooser_get_filters (GtkFileChooser *chooser);
GListModel * gtk_file_chooser_get_files (GtkFileChooser *chooser);
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_set_current_folder (GtkFileChooser *chooser,
GFile *file,
GError **error);
GDK_AVAILABLE_IN_ALL
GFile * gtk_file_chooser_get_current_folder (GtkFileChooser *chooser);
/* List of user selectable filters */
/* Current filter
*/
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_set_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
void gtk_file_chooser_add_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
GDK_AVAILABLE_IN_ALL
GtkFileFilter *gtk_file_chooser_get_filter (GtkFileChooser *chooser);
void gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
GDK_AVAILABLE_IN_ALL
GListModel * gtk_file_chooser_get_filters (GtkFileChooser *chooser);
/* Current filter */
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_set_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
GDK_AVAILABLE_IN_ALL
GtkFileFilter * gtk_file_chooser_get_filter (GtkFileChooser *chooser);
/* Per-application shortcut folders */
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser,
GFile *folder,
GError **error);
gboolean gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser,
GFile *folder,
GError **error);
GDK_AVAILABLE_IN_ALL
gboolean gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser,
GFile *folder,
GError **error);
gboolean gtk_file_chooser_remove_shortcut_folder
(GtkFileChooser *chooser,
GFile *folder,
GError **error);
GDK_AVAILABLE_IN_ALL
GListModel *gtk_file_chooser_get_shortcut_folders (GtkFileChooser *chooser);
GListModel * gtk_file_chooser_get_shortcut_folders (GtkFileChooser *chooser);
/* Custom widgets */
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_add_choice (GtkFileChooser *chooser,
const char *id,
const char *label,
const char **options,
const char **option_labels);
void gtk_file_chooser_add_choice (GtkFileChooser *chooser,
const char *id,
const char *label,
const char **options,
const char **option_labels);
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_remove_choice (GtkFileChooser *chooser,
const char *id);
void gtk_file_chooser_remove_choice (GtkFileChooser *chooser,
const char *id);
GDK_AVAILABLE_IN_ALL
void gtk_file_chooser_set_choice (GtkFileChooser *chooser,
const char *id,
const char *option);
void gtk_file_chooser_set_choice (GtkFileChooser *chooser,
const char *id,
const char *option);
GDK_AVAILABLE_IN_ALL
const char *gtk_file_chooser_get_choice (GtkFileChooser *chooser,
const char *id);
const char * gtk_file_chooser_get_choice (GtkFileChooser *chooser,
const char *id);
G_END_DECLS
+790 -583
View File
File diff suppressed because it is too large Load Diff
+11 -43
View File
@@ -25,8 +25,6 @@
#include "gtkfilechooserwidget.h"
#include "gtkfilechooserwidgetprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkfilechooserembed.h"
#include "gtkfilesystem.h"
#include "gtksizerequest.h"
#include "gtktypebuiltins.h"
#include "gtkintl.h"
@@ -265,12 +263,9 @@ static void gtk_file_chooser_dialog_size_allocate (GtkWidget *wid
int width,
int height,
int baseline);
static void file_chooser_widget_file_activated (GtkFileChooser *chooser,
GtkFileChooserDialog *dialog);
static void file_chooser_widget_response_requested (GtkWidget *widget,
GtkFileChooserDialog *dialog);
static void file_chooser_widget_selection_changed (GtkWidget *widget,
GtkFileChooserDialog *dialog);
static void gtk_file_chooser_dialog_activate_response (GtkWidget *widget,
const char *action_name,
GVariant *parameters);
static void response_cb (GtkDialog *dialog,
gint response_id);
@@ -310,9 +305,8 @@ gtk_file_chooser_dialog_class_init (GtkFileChooserDialogClass *class)
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserDialog, widget);
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserDialog, buttons);
gtk_widget_class_bind_template_callback (widget_class, response_cb);
gtk_widget_class_bind_template_callback (widget_class, file_chooser_widget_file_activated);
gtk_widget_class_bind_template_callback (widget_class, file_chooser_widget_response_requested);
gtk_widget_class_bind_template_callback (widget_class, file_chooser_widget_selection_changed);
gtk_widget_class_install_action (widget_class, "response.activate", NULL, gtk_file_chooser_dialog_activate_response);
}
static void
@@ -367,38 +361,12 @@ is_accept_response_id (gint response_id)
response_id == GTK_RESPONSE_APPLY);
}
/* Callback used when the user activates a file in the file chooser widget */
static void
file_chooser_widget_file_activated (GtkFileChooser *chooser,
GtkFileChooserDialog *dialog)
{
gtk_widget_activate_default (GTK_WIDGET (chooser));
}
static void
file_chooser_widget_selection_changed (GtkWidget *widget,
GtkFileChooserDialog *dialog)
{
GtkFileChooserDialogPrivate *priv = gtk_file_chooser_dialog_get_instance_private (dialog);
GtkWidget *button;
GSList *files;
gboolean sensitive;
button = get_accept_action_widget (GTK_DIALOG (dialog), FALSE);
if (button == NULL)
return;
files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->widget));
sensitive = (files != NULL);
gtk_widget_set_sensitive (button, sensitive);
g_slist_free_full (files, g_object_unref);
}
static void
file_chooser_widget_response_requested (GtkWidget *widget,
GtkFileChooserDialog *dialog)
gtk_file_chooser_dialog_activate_response (GtkWidget *widget,
const char *action_name,
GVariant *parameters)
{
GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (widget);
GtkFileChooserDialogPrivate *priv = gtk_file_chooser_dialog_get_instance_private (dialog);
GtkWidget *button;
@@ -641,7 +609,7 @@ gtk_file_chooser_dialog_map (GtkWidget *widget)
setup_save_entry (dialog);
ensure_default_response (dialog);
_gtk_file_chooser_embed_initial_focus (GTK_FILE_CHOOSER_EMBED (priv->widget));
gtk_file_chooser_widget_initial_focus (GTK_FILE_CHOOSER_WIDGET (priv->widget));
GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->map (widget);
}
@@ -705,7 +673,7 @@ response_cb (GtkDialog *dialog,
/* Act only on response IDs we recognize */
if (is_accept_response_id (response_id) &&
!priv->response_requested &&
!_gtk_file_chooser_embed_should_respond (GTK_FILE_CHOOSER_EMBED (priv->widget)))
!gtk_file_chooser_widget_should_respond (GTK_FILE_CHOOSER_WIDGET (priv->widget)))
{
g_signal_stop_emission_by_name (dialog, "response");
}
-152
View File
@@ -1,152 +0,0 @@
/* GTK - The GIMP Toolkit
* gtkfilechooserembed.h: Abstract sizing interface for file selector implementations
* Copyright (C) 2004, Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 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 "gtkfilechooserembed.h"
#include "gtkmarshalers.h"
#include "gtkintl.h"
static void gtk_file_chooser_embed_class_init (gpointer g_iface);
static gboolean delegate_should_respond (GtkFileChooserEmbed *chooser_embed);
static void delegate_initial_focus (GtkFileChooserEmbed *chooser_embed);
static void delegate_response_requested (GtkFileChooserEmbed *chooser_embed,
gpointer data);
static GtkFileChooserEmbed *
get_delegate (GtkFileChooserEmbed *receiver)
{
return g_object_get_data (G_OBJECT (receiver), "gtk-file-chooser-embed-delegate");
}
/**
* _gtk_file_chooser_embed_delegate_iface_init:
* @iface: a #GtkFileChoserEmbedIface structure
*
* An interface-initialization function for use in cases where an object is
* simply delegating the methods, signals of the #GtkFileChooserEmbed interface
* to another object. _gtk_file_chooser_embed_set_delegate() must be called on
* each instance of the object so that the delegate object can be found.
**/
void
_gtk_file_chooser_embed_delegate_iface_init (GtkFileChooserEmbedIface *iface)
{
iface->should_respond = delegate_should_respond;
iface->initial_focus = delegate_initial_focus;
}
/**
* _gtk_file_chooser_embed_set_delegate:
* @receiver: a GOobject implementing #GtkFileChooserEmbed
* @delegate: another GObject implementing #GtkFileChooserEmbed
*
* Establishes that calls on @receiver for #GtkFileChooser methods should be
* delegated to @delegate, and that #GtkFileChooser signals emitted on @delegate
* should be forwarded to @receiver. Must be used in conjunction with
* _gtk_file_chooser_embed_delegate_iface_init().
**/
void
_gtk_file_chooser_embed_set_delegate (GtkFileChooserEmbed *receiver,
GtkFileChooserEmbed *delegate)
{
g_return_if_fail (GTK_IS_FILE_CHOOSER_EMBED (receiver));
g_return_if_fail (GTK_IS_FILE_CHOOSER_EMBED (delegate));
g_object_set_data (G_OBJECT (receiver), I_("gtk-file-chooser-embed-delegate"), delegate);
g_signal_connect (delegate, "response-requested",
G_CALLBACK (delegate_response_requested), receiver);
}
static gboolean
delegate_should_respond (GtkFileChooserEmbed *chooser_embed)
{
return _gtk_file_chooser_embed_should_respond (get_delegate (chooser_embed));
}
static void
delegate_initial_focus (GtkFileChooserEmbed *chooser_embed)
{
_gtk_file_chooser_embed_initial_focus (get_delegate (chooser_embed));
}
static void
delegate_response_requested (GtkFileChooserEmbed *chooser_embed,
gpointer data)
{
g_signal_emit_by_name (data, "response-requested");
}
/* publicly callable functions */
GType
_gtk_file_chooser_embed_get_type (void)
{
static GType file_chooser_embed_type = 0;
if (!file_chooser_embed_type)
{
const GTypeInfo file_chooser_embed_info =
{
sizeof (GtkFileChooserEmbedIface), /* class_size */
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc)gtk_file_chooser_embed_class_init, /* class_init */
};
file_chooser_embed_type = g_type_register_static (G_TYPE_INTERFACE,
I_("GtkFileChooserEmbed"),
&file_chooser_embed_info, 0);
g_type_interface_add_prerequisite (file_chooser_embed_type, GTK_TYPE_WIDGET);
}
return file_chooser_embed_type;
}
static void
gtk_file_chooser_embed_class_init (gpointer g_iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
g_signal_new (I_("response-requested"),
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkFileChooserEmbedIface, response_requested),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
}
gboolean
_gtk_file_chooser_embed_should_respond (GtkFileChooserEmbed *chooser_embed)
{
g_return_val_if_fail (GTK_IS_FILE_CHOOSER_EMBED (chooser_embed), FALSE);
return GTK_FILE_CHOOSER_EMBED_GET_IFACE (chooser_embed)->should_respond (chooser_embed);
}
void
_gtk_file_chooser_embed_initial_focus (GtkFileChooserEmbed *chooser_embed)
{
g_return_if_fail (GTK_IS_FILE_CHOOSER_EMBED (chooser_embed));
GTK_FILE_CHOOSER_EMBED_GET_IFACE (chooser_embed)->initial_focus (chooser_embed);
}
-61
View File
@@ -1,61 +0,0 @@
/* GTK - The GIMP Toolkit
* gtkfilechooserembed.h: Abstract sizing interface for file selector implementations
* Copyright (C) 2004, Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 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/>.
*/
#ifndef __GTK_FILE_CHOOSER_EMBED_H__
#define __GTK_FILE_CHOOSER_EMBED_H__
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
#define GTK_TYPE_FILE_CHOOSER_EMBED (_gtk_file_chooser_embed_get_type ())
#define GTK_FILE_CHOOSER_EMBED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER_EMBED, GtkFileChooserEmbed))
#define GTK_IS_FILE_CHOOSER_EMBED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_CHOOSER_EMBED))
#define GTK_FILE_CHOOSER_EMBED_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_FILE_CHOOSER_EMBED, GtkFileChooserEmbedIface))
typedef struct _GtkFileChooserEmbed GtkFileChooserEmbed;
typedef struct _GtkFileChooserEmbedIface GtkFileChooserEmbedIface;
struct _GtkFileChooserEmbedIface
{
GTypeInterface base_iface;
/* Methods
*/
gboolean (*should_respond) (GtkFileChooserEmbed *chooser_embed);
void (*initial_focus) (GtkFileChooserEmbed *chooser_embed);
/* Signals
*/
void (*response_requested) (GtkFileChooserEmbed *chooser_embed);
};
GType _gtk_file_chooser_embed_get_type (void) G_GNUC_CONST;
gboolean _gtk_file_chooser_embed_should_respond (GtkFileChooserEmbed *chooser_embed);
void _gtk_file_chooser_embed_initial_focus (GtkFileChooserEmbed *chooser_embed);
void _gtk_file_chooser_embed_delegate_iface_init (GtkFileChooserEmbedIface *iface);
void _gtk_file_chooser_embed_set_delegate (GtkFileChooserEmbed *receiver,
GtkFileChooserEmbed *delegate);
G_END_DECLS
#endif /* __GTK_FILE_CHOOSER_EMBED_H__ */
+1 -1
View File
@@ -25,7 +25,7 @@
#include "gtkcelllayout.h"
#include "gtkcellrenderertext.h"
#include "gtkentryprivate.h"
#include "gtkfilesystemmodel.h"
#include "gtkfilechooserutils.h"
#include "gtklabel.h"
#include "gtkmain.h"
#include "gtksizerequest.h"
-1
View File
@@ -19,7 +19,6 @@
#ifndef __GTK_FILE_CHOOSER_ENTRY_H__
#define __GTK_FILE_CHOOSER_ENTRY_H__
#include "gtkfilesystem.h"
#include "gtkfilechooser.h"
G_BEGIN_DECLS
+1 -1
View File
@@ -148,7 +148,7 @@ void
gtk_file_chooser_error_stack_set_custom_error (GtkFileChooserErrorStack *self,
const char *label_text)
{
GtkWidget *label = gtk_stack_get_child_by_name (GTK_STACK (self->stack), "cutsom");
GtkWidget *label = gtk_stack_get_child_by_name (GTK_STACK (self->stack), "custom");
gtk_label_set_text (GTK_LABEL (label), label_text);
+15 -26
View File
@@ -28,8 +28,6 @@
#include "gtkfilechooserwidget.h"
#include "gtkfilechooserwidgetprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkfilechooserembed.h"
#include "gtkfilesystem.h"
#include "gtksizerequest.h"
#include "gtktypebuiltins.h"
#include "gtkintl.h"
@@ -158,21 +156,8 @@
* possible to use with #GtkFileChooserNative, as such use would
* prohibit the use of a native dialog.
*
* There is no support for the signals that are emitted when the user
* navigates in the dialog, including:
* * #GtkFileChooser::current-folder-changed
* * #GtkFileChooser::selection-changed
* * #GtkFileChooser::file-activated
*
* You can also not use the methods that directly control user navigation:
* * gtk_file_chooser_unselect_filename()
* * gtk_file_chooser_select_all()
* * gtk_file_chooser_unselect_all()
*
* If you need any of the above you will have to use #GtkFileChooserDialog directly.
*
* No operations that change the dialog work while the dialog is visible. Set
* all the properties that are required before showing the dialog.
* No operations that change the dialog work while the dialog is visible.
* Set all the properties that are required before showing the dialog.
*
* ## Win32 details ## {#gtkfilechooserdialognative-win32}
*
@@ -180,7 +165,7 @@
* used. It supports many of the features that #GtkFileChooserDialog
* does, but there are some things it does not handle:
*
* * Any #GtkFileFilter added using a mimetype or custom filter.
* * Any #GtkFileFilter added using a mimetype
*
* If any of these features are used the regular #GtkFileChooserDialog
* will be used in place of the native one.
@@ -190,10 +175,7 @@
* When the org.freedesktop.portal.FileChooser portal is available on the
* session bus, it is used to bring up an out-of-process file chooser. Depending
* on the kind of session the application is running in, this may or may not
* be a GTK+ file chooser. In this situation, the following things are not
* supported and will be silently ignored:
*
* * Any #GtkFileFilter added with a custom filter.
* be a GTK file chooser.
*
* ## macOS details ## {#gtkfilechooserdialognative-macos}
*
@@ -201,8 +183,6 @@
* file chooser dialogs. Some features provided by #GtkFileChooserDialog are
* not supported:
*
* * Any #GtkFileFilter added with a custom filter.
*
* * Shortcut folders.
*/
@@ -683,7 +663,7 @@ gtk_file_chooser_native_set_current_name (GtkFileChooser *chooser,
g_clear_object (&self->current_file);
}
static GSList *
static GListModel *
gtk_file_chooser_native_get_files (GtkFileChooser *chooser)
{
GtkFileChooserNative *self = GTK_FILE_CHOOSER_NATIVE (chooser);
@@ -693,7 +673,16 @@ gtk_file_chooser_native_get_files (GtkFileChooser *chooser)
case MODE_PORTAL:
case MODE_WIN32:
case MODE_QUARTZ:
return g_slist_copy_deep (self->custom_files, (GCopyFunc)g_object_ref, NULL);
{
GListStore *store;
GSList *l;
store = g_list_store_new (G_TYPE_FILE);
for (l = self->custom_files; l; l = l->next)
g_list_store_append (store, l->data);
return G_LIST_MODEL (store);
}
case MODE_FALLBACK:
default:
-2
View File
@@ -28,8 +28,6 @@
#include "gtkfilechooserwidget.h"
#include "gtkfilechooserwidgetprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkfilechooserembed.h"
#include "gtkfilesystem.h"
#include "gtksizerequest.h"
#include "gtktypebuiltins.h"
#include "gtkintl.h"
-2
View File
@@ -28,8 +28,6 @@
#include "gtkfilechooserwidget.h"
#include "gtkfilechooserwidgetprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkfilechooserembed.h"
#include "gtkfilesystem.h"
#include "gtksizerequest.h"
#include "gtktypebuiltins.h"
#include "gtkintl.h"
+1 -2
View File
@@ -34,8 +34,6 @@
#include "gtkfilechooserwidget.h"
#include "gtkfilechooserwidgetprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkfilechooserembed.h"
#include "gtkfilesystem.h"
#include "gtksizerequest.h"
#include "gtktypebuiltins.h"
#include "gtkintl.h"
@@ -908,6 +906,7 @@ gtk_file_chooser_native_win32_show (GtkFileChooserNative *self)
filechooser_win32_thread_data_free (data);
return FALSE;
}
g_object_unref (filter);
}
self->current_filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (self));
}
+8 -5
View File
@@ -20,7 +20,6 @@
#define __GTK_FILE_CHOOSER_PRIVATE_H__
#include "gtkfilechooser.h"
#include "gtkfilesystem.h"
#include "gtkfilesystemmodel.h"
#include "gtkliststore.h"
#include "gtkrecentmanager.h"
@@ -72,8 +71,7 @@ struct _GtkFileChooserIface
GFile *file);
void (*select_all) (GtkFileChooser *chooser);
void (*unselect_all) (GtkFileChooser *chooser);
GSList * (*get_files) (GtkFileChooser *chooser);
GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser);
GListModel * (*get_files) (GtkFileChooser *chooser);
void (*add_filter) (GtkFileChooser *chooser,
GtkFileFilter *filter);
void (*remove_filter) (GtkFileChooser *chooser,
@@ -109,8 +107,13 @@ struct _GtkFileChooserIface
const char *id);
};
GtkFileSystem *_gtk_file_chooser_get_file_system (GtkFileChooser *chooser);
void gtk_file_chooser_select_all (GtkFileChooser *chooser);
void gtk_file_chooser_unselect_all (GtkFileChooser *chooser);
gboolean gtk_file_chooser_select_file (GtkFileChooser *chooser,
GFile *file,
GError **error);
void gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
GFile *file);
G_END_DECLS
#endif /* __GTK_FILE_CHOOSER_PRIVATE_H__ */
+75 -44
View File
@@ -20,7 +20,6 @@
#include "config.h"
#include "gtkfilechooserutils.h"
#include "gtkfilechooser.h"
#include "gtkfilesystem.h"
#include "gtktypebuiltins.h"
#include "gtkintl.h"
@@ -39,8 +38,7 @@ static void delegate_unselect_file (GtkFileChooser *choose
GFile *file);
static void delegate_select_all (GtkFileChooser *chooser);
static void delegate_unselect_all (GtkFileChooser *chooser);
static GSList * delegate_get_files (GtkFileChooser *chooser);
static GtkFileSystem *delegate_get_file_system (GtkFileChooser *chooser);
static GListModel * delegate_get_files (GtkFileChooser *chooser);
static void delegate_add_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
static void delegate_remove_filter (GtkFileChooser *chooser,
@@ -56,12 +54,6 @@ static GListModel * delegate_get_shortcut_folders (GtkFileChooser *choose
static void delegate_notify (GObject *object,
GParamSpec *pspec,
gpointer data);
static void delegate_current_folder_changed (GtkFileChooser *chooser,
gpointer data);
static void delegate_selection_changed (GtkFileChooser *chooser,
gpointer data);
static void delegate_file_activated (GtkFileChooser *chooser,
gpointer data);
static void delegate_add_choice (GtkFileChooser *chooser,
const char *id,
@@ -134,7 +126,6 @@ _gtk_file_chooser_delegate_iface_init (GtkFileChooserIface *iface)
iface->select_all = delegate_select_all;
iface->unselect_all = delegate_unselect_all;
iface->get_files = delegate_get_files;
iface->get_file_system = delegate_get_file_system;
iface->add_filter = delegate_add_filter;
iface->remove_filter = delegate_remove_filter;
iface->get_filters = delegate_get_filters;
@@ -168,12 +159,6 @@ _gtk_file_chooser_set_delegate (GtkFileChooser *receiver,
g_object_set_data (G_OBJECT (receiver), I_("gtk-file-chooser-delegate"), delegate);
g_signal_connect (delegate, "notify",
G_CALLBACK (delegate_notify), receiver);
g_signal_connect (delegate, "current-folder-changed",
G_CALLBACK (delegate_current_folder_changed), receiver);
g_signal_connect (delegate, "selection-changed",
G_CALLBACK (delegate_selection_changed), receiver);
g_signal_connect (delegate, "file-activated",
G_CALLBACK (delegate_file_activated), receiver);
}
GQuark
@@ -221,18 +206,12 @@ delegate_unselect_all (GtkFileChooser *chooser)
gtk_file_chooser_unselect_all (get_delegate (chooser));
}
static GSList *
static GListModel *
delegate_get_files (GtkFileChooser *chooser)
{
return gtk_file_chooser_get_files (get_delegate (chooser));
}
static GtkFileSystem *
delegate_get_file_system (GtkFileChooser *chooser)
{
return _gtk_file_chooser_get_file_system (get_delegate (chooser));
}
static void
delegate_add_filter (GtkFileChooser *chooser,
GtkFileFilter *filter)
@@ -315,27 +294,6 @@ delegate_notify (GObject *object,
g_object_notify (data, pspec->name);
}
static void
delegate_selection_changed (GtkFileChooser *chooser,
gpointer data)
{
g_signal_emit_by_name (data, "selection-changed");
}
static void
delegate_current_folder_changed (GtkFileChooser *chooser,
gpointer data)
{
g_signal_emit_by_name (data, "current-folder-changed");
}
static void
delegate_file_activated (GtkFileChooser *chooser,
gpointer data)
{
g_signal_emit_by_name (data, "file-activated");
}
GSettings *
_gtk_file_chooser_get_settings_for_widget (GtkWidget *widget)
{
@@ -444,3 +402,76 @@ delegate_get_choice (GtkFileChooser *chooser,
{
return gtk_file_chooser_get_choice (get_delegate (chooser), id);
}
gboolean
_gtk_file_info_consider_as_directory (GFileInfo *info)
{
GFileType type = g_file_info_get_file_type (info);
return (type == G_FILE_TYPE_DIRECTORY ||
type == G_FILE_TYPE_MOUNTABLE ||
type == G_FILE_TYPE_SHORTCUT);
}
gboolean
_gtk_file_has_native_path (GFile *file)
{
char *local_file_path;
gboolean has_native_path;
/* Don't use g_file_is_native(), as we want to support FUSE paths if available */
local_file_path = g_file_get_path (file);
has_native_path = (local_file_path != NULL);
g_free (local_file_path);
return has_native_path;
}
gboolean
_gtk_file_consider_as_remote (GFile *file)
{
GFileInfo *info;
gboolean is_remote;
info = g_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE, NULL, NULL);
if (info)
{
is_remote = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE);
g_object_unref (info);
}
else
is_remote = FALSE;
return is_remote;
}
GIcon *
_gtk_file_info_get_icon (GFileInfo *info,
int icon_size,
int scale)
{
GIcon *icon;
GdkPixbuf *pixbuf;
const gchar *thumbnail_path;
thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
if (thumbnail_path)
{
pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
icon_size*scale, icon_size*scale,
NULL);
if (pixbuf != NULL)
return G_ICON (pixbuf);
}
icon = g_file_info_get_icon (info);
if (icon)
return g_object_ref (icon);
/* Use general fallback for all files without icon */
icon = g_themed_icon_new ("text-x-generic");
return icon;
}
+7
View File
@@ -49,6 +49,13 @@ GSettings *_gtk_file_chooser_get_settings_for_widget (GtkWidget *widget);
gchar * _gtk_file_chooser_label_for_file (GFile *file);
gboolean _gtk_file_info_consider_as_directory (GFileInfo *info);
gboolean _gtk_file_has_native_path (GFile *file);
gboolean _gtk_file_consider_as_remote (GFile *file);
GIcon * _gtk_file_info_get_icon (GFileInfo *info,
int icon_size,
int scale);
G_END_DECLS
#endif /* __GTK_FILE_CHOOSER_UTILS_H__ */
+260 -329
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -30,6 +30,12 @@ void
gtk_file_chooser_widget_set_save_entry (GtkFileChooserWidget *chooser,
GtkWidget *entry);
gboolean
gtk_file_chooser_widget_should_respond (GtkFileChooserWidget *chooser);
void
gtk_file_chooser_widget_initial_focus (GtkFileChooserWidget *chooser);
G_END_DECLS
#endif /* __GTK_FILE_CHOOSER_WIDGET_PRIVATE_H__ */
-823
View File
@@ -1,823 +0,0 @@
/* GTK - The GIMP Toolkit
* gtkfilesystem.c: Filesystem abstraction functions.
* Copyright (C) 2003, Red Hat, Inc.
* Copyright (C) 2007-2008 Carlos Garnacho
*
* 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.
*
* 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: Carlos Garnacho <carlos@imendio.com>
*/
#include "config.h"
#include "gtkfilesystem.h"
#include <string.h>
#include <glib/gi18n-lib.h>
#include "gtkfilechooser.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkstylecontextprivate.h"
/* #define DEBUG_MODE */
#ifdef DEBUG_MODE
#define DEBUG(x) g_debug (x);
#else
#define DEBUG(x)
#endif
#define FILES_PER_QUERY 100
/* The pointers we return for a GtkFileSystemVolume are opaque tokens; they are
* really pointers to GDrive, GVolume or GMount objects. We need an extra
* token for the fake File System volume. So, well return a pointer to
* this particular string.
*/
static const gchar *root_volume_token = N_("File System");
#define IS_ROOT_VOLUME(volume) ((gpointer) (volume) == (gpointer) root_volume_token)
enum {
PROP_0,
PROP_FILE,
PROP_ENUMERATOR,
PROP_ATTRIBUTES
};
enum {
VOLUMES_CHANGED,
FS_LAST_SIGNAL
};
enum {
FILES_ADDED,
FILES_REMOVED,
FILES_CHANGED,
FINISHED_LOADING,
DELETED,
FOLDER_LAST_SIGNAL
};
static guint fs_signals [FS_LAST_SIGNAL] = { 0, };
typedef struct AsyncFuncData AsyncFuncData;
struct GtkFileSystemPrivate
{
GVolumeMonitor *volume_monitor;
/* This list contains elements that can be
* of type GDrive, GVolume and GMount
*/
GSList *volumes;
};
struct AsyncFuncData
{
GtkFileSystem *file_system;
GFile *file;
GCancellable *cancellable;
gpointer callback;
gpointer data;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkFileSystem, _gtk_file_system, G_TYPE_OBJECT)
/* GtkFileSystem methods */
static void
volumes_changed (GVolumeMonitor *volume_monitor,
gpointer volume,
gpointer user_data)
{
GtkFileSystem *file_system = user_data;
g_signal_emit (file_system, fs_signals[VOLUMES_CHANGED], 0, volume);
}
static void
gtk_file_system_dispose (GObject *object)
{
GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
GtkFileSystemPrivate *priv = file_system->priv;
DEBUG ("dispose");
if (priv->volumes)
{
g_slist_free_full (priv->volumes, g_object_unref);
priv->volumes = NULL;
}
if (priv->volume_monitor)
{
g_signal_handlers_disconnect_by_func (priv->volume_monitor, volumes_changed, object);
g_object_unref (priv->volume_monitor);
priv->volume_monitor = NULL;
}
G_OBJECT_CLASS (_gtk_file_system_parent_class)->dispose (object);
}
static void
_gtk_file_system_class_init (GtkFileSystemClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = gtk_file_system_dispose;
fs_signals[VOLUMES_CHANGED] =
g_signal_new (I_("volumes-changed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkFileSystemClass, volumes_changed),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
}
static gboolean
mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
{
GList *l;
GFile *mount_root;
gboolean ret;
ret = FALSE;
mount_root = g_mount_get_root (mount);
for (l = volumes; l != NULL; l = l->next)
{
GVolume *volume = G_VOLUME (l->data);
GFile *volume_activation_root;
volume_activation_root = g_volume_get_activation_root (volume);
if (volume_activation_root != NULL)
{
if (g_file_has_prefix (volume_activation_root, mount_root))
{
ret = TRUE;
g_object_unref (volume_activation_root);
break;
}
g_object_unref (volume_activation_root);
}
}
g_object_unref (mount_root);
return ret;
}
static void
get_volumes_list (GtkFileSystem *file_system)
{
GtkFileSystemPrivate *priv = file_system->priv;
GList *l, *ll;
GList *drives;
GList *volumes;
GList *mounts;
GDrive *drive;
GVolume *volume;
GMount *mount;
if (priv->volumes)
{
g_slist_free_full (priv->volumes, g_object_unref);
priv->volumes = NULL;
}
/* first go through all connected drives */
drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
for (l = drives; l != NULL; l = l->next)
{
drive = l->data;
volumes = g_drive_get_volumes (drive);
if (volumes)
{
for (ll = volumes; ll != NULL; ll = ll->next)
{
volume = ll->data;
mount = g_volume_get_mount (volume);
if (mount)
{
/* Show mounted volume */
priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
g_object_unref (mount);
}
else
{
/* Do show the unmounted volumes in the sidebar;
* this is so the user can mount it (in case automounting
* is off).
*
* Also, even if automounting is enabled, this gives a visual
* cue that the user should remember to yank out the media if
* he just unmounted it.
*/
priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
}
g_object_unref (volume);
}
g_list_free (volumes);
}
else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
{
/* If the drive has no mountable volumes and we cannot detect media change.. we
* display the drive in the sidebar so the user can manually poll the drive by
* right clicking and selecting "Rescan..."
*
* This is mainly for drives like floppies where media detection doesn't
* work.. but it's also for human beings who like to turn off media detection
* in the OS to save battery juice.
*/
priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive));
}
g_object_unref (drive);
}
g_list_free (drives);
/* add all volumes that is not associated with a drive */
volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
for (l = volumes; l != NULL; l = l->next)
{
volume = l->data;
drive = g_volume_get_drive (volume);
if (drive)
{
g_object_unref (drive);
continue;
}
mount = g_volume_get_mount (volume);
if (mount)
{
/* show this mount */
priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
g_object_unref (mount);
}
else
{
/* see comment above in why we add an icon for a volume */
priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
}
g_object_unref (volume);
}
/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
for (l = mounts; l != NULL; l = l->next)
{
mount = l->data;
volume = g_mount_get_volume (mount);
if (volume)
{
g_object_unref (volume);
continue;
}
/* if there's exists one or more volumes with an activation root inside the mount,
* don't display the mount
*/
if (mount_referenced_by_volume_activation_root (volumes, mount))
{
g_object_unref (mount);
continue;
}
/* show this mount */
priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
g_object_unref (mount);
}
g_list_free (volumes);
g_list_free (mounts);
}
static void
_gtk_file_system_init (GtkFileSystem *file_system)
{
GtkFileSystemPrivate *priv;
DEBUG ("init");
file_system->priv = priv = _gtk_file_system_get_instance_private (file_system);
/* Volumes */
priv->volume_monitor = g_volume_monitor_get ();
g_signal_connect (priv->volume_monitor, "mount-added",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "mount-removed",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "mount-changed",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "volume-added",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "volume-removed",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "volume-changed",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "drive-connected",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "drive-disconnected",
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "drive-changed",
G_CALLBACK (volumes_changed), file_system);
}
/* GtkFileSystem public methods */
GtkFileSystem *
_gtk_file_system_new (void)
{
return g_object_new (GTK_TYPE_FILE_SYSTEM, NULL);
}
GSList *
_gtk_file_system_list_volumes (GtkFileSystem *file_system)
{
GtkFileSystemPrivate *priv = file_system->priv;
GSList *list;
DEBUG ("list_volumes");
get_volumes_list (file_system);
list = g_slist_copy (priv->volumes);
#ifndef G_OS_WIN32
/* Prepend root volume */
list = g_slist_prepend (list, (gpointer) root_volume_token);
#endif
return list;
}
static void
free_async_data (AsyncFuncData *async_data)
{
g_object_unref (async_data->file_system);
g_object_unref (async_data->file);
g_object_unref (async_data->cancellable);
g_free (async_data);
}
static void
query_info_callback (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
AsyncFuncData *async_data;
GError *error = NULL;
GFileInfo *file_info;
GFile *file;
DEBUG ("query_info_callback");
file = G_FILE (source_object);
async_data = (AsyncFuncData *) user_data;
file_info = g_file_query_info_finish (file, result, &error);
if (async_data->callback)
{
((GtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable,
file_info, error, async_data->data);
}
if (file_info)
g_object_unref (file_info);
if (error)
g_error_free (error);
free_async_data (async_data);
}
GCancellable *
_gtk_file_system_get_info (GtkFileSystem *file_system,
GFile *file,
const gchar *attributes,
GtkFileSystemGetInfoCallback callback,
gpointer data)
{
GCancellable *cancellable;
AsyncFuncData *async_data;
g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
g_return_val_if_fail (G_IS_FILE (file), NULL);
cancellable = g_cancellable_new ();
async_data = g_new0 (AsyncFuncData, 1);
async_data->file_system = g_object_ref (file_system);
async_data->file = g_object_ref (file);
async_data->cancellable = g_object_ref (cancellable);
async_data->callback = callback;
async_data->data = data;
g_file_query_info_async (file,
attributes,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
cancellable,
query_info_callback,
async_data);
return cancellable;
}
static void
drive_poll_for_media_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
AsyncFuncData *async_data;
GError *error = NULL;
g_drive_poll_for_media_finish (G_DRIVE (source_object), result, &error);
async_data = (AsyncFuncData *) user_data;
((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
(GtkFileSystemVolume *) source_object,
error, async_data->data);
if (error)
g_error_free (error);
}
static void
volume_mount_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
AsyncFuncData *async_data;
GError *error = NULL;
g_volume_mount_finish (G_VOLUME (source_object), result, &error);
async_data = (AsyncFuncData *) user_data;
((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
(GtkFileSystemVolume *) source_object,
error, async_data->data);
if (error)
g_error_free (error);
}
GCancellable *
_gtk_file_system_mount_volume (GtkFileSystem *file_system,
GtkFileSystemVolume *volume,
GMountOperation *mount_operation,
GtkFileSystemVolumeMountCallback callback,
gpointer data)
{
GCancellable *cancellable;
AsyncFuncData *async_data;
gboolean handled = FALSE;
DEBUG ("volume_mount");
cancellable = g_cancellable_new ();
async_data = g_new0 (AsyncFuncData, 1);
async_data->file_system = g_object_ref (file_system);
async_data->cancellable = g_object_ref (cancellable);
async_data->callback = callback;
async_data->data = data;
if (G_IS_DRIVE (volume))
{
/* this path happens for drives that are not polled by the OS and where the last media
* check indicated that no media was available. So the thing to do here is to
* invoke poll_for_media() on the drive
*/
g_drive_poll_for_media (G_DRIVE (volume), cancellable, drive_poll_for_media_cb, async_data);
handled = TRUE;
}
else if (G_IS_VOLUME (volume))
{
g_volume_mount (G_VOLUME (volume), G_MOUNT_MOUNT_NONE, mount_operation, cancellable, volume_mount_cb, async_data);
handled = TRUE;
}
if (!handled)
free_async_data (async_data);
return cancellable;
}
static void
enclosing_volume_mount_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
GtkFileSystemVolume *volume;
AsyncFuncData *async_data;
GError *error = NULL;
async_data = (AsyncFuncData *) user_data;
g_file_mount_enclosing_volume_finish (G_FILE (source_object), result, &error);
volume = _gtk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object));
/* Silently drop G_IO_ERROR_ALREADY_MOUNTED error for gvfs backends without visible mounts. */
/* Better than doing query_info with additional I/O every time. */
if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED))
g_clear_error (&error);
((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
error, async_data->data);
if (error)
g_error_free (error);
_gtk_file_system_volume_unref (volume);
}
GCancellable *
_gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system,
GFile *file,
GMountOperation *mount_operation,
GtkFileSystemVolumeMountCallback callback,
gpointer data)
{
GCancellable *cancellable;
AsyncFuncData *async_data;
g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
g_return_val_if_fail (G_IS_FILE (file), NULL);
DEBUG ("mount_enclosing_volume");
cancellable = g_cancellable_new ();
async_data = g_new0 (AsyncFuncData, 1);
async_data->file_system = g_object_ref (file_system);
async_data->file = g_object_ref (file);
async_data->cancellable = g_object_ref (cancellable);
async_data->callback = callback;
async_data->data = data;
g_file_mount_enclosing_volume (file,
G_MOUNT_MOUNT_NONE,
mount_operation,
cancellable,
enclosing_volume_mount_cb,
async_data);
return cancellable;
}
GtkFileSystemVolume *
_gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
GFile *file)
{
GMount *mount;
DEBUG ("get_volume_for_file");
mount = g_file_find_enclosing_mount (file, NULL, NULL);
if (!mount && g_file_is_native (file))
return (GtkFileSystemVolume *) root_volume_token;
return (GtkFileSystemVolume *) mount;
}
/* GtkFileSystemVolume public methods */
gchar *
_gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
{
DEBUG ("volume_get_display_name");
if (IS_ROOT_VOLUME (volume))
return g_strdup (_(root_volume_token));
if (G_IS_DRIVE (volume))
return g_drive_get_name (G_DRIVE (volume));
else if (G_IS_MOUNT (volume))
return g_mount_get_name (G_MOUNT (volume));
else if (G_IS_VOLUME (volume))
return g_volume_get_name (G_VOLUME (volume));
return NULL;
}
gboolean
_gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
{
gboolean mounted;
DEBUG ("volume_is_mounted");
if (IS_ROOT_VOLUME (volume))
return TRUE;
mounted = FALSE;
if (G_IS_MOUNT (volume))
mounted = TRUE;
else if (G_IS_VOLUME (volume))
{
GMount *mount;
mount = g_volume_get_mount (G_VOLUME (volume));
if (mount)
{
mounted = TRUE;
g_object_unref (mount);
}
}
return mounted;
}
GFile *
_gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
{
GFile *file = NULL;
DEBUG ("volume_get_base");
if (IS_ROOT_VOLUME (volume))
return g_file_new_for_uri ("file:///");
if (G_IS_MOUNT (volume))
file = g_mount_get_root (G_MOUNT (volume));
else if (G_IS_VOLUME (volume))
{
GMount *mount;
mount = g_volume_get_mount (G_VOLUME (volume));
if (mount)
{
file = g_mount_get_root (mount);
g_object_unref (mount);
}
}
return file;
}
GIcon *
_gtk_file_system_volume_get_icon (GtkFileSystemVolume *volume)
{
GIcon *icon = NULL;
if (IS_ROOT_VOLUME (volume))
icon = g_themed_icon_new ("drive-harddisk");
else if (G_IS_DRIVE (volume))
icon = g_drive_get_icon (G_DRIVE (volume));
else if (G_IS_VOLUME (volume))
icon = g_volume_get_icon (G_VOLUME (volume));
else if (G_IS_MOUNT (volume))
icon = g_mount_get_icon (G_MOUNT (volume));
return icon;
}
GIcon *
_gtk_file_system_volume_get_symbolic_icon (GtkFileSystemVolume *volume)
{
if (IS_ROOT_VOLUME (volume))
return g_themed_icon_new ("drive-harddisk-symbolic");
else if (G_IS_DRIVE (volume))
return g_drive_get_symbolic_icon (G_DRIVE (volume));
else if (G_IS_VOLUME (volume))
return g_volume_get_symbolic_icon (G_VOLUME (volume));
else if (G_IS_MOUNT (volume))
return g_mount_get_symbolic_icon (G_MOUNT (volume));
else
return NULL;
}
GtkFileSystemVolume *
_gtk_file_system_volume_ref (GtkFileSystemVolume *volume)
{
if (IS_ROOT_VOLUME (volume))
return volume;
if (G_IS_MOUNT (volume) ||
G_IS_VOLUME (volume) ||
G_IS_DRIVE (volume))
g_object_ref (volume);
return volume;
}
void
_gtk_file_system_volume_unref (GtkFileSystemVolume *volume)
{
/* Root volume doesn't need to be freed */
if (IS_ROOT_VOLUME (volume))
return;
if (G_IS_MOUNT (volume) ||
G_IS_VOLUME (volume) ||
G_IS_DRIVE (volume))
g_object_unref (volume);
}
/* GFileInfo helper functions */
GIcon *
_gtk_file_info_get_icon (GFileInfo *info,
int icon_size,
int scale)
{
GIcon *icon;
GdkPixbuf *pixbuf;
const gchar *thumbnail_path;
thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
if (thumbnail_path)
{
pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
icon_size*scale, icon_size*scale,
NULL);
if (pixbuf != NULL)
return G_ICON (pixbuf);
}
icon = g_file_info_get_icon (info);
if (icon)
return g_object_ref (icon);
/* Use general fallback for all files without icon */
icon = g_themed_icon_new ("text-x-generic");
return icon;
}
gboolean
_gtk_file_info_consider_as_directory (GFileInfo *info)
{
GFileType type = g_file_info_get_file_type (info);
return (type == G_FILE_TYPE_DIRECTORY ||
type == G_FILE_TYPE_MOUNTABLE ||
type == G_FILE_TYPE_SHORTCUT);
}
gboolean
_gtk_file_has_native_path (GFile *file)
{
char *local_file_path;
gboolean has_native_path;
/* Don't use g_file_is_native(), as we want to support FUSE paths if available */
local_file_path = g_file_get_path (file);
has_native_path = (local_file_path != NULL);
g_free (local_file_path);
return has_native_path;
}
gboolean
_gtk_file_consider_as_remote (GFile *file)
{
GFileInfo *info;
gboolean is_remote;
info = g_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE, NULL, NULL);
if (info)
{
is_remote = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE);
g_object_unref (info);
}
else
is_remote = FALSE;
return is_remote;
}
-116
View File
@@ -1,116 +0,0 @@
/* GTK - The GIMP Toolkit
* gtkfilesystem.h: Filesystem abstraction functions.
* Copyright (C) 2003, Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 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/>.
*/
#ifndef __GTK_FILE_SYSTEM_H__
#define __GTK_FILE_SYSTEM_H__
#include <gio/gio.h>
#include <gtk/gtkwidget.h> /* For icon handling */
G_BEGIN_DECLS
#define GTK_TYPE_FILE_SYSTEM (_gtk_file_system_get_type ())
#define GTK_FILE_SYSTEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_FILE_SYSTEM, GtkFileSystem))
#define GTK_FILE_SYSTEM_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_FILE_SYSTEM, GtkFileSystemClass))
#define GTK_IS_FILE_SYSTEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_FILE_SYSTEM))
#define GTK_IS_FILE_SYSTEM_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GTK_TYPE_FILE_SYSTEM))
#define GTK_FILE_SYSTEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_FILE_SYSTEM, GtkFileSystemClass))
typedef struct GtkFileSystem GtkFileSystem;
typedef struct GtkFileSystemPrivate GtkFileSystemPrivate;
typedef struct GtkFileSystemClass GtkFileSystemClass;
typedef struct GtkFileSystemVolume GtkFileSystemVolume; /* opaque struct */
struct GtkFileSystem
{
GObject parent_object;
GtkFileSystemPrivate *priv;
};
struct GtkFileSystemClass
{
GObjectClass parent_class;
void (*volumes_changed) (GtkFileSystem *file_system);
};
typedef void (* GtkFileSystemGetInfoCallback) (GCancellable *cancellable,
GFileInfo *file_info,
const GError *error,
gpointer data);
typedef void (* GtkFileSystemVolumeMountCallback) (GCancellable *cancellable,
GtkFileSystemVolume *volume,
const GError *error,
gpointer data);
/* GtkFileSystem methods */
GType _gtk_file_system_get_type (void) G_GNUC_CONST;
GtkFileSystem * _gtk_file_system_new (void);
GSList * _gtk_file_system_list_volumes (GtkFileSystem *file_system);
GCancellable * _gtk_file_system_get_info (GtkFileSystem *file_system,
GFile *file,
const gchar *attributes,
GtkFileSystemGetInfoCallback callback,
gpointer data);
GCancellable * _gtk_file_system_mount_volume (GtkFileSystem *file_system,
GtkFileSystemVolume *volume,
GMountOperation *mount_operation,
GtkFileSystemVolumeMountCallback callback,
gpointer data);
GCancellable * _gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system,
GFile *file,
GMountOperation *mount_operation,
GtkFileSystemVolumeMountCallback callback,
gpointer data);
GtkFileSystemVolume * _gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
GFile *file);
/* GtkFileSystemVolume methods */
gchar * _gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume);
gboolean _gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume);
GFile * _gtk_file_system_volume_get_root (GtkFileSystemVolume *volume);
GIcon * _gtk_file_system_volume_get_symbolic_icon (GtkFileSystemVolume *volume);
GIcon * _gtk_file_system_volume_get_icon (GtkFileSystemVolume *volume);
GtkFileSystemVolume *_gtk_file_system_volume_ref (GtkFileSystemVolume *volume);
void _gtk_file_system_volume_unref (GtkFileSystemVolume *volume);
/* GFileInfo helper functions */
GIcon * _gtk_file_info_get_icon (GFileInfo *info,
int icon_size,
int scale);
gboolean _gtk_file_info_consider_as_directory (GFileInfo *info);
/* GFile helper functions */
gboolean _gtk_file_has_native_path (GFile *file);
gboolean _gtk_file_consider_as_remote (GFile *file);
G_END_DECLS
#endif /* __GTK_FILE_SYSTEM_H__ */
+1 -1
View File
@@ -23,7 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include "gtkfilesystem.h"
#include "gtkfilechooserutils.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtktreedatalist.h"
+13 -12
View File
@@ -30,20 +30,21 @@
* @Short_description: Filtering items
* @See_also: #GtkFilerListModel
*
* #GtkFilter is the way to describe filters to be used in #GtkFilterListModel.
*
* The model will use a filter to determine if it should filter items or not
* by calling gtk_filter_match() for each item and only keeping the ones
* visible that the function returns %TRUE for.
* A #GtkFilter object describes the filtering to be performed by a
* #GtkFilterListModel.
*
* The model will use the filter to determine if it should include items
* or not by calling gtk_filter_match() for each item and only keeping the
* ones that the function returns %TRUE for.
*
* Filters may change what items they match through their lifetime. In that
* case, they can call gtk_filter_changed() which will emit the #GtkFilter:changed
* signal to notify that previous filter results are no longer valid and that
* items should be checked via gtk_filter_match() again.
* case, they will emit the #GtkFilter:changed signal to notify that previous
* filter results are no longer valid and that items should be checked again
* via gtk_filter_match().
*
* GTK provides various premade filter implementations for common filtering
* GTK provides various pre-made filter implementations for common filtering
* operations. These filters often include properties that can be linked to
* various widgets to easily allow searches.
* various widgets to easily allow searches.
*
* However, in particular for large lists or complex search methods, it is
* also possible to subclass #GtkFilter and provide one's own filter.
@@ -118,7 +119,7 @@ gtk_filter_init (GtkFilter *self)
* @self: a #GtkFilter
* @item: (type GObject) (transfer none): The item to check
*
* Checks if the given @item is matched by the filter or not.
* Checks if the given @item is matched by the filter or not.
*
* Returns: %TRUE if the filter matches the item and a filter model should
* keep it, %FALSE if not.
@@ -140,7 +141,7 @@ gtk_filter_match (GtkFilter *self,
* Gets the known strictness of @filters. If the strictness is not known,
* %GTK_FILTER_MATCH_SOME is returned.
*
* This value may change after emission of the GtkFilter:changed signal.
* This value may change after emission of the #GtkFilter:changed signal.
*
* This function is meant purely for optimization purposes, filters can
* choose to omit implementing it, but #GtkFilterListModel uses it.
+13 -7
View File
@@ -178,7 +178,7 @@ gtk_filter_list_model_run_filter (GtkFilterListModel *self,
}
if (more)
gtk_bitset_remove_range_closed (self->pending, 0, pos);
gtk_bitset_remove_range_closed (self->pending, 0, pos - 1);
else
g_clear_pointer (&self->pending, gtk_bitset_unref);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]);
@@ -494,7 +494,7 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self,
{
default:
g_assert_not_reached ();
G_GNUC_FALLTHROUGH;
/* fall thru */
case GTK_FILTER_CHANGE_DIFFERENT:
self->matches = gtk_bitset_new_empty ();
pending = gtk_bitset_new_range (0, g_list_model_get_n_items (self->model));
@@ -575,7 +575,7 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class)
properties[PROP_INCREMENTAL] =
g_param_spec_boolean ("incremental",
P_("Incremental"),
P_("Filer items incrementally"),
P_("Filter items incrementally"),
FALSE,
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
@@ -771,8 +771,8 @@ gtk_filter_list_model_get_model (GtkFilterListModel *self)
* @self: a #GtkFilterListModel
* @incremental: %TRUE to enable incremental filtering
*
* When incremental filtering is enabled, the filterlistmodel will not run
* filters immediately, but will instead queue an idle handler that
* When incremental filtering is enabled, the GtkFilterListModel will not
* run filters immediately, but will instead queue an idle handler that
* incrementally filters the items and adds them to the list. This of course
* means that items are not instantly added to the list, but only appear
* incrementally.
@@ -837,8 +837,14 @@ gtk_filter_list_model_get_incremental (GtkFilterListModel *self)
*
* You can use this value to check if @self is busy filtering by
* comparing the return value to 0 or you can compute the percentage
* of the filter remaining by dividing the return value by
* g_list_model_get_n_items(gtk_filter_list_model_get_model (self)).
* of the filter remaining by dividing the return value by the total
* number of items in the underlying model:
*
* |[
* pending = gtk_filter_list_model_get_pending (self);
* model = gtk_filter_list_model_get_model (self);
* percentage = pending / (double) g_list_model_get_n_items (model);
* ]|
*
* Returns: The number of items not yet filtered
**/
+1 -1
View File
@@ -300,7 +300,7 @@ gtk_flatten_list_model_add_items (GtkFlattenListModel *self,
G_CALLBACK (gtk_flatten_list_model_items_changed_cb),
node);
node->list = self;
added +=g_list_model_get_n_items (node->model);
added += g_list_model_get_n_items (node->model);
}
return added;
+1 -1
View File
@@ -45,7 +45,7 @@
/**
* SECTION:gtkgridview
* @title: GtkGridView
* @short_description: A widget for displaying lists in a grid
* @short_description: A widget for displaying grids
* @see_also: #GListModel, #GtkListView, #GtkColumnView
*
* GtkGridView is a widget to present a view into a large dynamic grid of items.
+12 -12
View File
@@ -55,13 +55,13 @@
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkprofilerprivate.h"
#define GTK_VECTOR_ELEMENT_TYPE char *
#define GTK_VECTOR_NULL_TERMINATED 1
#define GTK_VECTOR_FREE_FUNC g_free
#define GTK_VECTOR_TYPE_NAME GtkStrvBuilder
#define GTK_VECTOR_NAME gtk_strv_builder
#define GTK_VECTOR_PREALLOC 16
#include "gtkvectorimpl.c"
#define GDK_ARRAY_ELEMENT_TYPE char *
#define GDK_ARRAY_NULL_TERMINATED 1
#define GDK_ARRAY_FREE_FUNC g_free
#define GDK_ARRAY_TYPE_NAME GtkStrvBuilder
#define GDK_ARRAY_NAME gtk_strv_builder
#define GDK_ARRAY_PREALLOC 16
#include "gdk/gdkarrayimpl.c"
/**
* SECTION:gtkicontheme
@@ -3858,11 +3858,11 @@ gtk_icon_paintable_ensure_texture (GtkIconPaintable *self)
static void
init_color_matrix (graphene_matrix_t *color_matrix,
graphene_vec4_t *color_offset,
const GdkRGBA *foreground_color,
const GdkRGBA *success_color,
const GdkRGBA *warning_color,
const GdkRGBA *error_color)
graphene_vec4_t *color_offset,
const GdkRGBA *foreground_color,
const GdkRGBA *success_color,
const GdkRGBA *warning_color,
const GdkRGBA *error_color)
{
GdkRGBA fg_default = { 0.7450980392156863, 0.7450980392156863, 0.7450980392156863, 1.0};
GdkRGBA success_default = { 0.3046921492332342,0.6015716792553597, 0.023437857633325704, 1.0};
+13 -2
View File
@@ -725,6 +725,8 @@ static const GtkBuildableParser offset_parser =
offset_start_element
};
static GtkBuildableIface *parent_buildable_iface;
static gboolean
gtk_level_bar_buildable_custom_tag_start (GtkBuildable *buildable,
GtkBuilder *builder,
@@ -735,6 +737,10 @@ gtk_level_bar_buildable_custom_tag_start (GtkBuildable *buildable,
{
OffsetsParserData *data;
if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
tagname, parser, parser_data))
return TRUE;
if (child)
return FALSE;
@@ -767,7 +773,11 @@ gtk_level_bar_buildable_custom_finished (GtkBuildable *buildable,
self = data->self;
if (strcmp (tagname, "offsets") != 0)
goto out;
{
parent_buildable_iface->custom_finished (buildable, builder, child,
tagname, user_data);
return;
}
for (l = data->offsets; l != NULL; l = l->next)
{
@@ -775,7 +785,6 @@ gtk_level_bar_buildable_custom_finished (GtkBuildable *buildable,
gtk_level_bar_add_offset_value (self, offset->name, offset->value);
}
out:
g_list_free_full (data->offsets, (GDestroyNotify) gtk_level_bar_offset_free);
g_slice_free (OffsetsParserData, data);
}
@@ -783,6 +792,8 @@ gtk_level_bar_buildable_custom_finished (GtkBuildable *buildable,
static void
gtk_level_bar_buildable_init (GtkBuildableIface *iface)
{
parent_buildable_iface = g_type_interface_peek_parent (iface);
iface->custom_tag_start = gtk_level_bar_buildable_custom_tag_start;
iface->custom_finished = gtk_level_bar_buildable_custom_finished;
}
+1 -1
View File
@@ -26,7 +26,7 @@
/**
* SECTION:gtklistitem
* @title: GtkListItem
* @short_description: Object used to represent items of a ListModel
* @short_description: Object used to represent items of a list model
* @see_also: #GtkListView, #GListModel
*
* #GtkListItem is the object that list-handling containers such
+7 -13
View File
@@ -577,13 +577,11 @@ gtk_list_item_manager_model_items_changed_cb (GListModel *model,
GtkListItemManager *self)
{
GHashTable *change;
GHashTableIter iter;
gpointer list_item;
GSList *l;
guint n_items;
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->model));
change = g_hash_table_new (g_direct_hash, g_direct_equal);
change = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify )gtk_widget_unparent);
gtk_list_item_manager_remove_items (self, change, position, removed);
gtk_list_item_manager_add_items (self, position, added);
@@ -727,12 +725,6 @@ gtk_list_item_manager_model_items_changed_cb (GListModel *model,
tracker->widget = GTK_LIST_ITEM_WIDGET (item->widget);
}
g_hash_table_iter_init (&iter, change);
while (g_hash_table_iter_next (&iter, NULL, &list_item))
{
gtk_list_item_manager_release_list_item (self, NULL, list_item);
}
g_hash_table_unref (change);
gtk_widget_queue_resize (self->widget);
@@ -1073,10 +1065,12 @@ gtk_list_item_manager_release_list_item (GtkListItemManager *self,
if (change != NULL)
{
if (g_hash_table_insert (change, gtk_list_item_widget_get_item (GTK_LIST_ITEM_WIDGET (item)), item))
return;
g_warning ("FIXME: Handle the same item multiple times in the list.\nLars says this totally should not happen, but here we are.");
if (!g_hash_table_replace (change, gtk_list_item_widget_get_item (GTK_LIST_ITEM_WIDGET (item)), item))
{
g_warning ("FIXME: Handle the same item multiple times in the list.\nLars says this totally should not happen, but here we are.");
}
return;
}
gtk_widget_unparent (item);
+6 -7
View File
@@ -137,12 +137,12 @@
#include "a11y/gtkaccessibility.h"
#include "inspector/window.h"
#define GTK_VECTOR_ELEMENT_TYPE GtkWidget *
#define GTK_VECTOR_TYPE_NAME GtkWidgetStack
#define GTK_VECTOR_NAME gtk_widget_stack
#define GTK_VECTOR_FREE_FUNC g_object_unref
#define GTK_VECTOR_PREALLOC 16
#include "gtkvectorimpl.c"
#define GDK_ARRAY_ELEMENT_TYPE GtkWidget *
#define GDK_ARRAY_TYPE_NAME GtkWidgetStack
#define GDK_ARRAY_NAME gtk_widget_stack
#define GDK_ARRAY_FREE_FUNC g_object_unref
#define GDK_ARRAY_PREALLOC 16
#include "gdk/gdkarrayimpl.c"
static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
@@ -181,7 +181,6 @@ static const GdkDebugKey gtk_debug_keys[] = {
{ "no-css-cache", GTK_DEBUG_NO_CSS_CACHE, "Disable style property cache" },
{ "interactive", GTK_DEBUG_INTERACTIVE, "Enable the GTK inspector" },
{ "touchscreen", GTK_DEBUG_TOUCHSCREEN, "Pretend the pointer is a touchscreen" },
{ "resize", GTK_DEBUG_RESIZE, "Highlight resizing widgets" },
{ "layout", GTK_DEBUG_LAYOUT, "Show layout borders" },
{ "snapshot", GTK_DEBUG_SNAPSHOT, "Generate debug render nodes" },
};

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